/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 | } |