1 /*
2 * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <string.h>
11 #include <openssl/core_names.h>
12 #include <openssl/crypto.h>
13 #include <openssl/evp.h>
14 #include <openssl/params.h>
15 #include <openssl/err.h>
16 #include <openssl/proverr.h>
17 #include "internal/numbers.h"
18 #include "internal/sha3.h"
19 #include "prov/digestcommon.h"
20 #include "prov/implementations.h"
21
22 #define SHA3_FLAGS PROV_DIGEST_FLAG_ALGID_ABSENT
23 #define SHAKE_FLAGS PROV_DIGEST_FLAG_XOF
24 #define KMAC_FLAGS PROV_DIGEST_FLAG_XOF
25
26 /*
27 * Forward declaration of any unique methods implemented here. This is not strictly
28 * necessary for the compiler, but provides an assurance that the signatures
29 * of the functions in the dispatch table are correct.
30 */
31 static OSSL_FUNC_digest_init_fn keccak_init;
32 static OSSL_FUNC_digest_init_fn keccak_init_params;
33 static OSSL_FUNC_digest_update_fn keccak_update;
34 static OSSL_FUNC_digest_final_fn keccak_final;
35 static OSSL_FUNC_digest_freectx_fn keccak_freectx;
36 static OSSL_FUNC_digest_copyctx_fn keccak_copyctx;
37 static OSSL_FUNC_digest_dupctx_fn keccak_dupctx;
38 static OSSL_FUNC_digest_squeeze_fn shake_squeeze;
39 static OSSL_FUNC_digest_get_ctx_params_fn shake_get_ctx_params;
40 static OSSL_FUNC_digest_gettable_ctx_params_fn shake_gettable_ctx_params;
41 static OSSL_FUNC_digest_set_ctx_params_fn shake_set_ctx_params;
42 static OSSL_FUNC_digest_settable_ctx_params_fn shake_settable_ctx_params;
43 static sha3_absorb_fn generic_sha3_absorb;
44 static sha3_final_fn generic_sha3_final;
45 static sha3_squeeze_fn generic_sha3_squeeze;
46
47 #if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) && defined(KECCAK1600_ASM)
48 /*
49 * IBM S390X support
50 */
51 # include "s390x_arch.h"
52 # define S390_SHA3 1
53 # define S390_SHA3_CAPABLE(name) \
54 ((OPENSSL_s390xcap_P.kimd[0] & S390X_CAPBIT(S390X_##name)) && \
55 (OPENSSL_s390xcap_P.klmd[0] & S390X_CAPBIT(S390X_##name)))
56
57 #endif
58
keccak_init(void * vctx,ossl_unused const OSSL_PARAM params[])59 static int keccak_init(void *vctx, ossl_unused const OSSL_PARAM params[])
60 {
61 if (!ossl_prov_is_running())
62 return 0;
63 /* The newctx() handles most of the ctx fixed setup. */
64 ossl_sha3_reset((KECCAK1600_CTX *)vctx);
65 return 1;
66 }
67
keccak_init_params(void * vctx,const OSSL_PARAM params[])68 static int keccak_init_params(void *vctx, const OSSL_PARAM params[])
69 {
70 return keccak_init(vctx, NULL)
71 && shake_set_ctx_params(vctx, params);
72 }
73
keccak_update(void * vctx,const unsigned char * inp,size_t len)74 static int keccak_update(void *vctx, const unsigned char *inp, size_t len)
75 {
76 KECCAK1600_CTX *ctx = vctx;
77 const size_t bsz = ctx->block_size;
78 size_t num, rem;
79
80 if (len == 0)
81 return 1;
82
83 /* Is there anything in the buffer already ? */
84 if ((num = ctx->bufsz) != 0) {
85 /* Calculate how much space is left in the buffer */
86 rem = bsz - num;
87 /* If the new input does not fill the buffer then just add it */
88 if (len < rem) {
89 memcpy(ctx->buf + num, inp, len);
90 ctx->bufsz += len;
91 return 1;
92 }
93 /* otherwise fill up the buffer and absorb the buffer */
94 memcpy(ctx->buf + num, inp, rem);
95 /* Update the input pointer */
96 inp += rem;
97 len -= rem;
98 ctx->meth.absorb(ctx, ctx->buf, bsz);
99 ctx->bufsz = 0;
100 }
101 /* Absorb the input - rem = leftover part of the input < blocksize) */
102 rem = ctx->meth.absorb(ctx, inp, len);
103 /* Copy the leftover bit of the input into the buffer */
104 if (rem) {
105 memcpy(ctx->buf, inp + len - rem, rem);
106 ctx->bufsz = rem;
107 }
108 return 1;
109 }
110
keccak_final(void * vctx,unsigned char * out,size_t * outl,size_t outlen)111 static int keccak_final(void *vctx, unsigned char *out, size_t *outl,
112 size_t outlen)
113 {
114 int ret = 1;
115 KECCAK1600_CTX *ctx = vctx;
116
117 if (!ossl_prov_is_running())
118 return 0;
119 if (ctx->md_size == SIZE_MAX) {
120 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
121 return 0;
122 }
123 if (outlen > 0)
124 ret = ctx->meth.final(ctx, out, ctx->md_size);
125
126 *outl = ctx->md_size;
127 return ret;
128 }
129
shake_squeeze(void * vctx,unsigned char * out,size_t * outl,size_t outlen)130 static int shake_squeeze(void *vctx, unsigned char *out, size_t *outl,
131 size_t outlen)
132 {
133 int ret = 1;
134 KECCAK1600_CTX *ctx = vctx;
135
136 if (!ossl_prov_is_running())
137 return 0;
138 if (ctx->meth.squeeze == NULL)
139 return 0;
140 if (outlen > 0)
141 ret = ctx->meth.squeeze(ctx, out, outlen);
142
143 *outl = outlen;
144 return ret;
145 }
146
147 /*-
148 * Generic software version of the absorb() and final().
149 */
generic_sha3_absorb(void * vctx,const void * inp,size_t len)150 static size_t generic_sha3_absorb(void *vctx, const void *inp, size_t len)
151 {
152 KECCAK1600_CTX *ctx = vctx;
153
154 if (!(ctx->xof_state == XOF_STATE_INIT ||
155 ctx->xof_state == XOF_STATE_ABSORB))
156 return 0;
157 ctx->xof_state = XOF_STATE_ABSORB;
158 return SHA3_absorb(ctx->A, inp, len, ctx->block_size);
159 }
160
generic_sha3_final(void * vctx,unsigned char * out,size_t outlen)161 static int generic_sha3_final(void *vctx, unsigned char *out, size_t outlen)
162 {
163 return ossl_sha3_final((KECCAK1600_CTX *)vctx, out, outlen);
164 }
165
generic_sha3_squeeze(void * vctx,unsigned char * out,size_t outlen)166 static int generic_sha3_squeeze(void *vctx, unsigned char *out, size_t outlen)
167 {
168 return ossl_sha3_squeeze((KECCAK1600_CTX *)vctx, out, outlen);
169 }
170
171 static PROV_SHA3_METHOD sha3_generic_md = {
172 generic_sha3_absorb,
173 generic_sha3_final,
174 NULL
175 };
176
177 static PROV_SHA3_METHOD shake_generic_md =
178 {
179 generic_sha3_absorb,
180 generic_sha3_final,
181 generic_sha3_squeeze
182 };
183
184 #if defined(S390_SHA3)
185
186 static sha3_absorb_fn s390x_sha3_absorb;
187 static sha3_final_fn s390x_sha3_final;
188 static sha3_final_fn s390x_shake_final;
189
190 /*-
191 * The platform specific parts of the absorb() and final() for S390X.
192 */
s390x_sha3_absorb(void * vctx,const void * inp,size_t len)193 static size_t s390x_sha3_absorb(void *vctx, const void *inp, size_t len)
194 {
195 KECCAK1600_CTX *ctx = vctx;
196 size_t rem = len % ctx->block_size;
197 unsigned int fc;
198
199 if (!(ctx->xof_state == XOF_STATE_INIT ||
200 ctx->xof_state == XOF_STATE_ABSORB))
201 return 0;
202 if (len - rem > 0) {
203 fc = ctx->pad;
204 fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KIMD_NIP : 0;
205 ctx->xof_state = XOF_STATE_ABSORB;
206 s390x_kimd(inp, len - rem, fc, ctx->A);
207 }
208 return rem;
209 }
210
s390x_sha3_final(void * vctx,unsigned char * out,size_t outlen)211 static int s390x_sha3_final(void *vctx, unsigned char *out, size_t outlen)
212 {
213 KECCAK1600_CTX *ctx = vctx;
214 unsigned int fc;
215
216 if (!ossl_prov_is_running())
217 return 0;
218 if (!(ctx->xof_state == XOF_STATE_INIT ||
219 ctx->xof_state == XOF_STATE_ABSORB))
220 return 0;
221 fc = ctx->pad | S390X_KLMD_DUFOP;
222 fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KLMD_NIP : 0;
223 ctx->xof_state = XOF_STATE_FINAL;
224 s390x_klmd(ctx->buf, ctx->bufsz, NULL, 0, fc, ctx->A);
225 memcpy(out, ctx->A, outlen);
226 return 1;
227 }
228
s390x_shake_final(void * vctx,unsigned char * out,size_t outlen)229 static int s390x_shake_final(void *vctx, unsigned char *out, size_t outlen)
230 {
231 KECCAK1600_CTX *ctx = vctx;
232 unsigned int fc;
233
234 if (!ossl_prov_is_running())
235 return 0;
236 if (!(ctx->xof_state == XOF_STATE_INIT ||
237 ctx->xof_state == XOF_STATE_ABSORB))
238 return 0;
239 fc = ctx->pad | S390X_KLMD_DUFOP;
240 fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KLMD_NIP : 0;
241 ctx->xof_state = XOF_STATE_FINAL;
242 s390x_klmd(ctx->buf, ctx->bufsz, out, outlen, fc, ctx->A);
243 return 1;
244 }
245
s390x_shake_squeeze(void * vctx,unsigned char * out,size_t outlen)246 static int s390x_shake_squeeze(void *vctx, unsigned char *out, size_t outlen)
247 {
248 KECCAK1600_CTX *ctx = vctx;
249 unsigned int fc;
250 size_t len;
251
252 if (!ossl_prov_is_running())
253 return 0;
254 if (ctx->xof_state == XOF_STATE_FINAL)
255 return 0;
256 /*
257 * On the first squeeze call, finish the absorb process (incl. padding).
258 */
259 if (ctx->xof_state != XOF_STATE_SQUEEZE) {
260 fc = ctx->pad;
261 fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KLMD_NIP : 0;
262 ctx->xof_state = XOF_STATE_SQUEEZE;
263 s390x_klmd(ctx->buf, ctx->bufsz, out, outlen, fc, ctx->A);
264 ctx->bufsz = outlen % ctx->block_size;
265 /* reuse ctx->bufsz to count bytes squeezed from current sponge */
266 return 1;
267 }
268 ctx->xof_state = XOF_STATE_SQUEEZE;
269 if (ctx->bufsz != 0) {
270 len = ctx->block_size - ctx->bufsz;
271 if (outlen < len)
272 len = outlen;
273 memcpy(out, (char *)ctx->A + ctx->bufsz, len);
274 out += len;
275 outlen -= len;
276 ctx->bufsz += len;
277 if (ctx->bufsz == ctx->block_size)
278 ctx->bufsz = 0;
279 }
280 if (outlen == 0)
281 return 1;
282 s390x_klmd(NULL, 0, out, outlen, ctx->pad | S390X_KLMD_PS, ctx->A);
283 ctx->bufsz = outlen % ctx->block_size;
284
285 return 1;
286 }
287
s390x_keccakc_final(void * vctx,unsigned char * out,size_t outlen,int padding)288 static int s390x_keccakc_final(void *vctx, unsigned char *out, size_t outlen,
289 int padding)
290 {
291 KECCAK1600_CTX *ctx = vctx;
292 size_t bsz = ctx->block_size;
293 size_t num = ctx->bufsz;
294 size_t needed = outlen;
295 unsigned int fc;
296
297 if (!ossl_prov_is_running())
298 return 0;
299 if (!(ctx->xof_state == XOF_STATE_INIT ||
300 ctx->xof_state == XOF_STATE_ABSORB))
301 return 0;
302 fc = ctx->pad;
303 fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KIMD_NIP : 0;
304 ctx->xof_state = XOF_STATE_FINAL;
305 if (outlen == 0)
306 return 1;
307 memset(ctx->buf + num, 0, bsz - num);
308 ctx->buf[num] = padding;
309 ctx->buf[bsz - 1] |= 0x80;
310 s390x_kimd(ctx->buf, bsz, fc, ctx->A);
311 num = needed > bsz ? bsz : needed;
312 memcpy(out, ctx->A, num);
313 needed -= num;
314 if (needed > 0)
315 s390x_klmd(NULL, 0, out + bsz, needed,
316 ctx->pad | S390X_KLMD_PS | S390X_KLMD_DUFOP, ctx->A);
317
318 return 1;
319 }
320
s390x_keccak_final(void * vctx,unsigned char * out,size_t outlen)321 static int s390x_keccak_final(void *vctx, unsigned char *out, size_t outlen)
322 {
323 return s390x_keccakc_final(vctx, out, outlen, 0x01);
324 }
325
s390x_kmac_final(void * vctx,unsigned char * out,size_t outlen)326 static int s390x_kmac_final(void *vctx, unsigned char *out, size_t outlen)
327 {
328 return s390x_keccakc_final(vctx, out, outlen, 0x04);
329 }
330
s390x_keccakc_squeeze(void * vctx,unsigned char * out,size_t outlen,int padding)331 static int s390x_keccakc_squeeze(void *vctx, unsigned char *out, size_t outlen,
332 int padding)
333 {
334 KECCAK1600_CTX *ctx = vctx;
335 size_t len;
336 unsigned int fc;
337
338 if (!ossl_prov_is_running())
339 return 0;
340 if (ctx->xof_state == XOF_STATE_FINAL)
341 return 0;
342 /*
343 * On the first squeeze call, finish the absorb process
344 * by adding the trailing padding and then doing
345 * a final absorb.
346 */
347 if (ctx->xof_state != XOF_STATE_SQUEEZE) {
348 len = ctx->block_size - ctx->bufsz;
349 memset(ctx->buf + ctx->bufsz, 0, len);
350 ctx->buf[ctx->bufsz] = padding;
351 ctx->buf[ctx->block_size - 1] |= 0x80;
352 fc = ctx->pad;
353 fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KIMD_NIP : 0;
354 s390x_kimd(ctx->buf, ctx->block_size, fc, ctx->A);
355 ctx->bufsz = 0;
356 /* reuse ctx->bufsz to count bytes squeezed from current sponge */
357 }
358 if (ctx->bufsz != 0 || ctx->xof_state != XOF_STATE_SQUEEZE) {
359 len = ctx->block_size - ctx->bufsz;
360 if (outlen < len)
361 len = outlen;
362 memcpy(out, (char *)ctx->A + ctx->bufsz, len);
363 out += len;
364 outlen -= len;
365 ctx->bufsz += len;
366 if (ctx->bufsz == ctx->block_size)
367 ctx->bufsz = 0;
368 }
369 ctx->xof_state = XOF_STATE_SQUEEZE;
370 if (outlen == 0)
371 return 1;
372 s390x_klmd(NULL, 0, out, outlen, ctx->pad | S390X_KLMD_PS, ctx->A);
373 ctx->bufsz = outlen % ctx->block_size;
374
375 return 1;
376 }
377
s390x_keccak_squeeze(void * vctx,unsigned char * out,size_t outlen)378 static int s390x_keccak_squeeze(void *vctx, unsigned char *out, size_t outlen)
379 {
380 return s390x_keccakc_squeeze(vctx, out, outlen, 0x01);
381 }
382
s390x_kmac_squeeze(void * vctx,unsigned char * out,size_t outlen)383 static int s390x_kmac_squeeze(void *vctx, unsigned char *out, size_t outlen)
384 {
385 return s390x_keccakc_squeeze(vctx, out, outlen, 0x04);
386 }
387
388 static PROV_SHA3_METHOD sha3_s390x_md = {
389 s390x_sha3_absorb,
390 s390x_sha3_final,
391 NULL,
392 };
393
394 static PROV_SHA3_METHOD keccak_s390x_md = {
395 s390x_sha3_absorb,
396 s390x_keccak_final,
397 s390x_keccak_squeeze,
398 };
399
400 static PROV_SHA3_METHOD shake_s390x_md = {
401 s390x_sha3_absorb,
402 s390x_shake_final,
403 s390x_shake_squeeze,
404 };
405
406 static PROV_SHA3_METHOD kmac_s390x_md = {
407 s390x_sha3_absorb,
408 s390x_kmac_final,
409 s390x_kmac_squeeze,
410 };
411
412 # define SHAKE_SET_MD(uname, typ) \
413 if (S390_SHA3_CAPABLE(uname)) { \
414 ctx->pad = S390X_##uname; \
415 ctx->meth = typ##_s390x_md; \
416 } else { \
417 ctx->meth = shake_generic_md; \
418 }
419
420 # define SHA3_SET_MD(uname, typ) \
421 if (S390_SHA3_CAPABLE(uname)) { \
422 ctx->pad = S390X_##uname; \
423 ctx->meth = typ##_s390x_md; \
424 } else { \
425 ctx->meth = sha3_generic_md; \
426 }
427 # define KMAC_SET_MD(bitlen) \
428 if (S390_SHA3_CAPABLE(SHAKE_##bitlen)) { \
429 ctx->pad = S390X_SHAKE_##bitlen; \
430 ctx->meth = kmac_s390x_md; \
431 } else { \
432 ctx->meth = sha3_generic_md; \
433 }
434 #elif defined(__aarch64__) && defined(KECCAK1600_ASM)
435 # include "arm_arch.h"
436
437 static sha3_absorb_fn armsha3_sha3_absorb;
438
439 size_t SHA3_absorb_cext(uint64_t A[5][5], const unsigned char *inp, size_t len,
440 size_t r);
441 /*-
442 * Hardware-assisted ARMv8.2 SHA3 extension version of the absorb()
443 */
armsha3_sha3_absorb(void * vctx,const void * inp,size_t len)444 static size_t armsha3_sha3_absorb(void *vctx, const void *inp, size_t len)
445 {
446 KECCAK1600_CTX *ctx = vctx;
447
448 return SHA3_absorb_cext(ctx->A, inp, len, ctx->block_size);
449 }
450
451 static PROV_SHA3_METHOD sha3_ARMSHA3_md = {
452 armsha3_sha3_absorb,
453 generic_sha3_final
454 };
455 static PROV_SHA3_METHOD shake_ARMSHA3_md =
456 {
457 armsha3_sha3_absorb,
458 generic_sha3_final,
459 generic_sha3_squeeze
460 };
461 # define SHAKE_SET_MD(uname, typ) \
462 if (OPENSSL_armcap_P & ARMV8_HAVE_SHA3_AND_WORTH_USING) { \
463 ctx->meth = shake_ARMSHA3_md; \
464 } else { \
465 ctx->meth = shake_generic_md; \
466 }
467
468 # define SHA3_SET_MD(uname, typ) \
469 if (OPENSSL_armcap_P & ARMV8_HAVE_SHA3_AND_WORTH_USING) { \
470 ctx->meth = sha3_ARMSHA3_md; \
471 } else { \
472 ctx->meth = sha3_generic_md; \
473 }
474 # define KMAC_SET_MD(bitlen) \
475 if (OPENSSL_armcap_P & ARMV8_HAVE_SHA3_AND_WORTH_USING) { \
476 ctx->meth = sha3_ARMSHA3_md; \
477 } else { \
478 ctx->meth = sha3_generic_md; \
479 }
480 #else
481 # define SHA3_SET_MD(uname, typ) ctx->meth = sha3_generic_md;
482 # define KMAC_SET_MD(bitlen) ctx->meth = sha3_generic_md;
483 # define SHAKE_SET_MD(uname, typ) ctx->meth = shake_generic_md;
484 #endif /* S390_SHA3 */
485
486 #define SHA3_newctx(typ, uname, name, bitlen, pad) \
487 static OSSL_FUNC_digest_newctx_fn name##_newctx; \
488 static void *name##_newctx(void *provctx) \
489 { \
490 KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
491 : NULL; \
492 \
493 if (ctx == NULL) \
494 return NULL; \
495 ossl_sha3_init(ctx, pad, bitlen); \
496 SHA3_SET_MD(uname, typ) \
497 return ctx; \
498 }
499
500 #define SHAKE_newctx(typ, uname, name, bitlen, mdlen, pad) \
501 static OSSL_FUNC_digest_newctx_fn name##_newctx; \
502 static void *name##_newctx(void *provctx) \
503 { \
504 KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx))\
505 : NULL; \
506 \
507 if (ctx == NULL) \
508 return NULL; \
509 ossl_keccak_init(ctx, pad, bitlen, mdlen); \
510 if (mdlen == 0) \
511 ctx->md_size = SIZE_MAX; \
512 SHAKE_SET_MD(uname, typ) \
513 return ctx; \
514 }
515
516 #define KMAC_newctx(uname, bitlen, pad) \
517 static OSSL_FUNC_digest_newctx_fn uname##_newctx; \
518 static void *uname##_newctx(void *provctx) \
519 { \
520 KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
521 : NULL; \
522 \
523 if (ctx == NULL) \
524 return NULL; \
525 ossl_keccak_init(ctx, pad, bitlen, 2 * bitlen); \
526 KMAC_SET_MD(bitlen) \
527 return ctx; \
528 }
529
530 #define PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags) \
531 PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
532 const OSSL_DISPATCH ossl_##name##_functions[] = { \
533 { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
534 { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))keccak_update }, \
535 { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final }, \
536 { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx }, \
537 { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx }, \
538 { OSSL_FUNC_DIGEST_COPYCTX, (void (*)(void))keccak_copyctx }, \
539 PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
540
541 #define PROV_FUNC_SHA3_DIGEST(name, bitlen, blksize, dgstsize, flags) \
542 PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags), \
543 { OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init }, \
544 PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
545
546 #define PROV_FUNC_SHAKE_DIGEST(name, bitlen, blksize, dgstsize, flags) \
547 PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags), \
548 { OSSL_FUNC_DIGEST_SQUEEZE, (void (*)(void))shake_squeeze }, \
549 { OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init_params }, \
550 { OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))shake_set_ctx_params }, \
551 { OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, \
552 (void (*)(void))shake_settable_ctx_params }, \
553 { OSSL_FUNC_DIGEST_GET_CTX_PARAMS, (void (*)(void))shake_get_ctx_params }, \
554 { OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS, \
555 (void (*)(void))shake_gettable_ctx_params }, \
556 PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
557
keccak_freectx(void * vctx)558 static void keccak_freectx(void *vctx)
559 {
560 KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
561
562 OPENSSL_clear_free(ctx, sizeof(*ctx));
563 }
564
keccak_copyctx(void * voutctx,void * vinctx)565 static void keccak_copyctx(void *voutctx, void *vinctx)
566 {
567 KECCAK1600_CTX *outctx = (KECCAK1600_CTX *)voutctx;
568 KECCAK1600_CTX *inctx = (KECCAK1600_CTX *)vinctx;
569
570 *outctx = *inctx;
571 }
572
keccak_dupctx(void * ctx)573 static void *keccak_dupctx(void *ctx)
574 {
575 KECCAK1600_CTX *in = (KECCAK1600_CTX *)ctx;
576 KECCAK1600_CTX *ret = ossl_prov_is_running() ? OPENSSL_malloc(sizeof(*ret))
577 : NULL;
578
579 if (ret != NULL)
580 *ret = *in;
581 return ret;
582 }
583
shake_gettable_ctx_params(ossl_unused void * ctx,ossl_unused void * provctx)584 static const OSSL_PARAM *shake_gettable_ctx_params(ossl_unused void *ctx,
585 ossl_unused void *provctx)
586 {
587 static const OSSL_PARAM known_shake_gettable_ctx_params[] = {
588 {OSSL_DIGEST_PARAM_XOFLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
589 {OSSL_DIGEST_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
590 OSSL_PARAM_END
591 };
592 return known_shake_gettable_ctx_params;
593 }
594
shake_get_ctx_params(void * vctx,OSSL_PARAM params[])595 static int shake_get_ctx_params(void *vctx, OSSL_PARAM params[])
596 {
597 OSSL_PARAM *p;
598 KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
599
600 if (ctx == NULL)
601 return 0;
602 if (ossl_param_is_empty(params))
603 return 1;
604
605 p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_XOFLEN);
606 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->md_size)) {
607 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
608 return 0;
609 }
610 /* Size is an alias of xoflen */
611 p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE);
612 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->md_size)) {
613 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
614 return 0;
615 }
616 return 1;
617 }
618
shake_settable_ctx_params(ossl_unused void * ctx,ossl_unused void * provctx)619 static const OSSL_PARAM *shake_settable_ctx_params(ossl_unused void *ctx,
620 ossl_unused void *provctx)
621 {
622 static const OSSL_PARAM known_shake_settable_ctx_params[] = {
623 {OSSL_DIGEST_PARAM_XOFLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
624 {OSSL_DIGEST_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
625 OSSL_PARAM_END
626 };
627
628 return known_shake_settable_ctx_params;
629 }
630
shake_set_ctx_params(void * vctx,const OSSL_PARAM params[])631 static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[])
632 {
633 const OSSL_PARAM *p;
634 KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
635
636 if (ctx == NULL)
637 return 0;
638 if (ossl_param_is_empty(params))
639 return 1;
640
641 p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_XOFLEN);
642 if (p == NULL)
643 p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_SIZE);
644
645 if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->md_size)) {
646 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
647 return 0;
648 }
649 return 1;
650 }
651
652 #define IMPLEMENT_SHA3_functions(bitlen) \
653 SHA3_newctx(sha3, SHA3_##bitlen, sha3_##bitlen, bitlen, '\x06') \
654 PROV_FUNC_SHA3_DIGEST(sha3_##bitlen, bitlen, \
655 SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
656 SHA3_FLAGS)
657
658 #define IMPLEMENT_KECCAK_functions(bitlen) \
659 SHA3_newctx(keccak, KECCAK_##bitlen, keccak_##bitlen, bitlen, '\x01') \
660 PROV_FUNC_SHA3_DIGEST(keccak_##bitlen, bitlen, \
661 SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
662 SHA3_FLAGS)
663
664 #define IMPLEMENT_SHAKE_functions(bitlen) \
665 SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, \
666 0 /* no default md length */, '\x1f') \
667 PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen, \
668 SHA3_BLOCKSIZE(bitlen), 0, \
669 SHAKE_FLAGS)
670
671 #define IMPLEMENT_KMAC_functions(bitlen) \
672 KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04') \
673 PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen, \
674 SHA3_BLOCKSIZE(bitlen), KMAC_MDSIZE(bitlen), \
675 KMAC_FLAGS)
676
677 /* ossl_sha3_224_functions */
678 IMPLEMENT_SHA3_functions(224)
679 /* ossl_sha3_256_functions */
680 IMPLEMENT_SHA3_functions(256)
681 /* ossl_sha3_384_functions */
682 IMPLEMENT_SHA3_functions(384)
683 /* ossl_sha3_512_functions */
684 IMPLEMENT_SHA3_functions(512)
685 /* ossl_keccak_224_functions */
686 IMPLEMENT_KECCAK_functions(224)
687 /* ossl_keccak_256_functions */
688 IMPLEMENT_KECCAK_functions(256)
689 /* ossl_keccak_384_functions */
690 IMPLEMENT_KECCAK_functions(384)
691 /* ossl_keccak_512_functions */
692 IMPLEMENT_KECCAK_functions(512)
693 /* ossl_shake_128_functions */
694 IMPLEMENT_SHAKE_functions(128)
695 /* ossl_shake_256_functions */
696 IMPLEMENT_SHAKE_functions(256)
697 /* ossl_keccak_kmac_128_functions */
698 IMPLEMENT_KMAC_functions(128)
699 /* ossl_keccak_kmac_256_functions */
700 IMPLEMENT_KMAC_functions(256)
701