Commit | Line | Data |
---|---|---|
78b4ea88 MW |
1 | /* -*-c-*- |
2 | * | |
3 | * The SHA3 algorithm family | |
4 | * | |
5 | * (c) 2017 Straylight/Edgeware | |
6 | */ | |
7 | ||
8 | /*----- Licensing notice --------------------------------------------------* | |
9 | * | |
10 | * This file is part of Catacomb. | |
11 | * | |
12 | * Catacomb is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU Library General Public License as | |
14 | * published by the Free Software Foundation; either version 2 of the | |
15 | * License, or (at your option) any later version. | |
16 | * | |
17 | * Catacomb is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU Library General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Library General Public | |
23 | * License along with Catacomb; if not, write to the Free | |
24 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
25 | * MA 02111-1307, USA. | |
26 | */ | |
27 | ||
28 | #ifndef CATACOMB_SHA3_H | |
29 | #define CATACOMB_SHA3_H | |
30 | ||
31 | #ifdef __cplusplus | |
32 | extern "C" { | |
33 | #endif | |
34 | ||
35 | /*----- Notes on the SHA3 algorithm family --------------------------------* | |
36 | * | |
37 | * The winner of the SHA3 competition was Keccak, designed by Guido Bertoni, | |
38 | * Joan Daemen, Michaƫl Peeters, and Gilles Van Assche. The algorithm uses | |
39 | * their `sponge construction', based on a fixed attempt to instantiate an | |
40 | * `ideal permutation'. The construction is rather versatile, and NIST has | |
41 | * standardized a number of algorithms based on it. | |
42 | * | |
43 | * The basic offerings are the drop-in replacements for the SHA2 family. | |
44 | * These are slower than is ideal, because of the decision to provide O(2^n) | |
45 | * resistance to second-preimage attacks for the n-bit hash function, which | |
46 | * means that, effectively, the capacity parameter is set unnecessarily | |
47 | * large. (There was a major fuss when NIST tried to change this in a draft | |
48 | * of te standard.) All of the obvious hash modes, e.g., HMAC, MGF, can be | |
49 | * applied to the SHA3 hash functions, though I can't really recommend this: | |
50 | * there's almost certainly a better way of doing whatever it is. | |
51 | * | |
52 | * Other members of the family are: SHAKE and cSHAKE, `extendable-output | |
53 | * funnctions' which can be used directly in place of MGFs; and KMAC, a | |
54 | * message authentication code with arbitrary-length key, message, and tag, | |
55 | * which can therefore be used as a key-derivation function. The cSHAKE | |
56 | * construction, on which KMAC is based, introduces a personalization string | |
57 | * which can be used for domain separation. | |
58 | */ | |
59 | ||
60 | /*----- Header files ------------------------------------------------------*/ | |
61 | ||
62 | #include <mLib/bits.h> | |
63 | ||
64 | #ifndef CATACOMB_KECCAK1600_H | |
65 | # include "keccak1600.h" | |
66 | #endif | |
67 | ||
68 | #ifndef CATACOMB_GCIPHER_H | |
69 | # include "gcipher.h" | |
70 | #endif | |
71 | ||
72 | #ifndef CATACOMB_GHASH_H | |
73 | # include "ghash.h" | |
74 | #endif | |
75 | ||
76 | #ifndef CATACOMB_GMAC_H | |
77 | # include "gmac.h" | |
78 | #endif | |
79 | ||
80 | #ifndef CATACOMB_GRAND_H | |
81 | # include "grand.h" | |
82 | #endif | |
83 | ||
84 | /*----- The SHA3 hash function family -------------------------------------*/ | |
85 | ||
86 | typedef struct sha3_ctx { | |
87 | keccak1600_state s; | |
88 | unsigned r, w, n; | |
89 | octet buf[200]; | |
90 | } sha3_ctx; | |
91 | #define sha3_224_ctx sha3_ctx | |
92 | #define sha3_256_ctx sha3_ctx | |
93 | #define sha3_384_ctx sha3_ctx | |
94 | #define sha3_512_ctx sha3_ctx | |
95 | ||
96 | #define SHA3_224_HASHSZ 28 | |
97 | #define SHA3_256_HASHSZ 32 | |
98 | #define SHA3_384_HASHSZ 48 | |
99 | #define SHA3_512_HASHSZ 64 | |
100 | ||
101 | #define SHA3_224_BUFSZ 144 | |
102 | #define SHA3_256_BUFSZ 136 | |
103 | #define SHA3_384_BUFSZ 104 | |
104 | #define SHA3_512_BUFSZ 72 | |
105 | ||
106 | #define SHA3_STATESZ (sizeof(sha3_ctx)) | |
107 | #define SHA3_224_STATESZ SHA3_STATESZ | |
108 | #define SHA3_256_STATESZ SHA3_STATESZ | |
109 | #define SHA3_384_STATESZ SHA3_STATESZ | |
110 | #define SHA3_512_STATESZ SHA3_STATESZ | |
111 | ||
112 | /* --- @sha3_{224,256,384,512}_init@ --- * | |
113 | * | |
114 | * Arguments: @sha3_ctx *ctx@ = pointer to context block to initialize | |
115 | * | |
116 | * Returns: --- | |
117 | * | |
118 | * Use: Initializes a SHA3 hashing context for use. | |
119 | */ | |
120 | ||
121 | extern void sha3_224_init(sha3_ctx */*ctx*/); | |
122 | extern void sha3_256_init(sha3_ctx */*ctx*/); | |
123 | extern void sha3_384_init(sha3_ctx */*ctx*/); | |
124 | extern void sha3_512_init(sha3_ctx */*ctx*/); | |
125 | ||
126 | /* --- @sha3_hash@ --- * | |
127 | * | |
128 | * Arguments: @sha3_ctx *ctx@ = pointer to context bock | |
129 | * @const void *p@ = pointer to data to hash | |
130 | * @size_t sz@ = size of buffer to hash | |
131 | * | |
132 | * Returns: --- | |
133 | * | |
134 | * Use: Hashes a buffer of data. The buffer may be of any size and | |
135 | * alignment. | |
136 | */ | |
137 | ||
138 | #define sha3_224_hash sha3_hash | |
139 | #define sha3_256_hash sha3_hash | |
140 | #define sha3_384_hash sha3_hash | |
141 | #define sha3_512_hash sha3_hash | |
142 | ||
143 | extern void sha3_hash(sha3_ctx */*ctx*/, const void */*p*/, size_t /*sz*/); | |
144 | ||
145 | /* --- @sha3_done@ --- * | |
146 | * | |
147 | * Arguments: @sha3_ctx *ctx@ = pointer to context block | |
148 | * @void *hash@ = pointer to output buffer | |
149 | * | |
150 | * Returns: --- | |
151 | * | |
152 | * Use: Returns the hash of the data read so far. | |
153 | */ | |
154 | ||
155 | #define sha3_224_done sha3_done | |
156 | #define sha3_256_done sha3_done | |
157 | #define sha3_384_done sha3_done | |
158 | #define sha3_512_done sha3_done | |
159 | ||
160 | extern void sha3_done(sha3_ctx */*ctx*/, void */*hash*/); | |
161 | ||
162 | /* --- @sha3_{224,256,384,512}_set@ --- * | |
163 | * | |
164 | * Arguments: @sha3_ctx *ctx@ = pointer to context block | |
165 | * @const void *buf@ = pointer to state buffer | |
166 | * @unsigned long count@ = current count of bytes processed | |
167 | * | |
168 | * Returns: --- | |
169 | * | |
170 | * Use: Initializes a context block from a given state. This is | |
171 | * something of a kludge for the benefit of HMAC, but there are | |
172 | * better ways to use SHA3 as a MAC. | |
173 | * | |
174 | * Furthermore, the @count@ argument is expected to be zero or | |
175 | * be the output of @sha3_state@ below. Doing anything else | |
176 | * won't work properly. | |
177 | */ | |
178 | ||
179 | extern void sha3_224_set(sha3_ctx */*ctx*/, | |
180 | const void */*buf*/, unsigned long /*count*/); | |
181 | extern void sha3_256_set(sha3_ctx */*ctx*/, | |
182 | const void */*buf*/, unsigned long /*count*/); | |
183 | extern void sha3_384_set(sha3_ctx */*ctx*/, | |
184 | const void */*buf*/, unsigned long /*count*/); | |
185 | extern void sha3_512_set(sha3_ctx */*ctx*/, | |
186 | const void */*buf*/, unsigned long /*count*/); | |
187 | ||
188 | /* --- @sha3_state@ --- * | |
189 | * | |
190 | * Arguments: @sha3_ctx *ctx@ = pointer to context block | |
191 | * @void *state@ = pointer to buffer for current state | |
192 | * | |
193 | * Returns: A value which is meaningful to @sha3_..._set@. | |
194 | * | |
195 | * Use: Returns the current state of the hash function such that it | |
196 | * can be passed to @sha3_..._set@. | |
197 | */ | |
198 | ||
199 | #define sha3_224_state sha3_state | |
200 | #define sha3_256_state sha3_state | |
201 | #define sha3_384_state sha3_state | |
202 | #define sha3_512_state sha3_state | |
203 | ||
204 | extern unsigned long sha3_state(sha3_ctx */*ctx*/, void */*state*/); | |
205 | ||
206 | /* --- Generic hash interface --- */ | |
207 | ||
208 | extern const gchash sha3_224, sha3_256, sha3_384, sha3_512; | |
209 | ||
210 | /*----- The cSHAKE XOF algorithm ------------------------------------------*/ | |
211 | ||
212 | typedef struct shake_ctx { | |
213 | sha3_ctx h; | |
214 | unsigned st, op; | |
215 | } shake_ctx; | |
216 | #define shake128_ctx shake_ctx | |
217 | #define shake256_ctx shake_ctx | |
218 | ||
219 | #define SHAKE128_KEYSZ 16 | |
220 | #define SHAKE256_KEYSZ 32 | |
221 | ||
222 | #define SHAKE128_HASHSZ 32 /* Somewhat arbitrary... */ | |
223 | #define SHAKE256_HASHSZ 64 | |
224 | ||
225 | extern const octet shake128_keysz[], shake256_keysz[]; | |
226 | ||
227 | /* --- @cshake{128,256}_init@ --- * | |
228 | * | |
229 | * Arguments: @shake_ctx *ctx@ = pointer to context to initialize | |
230 | * @const void *func@ = NIST-allocated function name | |
231 | * @size_t fsz@ = length of function name | |
232 | * @const void *perso@ = user personalization string | |
233 | * @size_t psz@ = length of personalization string | |
234 | * | |
235 | * Returns: --- | |
236 | * | |
237 | * Use: Initializes a cSHAKE context. The context is initially in | |
238 | * the `absorbing' state: feed it data with @shake_hash@. | |
239 | */ | |
240 | ||
241 | extern void cshake128_init(shake_ctx */*ctx*/, | |
242 | const void */*func*/, size_t /*fsz*/, | |
243 | const void */*perso*/, size_t /*psz*/); | |
244 | ||
245 | extern void cshake256_init(shake_ctx */*ctx*/, | |
246 | const void */*func*/, size_t /*fsz*/, | |
247 | const void */*perso*/, size_t /*psz*/); | |
248 | ||
249 | /* --- @shake{128,256}_init@ --- * | |
250 | * | |
251 | * Arguments: @sha3_ctx *ctx@ = pointer to context to initialize | |
252 | * | |
253 | * Returns: --- | |
254 | * | |
255 | * Use: Initializes a SHAKE context. The context is initially in | |
256 | * the `absorbing' state: feed it data with @shake_hash@. | |
257 | */ | |
258 | ||
259 | extern void shake128_init(shake_ctx */*ctx*/); | |
260 | extern void shake256_init(shake_ctx */*ctx*/); | |
261 | ||
262 | /* --- @shake_hash@ --- * | |
263 | * | |
264 | * Arguments: @shake_ctx *ctx@ = context to update | |
265 | * @const void *p@ = input buffer | |
266 | * @size_t sz@ = size of input | |
267 | * | |
268 | * Returns: --- | |
269 | * | |
270 | * Use: Feeds input data into a SHAKE context. The context must be | |
271 | * in `absorbing' state. | |
272 | */ | |
273 | ||
274 | extern void shake_hash(shake_ctx */*ctx*/, const void */*p*/, size_t /*sz*/); | |
275 | ||
276 | /* --- @shake_xof@ --- * | |
277 | * | |
278 | * Arguments: @shake_ctx *ctx@ = context to update | |
279 | * | |
280 | * Returns: --- | |
281 | * | |
282 | * Use: Switches the context into `squeezing' state. Use @shake_get@ | |
283 | * or @shake_mask@ to extract data. | |
284 | */ | |
285 | ||
286 | extern void shake_xof(shake_ctx */*ctx*/); | |
287 | ||
288 | /* --- @shake_get@ --- * | |
289 | * | |
290 | * Arguments: @shake_ctx *ctx@ = context to update | |
291 | * @void *p@ = output buffer | |
292 | * @size_t sz@ = size of output | |
293 | * | |
294 | * Returns: --- | |
295 | * | |
296 | * Use: Extracts output from a SHAKE context. The context must be | |
297 | * in `squeezing' state. | |
298 | */ | |
299 | ||
300 | extern void shake_get(shake_ctx */*ctx*/, void */*p*/, size_t /*sz*/); | |
301 | ||
302 | /* --- @shake_mask@ --- * | |
303 | * | |
304 | * Arguments: @shake_ctx *ctx@ = context to update | |
305 | * @const void *src@ = pointer to source data, or null | |
306 | * @void *dest@ = output buffer | |
307 | * @size_t sz@ = size of output | |
308 | * | |
309 | * Returns: --- | |
310 | * | |
311 | * Use: Mask the @src@ data by XORing it with output from the SHAKE | |
312 | * context, writing the result to @dest@. The @src@ and @dest | |
313 | * buffers may be equal but must not otherwise overlap. The | |
314 | * context must be in `squeezing' state. | |
315 | */ | |
316 | ||
317 | extern void shake_mask(shake_ctx */*ctx*/, | |
318 | const void */*src*/, void */*dest*/, size_t /*sz*/); | |
319 | ||
320 | /* --- @shake_done@ --- * | |
321 | * | |
322 | * Arguments: @shake_ctx *ctx@ = context to update | |
323 | * @void *h@ = where to write the hash | |
324 | * @size_t hsz@ = size of the hash to make | |
325 | * | |
326 | * Returns: --- | |
327 | * | |
328 | * Use: Switches the context into `squeezing' state. Use @shake_get@ | |
329 | * or @shake_mask@ to extract data. | |
330 | */ | |
331 | ||
332 | extern void shake_done(shake_ctx */*ctx*/, void */*h*/, size_t /*hsz*/); | |
333 | ||
334 | /* --- @shake{128,256}_rand@ --- * | |
335 | * | |
336 | * Arguments: @const void *k@ = pointer to seed material | |
337 | * @size_t sz@ = size of the seed | |
338 | * | |
339 | * Returns: A pseudorandom generator with the given seed. | |
340 | */ | |
341 | ||
342 | extern grand *shake128_rand(const void */*k*/, size_t /*sz*/); | |
343 | extern grand *shake256_rand(const void */*k*/, size_t /*sz*/); | |
344 | ||
345 | /* --- @cshake{128,256}_rand@ --- * | |
346 | * | |
347 | * Arguments: @const void *func@ = function name | |
348 | * @size_t fsz@ = length of function name | |
349 | * @const void *perso@ = personalization string | |
350 | * @size_t psz@ = length of personalization string | |
351 | * @const void *k@ = pointer to seed material | |
352 | * @size_t sz@ = size of the seed | |
353 | * | |
354 | * Returns: A pseudorandom generator with the given seed. | |
355 | * | |
356 | * Use: Note that with null @func@ and @perso@ strings, this is | |
357 | * equivalent to @shake128_rand@ or @shake256_rand@. | |
358 | */ | |
359 | ||
360 | extern grand *cshake128_rand(const void */*func*/, size_t /*fsz*/, | |
361 | const void */*perso*/, size_t /*psz*/, | |
362 | const void */*k*/, size_t /*sz*/); | |
363 | ||
364 | extern grand *cshake256_rand(const void */*func*/, size_t /*fsz*/, | |
365 | const void */*perso*/, size_t /*psz*/, | |
366 | const void */*k*/, size_t /*sz*/); | |
367 | ||
368 | /* --- Generic cipher interface --- */ | |
369 | ||
370 | extern const gccipher shake128_xof, shake256_xof; | |
371 | extern const gchash shake128, shake256; | |
372 | ||
373 | /*----- The KMAC variable-length PRF --------------------------------------*/ | |
374 | ||
375 | typedef shake_ctx kmac_ctx; | |
376 | ||
377 | #define KMAC128_KEYSZ SHAKE128_KEYSZ | |
378 | #define KMAC256_KEYSZ SHAKE256_KEYSZ | |
379 | ||
380 | #define KMAC128_TAGSZ 16 | |
381 | #define KMAC256_TAGSZ 32 | |
382 | ||
383 | #define kmac128_keysz shake128_keysz | |
384 | #define kmac256_keysz shake256_keysz | |
385 | ||
386 | /* --- @kmac{128,256}_init@ --- * | |
387 | * | |
388 | * Arguments: @kmac_ctx *ctx@ = pointer to context to fill in | |
389 | * @const void *perso@ = personalization string, or null | |
390 | * @size_t psz@ = length of personalization string | |
391 | * @const void *k@ = pointer to key material | |
392 | * @size_t sz@ = size of key material | |
393 | * | |
394 | * Returns: --- | |
395 | * | |
396 | * Use: Sets up a KMAC context. Set @tsz@ to zero for a flexible- | |
397 | * length tag, which can be read using @kmac_get@. Use | |
398 | * @kmac_hash@ to feed in the input message. | |
399 | */ | |
400 | ||
401 | extern void kmac128_init(kmac_ctx */*ctx*/, | |
402 | const void */*perso*/, size_t /*psz*/, | |
403 | const void */*k*/, size_t /*sz*/); | |
404 | extern void kmac256_init(kmac_ctx */*ctx*/, | |
405 | const void */*perso*/, size_t /*psz*/, | |
406 | const void */*k*/, size_t /*sz*/); | |
407 | ||
408 | /* --- @kmac_xof@ --- * | |
409 | * | |
410 | * Arguments: @kmac_ctx *ctx@ = pointer to context | |
411 | * | |
412 | * Returns: --- | |
413 | * | |
414 | * Use: Marks the end of the message to be processed. The output can | |
415 | * be read using @kmac_get@. | |
416 | */ | |
417 | ||
418 | void kmac_xof(kmac_ctx */*ctx*/); | |
419 | ||
420 | /* --- @kmac_done@ --- * | |
421 | * | |
422 | * Arguments: @kmac_ctx *ctx@ = pointer to context | |
423 | * @void *h@ = where to put the tag | |
424 | * @size_t hsz@ = size of tag to produce | |
425 | * | |
426 | * Returns: --- | |
427 | * | |
428 | * Use: Marks the end of the message to be processed and returns a | |
429 | * tag. Note that the tag value is dependent on the output | |
430 | * size. | |
431 | */ | |
432 | ||
433 | void kmac_done(kmac_ctx */*ctx*/, void */*h*/, size_t /*hsz*/); | |
434 | ||
435 | /* --- Convenience aliases --- */ | |
436 | ||
437 | #define kmac_hash shake_hash | |
438 | #define kmac_get shake_get | |
439 | #define kmac_mask shake_mask | |
440 | ||
441 | /* --- @kmac{128,256}_rand@ --- * | |
442 | * | |
443 | * Arguments: @const void *perso@ = personalization string, or null | |
444 | * @size_t psz@ = length of personalization string | |
445 | * @const void *k@ = pointer to seed material | |
446 | * @size_t sz@ = size of the seed | |
447 | * | |
448 | * Returns: A pseudorandom generator with the given key. | |
449 | * | |
450 | * Use: The generator processes an empty message by default, but this | |
451 | * can be changed by seeding it. | |
452 | */ | |
453 | ||
454 | extern grand *kmac128_rand(const void */*perso*/, size_t /*psz*/, | |
455 | const void */*k*/, size_t /*sz*/); | |
456 | extern grand *kmac256_rand(const void */*perso*/, size_t /*psz*/, | |
457 | const void */*k*/, size_t /*sz*/); | |
458 | ||
459 | /* --- Generic MAC interface --- */ | |
460 | ||
461 | extern const gcmac kmac128, kmac256; | |
462 | ||
463 | /*----- That's all, folks -------------------------------------------------*/ | |
464 | ||
465 | #ifdef __cplusplus | |
466 | } | |
467 | #endif | |
468 | ||
469 | #endif |