Coverage Report

Created: 2026-02-22 06:11

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-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 "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_final(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
    unsigned char out[SLH_MAX_N];
86
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
87
0
    size_t n = params->n;
88
0
    KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->shactx);
89
90
0
    ossl_sha3_reset(sctx);
91
0
    ossl_sha3_absorb(sctx, sk_prf, n);
92
0
    ossl_sha3_absorb(sctx, opt_rand, n);
93
0
    ossl_sha3_absorb(sctx, msg, msg_len);
94
0
    ossl_sha3_final(sctx, out, n);
95
0
    return WPACKET_memcpy(pkt, out, n);
96
0
}
97
98
static int
99
slh_f_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
100
    const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
101
0
{
102
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
103
0
    size_t n = params->n;
104
0
    KECCAK1600_CTX sctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed));
105
106
0
    ossl_sha3_absorb(&sctx, adrs, SLH_ADRS_SIZE);
107
0
    ossl_sha3_absorb(&sctx, m1, m1_len);
108
0
    ossl_sha3_final(&sctx, out, n);
109
0
    return 1;
110
0
}
111
112
static int
113
slh_prf_shake(SLH_DSA_HASH_CTX *hctx,
114
    const uint8_t *pk_seed, const uint8_t *sk_seed,
115
    const uint8_t *adrs, uint8_t *out, size_t out_len)
116
0
{
117
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
118
0
    size_t n = params->n;
119
0
    KECCAK1600_CTX sctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed));
120
121
0
    ossl_sha3_absorb(&sctx, adrs, SLH_ADRS_SIZE);
122
0
    ossl_sha3_absorb(&sctx, sk_seed, n);
123
0
    ossl_sha3_final(&sctx, out, n);
124
0
    return 1;
125
0
}
126
127
static int
128
slh_h_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
129
    const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
130
0
{
131
0
    KECCAK1600_CTX ctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed)), *sctx = &ctx;
132
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
133
0
    size_t n = params->n;
134
135
0
    ossl_sha3_absorb(sctx, adrs, SLH_ADRS_SIZE);
136
0
    ossl_sha3_absorb(sctx, m1, n);
137
0
    ossl_sha3_absorb(sctx, m2, n);
138
0
    ossl_sha3_final(sctx, out, n);
139
0
    return 1;
140
0
}
141
142
/* FIPS 205 Section 11.2.1 and 11.2.2 */
143
144
static int
145
slh_hmsg_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
146
    const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
147
    uint8_t *out, size_t out_len)
148
0
{
149
0
    SHA256_CTX ctx, *sctx = &ctx;
150
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
151
0
    size_t m = params->m;
152
0
    size_t n = params->n;
153
0
    uint8_t seed[2 * SLH_MAX_N + SHA256_DIGEST_LENGTH];
154
0
    long seed_len = SHA256_DIGEST_LENGTH + (long)(2 * n);
155
156
0
    memcpy(seed, r, n);
157
0
    memcpy(seed + n, pk_seed, n);
158
159
0
    SHA256_Init(sctx);
160
0
    SHA256_Update(sctx, r, n);
161
0
    SHA256_Update(sctx, pk_seed, n);
162
0
    SHA256_Update(sctx, pk_root, n);
163
0
    SHA256_Update(sctx, msg, msg_len);
164
0
    return SHA256_Final(seed + 2 * n, sctx)
165
0
        && (PKCS1_MGF1(out, (long)m, seed, seed_len, hctx->key->md) == 0);
166
0
}
167
168
static int
169
slh_hmsg_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
170
    const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
171
    uint8_t *out, size_t out_len)
172
0
{
173
0
    SHA512_CTX ctx, *sctx = &ctx;
174
0
    const SLH_DSA_PARAMS *params = hctx->key->params;
175
0
    size_t m = params->m;
176
0
    size_t n = params->n;
177
0
    uint8_t seed[2 * SLH_MAX_N + SHA512_DIGEST_LENGTH];
178
0
    long seed_len = SHA512_DIGEST_LENGTH + (long)(2 * n);
179
180
0
    memcpy(seed, r, n);
181
0
    memcpy(seed + n, pk_seed, n);
182
183
0
    SHA512_Init(sctx);
184
0
    SHA512_Update(sctx, r, n);
185
0
    SHA512_Update(sctx, pk_seed, n);
186
0
    SHA512_Update(sctx, pk_root, n);
187
0
    SHA512_Update(sctx, msg, msg_len);
188
0
    return SHA512_Final(seed + 2 * n, sctx)
189
0
        && (PKCS1_MGF1(out, (long)m, seed, seed_len, hctx->key->md_sha512) == 0);
190
0
}
191
192
static int
193
slh_prf_msg_sha2(SLH_DSA_HASH_CTX *hctx,
194
    const uint8_t *sk_prf, const uint8_t *opt_rand,
195
    const uint8_t *msg, size_t msg_len, WPACKET *pkt)
196
0
{
197
0
    int ret;
198
0
    const SLH_DSA_KEY *key = hctx->key;
199
0
    EVP_MAC_CTX *mctx = hctx->hmac_ctx;
200
0
    const SLH_DSA_PARAMS *prms = key->params;
201
0
    size_t n = prms->n;
202
0
    uint8_t mac[MAX_DIGEST_SIZE] = { 0 };
203
0
    OSSL_PARAM *p = NULL;
204
0
    OSSL_PARAM params[3];
205
206
    /*
207
     * Due to the way HMAC works, it is not possible to do this code early
208
     * in hmac_ctx_new() since it requires a key in order to set the digest.
209
     * So we do a lazy update here on the first call.
210
     */
211
0
    if (hctx->hmac_digest_used == 0) {
212
0
        const char *nm = EVP_MD_get0_name(key->md_sha512 == NULL ? key->md : key->md_sha512);
213
214
0
        p = params;
215
        /* The underlying digest to be used */
216
0
        *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)nm, 0);
217
0
        if (key->propq != NULL)
218
0
            *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
219
0
                (char *)key->propq, 0);
220
0
        *p = OSSL_PARAM_construct_end();
221
0
        p = params;
222
0
        hctx->hmac_digest_used = 1;
223
0
    }
224
225
0
    ret = EVP_MAC_init(mctx, sk_prf, n, p) == 1
226
0
        && EVP_MAC_update(mctx, opt_rand, n) == 1
227
0
        && EVP_MAC_update(mctx, msg, msg_len) == 1
228
0
        && EVP_MAC_final(mctx, mac, NULL, sizeof(mac)) == 1
229
0
        && WPACKET_memcpy(pkt, mac, n); /* Truncate output to n bytes */
230
0
    return ret;
231
0
}
232
233
static int
234
slh_prf_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed,
235
    const uint8_t *sk_seed, const uint8_t *adrs,
236
    uint8_t *out, size_t out_len)
237
0
{
238
0
    SHA256_CTX ctx = *((SHA256_CTX *)hctx->shactx_pkseed), *sctx = &ctx;
239
0
    size_t n = hctx->key->params->n;
240
241
0
    SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
242
0
    SHA256_Update(sctx, sk_seed, n);
243
0
    sha256_final(sctx, out, n);
244
0
    return 1;
245
0
}
246
247
static int
248
slh_wots_pk_gen_sha2(SLH_DSA_HASH_CTX *hctx,
249
    const uint8_t *sk_seed, const uint8_t *pk_seed,
250
    uint8_t *adrs, uint8_t *pk_out, size_t pk_out_len)
251
0
{
252
0
    int ret = 0;
253
0
    size_t n = hctx->key->params->n;
254
0
    size_t i, j = 0, len = SLH_WOTS_LEN(n);
255
0
    uint8_t sk[SLH_MAX_N];
256
0
    SHA256_CTX *sctx = (SHA256_CTX *)(hctx->shactx_pkseed);
257
0
    SHA256_CTX ctx;
258
0
    const SLH_ADRS_FUNC *adrsf = hctx->key->adrs_func;
259
0
    SLH_ADRS_DECLARE(sk_adrs);
260
0
    SLH_ADRS_FN_DECLARE(adrsf, set_chain_address);
261
0
    SLH_ADRS_FN_DECLARE(adrsf, set_hash_address);
262
263
0
    adrsf->copy(sk_adrs, adrs);
264
0
    adrsf->set_type_and_clear(sk_adrs, SLH_ADRS_TYPE_WOTS_PRF);
265
0
    adrsf->copy_keypair_address(sk_adrs, adrs);
266
267
0
    for (i = 0; i < len; ++i) { /* len = 2n + 3 */
268
0
        set_chain_address(sk_adrs, (uint32_t)i);
269
270
        /* PRF */
271
0
        ctx = *sctx;
272
0
        SHA256_Update(&ctx, sk_adrs, SLH_ADRSC_SIZE);
273
0
        SHA256_Update(&ctx, sk_seed, n);
274
0
        sha256_final(&ctx, sk, n);
275
276
0
        set_chain_address(adrs, (uint32_t)i);
277
0
        for (j = 0; j < NIBBLE_MASK; ++j) {
278
0
            set_hash_address(adrs, (uint32_t)j);
279
            /* F */
280
0
            ctx = *sctx;
281
0
            SHA256_Update(&ctx, adrs, SLH_ADRSC_SIZE);
282
0
            SHA256_Update(&ctx, sk, n);
283
0
            sha256_final(&ctx, sk, n);
284
0
        }
285
0
        memcpy(pk_out, sk, n);
286
0
        pk_out += n;
287
0
    }
288
0
    ret = 1;
289
0
    return ret;
290
0
}
291
292
int slh_wots_pk_gen_shake(SLH_DSA_HASH_CTX *hctx,
293
    const uint8_t *sk_seed, const uint8_t *pk_seed,
294
    uint8_t *adrs, uint8_t *pk_out, size_t pk_out_len)
295
0
{
296
0
    int ret = 0;
297
0
    size_t n = hctx->key->params->n;
298
0
    size_t i, j = 0, len = SLH_WOTS_LEN(n);
299
0
    uint8_t sk[SLH_MAX_N];
300
0
    const SLH_ADRS_FUNC *adrsf = hctx->key->adrs_func;
301
0
    SLH_ADRS_DECLARE(sk_adrs);
302
0
    SLH_ADRS_FN_DECLARE(adrsf, set_chain_address);
303
0
    SLH_ADRS_FN_DECLARE(adrsf, set_hash_address);
304
0
    KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->shactx_pkseed);
305
0
    KECCAK1600_CTX ctx;
306
307
0
    adrsf->copy(sk_adrs, adrs);
308
0
    adrsf->set_type_and_clear(sk_adrs, SLH_ADRS_TYPE_WOTS_PRF);
309
0
    adrsf->copy_keypair_address(sk_adrs, adrs);
310
311
0
    for (i = 0; i < len; ++i) { /* len = 2n + 3 */
312
0
        set_chain_address(sk_adrs, (uint32_t)i);
313
314
        /* PRF */
315
0
        ctx = *sctx;
316
0
        ossl_sha3_absorb(&ctx, sk_adrs, SLH_ADRS_SIZE);
317
0
        ossl_sha3_absorb(&ctx, sk_seed, n);
318
0
        ossl_sha3_final(&ctx, sk, n);
319
320
0
        set_chain_address(adrs, (uint32_t)i);
321
0
        for (j = 0; j < NIBBLE_MASK; ++j) {
322
0
            set_hash_address(adrs, (uint32_t)j);
323
            /* F */
324
0
            ctx = *sctx;
325
0
            ossl_sha3_absorb(&ctx, adrs, SLH_ADRS_SIZE);
326
0
            ossl_sha3_absorb(&ctx, sk, n);
327
0
            ossl_sha3_final(&ctx, sk, n);
328
0
        }
329
0
        memcpy(pk_out, sk, n);
330
0
        pk_out += n;
331
0
    }
332
0
    ret = 1;
333
0
    return ret;
334
0
}
335
336
static int
337
slh_f_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
338
    const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
339
0
{
340
0
    SHA256_CTX ctx = *((SHA256_CTX *)hctx->shactx_pkseed), *sctx = &ctx;
341
342
0
    SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
343
0
    SHA256_Update(sctx, m1, m1_len);
344
0
    sha256_final(sctx, out, hctx->key->params->n);
345
0
    return 1;
346
0
}
347
348
static int
349
slh_h_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
350
    const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
351
0
{
352
0
    SHA256_CTX ctx = *((SHA256_CTX *)hctx->shactx_pkseed), *sctx = &ctx;
353
0
    const SLH_DSA_PARAMS *prms = hctx->key->params;
354
0
    size_t n = prms->n;
355
356
0
    SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
357
0
    SHA256_Update(sctx, m1, n);
358
0
    SHA256_Update(sctx, m2, n);
359
0
    sha256_final(sctx, out, n);
360
0
    return 1;
361
0
}
362
363
static int
364
slh_h_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
365
    const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
366
0
{
367
0
    SHA512_CTX ctx, *sctx = &ctx;
368
0
    const SLH_DSA_PARAMS *prms = hctx->key->params;
369
0
    size_t n = prms->n;
370
371
0
    SHA512_Init(sctx);
372
0
    SHA512_Update(sctx, pk_seed, n);
373
0
    SHA512_Update(sctx, zeros, 128 - n);
374
0
    SHA512_Update(sctx, adrs, SLH_ADRSC_SIZE);
375
0
    SHA512_Update(sctx, m1, n);
376
0
    SHA512_Update(sctx, m2, n);
377
0
    sha512_final(sctx, out, n);
378
0
    return 1;
379
0
}
380
381
static int
382
slh_t_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
383
    const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
384
0
{
385
0
    SHA256_CTX ctx = *((SHA256_CTX *)hctx->shactx_pkseed), *sctx = &ctx;
386
387
0
    SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
388
0
    SHA256_Update(sctx, ml, ml_len);
389
0
    sha256_final(sctx, out, hctx->key->params->n);
390
0
    return 1;
391
0
}
392
393
static int
394
slh_t_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
395
    const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
396
0
{
397
0
    SHA512_CTX ctx, *sctx = &ctx;
398
0
    const SLH_DSA_PARAMS *prms = hctx->key->params;
399
0
    size_t n = prms->n;
400
401
0
    SHA512_Init(sctx);
402
0
    SHA512_Update(sctx, pk_seed, n);
403
0
    SHA512_Update(sctx, zeros, 128 - n);
404
0
    SHA512_Update(sctx, adrs, SLH_ADRSC_SIZE);
405
0
    SHA512_Update(sctx, ml, ml_len);
406
0
    sha512_final(sctx, out, hctx->key->params->n);
407
0
    return 1;
408
0
}
409
410
static int slh_hash_shake_precache(SLH_DSA_HASH_CTX *hctx, const uint8_t *pkseed, size_t n)
411
0
{
412
0
    KECCAK1600_CTX *ctx = NULL, *seedctx = NULL;
413
414
0
    ctx = ossl_shake256_new();
415
0
    if (ctx == NULL)
416
0
        return 0;
417
0
    seedctx = OPENSSL_memdup(ctx, sizeof(*ctx));
418
0
    if (seedctx == NULL) {
419
0
        OPENSSL_free(ctx);
420
0
        return 0;
421
0
    }
422
0
    ossl_sha3_absorb(seedctx, pkseed, n);
423
0
    hctx->shactx = (void *)ctx;
424
0
    hctx->shactx_pkseed = (void *)seedctx;
425
0
    return 1;
426
0
}
427
428
static int slh_hash_shake_dup(SLH_DSA_HASH_CTX *dst, const SLH_DSA_HASH_CTX *src)
429
0
{
430
0
    if (src->shactx != NULL) {
431
0
        dst->shactx = OPENSSL_memdup(src->shactx, sizeof(KECCAK1600_CTX));
432
0
        if (dst->shactx == NULL)
433
0
            return 0;
434
0
    }
435
0
    if (src->shactx_pkseed != NULL) {
436
0
        dst->shactx_pkseed = OPENSSL_memdup(src->shactx_pkseed, sizeof(KECCAK1600_CTX));
437
0
        if (dst->shactx_pkseed == NULL) {
438
0
            OPENSSL_free(dst->shactx);
439
0
            dst->shactx = NULL;
440
0
            return 0;
441
0
        }
442
0
    }
443
0
    return 1;
444
0
}
445
446
static int slh_hash_sha256_precache(SLH_DSA_HASH_CTX *hctx, const uint8_t *pkseed, size_t n)
447
0
{
448
0
    SHA256_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
449
450
0
    if (ctx == NULL)
451
0
        return 0;
452
0
    SHA256_Init(ctx);
453
0
    SHA256_Update(ctx, pkseed, n);
454
0
    SHA256_Update(ctx, zeros, 64 - n);
455
0
    hctx->shactx_pkseed = (void *)ctx;
456
0
    return 1;
457
0
}
458
459
static int slh_hash_sha256_dup(SLH_DSA_HASH_CTX *dst, const SLH_DSA_HASH_CTX *src)
460
0
{
461
0
    if (src->shactx_pkseed != NULL) {
462
0
        dst->shactx_pkseed = OPENSSL_memdup(src->shactx_pkseed, sizeof(SHA256_CTX));
463
0
        if (dst->shactx_pkseed == NULL)
464
0
            return 0;
465
0
    }
466
0
    return 1;
467
0
}
468
469
const SLH_HASH_FUNC *ossl_slh_get_hash_fn(int is_shake, int security_category)
470
0
{
471
0
    static const SLH_HASH_FUNC methods[] = {
472
0
        { slh_hash_shake_precache,
473
0
            slh_hash_shake_dup,
474
0
            slh_hmsg_shake,
475
0
            slh_prf_shake,
476
0
            slh_prf_msg_shake,
477
0
            slh_f_shake,
478
0
            slh_h_shake,
479
0
            slh_f_shake,
480
0
            slh_wots_pk_gen_shake },
481
0
        { slh_hash_sha256_precache,
482
0
            slh_hash_sha256_dup,
483
0
            slh_hmsg_sha256,
484
0
            slh_prf_sha256,
485
0
            slh_prf_msg_sha2,
486
0
            slh_f_sha256,
487
0
            slh_h_sha256,
488
0
            slh_t_sha256,
489
0
            slh_wots_pk_gen_sha2 },
490
0
        { slh_hash_sha256_precache,
491
0
            slh_hash_sha256_dup,
492
0
            slh_hmsg_sha512,
493
0
            slh_prf_sha256,
494
0
            slh_prf_msg_sha2,
495
0
            slh_f_sha256,
496
0
            slh_h_sha512,
497
0
            slh_t_sha512,
498
0
            slh_wots_pk_gen_sha2 }
499
0
    };
500
0
    return &methods[is_shake ? 0 : (security_category == 1 ? 1 : 2)];
501
0
}