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