File Coverage

src/sha3.c
Criterion Covered Total %
statement 200 230 86.9
branch 76 94 80.8
condition n/a
subroutine n/a
pod n/a
total 276 324 85.1


line stmt bran cond sub pod time code
1             /*
2             * sha3.c: routines to compute SHA-3 digests
3             *
4             * Ref: http://keccak.noekeon.org/specs_summary.html
5             *
6             * Copyright (C) 2012-2022 Mark Shelor, All Rights Reserved
7             *
8             * Version: 1.05
9             * Mon 08 Aug 2022 11:30:32 AM MST
10             *
11             */
12              
13             #include
14             #include
15             #include
16             #include
17             #include "sha3.h"
18              
19             #define UCHR unsigned char /* useful abbreviations */
20             #define UINT unsigned int
21             #define ULNG unsigned long
22             #define W64 SHA64
23             #define C64 SHA64_CONST
24             #define SR64 SHA64_SHR
25             #define SL64 SHA64_SHL
26              
27             /* word2mem: write 64-bit value in little-endian order */
28 736           static void word2mem(UCHR *mem, W64 w)
29             {
30             int i;
31 736           UCHR *p = mem;
32              
33 6624 100         for (i = 0; i < 8; i++, w >>= 8)
34 5888           *p++ = (UCHR) (w & 0xff);
35 736           }
36              
37             static const W64 RC[] = { /* Keccak round constants */
38             C64(0x0000000000000001), C64(0x0000000000008082),
39             C64(0x800000000000808a), C64(0x8000000080008000),
40             C64(0x000000000000808b), C64(0x0000000080000001),
41             C64(0x8000000080008081), C64(0x8000000000008009),
42             C64(0x000000000000008a), C64(0x0000000000000088),
43             C64(0x0000000080008009), C64(0x000000008000000a),
44             C64(0x000000008000808b), C64(0x800000000000008b),
45             C64(0x8000000000008089), C64(0x8000000000008003),
46             C64(0x8000000000008002), C64(0x8000000000000080),
47             C64(0x000000000000800a), C64(0x800000008000000a),
48             C64(0x8000000080008081), C64(0x8000000000008080),
49             C64(0x0000000080000001), C64(0x8000000080008008)
50             };
51              
52             /* ROTL: rotate 64-bit word left by n bit positions */
53             #define ROTL(w, n) (SR64((w), (64 - (n))) | SL64((w), (n)))
54              
55             /* keccak_f: apply KECCAK-f[1600] permutation for 24 rounds */
56 37857           static void keccak_f(W64 A[][5])
57             {
58             int i;
59 37857           const W64 *rc = RC;
60 946425 100         for (i = 0; i < 24; i++, rc++) {
61             W64 B[5][5], C[5], D[5];
62 908568           C[0] = A[0][0]^A[0][1]^A[0][2]^A[0][3]^A[0][4];
63 908568           C[1] = A[1][0]^A[1][1]^A[1][2]^A[1][3]^A[1][4];
64 908568           C[2] = A[2][0]^A[2][1]^A[2][2]^A[2][3]^A[2][4];
65 908568           C[3] = A[3][0]^A[3][1]^A[3][2]^A[3][3]^A[3][4];
66 908568           C[4] = A[4][0]^A[4][1]^A[4][2]^A[4][3]^A[4][4];
67 908568           D[0] = C[4] ^ ROTL(C[1], 1);
68 908568           D[1] = C[0] ^ ROTL(C[2], 1);
69 908568           D[2] = C[1] ^ ROTL(C[3], 1);
70 908568           D[3] = C[2] ^ ROTL(C[4], 1);
71 908568           D[4] = C[3] ^ ROTL(C[0], 1);
72 908568           A[0][0] ^= D[0];
73 908568           A[0][1] ^= D[0];
74 908568           A[0][2] ^= D[0];
75 908568           A[0][3] ^= D[0];
76 908568           A[0][4] ^= D[0];
77 908568           A[1][0] ^= D[1];
78 908568           A[1][1] ^= D[1];
79 908568           A[1][2] ^= D[1];
80 908568           A[1][3] ^= D[1];
81 908568           A[1][4] ^= D[1];
82 908568           A[2][0] ^= D[2];
83 908568           A[2][1] ^= D[2];
84 908568           A[2][2] ^= D[2];
85 908568           A[2][3] ^= D[2];
86 908568           A[2][4] ^= D[2];
87 908568           A[3][0] ^= D[3];
88 908568           A[3][1] ^= D[3];
89 908568           A[3][2] ^= D[3];
90 908568           A[3][3] ^= D[3];
91 908568           A[3][4] ^= D[3];
92 908568           A[4][0] ^= D[4];
93 908568           A[4][1] ^= D[4];
94 908568           A[4][2] ^= D[4];
95 908568           A[4][3] ^= D[4];
96 908568           A[4][4] ^= D[4];
97 908568           B[0][0] = A[0][0];
98 908568           B[1][3] = ROTL(A[0][1], 36);
99 908568           B[2][1] = ROTL(A[0][2], 3);
100 908568           B[3][4] = ROTL(A[0][3], 41);
101 908568           B[4][2] = ROTL(A[0][4], 18);
102 908568           B[0][2] = ROTL(A[1][0], 1);
103 908568           B[1][0] = ROTL(A[1][1], 44);
104 908568           B[2][3] = ROTL(A[1][2], 10);
105 908568           B[3][1] = ROTL(A[1][3], 45);
106 908568           B[4][4] = ROTL(A[1][4], 2);
107 908568           B[0][4] = ROTL(A[2][0], 62);
108 908568           B[1][2] = ROTL(A[2][1], 6);
109 908568           B[2][0] = ROTL(A[2][2], 43);
110 908568           B[3][3] = ROTL(A[2][3], 15);
111 908568           B[4][1] = ROTL(A[2][4], 61);
112 908568           B[0][1] = ROTL(A[3][0], 28);
113 908568           B[1][4] = ROTL(A[3][1], 55);
114 908568           B[2][2] = ROTL(A[3][2], 25);
115 908568           B[3][0] = ROTL(A[3][3], 21);
116 908568           B[4][3] = ROTL(A[3][4], 56);
117 908568           B[0][3] = ROTL(A[4][0], 27);
118 908568           B[1][1] = ROTL(A[4][1], 20);
119 908568           B[2][4] = ROTL(A[4][2], 39);
120 908568           B[3][2] = ROTL(A[4][3], 8);
121 908568           B[4][0] = ROTL(A[4][4], 14);
122 908568           A[0][0] = B[0][0] ^ (~B[1][0] & B[2][0]);
123 908568           A[0][1] = B[0][1] ^ (~B[1][1] & B[2][1]);
124 908568           A[0][2] = B[0][2] ^ (~B[1][2] & B[2][2]);
125 908568           A[0][3] = B[0][3] ^ (~B[1][3] & B[2][3]);
126 908568           A[0][4] = B[0][4] ^ (~B[1][4] & B[2][4]);
127 908568           A[1][0] = B[1][0] ^ (~B[2][0] & B[3][0]);
128 908568           A[1][1] = B[1][1] ^ (~B[2][1] & B[3][1]);
129 908568           A[1][2] = B[1][2] ^ (~B[2][2] & B[3][2]);
130 908568           A[1][3] = B[1][3] ^ (~B[2][3] & B[3][3]);
131 908568           A[1][4] = B[1][4] ^ (~B[2][4] & B[3][4]);
132 908568           A[2][0] = B[2][0] ^ (~B[3][0] & B[4][0]);
133 908568           A[2][1] = B[2][1] ^ (~B[3][1] & B[4][1]);
134 908568           A[2][2] = B[2][2] ^ (~B[3][2] & B[4][2]);
135 908568           A[2][3] = B[2][3] ^ (~B[3][3] & B[4][3]);
136 908568           A[2][4] = B[2][4] ^ (~B[3][4] & B[4][4]);
137 908568           A[3][0] = B[3][0] ^ (~B[4][0] & B[0][0]);
138 908568           A[3][1] = B[3][1] ^ (~B[4][1] & B[0][1]);
139 908568           A[3][2] = B[3][2] ^ (~B[4][2] & B[0][2]);
140 908568           A[3][3] = B[3][3] ^ (~B[4][3] & B[0][3]);
141 908568           A[3][4] = B[3][4] ^ (~B[4][4] & B[0][4]);
142 908568           A[4][0] = B[4][0] ^ (~B[0][0] & B[1][0]);
143 908568           A[4][1] = B[4][1] ^ (~B[0][1] & B[1][1]);
144 908568           A[4][2] = B[4][2] ^ (~B[0][2] & B[1][2]);
145 908568           A[4][3] = B[4][3] ^ (~B[0][3] & B[1][3]);
146 908568           A[4][4] = B[4][4] ^ (~B[0][4] & B[1][4]);
147 908568           A[0][0] ^= *rc;
148             }
149 37857           }
150              
151             /* sha3: update SHA3 state with one block of data */
152 37841           static void sha3(SHA3 *s, UCHR *block)
153             {
154             unsigned int i, x, y;
155             W64 P0[5][5];
156              
157 538438 100         for (i = 0; i < s->blocksize/64; i++, block += 8)
158 500597           MEM2WORD(&P0[i%5][i/5], block);
159 227046 100         for (x = 0; x < 5; x++)
160 689802 100         for (y = 0; y < 5; y++) {
161 689799 100         if (x + y*5 >= s->blocksize/64)
162 189202           break;
163 500597           s->S[x][y] ^= P0[x][y];
164             }
165 37841           keccak_f(s->S);
166 37841           }
167              
168             /* digcpy: write SHA3 state to digest buffer */
169 45           static UCHR *digcpy(SHA3 *s)
170             {
171             unsigned int x, y;
172 45           UCHR *Z = s->digest;
173 45           int outbits = s->digestlen*8;
174              
175 90 100         while (outbits > 0) {
176 270 100         for (y = 0; y < 5; y++)
177 961 100         for (x = 0; x < 5; x++, Z += 8) {
178 836 100         if (x + y*5 >= s->blocksize/64)
179 100           break;
180 736           word2mem(Z, s->S[x][y]);
181             }
182 45 50         if ((outbits -= (int) s->blocksize) > 0)
183 0           keccak_f(s->S);
184             }
185 45           return(s->digest);
186             }
187              
188             #define BITSET(s, pos) s[(pos) >> 3] & (UCHR) (0x01 << ((pos) % 8))
189             #define SETBIT(s, pos) s[(pos) >> 3] |= (UCHR) (0x01 << ((pos) % 8))
190             #define CLRBIT(s, pos) s[(pos) >> 3] &= (UCHR) ~(0x01 << ((pos) % 8))
191             #define NBYTES(nbits) (((nbits) + 7) >> 3)
192             #define HEXLEN(nbytes) ((nbytes) << 1)
193             #define B64LEN(nbytes) (((nbytes) % 3 == 0) ? ((nbytes) / 3) * 4 \
194             : ((nbytes) / 3) * 4 + ((nbytes) % 3) + 1)
195              
196             #define SHA3_INIT(s, algo, xof) \
197             do { \
198             Zero(s, 1, SHA3); \
199             s->alg = algo; \
200             s->shake = xof; \
201             s->blocksize = algo ## _BLOCK_BITS; \
202             s->digestlen = algo ## _DIGEST_BITS >> 3; \
203             } while (0)
204              
205             /* sharewind: resets digest object */
206 47           static void sharewind(SHA3 *s)
207             {
208 47 100         if (s->alg == SHA3_224) SHA3_INIT(s, SHA3_224, 0);
209 31 100         else if (s->alg == SHA3_256) SHA3_INIT(s, SHA3_256, 0);
210 22 100         else if (s->alg == SHA3_384) SHA3_INIT(s, SHA3_384, 0);
211 13 100         else if (s->alg == SHA3_512) SHA3_INIT(s, SHA3_512, 0);
212 4 100         else if (s->alg == SHAKE128) SHA3_INIT(s, SHAKE128, 1);
213 2 50         else if (s->alg == SHAKE256) SHA3_INIT(s, SHAKE256, 1);
214 47           }
215              
216             /* shainit: initializes digest object */
217 30           static int shainit(SHA3 *s, int alg)
218             {
219 30 100         if (alg != SHA3_224 && alg != SHA3_256 &&
    100          
    100          
220 10 100         alg != SHA3_384 && alg != SHA3_512 &&
    100          
221 2 50         alg != SHAKE128 && alg != SHAKE256)
222 0           return 0;
223 30           s->alg = alg;
224 30           sharewind(s);
225 30           return 1;
226             }
227              
228             /* shadirect: updates state directly (w/o going through s->block) */
229 277           static ULNG shadirect(UCHR *bitstr, ULNG bitcnt, SHA3 *s)
230             {
231 277           ULNG savecnt = bitcnt;
232              
233 37860 100         while (bitcnt >= s->blocksize) {
234 37583           sha3(s, bitstr);
235 37583           bitstr += (s->blocksize >> 3);
236 37583           bitcnt -= s->blocksize;
237             }
238 277 100         if (bitcnt > 0) {
239 258           Copy(bitstr, s->block, NBYTES(bitcnt), char);
240 258           s->blockcnt = bitcnt;
241             }
242 277           return(savecnt);
243             }
244              
245             /* shabytes: updates state for byte-aligned data in s->block */
246 225           static ULNG shabytes(UCHR *bitstr, ULNG bitcnt, SHA3 *s)
247             {
248             UINT offset;
249             UINT nbits;
250 225           ULNG savecnt = bitcnt;
251              
252 225           offset = s->blockcnt >> 3;
253 225 50         if (s->blockcnt + bitcnt >= s->blocksize) {
254 225           nbits = s->blocksize - s->blockcnt;
255 225           Copy(bitstr, s->block+offset, nbits>>3, char);
256 225           bitcnt -= nbits;
257 225           bitstr += (nbits >> 3);
258 225           sha3(s, s->block), s->blockcnt = 0;
259 225           shadirect(bitstr, bitcnt, s);
260             }
261             else {
262 0           Copy(bitstr, s->block+offset, NBYTES(bitcnt), char);
263 0           s->blockcnt += bitcnt;
264             }
265 225           return(savecnt);
266             }
267              
268             /* shabits: updates state for bit-aligned data in s->block */
269 23           static ULNG shabits(UCHR *bitstr, ULNG bitcnt, SHA3 *s)
270             {
271             ULNG i;
272              
273 96 100         for (i = 0UL; i < bitcnt; i++) {
274 73 100         if (BITSET(bitstr, i))
275 56           SETBIT(s->block, s->blockcnt);
276             else
277 17           CLRBIT(s->block, s->blockcnt);
278 73 50         if (++s->blockcnt == s->blocksize)
279 0           sha3(s, s->block), s->blockcnt = 0;
280             }
281 23           return(bitcnt);
282             }
283              
284             /* shawrite: triggers a state update using data in bitstr/bitcnt */
285 300           static ULNG shawrite(UCHR *bitstr, ULNG bitcnt, SHA3 *s)
286             {
287 300 50         if (!bitcnt)
288 0           return(0);
289 300 100         if (s->blockcnt == 0)
290 52           return(shadirect(bitstr, bitcnt, s));
291 248 100         else if (s->blockcnt % 8 == 0)
292 225           return(shabytes(bitstr, bitcnt, s));
293             else
294 23           return(shabits(bitstr, bitcnt, s));
295             }
296              
297             /* shapad: pads byte-aligned block with 0*1 and computes final digest */
298 33           static void shapad(SHA3 *s)
299             {
300 2545 100         while (s->blockcnt < s->blocksize)
301 2512           s->block[s->blockcnt>>3] = 0x00, s->blockcnt += 8;
302 33           s->block[(s->blocksize>>3)-1] |= 0x80;
303 33           sha3(s, s->block);
304 33           }
305              
306             /* shafinish: pads remaining block(s) and computes final digest state */
307 45           static void shafinish(SHA3 *s)
308             {
309 45 100         UCHR domain = s->shake ? 0x1f : 0x06;
310              
311 45 100         if (s->padded)
312 24           return;
313 33           s->padded = 1;
314 33 100         if (s->blockcnt % 8 == 0) {
315 12           s->block[s->blockcnt>>3] = domain;
316 12           s->blockcnt += 8;
317 12           shapad(s);
318 12           return;
319             }
320 21 100         shawrite((UCHR *) &domain, s->shake ? 5 : 3, s);
321 94 100         while (s->blockcnt % 8)
322 73           CLRBIT(s->block, s->blockcnt), s->blockcnt++;
323 21           shapad(s);
324             }
325              
326             /* shasqueeze: returns pointer to squeezed digest (binary) */
327 16           static UCHR *shasqueeze(SHA3 *s)
328             {
329 16 100         if (s->alg != SHAKE128 && s->alg != SHAKE256)
    50          
330 0           return(NULL);
331 16           digcpy(s);
332 16           keccak_f(s->S);
333 16           return(s->digest);
334             }
335              
336             #define shadigest(state) digcpy(state)
337              
338             /* xmap: translation map for hexadecimal encoding */
339             static const char xmap[] =
340             "0123456789abcdef";
341              
342             /* shahex: returns pointer to current digest (hexadecimal) */
343 29           static char *shahex(SHA3 *s)
344             {
345             int i;
346             char *h;
347             UCHR *d;
348              
349 29           d = digcpy(s);
350 29           s->hex[0] = '\0';
351 29 50         if (HEXLEN((size_t) s->digestlen) >= sizeof(s->hex))
352 0           return(s->hex);
353 1201 100         for (i = 0, h = s->hex; i < s->digestlen; i++) {
354 1172           *h++ = xmap[(*d >> 4) & 0x0f];
355 1172           *h++ = xmap[(*d++ ) & 0x0f];
356             }
357 29           *h = '\0';
358 29           return(s->hex);
359             }
360              
361             /* bmap: translation map for Base 64 encoding */
362             static const char bmap[] =
363             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
364              
365             /* encbase64: encodes input (0 to 3 bytes) into Base 64 */
366 0           static void encbase64(UCHR *in, int n, char *out)
367             {
368 0           UCHR byte[3] = {0, 0, 0};
369              
370 0           out[0] = '\0';
371 0 0         if (n < 1 || n > 3)
    0          
372 0           return;
373 0           Copy(in, byte, (unsigned) n, UCHR);
374 0           out[0] = bmap[byte[0] >> 2];
375 0           out[1] = bmap[((byte[0] & 0x03) << 4) | (byte[1] >> 4)];
376 0           out[2] = bmap[((byte[1] & 0x0f) << 2) | (byte[2] >> 6)];
377 0           out[3] = bmap[byte[2] & 0x3f];
378 0           out[n+1] = '\0';
379             }
380              
381             /* shabase64: returns pointer to current digest (Base 64) */
382 0           static char *shabase64(SHA3 *s)
383             {
384             int n;
385             UCHR *q;
386             char out[5];
387              
388 0           q = digcpy(s);
389 0           s->base64[0] = '\0';
390 0 0         if (B64LEN((size_t) s->digestlen) >= sizeof(s->base64))
    0          
391 0           return(s->base64);
392 0 0         for (n = s->digestlen; n > 3; n -= 3, q += 3) {
393 0           encbase64(q, 3, out);
394 0           strcat(s->base64, out);
395             }
396 0           encbase64(q, n, out);
397 0           strcat(s->base64, out);
398 0           return(s->base64);
399             }