Coverage Report

Created: 2025-07-23 06:33

/src/php-src/ext/hash/sha3/generic64lc/KeccakSponge.inc
Line
Count
Source (jump to first uncovered line)
1
/*
2
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3
Joan Daemen, Michaƫl Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4
denoted as "the implementer".
5
6
For more information, feedback or questions, please refer to our websites:
7
http://keccak.noekeon.org/
8
http://keyak.noekeon.org/
9
http://ketje.noekeon.org/
10
11
To the extent possible under law, the implementer has waived all copyright
12
and related or neighboring rights to the source code in this file.
13
http://creativecommons.org/publicdomain/zero/1.0/
14
*/
15
16
478
#define JOIN0(a, b)                     a ## b
17
478
#define JOIN(a, b)                      JOIN0(a, b)
18
19
#define Sponge                          JOIN(prefix, _Sponge)
20
#define SpongeInstance                  JOIN(prefix, _SpongeInstance)
21
#define SpongeInitialize                JOIN(prefix, _SpongeInitialize)
22
#define SpongeAbsorb                    JOIN(prefix, _SpongeAbsorb)
23
0
#define SpongeAbsorbLastFewBits         JOIN(prefix, _SpongeAbsorbLastFewBits)
24
#define SpongeSqueeze                   JOIN(prefix, _SpongeSqueeze)
25
26
#define SnP_stateSizeInBytes            JOIN(SnP, _stateSizeInBytes)
27
#define SnP_stateAlignment              JOIN(SnP, _stateAlignment)
28
#define SnP_StaticInitialize            JOIN(SnP, _StaticInitialize)
29
134
#define SnP_Initialize                  JOIN(SnP, _Initialize)
30
168
#define SnP_AddByte                     JOIN(SnP, _AddByte)
31
92
#define SnP_AddBytes                    JOIN(SnP, _AddBytes)
32
84
#define SnP_ExtractBytes                JOIN(SnP, _ExtractBytes)
33
34
int Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen)
35
0
{
36
0
    ALIGN(SnP_stateAlignment) unsigned char state[SnP_stateSizeInBytes];
37
0
    unsigned int partialBlock;
38
0
    const unsigned char *curInput = input;
39
0
    unsigned char *curOutput = output;
40
0
    unsigned int rateInBytes = rate/8;
41
42
0
    if (rate+capacity != SnP_width)
43
0
        return 1;
44
0
    if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
45
0
        return 1;
46
0
    if (suffix == 0)
47
0
        return 1;
48
49
    /* Initialize the state */
50
0
    SnP_StaticInitialize();
51
0
    SnP_Initialize(state);
52
53
    /* First, absorb whole blocks */
54
#ifdef SnP_FastLoop_Absorb
55
0
    if (((rateInBytes % (SnP_width/200)) == 0) && (inputByteLen >= rateInBytes)) {
56
        /* fast lane: whole lane rate */
57
0
        size_t j;
58
0
        j = SnP_FastLoop_Absorb(state, rateInBytes/(SnP_width/200), curInput, inputByteLen);
59
0
        curInput += j;
60
0
        inputByteLen -= j;
61
0
    }
62
#endif
63
0
    while(inputByteLen >= (size_t)rateInBytes) {
64
        #ifdef KeccakReference
65
        displayBytes(1, "Block to be absorbed", curInput, rateInBytes);
66
        #endif
67
0
        SnP_AddBytes(state, curInput, 0, rateInBytes);
68
0
        SnP_Permute(state);
69
0
        curInput += rateInBytes;
70
0
        inputByteLen -= rateInBytes;
71
0
    }
72
73
    /* Then, absorb what remains */
74
0
    partialBlock = (unsigned int)inputByteLen;
75
    #ifdef KeccakReference
76
    displayBytes(1, "Block to be absorbed (part)", curInput, partialBlock);
77
    #endif
78
0
    SnP_AddBytes(state, curInput, 0, partialBlock);
79
80
    /* Finally, absorb the suffix */
81
    #ifdef KeccakReference
82
    {
83
        unsigned char delimitedData1[1];
84
        delimitedData1[0] = suffix;
85
        displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
86
    }
87
    #endif
88
    /* Last few bits, whose delimiter coincides with first bit of padding */
89
0
    SnP_AddByte(state, suffix, partialBlock);
90
    /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
91
0
    if ((suffix >= 0x80) && (partialBlock == (rateInBytes-1)))
92
0
        SnP_Permute(state);
93
    /* Second bit of padding */
94
0
    SnP_AddByte(state, 0x80, rateInBytes-1);
95
    #ifdef KeccakReference
96
    {
97
        unsigned char block[SnP_width/8];
98
        memset(block, 0, SnP_width/8);
99
        block[rateInBytes-1] = 0x80;
100
        displayBytes(1, "Second bit of padding", block, rateInBytes);
101
    }
102
    #endif
103
0
    SnP_Permute(state);
104
    #ifdef KeccakReference
105
    displayText(1, "--- Switching to squeezing phase ---");
106
    #endif
107
108
    /* First, output whole blocks */
109
0
    while(outputByteLen > (size_t)rateInBytes) {
110
0
        SnP_ExtractBytes(state, curOutput, 0, rateInBytes);
111
0
        SnP_Permute(state);
112
        #ifdef KeccakReference
113
        displayBytes(1, "Squeezed block", curOutput, rateInBytes);
114
        #endif
115
0
        curOutput += rateInBytes;
116
0
        outputByteLen -= rateInBytes;
117
0
    }
118
119
    /* Finally, output what remains */
120
0
    partialBlock = (unsigned int)outputByteLen;
121
0
    SnP_ExtractBytes(state, curOutput, 0, partialBlock);
122
    #ifdef KeccakReference
123
    displayBytes(1, "Squeezed block (part)", curOutput, partialBlock);
124
    #endif
125
126
0
    return 0;
127
0
}
Unexecuted instantiation: KeccakWidth1600_Sponge
Unexecuted instantiation: KeccakWidth1600_12rounds_Sponge
128
129
/* ---------------------------------------------------------------- */
130
/* ---------------------------------------------------------------- */
131
/* ---------------------------------------------------------------- */
132
133
int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity)
134
134
{
135
134
    if (rate+capacity != SnP_width)
136
0
        return 1;
137
134
    if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
138
0
        return 1;
139
134
    SnP_StaticInitialize();
140
134
    SnP_Initialize(instance->state);
141
134
    instance->rate = rate;
142
134
    instance->byteIOIndex = 0;
143
134
    instance->squeezing = 0;
144
145
134
    return 0;
146
134
}
KeccakWidth1600_SpongeInitialize
Line
Count
Source
134
134
{
135
134
    if (rate+capacity != SnP_width)
136
0
        return 1;
137
134
    if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
138
0
        return 1;
139
134
    SnP_StaticInitialize();
140
134
    SnP_Initialize(instance->state);
141
134
    instance->rate = rate;
142
134
    instance->byteIOIndex = 0;
143
134
    instance->squeezing = 0;
144
145
134
    return 0;
146
134
}
Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeInitialize
147
148
/* ---------------------------------------------------------------- */
149
150
int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen)
151
84
{
152
84
    size_t i, j;
153
84
    unsigned int partialBlock;
154
84
    const unsigned char *curData;
155
84
    unsigned int rateInBytes = instance->rate/8;
156
157
84
    if (instance->squeezing)
158
0
        return 1; /* Too late for additional input */
159
160
84
    i = 0;
161
84
    curData = data;
162
239
    while(i < dataByteLen) {
163
155
        if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) {
164
#ifdef SnP_FastLoop_Absorb
165
            /* processing full blocks first */
166
63
            if ((rateInBytes % (SnP_width/200)) == 0) {
167
                /* fast lane: whole lane rate */
168
63
                j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i);
169
63
                i += j;
170
63
                curData += j;
171
63
            }
172
0
            else {
173
0
#endif
174
0
                for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
175
                    #ifdef KeccakReference
176
                    displayBytes(1, "Block to be absorbed", curData, rateInBytes);
177
                    #endif
178
0
                    SnP_AddBytes(instance->state, curData, 0, rateInBytes);
179
0
                    SnP_Permute(instance->state);
180
0
                    curData+=rateInBytes;
181
0
                }
182
0
                i = dataByteLen - j;
183
#ifdef SnP_FastLoop_Absorb
184
            }
185
#endif
186
63
        }
187
92
        else {
188
            /* normal lane: using the message queue */
189
92
            if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
190
34
                partialBlock = rateInBytes-instance->byteIOIndex;
191
58
            else
192
58
                partialBlock = (unsigned int)(dataByteLen - i);
193
            #ifdef KeccakReference
194
            displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);
195
            #endif
196
92
            i += partialBlock;
197
198
92
            SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
199
92
            curData += partialBlock;
200
92
            instance->byteIOIndex += partialBlock;
201
92
            if (instance->byteIOIndex == rateInBytes) {
202
34
                SnP_Permute(instance->state);
203
34
                instance->byteIOIndex = 0;
204
34
            }
205
92
        }
206
155
    }
207
84
    return 0;
208
84
}
KeccakWidth1600_SpongeAbsorb
Line
Count
Source
151
84
{
152
84
    size_t i, j;
153
84
    unsigned int partialBlock;
154
84
    const unsigned char *curData;
155
84
    unsigned int rateInBytes = instance->rate/8;
156
157
84
    if (instance->squeezing)
158
0
        return 1; /* Too late for additional input */
159
160
84
    i = 0;
161
84
    curData = data;
162
239
    while(i < dataByteLen) {
163
155
        if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) {
164
63
#ifdef SnP_FastLoop_Absorb
165
            /* processing full blocks first */
166
63
            if ((rateInBytes % (SnP_width/200)) == 0) {
167
                /* fast lane: whole lane rate */
168
63
                j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i);
169
63
                i += j;
170
63
                curData += j;
171
63
            }
172
0
            else {
173
0
#endif
174
0
                for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
175
                    #ifdef KeccakReference
176
                    displayBytes(1, "Block to be absorbed", curData, rateInBytes);
177
                    #endif
178
0
                    SnP_AddBytes(instance->state, curData, 0, rateInBytes);
179
0
                    SnP_Permute(instance->state);
180
0
                    curData+=rateInBytes;
181
0
                }
182
0
                i = dataByteLen - j;
183
0
#ifdef SnP_FastLoop_Absorb
184
0
            }
185
63
#endif
186
63
        }
187
92
        else {
188
            /* normal lane: using the message queue */
189
92
            if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
190
34
                partialBlock = rateInBytes-instance->byteIOIndex;
191
58
            else
192
58
                partialBlock = (unsigned int)(dataByteLen - i);
193
            #ifdef KeccakReference
194
            displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);
195
            #endif
196
92
            i += partialBlock;
197
198
92
            SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
199
92
            curData += partialBlock;
200
92
            instance->byteIOIndex += partialBlock;
201
92
            if (instance->byteIOIndex == rateInBytes) {
202
34
                SnP_Permute(instance->state);
203
34
                instance->byteIOIndex = 0;
204
34
            }
205
92
        }
206
155
    }
207
84
    return 0;
208
84
}
Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeAbsorb
209
210
/* ---------------------------------------------------------------- */
211
212
int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData)
213
84
{
214
84
    unsigned int rateInBytes = instance->rate/8;
215
216
84
    if (delimitedData == 0)
217
0
        return 1;
218
84
    if (instance->squeezing)
219
0
        return 1; /* Too late for additional input */
220
221
    #ifdef KeccakReference
222
    {
223
        unsigned char delimitedData1[1];
224
        delimitedData1[0] = delimitedData;
225
        displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
226
    }
227
    #endif
228
    /* Last few bits, whose delimiter coincides with first bit of padding */
229
84
    SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex);
230
    /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
231
84
    if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1)))
232
0
        SnP_Permute(instance->state);
233
    /* Second bit of padding */
234
84
    SnP_AddByte(instance->state, 0x80, rateInBytes-1);
235
    #ifdef KeccakReference
236
    {
237
        unsigned char block[SnP_width/8];
238
        memset(block, 0, SnP_width/8);
239
        block[rateInBytes-1] = 0x80;
240
        displayBytes(1, "Second bit of padding", block, rateInBytes);
241
    }
242
    #endif
243
84
    SnP_Permute(instance->state);
244
84
    instance->byteIOIndex = 0;
245
84
    instance->squeezing = 1;
246
    #ifdef KeccakReference
247
    displayText(1, "--- Switching to squeezing phase ---");
248
    #endif
249
84
    return 0;
250
84
}
KeccakWidth1600_SpongeAbsorbLastFewBits
Line
Count
Source
213
84
{
214
84
    unsigned int rateInBytes = instance->rate/8;
215
216
84
    if (delimitedData == 0)
217
0
        return 1;
218
84
    if (instance->squeezing)
219
0
        return 1; /* Too late for additional input */
220
221
    #ifdef KeccakReference
222
    {
223
        unsigned char delimitedData1[1];
224
        delimitedData1[0] = delimitedData;
225
        displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
226
    }
227
    #endif
228
    /* Last few bits, whose delimiter coincides with first bit of padding */
229
84
    SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex);
230
    /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
231
84
    if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1)))
232
0
        SnP_Permute(instance->state);
233
    /* Second bit of padding */
234
84
    SnP_AddByte(instance->state, 0x80, rateInBytes-1);
235
    #ifdef KeccakReference
236
    {
237
        unsigned char block[SnP_width/8];
238
        memset(block, 0, SnP_width/8);
239
        block[rateInBytes-1] = 0x80;
240
        displayBytes(1, "Second bit of padding", block, rateInBytes);
241
    }
242
    #endif
243
84
    SnP_Permute(instance->state);
244
84
    instance->byteIOIndex = 0;
245
84
    instance->squeezing = 1;
246
    #ifdef KeccakReference
247
    displayText(1, "--- Switching to squeezing phase ---");
248
    #endif
249
84
    return 0;
250
84
}
Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits
251
252
/* ---------------------------------------------------------------- */
253
254
int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen)
255
84
{
256
84
    size_t i, j;
257
84
    unsigned int partialBlock;
258
84
    unsigned int rateInBytes = instance->rate/8;
259
84
    unsigned char *curData;
260
261
84
    if (!instance->squeezing)
262
0
        SpongeAbsorbLastFewBits(instance, 0x01);
263
264
84
    i = 0;
265
84
    curData = data;
266
168
    while(i < dataByteLen) {
267
84
        if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) {
268
0
            for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
269
0
                SnP_Permute(instance->state);
270
0
                SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);
271
                #ifdef KeccakReference
272
                displayBytes(1, "Squeezed block", curData, rateInBytes);
273
                #endif
274
0
                curData+=rateInBytes;
275
0
            }
276
0
            i = dataByteLen - j;
277
0
        }
278
84
        else {
279
            /* normal lane: using the message queue */
280
84
            if (instance->byteIOIndex == rateInBytes) {
281
0
                SnP_Permute(instance->state);
282
0
                instance->byteIOIndex = 0;
283
0
            }
284
84
            if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
285
0
                partialBlock = rateInBytes-instance->byteIOIndex;
286
84
            else
287
84
                partialBlock = (unsigned int)(dataByteLen - i);
288
84
            i += partialBlock;
289
290
84
            SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
291
            #ifdef KeccakReference
292
            displayBytes(1, "Squeezed block (part)", curData, partialBlock);
293
            #endif
294
84
            curData += partialBlock;
295
84
            instance->byteIOIndex += partialBlock;
296
84
        }
297
84
    }
298
84
    return 0;
299
84
}
KeccakWidth1600_SpongeSqueeze
Line
Count
Source
255
84
{
256
84
    size_t i, j;
257
84
    unsigned int partialBlock;
258
84
    unsigned int rateInBytes = instance->rate/8;
259
84
    unsigned char *curData;
260
261
84
    if (!instance->squeezing)
262
0
        SpongeAbsorbLastFewBits(instance, 0x01);
263
264
84
    i = 0;
265
84
    curData = data;
266
168
    while(i < dataByteLen) {
267
84
        if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) {
268
0
            for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
269
0
                SnP_Permute(instance->state);
270
0
                SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);
271
                #ifdef KeccakReference
272
                displayBytes(1, "Squeezed block", curData, rateInBytes);
273
                #endif
274
0
                curData+=rateInBytes;
275
0
            }
276
0
            i = dataByteLen - j;
277
0
        }
278
84
        else {
279
            /* normal lane: using the message queue */
280
84
            if (instance->byteIOIndex == rateInBytes) {
281
0
                SnP_Permute(instance->state);
282
0
                instance->byteIOIndex = 0;
283
0
            }
284
84
            if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
285
0
                partialBlock = rateInBytes-instance->byteIOIndex;
286
84
            else
287
84
                partialBlock = (unsigned int)(dataByteLen - i);
288
84
            i += partialBlock;
289
290
84
            SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
291
            #ifdef KeccakReference
292
            displayBytes(1, "Squeezed block (part)", curData, partialBlock);
293
            #endif
294
84
            curData += partialBlock;
295
84
            instance->byteIOIndex += partialBlock;
296
84
        }
297
84
    }
298
84
    return 0;
299
84
}
Unexecuted instantiation: KeccakWidth1600_12rounds_SpongeSqueeze
300
301
/* ---------------------------------------------------------------- */
302
303
#undef Sponge
304
#undef SpongeInstance
305
#undef SpongeInitialize
306
#undef SpongeAbsorb
307
#undef SpongeAbsorbLastFewBits
308
#undef SpongeSqueeze
309
#undef SnP_stateSizeInBytes
310
#undef SnP_stateAlignment
311
#undef SnP_StaticInitialize
312
#undef SnP_Initialize
313
#undef SnP_AddByte
314
#undef SnP_AddBytes
315
#undef SnP_ExtractBytes