Coverage Report

Created: 2026-01-09 07:00

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/byteorder.h>
12
#include <openssl/core_names.h>
13
#include <openssl/crypto.h>
14
#include <openssl/evp.h>
15
#include <openssl/params.h>
16
#include <openssl/err.h>
17
#include <openssl/proverr.h>
18
#include "internal/cryptlib.h"
19
#include "internal/numbers.h"
20
#include "internal/sha3.h"
21
#include "prov/digestcommon.h"
22
#include "prov/implementations.h"
23
#include "internal/common.h"
24
#include "providers/implementations/digests/sha3_prov.inc"
25
26
#define SHA3_FLAGS PROV_DIGEST_FLAG_ALGID_ABSENT
27
#define SHAKE_FLAGS (PROV_DIGEST_FLAG_XOF | PROV_DIGEST_FLAG_ALGID_ABSENT)
28
#define KMAC_FLAGS PROV_DIGEST_FLAG_XOF
29
30
/*
31
 * Forward declaration of any unique methods implemented here. This is not strictly
32
 * necessary for the compiler, but provides an assurance that the signatures
33
 * of the functions in the dispatch table are correct.
34
 */
35
static OSSL_FUNC_digest_init_fn keccak_init;
36
static OSSL_FUNC_digest_init_fn keccak_init_params;
37
static OSSL_FUNC_digest_update_fn keccak_update;
38
static OSSL_FUNC_digest_final_fn keccak_final;
39
static OSSL_FUNC_digest_freectx_fn keccak_freectx;
40
static OSSL_FUNC_digest_copyctx_fn keccak_copyctx;
41
static OSSL_FUNC_digest_dupctx_fn keccak_dupctx;
42
static OSSL_FUNC_digest_squeeze_fn shake_squeeze;
43
static OSSL_FUNC_digest_get_ctx_params_fn shake_get_ctx_params;
44
static OSSL_FUNC_digest_gettable_ctx_params_fn shake_gettable_ctx_params;
45
static OSSL_FUNC_digest_set_ctx_params_fn shake_set_ctx_params;
46
static OSSL_FUNC_digest_settable_ctx_params_fn shake_settable_ctx_params;
47
static sha3_absorb_fn generic_sha3_absorb;
48
static sha3_final_fn generic_sha3_final;
49
static sha3_squeeze_fn generic_sha3_squeeze;
50
51
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) && defined(KECCAK1600_ASM)
52
/*
53
 * IBM S390X support
54
 */
55
#include "s390x_arch.h"
56
#define S390_SHA3 1
57
#define S390_SHA3_CAPABLE(name) \
58
    ((OPENSSL_s390xcap_P.kimd[0] & S390X_CAPBIT(S390X_##name)) && (OPENSSL_s390xcap_P.klmd[0] & S390X_CAPBIT(S390X_##name)))
59
60
#endif
61
62
static int keccak_init(void *vctx, ossl_unused const OSSL_PARAM params[])
63
112
{
64
112
    if (ossl_unlikely(!ossl_prov_is_running()))
65
0
        return 0;
66
    /* The newctx() handles most of the ctx fixed setup. */
67
112
    ossl_sha3_reset((KECCAK1600_CTX *)vctx);
68
112
    return 1;
69
112
}
70
71
static int keccak_init_params(void *vctx, const OSSL_PARAM params[])
72
0
{
73
0
    return keccak_init(vctx, NULL)
74
0
        && shake_set_ctx_params(vctx, params);
75
0
}
76
77
static int keccak_update(void *vctx, const unsigned char *inp, size_t len)
78
112
{
79
112
    KECCAK1600_CTX *ctx = vctx;
80
112
    const size_t bsz = ctx->block_size;
81
112
    size_t num, rem;
82
83
112
    if (ossl_unlikely(len == 0))
84
0
        return 1;
85
86
    /* Is there anything in the buffer already ? */
87
112
    if (ossl_likely((num = ctx->bufsz) != 0)) {
88
        /* Calculate how much space is left in the buffer */
89
56
        rem = bsz - num;
90
        /* If the new input does not fill the buffer then just add it */
91
56
        if (len < rem) {
92
0
            memcpy(ctx->buf + num, inp, len);
93
0
            ctx->bufsz += len;
94
0
            return 1;
95
0
        }
96
        /* otherwise fill up the buffer and absorb the buffer */
97
56
        memcpy(ctx->buf + num, inp, rem);
98
        /* Update the input pointer */
99
56
        inp += rem;
100
56
        len -= rem;
101
56
        ctx->meth.absorb(ctx, ctx->buf, bsz);
102
56
        ctx->bufsz = 0;
103
56
    }
104
    /* Absorb the input - rem = leftover part of the input < blocksize) */
105
112
    rem = ctx->meth.absorb(ctx, inp, len);
106
    /* Copy the leftover bit of the input into the buffer */
107
112
    if (ossl_likely(rem)) {
108
108
        memcpy(ctx->buf, inp + len - rem, rem);
109
108
        ctx->bufsz = rem;
110
108
    }
111
112
    return 1;
112
112
}
113
114
static int keccak_final(void *vctx, unsigned char *out, size_t *outl,
115
    size_t outlen)
116
56
{
117
56
    int ret = 1;
118
56
    KECCAK1600_CTX *ctx = vctx;
119
120
56
    if (ossl_unlikely(!ossl_prov_is_running()))
121
0
        return 0;
122
56
    if (ossl_unlikely(ctx->md_size == SIZE_MAX)) {
123
0
        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
124
0
        return 0;
125
0
    }
126
56
    if (ossl_likely(outlen > 0))
127
56
        ret = ctx->meth.final(ctx, out, ctx->md_size);
128
129
56
    *outl = ctx->md_size;
130
56
    return ret;
131
56
}
132
133
static int shake_squeeze(void *vctx, unsigned char *out, size_t *outl,
134
    size_t outlen)
135
0
{
136
0
    int ret = 1;
137
0
    KECCAK1600_CTX *ctx = vctx;
138
139
0
    if (!ossl_prov_is_running())
140
0
        return 0;
141
0
    if (ctx->meth.squeeze == NULL)
142
0
        return 0;
143
0
    if (outlen > 0)
144
0
        ret = ctx->meth.squeeze(ctx, out, outlen);
145
146
0
    *outl = outlen;
147
0
    return ret;
148
0
}
149
150
/*-
151
 * Generic software version of the absorb() and final().
152
 */
153
static size_t generic_sha3_absorb(void *vctx, const void *inp, size_t len)
154
168
{
155
168
    KECCAK1600_CTX *ctx = vctx;
156
157
168
    if (!(ctx->xof_state == XOF_STATE_INIT || ctx->xof_state == XOF_STATE_ABSORB))
158
0
        return 0;
159
168
    ctx->xof_state = XOF_STATE_ABSORB;
160
168
    return SHA3_absorb(ctx->A, inp, len, ctx->block_size);
161
168
}
162
163
static int generic_sha3_final(void *vctx, unsigned char *out, size_t outlen)
164
56
{
165
56
    return ossl_sha3_final((KECCAK1600_CTX *)vctx, out, outlen);
166
56
}
167
168
static int generic_sha3_squeeze(void *vctx, unsigned char *out, size_t outlen)
169
0
{
170
0
    return ossl_sha3_squeeze((KECCAK1600_CTX *)vctx, out, outlen);
171
0
}
172
173
static PROV_SHA3_METHOD sha3_generic_md = {
174
    generic_sha3_absorb,
175
    generic_sha3_final,
176
    NULL
177
};
178
179
static PROV_SHA3_METHOD shake_generic_md = {
180
    generic_sha3_absorb,
181
    generic_sha3_final,
182
    generic_sha3_squeeze
183
};
184
185
#if defined(S390_SHA3)
186
187
static sha3_absorb_fn s390x_sha3_absorb;
188
static sha3_final_fn s390x_sha3_final;
189
static sha3_final_fn s390x_shake_final;
190
191
/*-
192
 * The platform specific parts of the absorb() and final() for S390X.
193
 */
194
static size_t s390x_sha3_absorb(void *vctx, const void *inp, size_t len)
195
{
196
    KECCAK1600_CTX *ctx = vctx;
197
    size_t rem = len % ctx->block_size;
198
    unsigned int fc;
199
200
    if (!(ctx->xof_state == XOF_STATE_INIT || 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
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 || 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
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 || ctx->xof_state == XOF_STATE_ABSORB))
236
        return 0;
237
    fc = ctx->pad | S390X_KLMD_DUFOP;
238
    fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KLMD_NIP : 0;
239
    ctx->xof_state = XOF_STATE_FINAL;
240
    s390x_klmd(ctx->buf, ctx->bufsz, out, outlen, fc, ctx->A);
241
    return 1;
242
}
243
244
static int s390x_shake_squeeze(void *vctx, unsigned char *out, size_t outlen)
245
{
246
    KECCAK1600_CTX *ctx = vctx;
247
    unsigned int fc;
248
    size_t len;
249
250
    if (!ossl_prov_is_running())
251
        return 0;
252
    if (ctx->xof_state == XOF_STATE_FINAL)
253
        return 0;
254
    /*
255
     * On the first squeeze call, finish the absorb process (incl. padding).
256
     */
257
    if (ctx->xof_state != XOF_STATE_SQUEEZE) {
258
        fc = ctx->pad;
259
        fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KLMD_NIP : 0;
260
        ctx->xof_state = XOF_STATE_SQUEEZE;
261
        s390x_klmd(ctx->buf, ctx->bufsz, out, outlen, fc, ctx->A);
262
        ctx->bufsz = outlen % ctx->block_size;
263
        /* reuse ctx->bufsz to count bytes squeezed from current sponge */
264
        return 1;
265
    }
266
    ctx->xof_state = XOF_STATE_SQUEEZE;
267
    if (ctx->bufsz != 0) {
268
        len = ctx->block_size - ctx->bufsz;
269
        if (outlen < len)
270
            len = outlen;
271
        memcpy(out, (char *)ctx->A + ctx->bufsz, len);
272
        out += len;
273
        outlen -= len;
274
        ctx->bufsz += len;
275
        if (ctx->bufsz == ctx->block_size)
276
            ctx->bufsz = 0;
277
    }
278
    if (outlen == 0)
279
        return 1;
280
    s390x_klmd(NULL, 0, out, outlen, ctx->pad | S390X_KLMD_PS, ctx->A);
281
    ctx->bufsz = outlen % ctx->block_size;
282
283
    return 1;
284
}
285
286
static int s390x_keccakc_final(void *vctx, unsigned char *out, size_t outlen,
287
    int padding)
288
{
289
    KECCAK1600_CTX *ctx = vctx;
290
    size_t bsz = ctx->block_size;
291
    size_t num = ctx->bufsz;
292
    size_t needed = outlen;
293
    unsigned int fc;
294
295
    if (!ossl_prov_is_running())
296
        return 0;
297
    if (!(ctx->xof_state == XOF_STATE_INIT || ctx->xof_state == XOF_STATE_ABSORB))
298
        return 0;
299
    fc = ctx->pad;
300
    fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KIMD_NIP : 0;
301
    ctx->xof_state = XOF_STATE_FINAL;
302
    if (outlen == 0)
303
        return 1;
304
    memset(ctx->buf + num, 0, bsz - num);
305
    ctx->buf[num] = padding;
306
    ctx->buf[bsz - 1] |= 0x80;
307
    s390x_kimd(ctx->buf, bsz, fc, ctx->A);
308
    num = needed > bsz ? bsz : needed;
309
    memcpy(out, ctx->A, num);
310
    needed -= num;
311
    if (needed > 0)
312
        s390x_klmd(NULL, 0, out + bsz, needed,
313
            ctx->pad | S390X_KLMD_PS | S390X_KLMD_DUFOP, ctx->A);
314
315
    return 1;
316
}
317
318
static int s390x_keccak_final(void *vctx, unsigned char *out, size_t outlen)
319
{
320
    return s390x_keccakc_final(vctx, out, outlen, 0x01);
321
}
322
323
static int s390x_kmac_final(void *vctx, unsigned char *out, size_t outlen)
324
{
325
    return s390x_keccakc_final(vctx, out, outlen, 0x04);
326
}
327
328
static int s390x_keccakc_squeeze(void *vctx, unsigned char *out, size_t outlen,
329
    int padding)
330
{
331
    KECCAK1600_CTX *ctx = vctx;
332
    size_t len;
333
    unsigned int fc;
334
335
    if (!ossl_prov_is_running())
336
        return 0;
337
    if (ctx->xof_state == XOF_STATE_FINAL)
338
        return 0;
339
    /*
340
     * On the first squeeze call, finish the absorb process
341
     * by adding the trailing padding and then doing
342
     * a final absorb.
343
     */
344
    if (ctx->xof_state != XOF_STATE_SQUEEZE) {
345
        len = ctx->block_size - ctx->bufsz;
346
        memset(ctx->buf + ctx->bufsz, 0, len);
347
        ctx->buf[ctx->bufsz] = padding;
348
        ctx->buf[ctx->block_size - 1] |= 0x80;
349
        fc = ctx->pad;
350
        fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KIMD_NIP : 0;
351
        s390x_kimd(ctx->buf, ctx->block_size, fc, ctx->A);
352
        ctx->bufsz = 0;
353
        /* reuse ctx->bufsz to count bytes squeezed from current sponge */
354
    }
355
    if (ctx->bufsz != 0 || ctx->xof_state != XOF_STATE_SQUEEZE) {
356
        len = ctx->block_size - ctx->bufsz;
357
        if (outlen < len)
358
            len = outlen;
359
        memcpy(out, (char *)ctx->A + ctx->bufsz, len);
360
        out += len;
361
        outlen -= len;
362
        ctx->bufsz += len;
363
        if (ctx->bufsz == ctx->block_size)
364
            ctx->bufsz = 0;
365
    }
366
    ctx->xof_state = XOF_STATE_SQUEEZE;
367
    if (outlen == 0)
368
        return 1;
369
    s390x_klmd(NULL, 0, out, outlen, ctx->pad | S390X_KLMD_PS, ctx->A);
370
    ctx->bufsz = outlen % ctx->block_size;
371
372
    return 1;
373
}
374
375
static int s390x_keccak_squeeze(void *vctx, unsigned char *out, size_t outlen)
376
{
377
    return s390x_keccakc_squeeze(vctx, out, outlen, 0x01);
378
}
379
380
static int s390x_kmac_squeeze(void *vctx, unsigned char *out, size_t outlen)
381
{
382
    return s390x_keccakc_squeeze(vctx, out, outlen, 0x04);
383
}
384
385
static PROV_SHA3_METHOD sha3_s390x_md = {
386
    s390x_sha3_absorb,
387
    s390x_sha3_final,
388
    NULL,
389
};
390
391
static PROV_SHA3_METHOD keccak_s390x_md = {
392
    s390x_sha3_absorb,
393
    s390x_keccak_final,
394
    s390x_keccak_squeeze,
395
};
396
397
static PROV_SHA3_METHOD shake_s390x_md = {
398
    s390x_sha3_absorb,
399
    s390x_shake_final,
400
    s390x_shake_squeeze,
401
};
402
403
static PROV_SHA3_METHOD kmac_s390x_md = {
404
    s390x_sha3_absorb,
405
    s390x_kmac_final,
406
    s390x_kmac_squeeze,
407
};
408
409
#define SHAKE_SET_MD(uname, typ)      \
410
    if (S390_SHA3_CAPABLE(uname)) {   \
411
        ctx->pad = S390X_##uname;     \
412
        ctx->meth = typ##_s390x_md;   \
413
    } else {                          \
414
        ctx->meth = shake_generic_md; \
415
    }
416
417
#define SHA3_SET_MD(uname, typ)      \
418
    if (S390_SHA3_CAPABLE(uname)) {  \
419
        ctx->pad = S390X_##uname;    \
420
        ctx->meth = typ##_s390x_md;  \
421
    } else {                         \
422
        ctx->meth = sha3_generic_md; \
423
    }
424
#define KMAC_SET_MD(bitlen)                  \
425
    if (S390_SHA3_CAPABLE(SHAKE_##bitlen)) { \
426
        ctx->pad = S390X_SHAKE_##bitlen;     \
427
        ctx->meth = kmac_s390x_md;           \
428
    } else {                                 \
429
        ctx->meth = sha3_generic_md;         \
430
    }
431
#elif defined(__aarch64__) && defined(KECCAK1600_ASM)
432
#include "arm_arch.h"
433
434
static sha3_absorb_fn armsha3_sha3_absorb;
435
436
size_t SHA3_absorb_cext(uint64_t A[5][5], const unsigned char *inp, size_t len,
437
    size_t r);
438
/*-
439
 * Hardware-assisted ARMv8.2 SHA3 extension version of the absorb()
440
 */
441
static size_t armsha3_sha3_absorb(void *vctx, const void *inp, size_t len)
442
{
443
    KECCAK1600_CTX *ctx = vctx;
444
445
    return SHA3_absorb_cext(ctx->A, inp, len, ctx->block_size);
446
}
447
448
static PROV_SHA3_METHOD sha3_ARMSHA3_md = {
449
    armsha3_sha3_absorb,
450
    generic_sha3_final
451
};
452
static PROV_SHA3_METHOD shake_ARMSHA3_md = {
453
    armsha3_sha3_absorb,
454
    generic_sha3_final,
455
    generic_sha3_squeeze
456
};
457
#define SHAKE_SET_MD(uname, typ)                              \
458
    if (OPENSSL_armcap_P & ARMV8_HAVE_SHA3_AND_WORTH_USING) { \
459
        ctx->meth = shake_ARMSHA3_md;                         \
460
    } else {                                                  \
461
        ctx->meth = shake_generic_md;                         \
462
    }
463
464
#define SHA3_SET_MD(uname, typ)                               \
465
    if (OPENSSL_armcap_P & ARMV8_HAVE_SHA3_AND_WORTH_USING) { \
466
        ctx->meth = sha3_ARMSHA3_md;                          \
467
    } else {                                                  \
468
        ctx->meth = sha3_generic_md;                          \
469
    }
470
#define KMAC_SET_MD(bitlen)                                   \
471
    if (OPENSSL_armcap_P & ARMV8_HAVE_SHA3_AND_WORTH_USING) { \
472
        ctx->meth = sha3_ARMSHA3_md;                          \
473
    } else {                                                  \
474
        ctx->meth = sha3_generic_md;                          \
475
    }
476
#else
477
56
#define SHA3_SET_MD(uname, typ) ctx->meth = sha3_generic_md;
478
0
#define KMAC_SET_MD(bitlen) ctx->meth = sha3_generic_md;
479
0
#define SHAKE_SET_MD(uname, typ) ctx->meth = shake_generic_md;
480
#endif /* S390_SHA3 */
481
482
#define SHA3_newctx(typ, uname, name, bitlen, pad)                                  \
483
    static OSSL_FUNC_digest_newctx_fn name##_newctx;                                \
484
    static void *name##_newctx(void *provctx)                                       \
485
56
    {                                                                               \
486
56
        KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
487
56
                                                     : NULL;                        \
488
56
                                                                                    \
489
56
        if (ctx == NULL)                                                            \
490
56
            return NULL;                                                            \
491
56
        ossl_sha3_init(ctx, pad, bitlen);                                           \
492
56
        SHA3_SET_MD(uname, typ)                                                     \
493
56
        return ctx;                                                                 \
494
56
    }
495
496
#define SHAKE_newctx(typ, uname, name, bitlen, mdlen, pad)                          \
497
    static OSSL_FUNC_digest_newctx_fn name##_newctx;                                \
498
    static void *name##_newctx(void *provctx)                                       \
499
0
    {                                                                               \
500
0
        KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
501
0
                                                     : NULL;                        \
502
0
                                                                                    \
503
0
        if (ctx == NULL)                                                            \
504
0
            return NULL;                                                            \
505
0
        ossl_keccak_init(ctx, pad, bitlen, mdlen);                                  \
506
0
        if (mdlen == 0)                                                             \
507
0
            ctx->md_size = SIZE_MAX;                                                \
508
0
        SHAKE_SET_MD(uname, typ)                                                    \
509
0
        return ctx;                                                                 \
510
0
    }
511
512
#define KMAC_newctx(uname, bitlen, pad)                                             \
513
    static OSSL_FUNC_digest_newctx_fn uname##_newctx;                               \
514
    static void *uname##_newctx(void *provctx)                                      \
515
0
    {                                                                               \
516
0
        KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
517
0
                                                     : NULL;                        \
518
0
                                                                                    \
519
0
        if (ctx == NULL)                                                            \
520
0
            return NULL;                                                            \
521
0
        ossl_keccak_init(ctx, pad, bitlen, 2 * bitlen);                             \
522
0
        KMAC_SET_MD(bitlen)                                                         \
523
0
        return ctx;                                                                 \
524
0
    }
525
526
#define PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags)  \
527
    PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags)                \
528
    const OSSL_DISPATCH ossl_##name##_functions[] = {                         \
529
        { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx },           \
530
        { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))keccak_update },           \
531
        { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final },             \
532
        { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx },         \
533
        { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx },           \
534
        { OSSL_FUNC_DIGEST_COPYCTX, (void (*)(void))keccak_copyctx },         \
535
        { OSSL_FUNC_DIGEST_SERIALIZE, (void (*)(void))name##_serialize },     \
536
        { OSSL_FUNC_DIGEST_DESERIALIZE, (void (*)(void))name##_deserialize }, \
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
556
static void keccak_freectx(void *vctx)
557
56
{
558
56
    KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
559
560
56
    OPENSSL_clear_free(ctx, sizeof(*ctx));
561
56
}
562
563
static void keccak_copyctx(void *voutctx, void *vinctx)
564
0
{
565
0
    KECCAK1600_CTX *outctx = (KECCAK1600_CTX *)voutctx;
566
0
    KECCAK1600_CTX *inctx = (KECCAK1600_CTX *)vinctx;
567
568
0
    *outctx = *inctx;
569
0
}
570
571
static void *keccak_dupctx(void *ctx)
572
0
{
573
0
    KECCAK1600_CTX *in = (KECCAK1600_CTX *)ctx;
574
0
    KECCAK1600_CTX *ret = ossl_prov_is_running() ? OPENSSL_malloc(sizeof(*ret))
575
0
                                                 : NULL;
576
577
0
    if (ret != NULL)
578
0
        *ret = *in;
579
0
    return ret;
580
0
}
581
582
static const unsigned char keccakmagic[] = "KECCAKv1";
583
0
#define KECCAKMAGIC_LEN (sizeof(keccakmagic) - 1)
584
#define KECCAK_SERIALIZATION_LEN                                                     \
585
0
    (                                                                                \
586
0
        KECCAKMAGIC_LEN /* magic string */                                           \
587
0
        + sizeof(uint64_t) /* impl-ID */                                             \
588
0
        + sizeof(uint64_t) /* c->md_size */                                          \
589
0
        + (sizeof(uint64_t) * 4) /* c->block_size, c->bufsz, c->pad, c->xof_state */ \
590
0
        + (sizeof(uint64_t) * 5 * 5) /* c->A */                                      \
591
0
        + (KECCAK1600_WIDTH / 8 - 32) /* c->buf */                                   \
592
0
    )
593
594
static int KECCAK_Serialize(KECCAK1600_CTX *c, int impl_id,
595
    unsigned char *output, size_t *outlen)
596
0
{
597
0
    unsigned char *p;
598
0
    int i, j;
599
600
0
    if (output == NULL) {
601
0
        if (outlen == NULL)
602
0
            return 0;
603
604
0
        *outlen = KECCAK_SERIALIZATION_LEN;
605
0
        return 1;
606
0
    }
607
608
0
    if (outlen != NULL && *outlen < KECCAK_SERIALIZATION_LEN)
609
0
        return 0;
610
611
0
    p = output;
612
613
    /* Magic code */
614
0
    memcpy(p, keccakmagic, KECCAKMAGIC_LEN);
615
0
    p += KECCAKMAGIC_LEN;
616
617
    /* Additional check data */
618
0
    p = OPENSSL_store_u64_le(p, impl_id);
619
0
    p = OPENSSL_store_u64_le(p, c->md_size);
620
621
0
    p = OPENSSL_store_u64_le(p, c->block_size);
622
0
    p = OPENSSL_store_u64_le(p, c->bufsz);
623
0
    p = OPENSSL_store_u64_le(p, c->pad);
624
0
    p = OPENSSL_store_u64_le(p, c->xof_state);
625
626
    /* A matrix */
627
0
    for (i = 0; i < 5; i++) {
628
0
        for (j = 0; j < 5; j++)
629
0
            p = OPENSSL_store_u64_le(p, c->A[i][j]);
630
0
    }
631
632
0
    if (outlen != NULL)
633
0
        *outlen = KECCAK_SERIALIZATION_LEN;
634
635
    /* buf */
636
0
    memcpy(p, c->buf, sizeof(c->buf));
637
638
0
    return 1;
639
0
}
640
641
/*
642
 * This function only performs basic input sanity checks and is not
643
 * built to handle malicious input data. Only trusted input should be
644
 * fed to this function
645
 */
646
static int KECCAK_Deserialize(KECCAK1600_CTX *c, int impl_id,
647
    const unsigned char *input, size_t len)
648
0
{
649
0
    const unsigned char *p;
650
0
    uint64_t val;
651
0
    int i, j;
652
653
0
    if (c == NULL || input == NULL || len != KECCAK_SERIALIZATION_LEN)
654
0
        return 0;
655
656
    /* Magic code */
657
0
    if (memcmp(input, keccakmagic, KECCAKMAGIC_LEN) != 0)
658
0
        return 0;
659
660
0
    p = input + KECCAKMAGIC_LEN;
661
662
    /* Check for matching Impl ID */
663
0
    p = OPENSSL_load_u64_le(&val, p);
664
0
    if (val != (uint64_t)impl_id)
665
0
        return 0;
666
667
    /* Check for matching md_size */
668
0
    p = OPENSSL_load_u64_le(&val, p);
669
0
    if (val != (uint64_t)c->md_size)
670
0
        return 0;
671
672
    /* check that block_size is congruent with the initialized value */
673
0
    p = OPENSSL_load_u64_le(&val, p);
674
0
    if (val != c->block_size)
675
0
        return 0;
676
    /* check that bufsz does not exceed block_size */
677
0
    p = OPENSSL_load_u64_le(&val, p);
678
0
    if (val > c->block_size)
679
0
        return 0;
680
0
    c->bufsz = (size_t)val;
681
0
    p = OPENSSL_load_u64_le(&val, p);
682
0
    if (val != c->pad)
683
0
        return 0;
684
0
    p = OPENSSL_load_u64_le(&val, p);
685
0
    c->xof_state = (int)val;
686
687
    /* A matrix */
688
0
    for (i = 0; i < 5; i++) {
689
0
        for (j = 0; j < 5; j++) {
690
0
            p = OPENSSL_load_u64_le(&val, p);
691
0
            c->A[i][j] = val;
692
0
        }
693
0
    }
694
695
    /* buf */
696
0
    memcpy(c->buf, p, sizeof(c->buf));
697
698
0
    return 1;
699
0
}
700
701
#define IMPLEMENT_SERIALIZE_FNS(name, id)                              \
702
    static int name##_serialize(void *vctx, unsigned char *out,        \
703
        size_t *outlen)                                                \
704
0
    {                                                                  \
705
0
        return KECCAK_Serialize(vctx, id, out, outlen);                \
706
0
    }                                                                  \
Unexecuted instantiation: sha3_prov.c:sha3_224_serialize
Unexecuted instantiation: sha3_prov.c:sha3_256_serialize
Unexecuted instantiation: sha3_prov.c:sha3_384_serialize
Unexecuted instantiation: sha3_prov.c:sha3_512_serialize
Unexecuted instantiation: sha3_prov.c:keccak_224_serialize
Unexecuted instantiation: sha3_prov.c:keccak_256_serialize
Unexecuted instantiation: sha3_prov.c:keccak_384_serialize
Unexecuted instantiation: sha3_prov.c:keccak_512_serialize
Unexecuted instantiation: sha3_prov.c:shake_128_serialize
Unexecuted instantiation: sha3_prov.c:shake_256_serialize
Unexecuted instantiation: sha3_prov.c:keccak_kmac_128_serialize
Unexecuted instantiation: sha3_prov.c:keccak_kmac_256_serialize
707
    static int name##_deserialize(void *vctx, const unsigned char *in, \
708
        size_t inlen)                                                  \
709
0
    {                                                                  \
710
0
        return KECCAK_Deserialize(vctx, id, in, inlen);                \
711
0
    }
Unexecuted instantiation: sha3_prov.c:sha3_224_deserialize
Unexecuted instantiation: sha3_prov.c:sha3_256_deserialize
Unexecuted instantiation: sha3_prov.c:sha3_384_deserialize
Unexecuted instantiation: sha3_prov.c:sha3_512_deserialize
Unexecuted instantiation: sha3_prov.c:keccak_224_deserialize
Unexecuted instantiation: sha3_prov.c:keccak_256_deserialize
Unexecuted instantiation: sha3_prov.c:keccak_384_deserialize
Unexecuted instantiation: sha3_prov.c:keccak_512_deserialize
Unexecuted instantiation: sha3_prov.c:shake_128_deserialize
Unexecuted instantiation: sha3_prov.c:shake_256_deserialize
Unexecuted instantiation: sha3_prov.c:keccak_kmac_128_deserialize
Unexecuted instantiation: sha3_prov.c:keccak_kmac_256_deserialize
712
713
static const OSSL_PARAM *shake_gettable_ctx_params(ossl_unused void *ctx,
714
    ossl_unused void *provctx)
715
0
{
716
0
    return shake_get_ctx_params_list;
717
0
}
718
719
static int shake_get_ctx_params(void *vctx, OSSL_PARAM params[])
720
0
{
721
0
    struct shake_get_ctx_params_st p;
722
0
    KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
723
724
0
    if (ctx == NULL || !shake_get_ctx_params_decoder(params, &p))
725
0
        return 0;
726
727
0
    if (p.xoflen != NULL && !OSSL_PARAM_set_size_t(p.xoflen, ctx->md_size)) {
728
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
729
0
        return 0;
730
0
    }
731
    /* Size is an alias of xoflen but separate them for compatibility */
732
0
    if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, ctx->md_size)) {
733
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
734
0
        return 0;
735
0
    }
736
0
    return 1;
737
0
}
738
739
static const OSSL_PARAM *shake_settable_ctx_params(ossl_unused void *ctx,
740
    ossl_unused void *provctx)
741
0
{
742
0
    return shake_set_ctx_params_list;
743
0
}
744
745
static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[])
746
0
{
747
0
    struct shake_set_ctx_params_st p;
748
0
    KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
749
750
0
    if (ossl_unlikely(ctx == NULL || !shake_set_ctx_params_decoder(params, &p)))
751
0
        return 0;
752
753
0
    if (ossl_unlikely(p.xoflen != NULL
754
0
            && !OSSL_PARAM_get_size_t(p.xoflen, &ctx->md_size))) {
755
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
756
0
        return 0;
757
0
    }
758
0
    return 1;
759
0
}
760
761
#define KECCAK_SER_ID 0x010000
762
#define SHAKE_SER_ID 0x020000
763
#define SHA3_SER_ID 0x040000
764
#define KMAK_SER_ID 0x080000
765
766
#define IMPLEMENT_SHA3_functions(bitlen)                             \
767
    SHA3_newctx(sha3, SHA3_##bitlen, sha3_##bitlen, bitlen, '\x06')  \
768
        IMPLEMENT_SERIALIZE_FNS(sha3_##bitlen, SHA3_SER_ID + bitlen) \
769
            PROV_FUNC_SHA3_DIGEST(sha3_##bitlen, bitlen,             \
770
                SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen),         \
771
                SHA3_FLAGS)
772
773
#define IMPLEMENT_KECCAK_functions(bitlen)                                \
774
    SHA3_newctx(keccak, KECCAK_##bitlen, keccak_##bitlen, bitlen, '\x01') \
775
        IMPLEMENT_SERIALIZE_FNS(keccak_##bitlen, KECCAK_SER_ID + bitlen)  \
776
            PROV_FUNC_SHA3_DIGEST(keccak_##bitlen, bitlen,                \
777
                SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen),              \
778
                SHA3_FLAGS)
779
780
#define IMPLEMENT_SHAKE_functions(bitlen)                              \
781
    SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen,        \
782
        0 /* no default md length */, '\x1f')                          \
783
        IMPLEMENT_SERIALIZE_FNS(shake_##bitlen, SHAKE_SER_ID + bitlen) \
784
            PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen,             \
785
                SHA3_BLOCKSIZE(bitlen), 0,                             \
786
                SHAKE_FLAGS)
787
788
#define IMPLEMENT_KMAC_functions(bitlen)                                    \
789
    KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04')                       \
790
        IMPLEMENT_SERIALIZE_FNS(keccak_kmac_##bitlen, KMAK_SER_ID + bitlen) \
791
            PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen,            \
792
                SHA3_BLOCKSIZE(bitlen), KMAC_MDSIZE(bitlen),                \
793
                KMAC_FLAGS)
794
795
/* ossl_sha3_224_functions */
796
58
IMPLEMENT_SHA3_functions(224)
797
58
/* ossl_sha3_256_functions */
798
58
IMPLEMENT_SHA3_functions(256)
799
12
/* ossl_sha3_384_functions */
800
32
IMPLEMENT_SHA3_functions(384)
801
32
/* ossl_sha3_512_functions */
802
32
IMPLEMENT_SHA3_functions(512)
803
10
/* ossl_keccak_224_functions */
804
10
IMPLEMENT_KECCAK_functions(224)
805
0
/* ossl_keccak_256_functions */
806
0
IMPLEMENT_KECCAK_functions(256)
807
0
/* ossl_keccak_384_functions */
808
0
IMPLEMENT_KECCAK_functions(384)
809
0
/* ossl_keccak_512_functions */
810
0
IMPLEMENT_KECCAK_functions(512)
811
0
/* ossl_shake_128_functions */
812
0
IMPLEMENT_SHAKE_functions(128)
813
0
/* ossl_shake_256_functions */
814
0
IMPLEMENT_SHAKE_functions(256)
815
0
/* ossl_keccak_kmac_128_functions */
816
0
IMPLEMENT_KMAC_functions(128)
817
0
/* ossl_keccak_kmac_256_functions */
818
IMPLEMENT_KMAC_functions(256)