Coverage Report

Created: 2026-10-28 06:28

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