Coverage Report

Created: 2026-08-18 07:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/slh_dsa/slh_hash.c
Line
Count
Source
1
/*
2
 * Copyright 2024-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 "internal/deprecated.h" /* PKCS1_MGF1() */
11
12
#include <string.h>
13
#include <openssl/evp.h>
14
#include <openssl/core_names.h>
15
#include <openssl/rsa.h> /* PKCS1_MGF1() */
16
#include "slh_dsa_local.h"
17
#include "slh_dsa_key.h"
18
19
#include "openssl/sha.h"
20
#include "internal/sha3.h"
21
#include "crypto/evp.h"
22
#include "crypto/sha.h"
23
24
#define MAX_DIGEST_SIZE 64 /* SHA-512 is used for security category 3 & 5 */
25
0
#define NIBBLE_MASK 15
26
27
/* Most hash functions in SLH-DSA truncate the output */
28
#define sha256_final(ctx, out, outlen)    \
29
0
    (ctx)->md_len = (unsigned int)outlen; \
30
0
    SHA256_Final(out, ctx)
31
32
#define sha512_final(ctx, out, outlen)    \
33
0
    (ctx)->md_len = (unsigned int)outlen; \
34
0
    SHA512_Final(out, ctx)
35
36
static OSSL_SLH_HASHFUNC_PRF slh_prf_sha256;
37
static OSSL_SLH_HASHFUNC_PRF slh_prf_shake;
38
39
static OSSL_SLH_HASHFUNC_F slh_f_sha256;
40
static OSSL_SLH_HASHFUNC_F slh_f_shake;
41
42
static OSSL_SLH_HASHFUNC_PRF_MSG slh_prf_msg_sha2;
43
static OSSL_SLH_HASHFUNC_PRF_MSG slh_prf_msg_shake;
44
45
static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_sha256;
46
static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_sha512;
47
static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_shake;
48
49
static OSSL_SLH_HASHFUNC_H slh_h_sha256;
50
static OSSL_SLH_HASHFUNC_H slh_h_sha512;
51
static OSSL_SLH_HASHFUNC_H slh_h_shake;
52
static OSSL_SLH_HASHFUNC_T slh_t_sha256;
53
static OSSL_SLH_HASHFUNC_T slh_t_sha512;
54
static OSSL_SLH_HASHFUNC_wots_pk_gen slh_wots_pk_gen_sha2;
55
static OSSL_SLH_HASHFUNC_wots_pk_gen slh_wots_pk_gen_shake;
56
57
static const uint8_t zeros[128] = { 0 };
58
59
/* See FIPS 205 Section 11.1 */
60
static int
61
slh_hmsg_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *r,
62
    const uint8_t *pk_seed, const uint8_t *pk_root,
63
    const uint8_t *msg, size_t msg_len,
64
    uint8_t *out, size_t out_len)
65
0
{
66
0
    KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->shactx);
67
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
68
0
    size_t m = params->m;
69
0
    size_t n = params->n;
70
71
0
    ossl_sha3_reset(sctx);
72
0
    ossl_sha3_absorb(sctx, r, n);
73
0
    ossl_sha3_absorb(sctx, pk_seed, n);
74
0
    ossl_sha3_absorb(sctx, pk_root, n);
75
0
    ossl_sha3_absorb(sctx, msg, msg_len);
76
0
    ossl_sha3_squeeze(sctx, out, m);
77
0
    return 1;
78
0
}
79
80
static int
81
slh_prf_msg_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *sk_prf,
82
    const uint8_t *opt_rand, const uint8_t *msg, size_t msg_len,
83
    WPACKET *pkt)
84
0
{
85
0
    int ret;
86
0
    unsigned char out[SLH_MAX_N];
87
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
88
0
    size_t n = params->n;
89
0
    KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->shactx);
90
91
0
    ossl_sha3_reset(sctx);
92
0
    ossl_sha3_absorb(sctx, sk_prf, n);
93
0
    ossl_sha3_absorb(sctx, opt_rand, n);
94
0
    ossl_sha3_absorb(sctx, msg, msg_len);
95
0
    ossl_sha3_squeeze(sctx, out, n);
96
0
    ret = WPACKET_memcpy(pkt, out, n);
97
0
    OPENSSL_cleanse(out, sizeof(out));
98
0
    return ret;
99
0
}
100
101
static int
102
slh_f_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
103
    const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
104
0
{
105
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
106
0
    size_t n = params->n;
107
0
    KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->scratch);
108
109
0
    *sctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed));
110
0
    ossl_sha3_absorb(sctx, adrs, SLH_ADRS_SIZE);
111
0
    ossl_sha3_absorb(sctx, m1, m1_len);
112
0
    ossl_sha3_squeeze(sctx, out, n);
113
0
    return 1;
114
0
}
115
116
static int
117
slh_prf_shake(SLH_DSA_HASH_CTX *hctx,
118
    const uint8_t *pk_seed, const uint8_t *sk_seed,
119
    const uint8_t *adrs, uint8_t *out, size_t out_len)
120
0
{
121
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
122
0
    size_t n = params->n;
123
0
    KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->scratch);
124
125
0
    *sctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed));
126
0
    ossl_sha3_absorb(sctx, adrs, SLH_ADRS_SIZE);
127
0
    ossl_sha3_absorb(sctx, sk_seed, n);
128
0
    ossl_sha3_squeeze(sctx, out, n);
129
0
    return 1;
130
0
}
131
132
static int
133
slh_h_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
134
    const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
135
0
{
136
0
    KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->scratch);
137
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
138
0
    size_t n = params->n;
139
140
0
    *sctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed));
141
0
    ossl_sha3_absorb(sctx, adrs, SLH_ADRS_SIZE);
142
0
    ossl_sha3_absorb(sctx, m1, n);
143
0
    ossl_sha3_absorb(sctx, m2, n);
144
0
    ossl_sha3_squeeze(sctx, out, n);
145
0
    return 1;
146
0
}
147
148
/* FIPS 205 Section 11.2.1 and 11.2.2 */
149
150
static int
151
slh_hmsg_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
152
    const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
153
    uint8_t *out, size_t out_len)
154
0
{
155
0
    int ret;
156
0
    SHA256_CTX *sctx = (SHA256_CTX *)(hctx->scratch);
157
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
158
0
    size_t m = params->m;
159
0
    size_t n = params->n;
160
0
    uint8_t seed[2 * SLH_MAX_N + SHA256_DIGEST_LENGTH];
161
0
    long seed_len = SHA256_DIGEST_LENGTH + (long)(2 * n);
162
163
0
    memcpy(seed, r, n);
164
0
    memcpy(seed + n, pk_seed, n);
165
166
0
    SHA256_Init(sctx);
167
0
    SHA256_Update(sctx, r, n);
168
0
    SHA256_Update(sctx, pk_seed, n);
169
0
    SHA256_Update(sctx, pk_root, n);
170
0
    SHA256_Update(sctx, msg, msg_len);
171
0
    ret = SHA256_Final(seed + 2 * n, sctx)
172
0
        && (PKCS1_MGF1(out, (long)m, seed, seed_len, hctx->key->md) == 0);
173
0
    OPENSSL_cleanse(seed, sizeof(seed));
174
0
    return ret;
175
0
}
176
177
static int
178
slh_hmsg_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
179
    const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
180
    uint8_t *out, size_t out_len)
181
0
{
182
0
    int ret;
183
0
    SHA512_CTX *sctx = (SHA512_CTX *)(hctx->scratch);
184
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
185
0
    size_t m = params->m;
186
0
    size_t n = params->n;
187
0
    uint8_t seed[2 * SLH_MAX_N + SHA512_DIGEST_LENGTH];
188
0
    long seed_len = SHA512_DIGEST_LENGTH + (long)(2 * n);
189
190
0
    memcpy(seed, r, n);
191
0
    memcpy(seed + n, pk_seed, n);
192
193
0
    SHA512_Init(sctx);
194
0
    SHA512_Update(sctx, r, n);
195
0
    SHA512_Update(sctx, pk_seed, n);
196
0
    SHA512_Update(sctx, pk_root, n);
197
0
    SHA512_Update(sctx, msg, msg_len);
198
0
    ret = SHA512_Final(seed + 2 * n, sctx)
199
0
        && (PKCS1_MGF1(out, (long)m, seed, seed_len, hctx->key->md_sha512) == 0);
200
0
    OPENSSL_cleanse(seed, sizeof(seed));
201
0
    return ret;
202
0
}
203
204
static int
205
slh_prf_msg_sha2(SLH_DSA_HASH_CTX *hctx,
206
    const uint8_t *sk_prf, const uint8_t *opt_rand,
207
    const uint8_t *msg, size_t msg_len, WPACKET *pkt)
208
0
{
209
0
    int ret;
210
0
    const SLH_DSA_KEY *key = hctx->key;
211
0
    EVP_MAC_CTX *mctx = hctx->hmac_ctx;
212
0
    const SLH_DSA_PARAMS *prms = key->params;
213
0
    size_t n = prms->n;
214
0
    uint8_t mac[MAX_DIGEST_SIZE] = { 0 };
215
0
    OSSL_PARAM *p = NULL;
216
0
    OSSL_PARAM params[3];
217
218
    /*
219
     * Due to the way HMAC works, it is not possible to do this code early
220
     * in hmac_ctx_new() since it requires a key in order to set the digest.
221
     * So we do a lazy update here on the first call.
222
     */
223
0
    if (hctx->hmac_digest_used == 0) {
224
0
        const char *nm = EVP_MD_get0_name(key->md_sha512 == NULL ? key->md : key->md_sha512);
225
226
0
        p = params;
227
        /* The underlying digest to be used */
228
0
        *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)nm, 0);
229
0
        if (key->propq != NULL)
230
0
            *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
231
0
                (char *)key->propq, 0);
232
0
        *p = OSSL_PARAM_construct_end();
233
0
        p = params;
234
0
        hctx->hmac_digest_used = 1;
235
0
    }
236
237
0
    ret = EVP_MAC_init(mctx, sk_prf, n, p) == 1
238
0
        && EVP_MAC_update(mctx, opt_rand, n) == 1
239
0
        && EVP_MAC_update(mctx, msg, msg_len) == 1
240
0
        && EVP_MAC_final(mctx, mac, NULL, sizeof(mac)) == 1
241
0
        && WPACKET_memcpy(pkt, mac, n); /* Truncate output to n bytes */
242
0
    OPENSSL_cleanse(mac, sizeof(mac));
243
0
    return ret;
244
0
}
245
246
static int
247
slh_prf_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed,
248
    const uint8_t *sk_seed, const uint8_t *adrs,
249
    uint8_t *out, size_t out_len)
250
0
{
251
0
    SHA256_CTX *sctx = (SHA256_CTX *)(hctx->scratch);
252
0
    size_t n = hctx->key->params->n;
253
254
0
    *sctx = *((SHA256_CTX *)hctx->shactx_pkseed);
255
0
    SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
256
0
    SHA256_Update(sctx, sk_seed, n);
257
0
    sha256_final(sctx, out, n);
258
0
    return 1;
259
0
}
260
261
static int
262
slh_wots_pk_gen_sha2(SLH_DSA_HASH_CTX *hctx,
263
    const uint8_t *sk_seed, const uint8_t *pk_seed,
264
    uint8_t *adrs, uint8_t *pk_out, size_t pk_out_len)
265
0
{
266
0
    int ret = 0;
267
0
    size_t n = hctx->key->params->n;
268
0
    size_t i, j = 0, len = SLH_WOTS_LEN(n);
269
0
    uint8_t sk[SLH_MAX_N];
270
0
    SHA256_CTX *sctx = (SHA256_CTX *)(hctx->shactx_pkseed);
271
0
    SHA256_CTX *ctx = (SHA256_CTX *)(hctx->scratch);
272
0
    const SLH_ADRS_FUNC *adrsf = hctx->key->adrs_func;
273
0
    SLH_ADRS_DECLARE(sk_adrs);
274
0
    SLH_ADRS_FN_DECLARE(adrsf, set_chain_address);
275
0
    SLH_ADRS_FN_DECLARE(adrsf, set_hash_address);
276
277
0
    adrsf->copy(sk_adrs, adrs);
278
0
    adrsf->set_type_and_clear(sk_adrs, SLH_ADRS_TYPE_WOTS_PRF);
279
0
    adrsf->copy_keypair_address(sk_adrs, adrs);
280
281
0
    for (i = 0; i < len; ++i) { /* len = 2n + 3 */
282
0
        set_chain_address(sk_adrs, (uint32_t)i);
283
284
        /* PRF */
285
0
        *ctx = *sctx;
286
0
        SHA256_Update(ctx, sk_adrs, SLH_ADRSC_SIZE);
287
0
        SHA256_Update(ctx, sk_seed, n);
288
0
        sha256_final(ctx, sk, n);
289
290
0
        set_chain_address(adrs, (uint32_t)i);
291
0
        for (j = 0; j < NIBBLE_MASK; ++j) {
292
0
            set_hash_address(adrs, (uint32_t)j);
293
            /* F */
294
0
            *ctx = *sctx;
295
0
            SHA256_Update(ctx, adrs, SLH_ADRSC_SIZE);
296
0
            SHA256_Update(ctx, sk, n);
297
0
            sha256_final(ctx, sk, n);
298
0
        }
299
0
        memcpy(pk_out, sk, n);
300
0
        pk_out += n;
301
0
    }
302
0
    ret = 1;
303
0
    OPENSSL_cleanse(sk, sizeof(sk));
304
0
    return ret;
305
0
}
306
307
int slh_wots_pk_gen_shake(SLH_DSA_HASH_CTX *hctx,
308
    const uint8_t *sk_seed, const uint8_t *pk_seed,
309
    uint8_t *adrs, uint8_t *pk_out, size_t pk_out_len)
310
0
{
311
0
    int ret = 0;
312
0
    size_t n = hctx->key->params->n;
313
0
    size_t i, j = 0, len = SLH_WOTS_LEN(n);
314
0
    uint8_t sk[SLH_MAX_N];
315
0
    const SLH_ADRS_FUNC *adrsf = hctx->key->adrs_func;
316
0
    SLH_ADRS_DECLARE(sk_adrs);
317
0
    SLH_ADRS_FN_DECLARE(adrsf, set_chain_address);
318
0
    SLH_ADRS_FN_DECLARE(adrsf, set_hash_address);
319
0
    KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->shactx_pkseed);
320
0
    KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)(hctx->scratch);
321
322
0
    adrsf->copy(sk_adrs, adrs);
323
0
    adrsf->set_type_and_clear(sk_adrs, SLH_ADRS_TYPE_WOTS_PRF);
324
0
    adrsf->copy_keypair_address(sk_adrs, adrs);
325
326
0
    for (i = 0; i < len; ++i) { /* len = 2n + 3 */
327
0
        set_chain_address(sk_adrs, (uint32_t)i);
328
329
        /* PRF */
330
0
        *ctx = *sctx;
331
0
        ossl_sha3_absorb(ctx, sk_adrs, SLH_ADRS_SIZE);
332
0
        ossl_sha3_absorb(ctx, sk_seed, n);
333
0
        ossl_sha3_squeeze(ctx, sk, n);
334
335
0
        set_chain_address(adrs, (uint32_t)i);
336
0
        for (j = 0; j < NIBBLE_MASK; ++j) {
337
0
            set_hash_address(adrs, (uint32_t)j);
338
            /* F */
339
0
            *ctx = *sctx;
340
0
            ossl_sha3_absorb(ctx, adrs, SLH_ADRS_SIZE);
341
0
            ossl_sha3_absorb(ctx, sk, n);
342
0
            ossl_sha3_squeeze(ctx, sk, n);
343
0
        }
344
0
        memcpy(pk_out, sk, n);
345
0
        pk_out += n;
346
0
    }
347
0
    ret = 1;
348
0
    OPENSSL_cleanse(sk, sizeof(sk));
349
0
    return ret;
350
0
}
351
352
static int
353
slh_f_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
354
    const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
355
0
{
356
0
    SHA256_CTX *sctx = (SHA256_CTX *)(hctx->scratch);
357
358
0
    *sctx = *((SHA256_CTX *)hctx->shactx_pkseed);
359
0
    SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
360
0
    SHA256_Update(sctx, m1, m1_len);
361
0
    sha256_final(sctx, out, hctx->key->params->n);
362
0
    return 1;
363
0
}
364
365
static int
366
slh_h_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
367
    const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
368
0
{
369
0
    SHA256_CTX *sctx = (SHA256_CTX *)(hctx->scratch);
370
0
    const SLH_DSA_PARAMS *prms = hctx->key->params;
371
0
    size_t n = prms->n;
372
373
0
    *sctx = *((SHA256_CTX *)hctx->shactx_pkseed);
374
0
    SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
375
0
    SHA256_Update(sctx, m1, n);
376
0
    SHA256_Update(sctx, m2, n);
377
0
    sha256_final(sctx, out, n);
378
0
    return 1;
379
0
}
380
381
static int
382
slh_h_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
383
    const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
384
0
{
385
0
    SHA512_CTX *sctx = (SHA512_CTX *)(hctx->scratch);
386
0
    const SLH_DSA_PARAMS *prms = hctx->key->params;
387
0
    size_t n = prms->n;
388
389
0
    SHA512_Init(sctx);
390
0
    SHA512_Update(sctx, pk_seed, n);
391
0
    SHA512_Update(sctx, zeros, 128 - n);
392
0
    SHA512_Update(sctx, adrs, SLH_ADRSC_SIZE);
393
0
    SHA512_Update(sctx, m1, n);
394
0
    SHA512_Update(sctx, m2, n);
395
0
    sha512_final(sctx, out, n);
396
0
    return 1;
397
0
}
398
399
static int
400
slh_t_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
401
    const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
402
0
{
403
0
    SHA256_CTX *sctx = (SHA256_CTX *)(hctx->scratch);
404
405
0
    *sctx = *((SHA256_CTX *)hctx->shactx_pkseed);
406
0
    SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
407
0
    SHA256_Update(sctx, ml, ml_len);
408
0
    sha256_final(sctx, out, hctx->key->params->n);
409
0
    return 1;
410
0
}
411
412
static int
413
slh_t_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
414
    const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
415
0
{
416
0
    SHA512_CTX *sctx = (SHA512_CTX *)(hctx->scratch);
417
0
    const SLH_DSA_PARAMS *prms = hctx->key->params;
418
0
    size_t n = prms->n;
419
420
0
    SHA512_Init(sctx);
421
0
    SHA512_Update(sctx, pk_seed, n);
422
0
    SHA512_Update(sctx, zeros, 128 - n);
423
0
    SHA512_Update(sctx, adrs, SLH_ADRSC_SIZE);
424
0
    SHA512_Update(sctx, ml, ml_len);
425
0
    sha512_final(sctx, out, hctx->key->params->n);
426
0
    return 1;
427
0
}
428
429
static int slh_hash_shake_precache(SLH_DSA_HASH_CTX *hctx, const uint8_t *pkseed, size_t n)
430
0
{
431
0
    KECCAK1600_CTX *ctx = NULL, *seedctx = NULL, *scratch = NULL;
432
433
0
    ctx = ossl_shake256_new();
434
0
    if (ctx == NULL)
435
0
        return 0;
436
0
    seedctx = OPENSSL_memdup(ctx, sizeof(*ctx));
437
0
    scratch = OPENSSL_malloc(sizeof(*scratch));
438
0
    if (seedctx == NULL || scratch == NULL) {
439
0
        OPENSSL_free(ctx);
440
0
        OPENSSL_free(seedctx);
441
0
        OPENSSL_free(scratch);
442
0
        return 0;
443
0
    }
444
0
    ossl_sha3_absorb(seedctx, pkseed, n);
445
0
    hctx->shactx = (void *)ctx;
446
0
    hctx->shactx_pkseed = (void *)seedctx;
447
0
    hctx->shactx_len = sizeof(*ctx);
448
0
    hctx->scratch = (void *)scratch;
449
0
    hctx->scratch_len = sizeof(*scratch);
450
0
    return 1;
451
0
}
452
453
static int slh_hash_shake_dup(SLH_DSA_HASH_CTX *dst, const SLH_DSA_HASH_CTX *src)
454
0
{
455
0
    if (src->shactx != NULL) {
456
0
        dst->shactx = OPENSSL_memdup(src->shactx, sizeof(KECCAK1600_CTX));
457
0
        if (dst->shactx == NULL)
458
0
            return 0;
459
0
    }
460
0
    if (src->shactx_pkseed != NULL) {
461
0
        dst->shactx_pkseed = OPENSSL_memdup(src->shactx_pkseed, sizeof(KECCAK1600_CTX));
462
0
        if (dst->shactx_pkseed == NULL) {
463
0
            OPENSSL_free(dst->shactx);
464
0
            dst->shactx = NULL;
465
0
            return 0;
466
0
        }
467
0
    }
468
0
    dst->shactx_len = src->shactx_len;
469
    /* A prehashed context needs a scratch context, its content is transient */
470
0
    if (dst->shactx_pkseed != NULL) {
471
0
        dst->scratch = OPENSSL_malloc(sizeof(KECCAK1600_CTX));
472
0
        if (dst->scratch == NULL)
473
0
            return 0;
474
0
        dst->scratch_len = sizeof(KECCAK1600_CTX);
475
0
    } else {
476
0
        dst->scratch = NULL;
477
0
        dst->scratch_len = 0;
478
0
    }
479
0
    return 1;
480
0
}
481
482
static int slh_hash_sha256_precache(SLH_DSA_HASH_CTX *hctx, const uint8_t *pkseed, size_t n)
483
0
{
484
0
    SHA256_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
485
    /* The scratch context is also used as a SHA512_CTX by category 3 and 5 */
486
0
    size_t scratch_len = sizeof(SHA512_CTX);
487
488
0
    if (ctx == NULL)
489
0
        return 0;
490
0
    if ((hctx->scratch = OPENSSL_malloc(scratch_len)) == NULL) {
491
0
        OPENSSL_free(ctx);
492
0
        return 0;
493
0
    }
494
0
    hctx->scratch_len = scratch_len;
495
0
    SHA256_Init(ctx);
496
0
    SHA256_Update(ctx, pkseed, n);
497
0
    SHA256_Update(ctx, zeros, 64 - n);
498
0
    hctx->shactx_pkseed = (void *)ctx;
499
0
    hctx->shactx_len = sizeof(*ctx);
500
0
    return 1;
501
0
}
502
503
static int slh_hash_sha256_dup(SLH_DSA_HASH_CTX *dst, const SLH_DSA_HASH_CTX *src)
504
0
{
505
0
    if (src->shactx_pkseed != NULL) {
506
0
        dst->shactx_pkseed = OPENSSL_memdup(src->shactx_pkseed, sizeof(SHA256_CTX));
507
0
        if (dst->shactx_pkseed == NULL)
508
0
            return 0;
509
0
    }
510
    /*
511
     * A prehashed context needs a scratch context, its content is transient.
512
     * As in slh_hash_sha256_precache() the scratch context is sized to also
513
     * serve as a SHA512_CTX for security categories 3 and 5.
514
     */
515
0
    dst->shactx_len = src->shactx_len;
516
0
    if (dst->shactx_pkseed != NULL) {
517
0
        dst->scratch = OPENSSL_malloc(sizeof(SHA512_CTX));
518
0
        if (dst->scratch == NULL)
519
0
            return 0;
520
0
        dst->scratch_len = sizeof(SHA512_CTX);
521
0
    } else {
522
0
        dst->scratch = NULL;
523
0
        dst->scratch_len = 0;
524
0
    }
525
0
    return 1;
526
0
}
527
528
const SLH_HASH_FUNC *ossl_slh_get_hash_fn(int is_shake, int security_category)
529
0
{
530
0
    static const SLH_HASH_FUNC methods[] = {
531
0
        { slh_hash_shake_precache,
532
0
            slh_hash_shake_dup,
533
0
            slh_hmsg_shake,
534
0
            slh_prf_shake,
535
0
            slh_prf_msg_shake,
536
0
            slh_f_shake,
537
0
            slh_h_shake,
538
0
            slh_f_shake,
539
0
            slh_wots_pk_gen_shake },
540
0
        { slh_hash_sha256_precache,
541
0
            slh_hash_sha256_dup,
542
0
            slh_hmsg_sha256,
543
0
            slh_prf_sha256,
544
0
            slh_prf_msg_sha2,
545
0
            slh_f_sha256,
546
0
            slh_h_sha256,
547
0
            slh_t_sha256,
548
0
            slh_wots_pk_gen_sha2 },
549
0
        { slh_hash_sha256_precache,
550
0
            slh_hash_sha256_dup,
551
0
            slh_hmsg_sha512,
552
0
            slh_prf_sha256,
553
0
            slh_prf_msg_sha2,
554
0
            slh_f_sha256,
555
0
            slh_h_sha512,
556
0
            slh_t_sha512,
557
0
            slh_wots_pk_gen_sha2 }
558
0
    };
559
0
    return &methods[is_shake ? 0 : (security_category == 1 ? 1 : 2)];
560
0
}