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