Coverage Report

Created: 2025-12-10 06:24

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