0fede83d2ee9a291712912c6d0b2888405eb7f11
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 rightenc_sz(shake_ctx
*ctx
, size_t n
)
204 SET64(t
, ((n
&~(size_t)MASK32
) >> 16) >> 16, n
&MASK32
);
206 for (i
= 0; i
< 7 && !b
[i
]; i
++);
208 shake_hash(ctx
, b
+ i
, 9 - i
);
211 static void stringenc(shake_ctx
*ctx
, const void *p
, size_t sz
)
212 { leftenc_sz(ctx
, 8*sz
); if (sz
) shake_hash(ctx
, p
, sz
); }
214 static void bytepad_before(shake_ctx
*ctx
)
215 { leftenc_sz(ctx
, ctx
->h
.r
); }
217 static void bytepad_after(shake_ctx
*ctx
)
222 pad
= 8 - ctx
->h
.n
%8;
223 memset(ctx
->h
.buf
+ ctx
->h
.n
, 0, pad
);
227 absorb(&ctx
->h
, ctx
->h
.buf
, ctx
->h
.n
/8);
228 step(&ctx
->h
); ctx
->h
.n
= 0;
232 /* --- @cshake{128,256}_init@ --- *
234 * Arguments: @shake_ctx *ctx@ = pointer to context to initialize
235 * @const void *func@ = NIST-allocated function name
236 * @size_t fsz@ = length of function name
237 * @const void *perso@ = user personalization string
238 * @size_t psz@ = length of personalization string
242 * Use: Initializes a cSHAKE context. The context is initially in
243 * the `absorbing' state: feed it data with @shake_hash@.
246 static void init_shake(shake_ctx
*ctx
, unsigned c0
,
247 const void *func
, size_t fsz
,
248 const void *perso
, size_t psz
)
250 keccak1600_init(&ctx
->h
.s
); ctx
->st
= ST_ABSORB
;
251 ctx
->h
.r
= (1600 - 2*c0
)/8; ctx
->h
.w
= 0; ctx
->h
.n
= 0;
256 stringenc(ctx
, func
, fsz
);
257 stringenc(ctx
, perso
, psz
);
263 void cshake128_init(shake_ctx
*ctx
,
264 const void *func
, size_t fsz
,
265 const void *perso
, size_t psz
)
266 { init_shake(ctx
, 128, func
, fsz
, perso
, psz
); }
268 void cshake256_init(shake_ctx
*ctx
,
269 const void *func
, size_t fsz
,
270 const void *perso
, size_t psz
)
271 { init_shake(ctx
, 256, func
, fsz
, perso
, psz
); }
273 /* --- @shake{128,256}_init@ --- *
275 * Arguments: @sha3_ctx *ctx@ = pointer to context to initialize
279 * Use: Initializes a SHAKE context. The context is initially in
280 * the `absorbing' state: feed it data with @shake_hash@.
283 void shake128_init(shake_ctx
*ctx
) { init_shake(ctx
, 128, 0, 0, 0, 0); }
284 void shake256_init(shake_ctx
*ctx
) { init_shake(ctx
, 256, 0, 0, 0, 0); }
286 /* --- @shake_hash@ --- *
288 * Arguments: @shake_ctx *ctx@ = context to update
289 * @const void *p@ = input buffer
290 * @size_t sz@ = size of input
294 * Use: Feeds input data into a SHAKE context. The context must be
295 * in `absorbing' state.
298 void shake_hash(shake_ctx
*ctx
, const void *p
, size_t sz
)
299 { assert(ctx
->st
== ST_ABSORB
); sha3_hash(&ctx
->h
, p
, sz
); }
301 /* --- @shake_xof@ --- *
303 * Arguments: @shake_ctx *ctx@ = context to update
307 * Use: Switches the context into `squeezing' state. Use @shake_get@
308 * or @shake_mask@ to extract data.
311 void shake_xof(shake_ctx
*ctx
)
313 assert(ctx
->st
== ST_ABSORB
);
314 pad(&ctx
->h
, ctx
->op
, 0x80);
315 ctx
->st
= ST_SQUEEZE
;
319 /* --- @shake_get@ --- *
321 * Arguments: @shake_ctx *ctx@ = context to update
322 * @void *p@ = output buffer
323 * @size_t sz@ = size of output
327 * Use: Extracts output from a SHAKE context. The context must be
328 * in `squeezing' state.
331 void shake_get(shake_ctx
*ctx
, void *p
, size_t sz
)
334 size_t left
= ctx
->h
.r
- ctx
->h
.n
;
336 assert(ctx
->st
== ST_SQUEEZE
);
338 memcpy(q
, ctx
->h
.buf
+ ctx
->h
.n
, sz
);
343 memcpy(q
, ctx
->h
.buf
+ ctx
->h
.n
, left
);
344 q
+= left
; sz
-= left
;
346 while (sz
>= ctx
->h
.r
) {
348 squeeze(&ctx
->h
, q
, ctx
->h
.r
/8);
349 q
+= ctx
->h
.r
; sz
-= ctx
->h
.r
;
355 squeeze(&ctx
->h
, ctx
->h
.buf
, ctx
->h
.r
/8);
356 memcpy(q
, ctx
->h
.buf
, sz
);
361 /* --- @shake_done@ --- *
363 * Arguments: @shake_ctx *ctx@ = context to update
364 * @void *h@ = where to write the hash
365 * @size_t hsz@ = size of the hash to make
369 * Use: Switches the context into `squeezing' state. Use @shake_get@
370 * or @shake_mask@ to extract data.
373 void shake_done(shake_ctx
*ctx
, void *h
, size_t hsz
)
374 { shake_xof(ctx
); shake_get(ctx
, h
, hsz
); ctx
->st
= ST_DEAD
; }
376 /*----- That's all, folks -------------------------------------------------*/