3 * The SHA3 algorithm family
5 * (c) 2017 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of secnet.
11 * See README for full list of copyright holders.
13 * secnet is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version d of the License, or
16 * (at your option) any later version.
18 * secnet is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * version 3 along with secnet; if not, see
25 * https://www.gnu.org/licenses/gpl.html.
27 * This file was originally part of Catacomb, but has been automatically
28 * modified for incorporation into secnet: see `import-catacomb-crypto'
31 * Catacomb is free software; you can redistribute it and/or modify
32 * it under the terms of the GNU Library General Public License as
33 * published by the Free Software Foundation; either version 2 of the
34 * License, or (at your option) any later version.
36 * Catacomb is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU Library General Public License for more details.
41 * You should have received a copy of the GNU Library General Public
42 * License along with Catacomb; if not, write to the Free
43 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
47 /*----- Header files ------------------------------------------------------*/
55 /*----- General utilities -------------------------------------------------*/
57 static void absorb(sha3_ctx
*ctx
, const octet
*p
, unsigned r
)
62 /* memdump("absorb", p, 8*r, 0); */
63 for (i
= 0; i
< r
; i
++) { LOAD64_L_(t
[i
], p
); p
+= 8; }
64 keccak1600_mix(&ctx
->s
, t
, r
);
67 static void step(sha3_ctx
*ctx
) { keccak1600_p(&ctx
->s
, &ctx
->s
, 24); }
69 static void pad(sha3_ctx
*ctx
, unsigned lo
, unsigned hi
)
71 size_t spare
= ctx
->r
- ctx
->n
;
74 ctx
->buf
[ctx
->n
] = lo
| hi
;
76 ctx
->buf
[ctx
->n
] = lo
;
77 ctx
->buf
[ctx
->r
- 1] = hi
;
78 memset(ctx
->buf
+ ctx
->n
+ 1, 0, spare
- 2);
80 absorb(ctx
, ctx
->buf
, ctx
->r
/8);
83 static void squeeze(sha3_ctx
*ctx
, octet
*p
, unsigned r
)
88 keccak1600_extract(&ctx
->s
, t
, r
);
89 for (i
= 0; i
< r
; i
++) { STORE64_L_(p
, t
[i
]); p
+= 8; }
90 /* memdump("squeeze", p - 8*r, 8*r, 0); */
99 enum { ST_ABSORB
, ST_SQUEEZE
, ST_DEAD
};
101 /*----- The SHA3 algorithms -----------------------------------------------*/
103 /* --- @sha3_{224,256,384,512}_init@ --- *
105 * Arguments: @sha3_ctx *ctx@ = pointer to context block to initialize
109 * Use: Initializes a SHA3 hashing context for use.
112 static void init_sha3(sha3_ctx
*ctx
, unsigned w
)
114 keccak1600_init(&ctx
->s
);
115 ctx
->w
= w
/8; ctx
->r
= (1600 - 2*w
)/8; ctx
->n
= 0;
118 void sha3_224_init(sha3_ctx
*ctx
) { init_sha3(ctx
, 224); }
119 void sha3_256_init(sha3_ctx
*ctx
) { init_sha3(ctx
, 256); }
120 void sha3_384_init(sha3_ctx
*ctx
) { init_sha3(ctx
, 384); }
121 void sha3_512_init(sha3_ctx
*ctx
) { init_sha3(ctx
, 512); }
123 /* --- @sha3_hash@ --- *
125 * Arguments: @sha3_ctx *ctx@ = pointer to context bock
126 * @const void *p@ = pointer to data to hash
127 * @size_t sz@ = size of buffer to hash
131 * Use: Hashes a buffer of data. The buffer may be of any size and
135 void sha3_hash(sha3_ctx
*ctx
, const void *p
, size_t sz
)
138 size_t spare
= ctx
->r
- ctx
->n
;
141 memcpy(ctx
->buf
+ ctx
->n
, q
, sz
);
146 memcpy(ctx
->buf
+ ctx
->n
, q
, spare
);
147 absorb(ctx
, ctx
->buf
, ctx
->r
/8);
149 q
+= spare
; sz
-= spare
;
151 while (sz
>= ctx
->r
) {
152 absorb(ctx
, q
, ctx
->r
/8);
154 q
+= ctx
->r
; sz
-= ctx
->r
;
156 if (sz
) memcpy(ctx
->buf
, q
, sz
);
160 /* --- @sha3_done@ --- *
162 * Arguments: @sha3_ctx *ctx@ = pointer to context block
163 * @void *hash@ = pointer to output buffer
167 * Use: Returns the hash of the data read so far.
170 void sha3_done(sha3_ctx
*ctx
, void *hash
)
172 pad(ctx
, OP_SHA3
, 0x80);
176 squeeze(ctx
, hash
, ctx
->w
/8);
178 squeeze(ctx
, ctx
->buf
, (ctx
->w
+ 7)/8);
179 memcpy(hash
, ctx
->buf
, ctx
->w
);
183 /*----- The cSHAKE XOF algorithm ------------------------------------------*/
185 static void leftenc_sz(shake_ctx
*ctx
, size_t n
)
191 SET64(t
, ((n
&~(size_t)MASK32
) >> 16) >> 16, n
&MASK32
);
192 STORE64_B_(b
+ 1, t
);
193 for (i
= 1; i
< 8 && !b
[i
]; i
++);
195 shake_hash(ctx
, b
+ i
, 9 - i
);
198 static void stringenc(shake_ctx
*ctx
, const void *p
, size_t sz
)
199 { leftenc_sz(ctx
, 8*sz
); if (sz
) shake_hash(ctx
, p
, sz
); }
201 static void bytepad_before(shake_ctx
*ctx
)
202 { leftenc_sz(ctx
, ctx
->h
.r
); }
204 static void bytepad_after(shake_ctx
*ctx
)
209 pad
= 8 - ctx
->h
.n
%8;
210 memset(ctx
->h
.buf
+ ctx
->h
.n
, 0, pad
);
214 absorb(&ctx
->h
, ctx
->h
.buf
, ctx
->h
.n
/8);
215 step(&ctx
->h
); ctx
->h
.n
= 0;
219 /* --- @cshake{128,256}_init@ --- *
221 * Arguments: @shake_ctx *ctx@ = pointer to context to initialize
222 * @const void *func@ = NIST-allocated function name
223 * @size_t fsz@ = length of function name
224 * @const void *perso@ = user personalization string
225 * @size_t psz@ = length of personalization string
229 * Use: Initializes a cSHAKE context. The context is initially in
230 * the `absorbing' state: feed it data with @shake_hash@.
233 static void init_shake(shake_ctx
*ctx
, unsigned c0
,
234 const void *func
, size_t fsz
,
235 const void *perso
, size_t psz
)
237 keccak1600_init(&ctx
->h
.s
); ctx
->st
= ST_ABSORB
;
238 ctx
->h
.r
= (1600 - 2*c0
)/8; ctx
->h
.w
= 0; ctx
->h
.n
= 0;
243 stringenc(ctx
, func
, fsz
);
244 stringenc(ctx
, perso
, psz
);
250 void cshake128_init(shake_ctx
*ctx
,
251 const void *func
, size_t fsz
,
252 const void *perso
, size_t psz
)
253 { init_shake(ctx
, 128, func
, fsz
, perso
, psz
); }
255 void cshake256_init(shake_ctx
*ctx
,
256 const void *func
, size_t fsz
,
257 const void *perso
, size_t psz
)
258 { init_shake(ctx
, 256, func
, fsz
, perso
, psz
); }
260 /* --- @shake{128,256}_init@ --- *
262 * Arguments: @sha3_ctx *ctx@ = pointer to context to initialize
266 * Use: Initializes a SHAKE context. The context is initially in
267 * the `absorbing' state: feed it data with @shake_hash@.
270 void shake128_init(shake_ctx
*ctx
) { init_shake(ctx
, 128, 0, 0, 0, 0); }
271 void shake256_init(shake_ctx
*ctx
) { init_shake(ctx
, 256, 0, 0, 0, 0); }
273 /* --- @shake_hash@ --- *
275 * Arguments: @shake_ctx *ctx@ = context to update
276 * @const void *p@ = input buffer
277 * @size_t sz@ = size of input
281 * Use: Feeds input data into a SHAKE context. The context must be
282 * in `absorbing' state.
285 void shake_hash(shake_ctx
*ctx
, const void *p
, size_t sz
)
286 { assert(ctx
->st
== ST_ABSORB
); sha3_hash(&ctx
->h
, p
, sz
); }
288 /* --- @shake_xof@ --- *
290 * Arguments: @shake_ctx *ctx@ = context to update
294 * Use: Switches the context into `squeezing' state. Use @shake_get@
295 * or @shake_mask@ to extract data.
298 void shake_xof(shake_ctx
*ctx
)
300 assert(ctx
->st
== ST_ABSORB
);
301 pad(&ctx
->h
, ctx
->op
, 0x80);
302 ctx
->st
= ST_SQUEEZE
;
306 /* --- @shake_get@ --- *
308 * Arguments: @shake_ctx *ctx@ = context to update
309 * @void *p@ = output buffer
310 * @size_t sz@ = size of output
314 * Use: Extracts output from a SHAKE context. The context must be
315 * in `squeezing' state.
318 void shake_get(shake_ctx
*ctx
, void *p
, size_t sz
)
321 size_t left
= ctx
->h
.r
- ctx
->h
.n
;
323 assert(ctx
->st
== ST_SQUEEZE
);
325 memcpy(q
, ctx
->h
.buf
+ ctx
->h
.n
, sz
);
330 memcpy(q
, ctx
->h
.buf
+ ctx
->h
.n
, left
);
331 q
+= left
; sz
-= left
;
333 while (sz
>= ctx
->h
.r
) {
335 squeeze(&ctx
->h
, q
, ctx
->h
.r
/8);
336 q
+= ctx
->h
.r
; sz
-= ctx
->h
.r
;
342 squeeze(&ctx
->h
, ctx
->h
.buf
, ctx
->h
.r
/8);
343 memcpy(q
, ctx
->h
.buf
, sz
);
348 /* --- @shake_done@ --- *
350 * Arguments: @shake_ctx *ctx@ = context to update
351 * @void *h@ = where to write the hash
352 * @size_t hsz@ = size of the hash to make
356 * Use: Switches the context into `squeezing' state. Use @shake_get@
357 * or @shake_mask@ to extract data.
360 void shake_done(shake_ctx
*ctx
, void *h
, size_t hsz
)
361 { shake_xof(ctx
); shake_get(ctx
, h
, hsz
); ctx
->st
= ST_DEAD
; }
363 /*----- That's all, folks -------------------------------------------------*/