Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl30/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/sha3.h"
18
#include "prov/digestcommon.h"
19
#include "prov/implementations.h"
20
21
#define SHA3_FLAGS PROV_DIGEST_FLAG_ALGID_ABSENT
22
#define SHAKE_FLAGS (PROV_DIGEST_FLAG_XOF | PROV_DIGEST_FLAG_ALGID_ABSENT)
23
#define KMAC_FLAGS PROV_DIGEST_FLAG_XOF
24
25
/*
26
 * Forward declaration of any unique methods implemented here. This is not strictly
27
 * necessary for the compiler, but provides an assurance that the signatures
28
 * of the functions in the dispatch table are correct.
29
 */
30
static OSSL_FUNC_digest_init_fn keccak_init;
31
static OSSL_FUNC_digest_init_fn keccak_init_params;
32
static OSSL_FUNC_digest_update_fn keccak_update;
33
static OSSL_FUNC_digest_final_fn keccak_final;
34
static OSSL_FUNC_digest_freectx_fn keccak_freectx;
35
static OSSL_FUNC_digest_dupctx_fn keccak_dupctx;
36
static OSSL_FUNC_digest_set_ctx_params_fn shake_set_ctx_params;
37
static OSSL_FUNC_digest_settable_ctx_params_fn shake_settable_ctx_params;
38
static sha3_absorb_fn generic_sha3_absorb;
39
static sha3_final_fn generic_sha3_final;
40
41
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) && defined(KECCAK1600_ASM)
42
/*
43
 * IBM S390X support
44
 */
45
#include "s390x_arch.h"
46
#define S390_SHA3 1
47
#define S390_SHA3_CAPABLE(name) \
48
    ((OPENSSL_s390xcap_P.kimd[0] & S390X_CAPBIT(S390X_##name)) && (OPENSSL_s390xcap_P.klmd[0] & S390X_CAPBIT(S390X_##name)))
49
50
#endif
51
52
static int keccak_init(void *vctx, ossl_unused const OSSL_PARAM params[])
53
137M
{
54
137M
    if (!ossl_prov_is_running())
55
0
        return 0;
56
    /* The newctx() handles most of the ctx fixed setup. */
57
137M
    ossl_sha3_reset((KECCAK1600_CTX *)vctx);
58
137M
    return 1;
59
137M
}
60
61
static int keccak_init_params(void *vctx, const OSSL_PARAM params[])
62
467M
{
63
467M
    return keccak_init(vctx, NULL)
64
467M
        && shake_set_ctx_params(vctx, params);
65
467M
}
66
67
static int keccak_update(void *vctx, const unsigned char *inp, size_t len)
68
419M
{
69
419M
    KECCAK1600_CTX *ctx = vctx;
70
419M
    const size_t bsz = ctx->block_size;
71
419M
    size_t num, rem;
72
73
419M
    if (len == 0)
74
0
        return 1;
75
76
    /* Is there anything in the buffer already ? */
77
419M
    if ((num = ctx->bufsz) != 0) {
78
        /* Calculate how much space is left in the buffer */
79
281M
        rem = bsz - num;
80
        /* If the new input does not fill the buffer then just add it */
81
281M
        if (len < rem) {
82
281M
            memcpy(ctx->buf + num, inp, len);
83
281M
            ctx->bufsz += len;
84
281M
            return 1;
85
281M
        }
86
        /* otherwise fill up the buffer and absorb the buffer */
87
179k
        memcpy(ctx->buf + num, inp, rem);
88
        /* Update the input pointer */
89
179k
        inp += rem;
90
179k
        len -= rem;
91
179k
        ctx->meth.absorb(ctx, ctx->buf, bsz);
92
179k
        ctx->bufsz = 0;
93
179k
    }
94
    /* Absorb the input - rem = leftover part of the input < blocksize) */
95
137M
    rem = ctx->meth.absorb(ctx, inp, len);
96
    /* Copy the leftover bit of the input into the buffer */
97
137M
    if (rem) {
98
137M
        memcpy(ctx->buf, inp + len - rem, rem);
99
137M
        ctx->bufsz = rem;
100
137M
    }
101
137M
    return 1;
102
419M
}
103
104
static int keccak_final(void *vctx, unsigned char *out, size_t *outl,
105
    size_t outsz)
106
268k
{
107
268k
    int ret = 1;
108
268k
    KECCAK1600_CTX *ctx = vctx;
109
110
268k
    if (!ossl_prov_is_running())
111
0
        return 0;
112
268k
    if (outsz > 0)
113
268k
        ret = ctx->meth.final(out, ctx);
114
115
268k
    *outl = ctx->md_size;
116
268k
    return ret;
117
268k
}
118
119
/*-
120
 * Generic software version of the absorb() and final().
121
 */
122
static size_t generic_sha3_absorb(void *vctx, const void *inp, size_t len)
123
174k
{
124
174k
    KECCAK1600_CTX *ctx = vctx;
125
126
174k
    return SHA3_absorb(ctx->A, inp, len, ctx->block_size);
127
174k
}
128
129
static int generic_sha3_final(unsigned char *md, void *vctx)
130
466M
{
131
466M
    return ossl_sha3_final(md, (KECCAK1600_CTX *)vctx);
132
466M
}
133
134
static PROV_SHA3_METHOD sha3_generic_md = {
135
    generic_sha3_absorb,
136
    generic_sha3_final
137
};
138
139
#if defined(S390_SHA3)
140
141
static sha3_absorb_fn s390x_sha3_absorb;
142
static sha3_final_fn s390x_sha3_final;
143
static sha3_final_fn s390x_shake_final;
144
145
/*-
146
 * The platform specific parts of the absorb() and final() for S390X.
147
 */
148
static size_t s390x_sha3_absorb(void *vctx, const void *inp, size_t len)
149
{
150
    KECCAK1600_CTX *ctx = vctx;
151
    size_t rem = len % ctx->block_size;
152
153
    s390x_kimd(inp, len - rem, ctx->pad, ctx->A);
154
    return rem;
155
}
156
157
static int s390x_sha3_final(unsigned char *md, void *vctx)
158
{
159
    KECCAK1600_CTX *ctx = vctx;
160
161
    if (!ossl_prov_is_running())
162
        return 0;
163
    s390x_klmd(ctx->buf, ctx->bufsz, NULL, 0, ctx->pad, ctx->A);
164
    memcpy(md, ctx->A, ctx->md_size);
165
    return 1;
166
}
167
168
static int s390x_shake_final(unsigned char *md, void *vctx)
169
{
170
    KECCAK1600_CTX *ctx = vctx;
171
172
    if (!ossl_prov_is_running())
173
        return 0;
174
    s390x_klmd(ctx->buf, ctx->bufsz, md, ctx->md_size, ctx->pad, ctx->A);
175
    return 1;
176
}
177
178
static PROV_SHA3_METHOD sha3_s390x_md = {
179
    s390x_sha3_absorb,
180
    s390x_sha3_final
181
};
182
183
static PROV_SHA3_METHOD shake_s390x_md = {
184
    s390x_sha3_absorb,
185
    s390x_shake_final
186
};
187
188
#define SHA3_SET_MD(uname, typ)      \
189
    if (S390_SHA3_CAPABLE(uname)) {  \
190
        ctx->pad = S390X_##uname;    \
191
        ctx->meth = typ##_s390x_md;  \
192
    } else {                         \
193
        ctx->meth = sha3_generic_md; \
194
    }
195
#else
196
278k
#define SHA3_SET_MD(uname, typ) ctx->meth = sha3_generic_md;
197
#endif /* S390_SHA3 */
198
199
#define SHA3_newctx(typ, uname, name, bitlen, pad)                                  \
200
    static OSSL_FUNC_digest_newctx_fn name##_newctx;                                \
201
    static void *name##_newctx(void *provctx)                                       \
202
278k
    {                                                                               \
203
278k
        KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
204
278k
                                                     : NULL;                        \
205
278k
                                                                                    \
206
278k
        if (ctx == NULL)                                                            \
207
278k
            return NULL;                                                            \
208
278k
        ossl_sha3_init(ctx, pad, bitlen);                                           \
209
278k
        SHA3_SET_MD(uname, typ)                                                     \
210
278k
        return ctx;                                                                 \
211
278k
    }
212
213
#define KMAC_newctx(uname, bitlen, pad)                                             \
214
    static OSSL_FUNC_digest_newctx_fn uname##_newctx;                               \
215
    static void *uname##_newctx(void *provctx)                                      \
216
379
    {                                                                               \
217
379
        KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
218
379
                                                     : NULL;                        \
219
379
                                                                                    \
220
379
        if (ctx == NULL)                                                            \
221
379
            return NULL;                                                            \
222
379
        ossl_keccak_kmac_init(ctx, pad, bitlen);                                    \
223
379
        ctx->meth = sha3_generic_md;                                                \
224
379
        return ctx;                                                                 \
225
379
    }
226
227
#define PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags) \
228
    PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags)               \
229
    const OSSL_DISPATCH ossl_##name##_functions[] = {                        \
230
        { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx },          \
231
        { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))keccak_update },          \
232
        { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final },            \
233
        { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx },        \
234
        { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx },          \
235
        PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
236
237
#define PROV_FUNC_SHA3_DIGEST(name, bitlen, blksize, dgstsize, flags)     \
238
    PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags), \
239
        { OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init },           \
240
        PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
241
242
#define PROV_FUNC_SHAKE_DIGEST(name, bitlen, blksize, dgstsize, flags)             \
243
    PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags),          \
244
        { OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init_params },             \
245
        { OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))shake_set_ctx_params }, \
246
        { OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS,                                    \
247
            (void (*)(void))shake_settable_ctx_params },                           \
248
        PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
249
250
static void keccak_freectx(void *vctx)
251
392k
{
252
392k
    KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
253
254
392k
    OPENSSL_clear_free(ctx, sizeof(*ctx));
255
392k
}
256
257
static void *keccak_dupctx(void *ctx)
258
1.82k
{
259
1.82k
    KECCAK1600_CTX *in = (KECCAK1600_CTX *)ctx;
260
1.82k
    KECCAK1600_CTX *ret = ossl_prov_is_running() ? OPENSSL_malloc(sizeof(*ret))
261
1.82k
                                                 : NULL;
262
263
1.82k
    if (ret != NULL)
264
1.82k
        *ret = *in;
265
1.82k
    return ret;
266
1.82k
}
267
268
static const OSSL_PARAM known_shake_settable_ctx_params[] = {
269
    { OSSL_DIGEST_PARAM_XOFLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0 },
270
    OSSL_PARAM_END
271
};
272
static const OSSL_PARAM *shake_settable_ctx_params(ossl_unused void *ctx,
273
    ossl_unused void *provctx)
274
28
{
275
28
    return known_shake_settable_ctx_params;
276
28
}
277
278
static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[])
279
142k
{
280
142k
    const OSSL_PARAM *p;
281
142k
    KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
282
283
142k
    if (ctx == NULL)
284
0
        return 0;
285
142k
    if (params == NULL)
286
142k
        return 1;
287
288
46
    p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_XOFLEN);
289
46
    if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->md_size)) {
290
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
291
0
        return 0;
292
0
    }
293
46
    return 1;
294
46
}
295
296
#define IMPLEMENT_SHA3_functions(bitlen)                            \
297
    SHA3_newctx(sha3, SHA3_##bitlen, sha3_##bitlen, bitlen, '\x06') \
298
        PROV_FUNC_SHA3_DIGEST(sha3_##bitlen, bitlen,                \
299
            SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen),            \
300
            SHA3_FLAGS)
301
302
#define IMPLEMENT_SHAKE_functions(bitlen)                              \
303
    SHA3_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, '\x1f') \
304
        PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen,                 \
305
            SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen),               \
306
            SHAKE_FLAGS)
307
#define IMPLEMENT_KMAC_functions(bitlen)                     \
308
    KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04')        \
309
        PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen, \
310
            SHA3_BLOCKSIZE(bitlen), KMAC_MDSIZE(bitlen),     \
311
            KMAC_FLAGS)
312
313
/* ossl_sha3_224_functions */
314
57.7k
IMPLEMENT_SHA3_functions(224)
315
57.7k
/* ossl_sha3_256_functions */
316
159k
IMPLEMENT_SHA3_functions(256)
317
159k
/* ossl_sha3_384_functions */
318
159k
IMPLEMENT_SHA3_functions(384)
319
20.8k
/* ossl_sha3_512_functions */
320
109k
IMPLEMENT_SHA3_functions(512)
321
109k
/* ossl_shake_128_functions */
322
134k
IMPLEMENT_SHAKE_functions(128)
323
134k
/* ossl_shake_256_functions */
324
134k
IMPLEMENT_SHAKE_functions(256)
325
75.7k
/* ossl_keccak_kmac_128_functions */
326
75.7k
IMPLEMENT_KMAC_functions(128)
327
336
/* ossl_keccak_kmac_256_functions */
328
IMPLEMENT_KMAC_functions(256)