/src/openssh/libcrux-mlkem-mldsa.c
Line | Count | Source |
1 | | /* $OpenBSD: libcrux-mlkem-mldsa.c,v 1.1 2026/06/14 03:59:34 djm Exp $ */ |
2 | | /* |
3 | | * Copyright (c) 2026 Damien Miller <djm@mindrot.org> |
4 | | * |
5 | | * Permission to use, copy, modify, and distribute this software for any |
6 | | * purpose with or without fee is hereby granted, provided that the above |
7 | | * copyright notice and this permission notice appear in all copies. |
8 | | * |
9 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
12 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | | */ |
17 | | |
18 | | #include "includes.h" |
19 | | |
20 | | #if defined(USE_MLDSA) || defined(USE_MLKEM768X25519) |
21 | | |
22 | | #include <sys/types.h> |
23 | | #include <stdint.h> |
24 | | #include <stdlib.h> |
25 | | #include <stdbool.h> |
26 | | #include <string.h> |
27 | | |
28 | | #include "log.h" |
29 | | #include "crypto_api.h" |
30 | | #include "libcrux_internal.h" |
31 | | |
32 | | /* ML-KEM 768 */ |
33 | | |
34 | | int |
35 | | crypto_kem_mlkem768_keypair(uint8_t pk[crypto_kem_mlkem768_PUBLICKEYBYTES], |
36 | | uint8_t sk[crypto_kem_mlkem768_SECRETKEYBYTES]) |
37 | 0 | { |
38 | 0 | uint8_t rnd[crypto_kem_mlkem768_KEYPAIRSEEDBYTES]; |
39 | 0 | int r; |
40 | |
|
41 | 0 | arc4random_buf(rnd, sizeof(rnd)); |
42 | 0 | r = crypto_kem_mlkem768_keypair_seeded(pk, sk, rnd); |
43 | 0 | explicit_bzero(rnd, sizeof(rnd)); |
44 | 0 | return r; |
45 | 0 | } |
46 | | |
47 | | int |
48 | | crypto_kem_mlkem768_keypair_seeded(uint8_t pk[crypto_kem_mlkem768_PUBLICKEYBYTES], |
49 | | uint8_t sk[crypto_kem_mlkem768_SECRETKEYBYTES], |
50 | | const uint8_t seed[crypto_kem_mlkem768_KEYPAIRSEEDBYTES]) |
51 | 0 | { |
52 | 0 | libcrux_mlkem768_keypair keypair; |
53 | 0 | libcrux_mlkem768_keypair_rnd rnd; |
54 | |
|
55 | 0 | memcpy(rnd.data, seed, sizeof(rnd.data)); |
56 | 0 | keypair = libcrux_ml_kem_mlkem768_portable_generate_key_pair(rnd); |
57 | 0 | memcpy(pk, keypair.pk.data, crypto_kem_mlkem768_PUBLICKEYBYTES); |
58 | 0 | memcpy(sk, keypair.sk.data, crypto_kem_mlkem768_SECRETKEYBYTES); |
59 | |
|
60 | 0 | explicit_bzero(&keypair, sizeof(keypair)); |
61 | 0 | explicit_bzero(&rnd, sizeof(rnd)); |
62 | 0 | return 0; |
63 | 0 | } |
64 | | |
65 | | int |
66 | | crypto_kem_mlkem768_enc(uint8_t ct[crypto_kem_mlkem768_CIPHERTEXTBYTES], |
67 | | uint8_t shared_secret[crypto_kem_mlkem768_BYTES], |
68 | | const uint8_t pk[crypto_kem_mlkem768_PUBLICKEYBYTES]) |
69 | 0 | { |
70 | 0 | uint8_t rnd[crypto_kem_mlkem768_ENCSEEDBYTES]; |
71 | 0 | int r; |
72 | |
|
73 | 0 | arc4random_buf(rnd, sizeof(rnd)); |
74 | 0 | r = crypto_kem_mlkem768_enc_seeded(ct, shared_secret, pk, rnd); |
75 | 0 | explicit_bzero(rnd, sizeof(rnd)); |
76 | 0 | return r; |
77 | 0 | } |
78 | | |
79 | | int |
80 | | crypto_kem_mlkem768_enc_seeded(uint8_t ct[crypto_kem_mlkem768_CIPHERTEXTBYTES], |
81 | | uint8_t shared_secret[crypto_kem_mlkem768_BYTES], |
82 | | const uint8_t pk[crypto_kem_mlkem768_PUBLICKEYBYTES], |
83 | | const uint8_t seed[crypto_kem_mlkem768_ENCSEEDBYTES]) |
84 | 0 | { |
85 | 0 | libcrux_mlkem768_enc_result enc; |
86 | 0 | libcrux_mlkem768_pk pk_internal; |
87 | 0 | libcrux_mlkem768_enc_rnd rnd; |
88 | |
|
89 | 0 | memcpy(pk_internal.data, pk, crypto_kem_mlkem768_PUBLICKEYBYTES); |
90 | 0 | if (!libcrux_ml_kem_mlkem768_portable_validate_public_key(&pk_internal)) |
91 | 0 | return -1; |
92 | 0 | memcpy(rnd.data, seed, sizeof(rnd.data)); |
93 | 0 | enc = libcrux_ml_kem_mlkem768_portable_encapsulate(&pk_internal, rnd); |
94 | 0 | memcpy(ct, enc.fst.data, crypto_kem_mlkem768_CIPHERTEXTBYTES); |
95 | 0 | memcpy(shared_secret, enc.snd.data, crypto_kem_mlkem768_BYTES); |
96 | |
|
97 | 0 | explicit_bzero(&enc, sizeof(enc)); |
98 | 0 | explicit_bzero(&rnd, sizeof(rnd)); |
99 | 0 | return 0; |
100 | 0 | } |
101 | | |
102 | | int |
103 | | crypto_kem_mlkem768_dec(uint8_t shared_secret[crypto_kem_mlkem768_BYTES], |
104 | | const uint8_t ct[crypto_kem_mlkem768_CIPHERTEXTBYTES], |
105 | | const uint8_t sk[crypto_kem_mlkem768_SECRETKEYBYTES]) |
106 | 0 | { |
107 | 0 | libcrux_mlkem768_sk sk_internal; |
108 | 0 | libcrux_mlkem768_ciphertext ct_internal; |
109 | 0 | libcrux_mlkem768_dec_result shared_secret_internal; |
110 | |
|
111 | 0 | memcpy(sk_internal.data, sk, crypto_kem_mlkem768_SECRETKEYBYTES); |
112 | 0 | memcpy(ct_internal.data, ct, crypto_kem_mlkem768_CIPHERTEXTBYTES); |
113 | 0 | shared_secret_internal = libcrux_ml_kem_mlkem768_portable_decapsulate( |
114 | 0 | &sk_internal, &ct_internal); |
115 | 0 | memcpy(shared_secret, shared_secret_internal.data, |
116 | 0 | crypto_kem_mlkem768_BYTES); |
117 | |
|
118 | 0 | explicit_bzero(&sk_internal, sizeof(sk_internal)); |
119 | 0 | explicit_bzero(&shared_secret_internal, sizeof(shared_secret_internal)); |
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | | /* ML-DSA 44 */ |
124 | | |
125 | | int |
126 | | crypto_sign_mldsa44_keypair(uint8_t pk[MLDSA44_PUBLICKEYBYTES], |
127 | | uint8_t sk[MLDSA44_SECRETKEYBYTES]) |
128 | 0 | { |
129 | 0 | uint8_t rnd[MLDSA44_SEEDBYTES]; |
130 | 0 | int r; |
131 | |
|
132 | 0 | arc4random_buf(rnd, sizeof(rnd)); |
133 | 0 | r = crypto_sign_mldsa44_keypair_seeded(pk, sk, rnd); |
134 | 0 | explicit_bzero(rnd, sizeof(rnd)); |
135 | 0 | return r; |
136 | 0 | } |
137 | | |
138 | | int |
139 | | crypto_sign_mldsa44_keypair_seeded(uint8_t pk[MLDSA44_PUBLICKEYBYTES], |
140 | | uint8_t sk[MLDSA44_SECRETKEYBYTES], const uint8_t seed[MLDSA44_SEEDBYTES]) |
141 | 0 | { |
142 | 0 | libcrux_mldsa44_keypair_rnd rnd; |
143 | 0 | libcrux_mldsa44_keypair keypair; |
144 | |
|
145 | 0 | memcpy(rnd.data, seed, sizeof(rnd.data)); |
146 | 0 | keypair = libcrux_ml_dsa_ml_dsa_44_portable_generate_key_pair(rnd); |
147 | 0 | memcpy(pk, keypair.verification_key.data, MLDSA44_PUBLICKEYBYTES); |
148 | 0 | memcpy(sk, keypair.signing_key.data, MLDSA44_SECRETKEYBYTES); |
149 | |
|
150 | 0 | explicit_bzero(&keypair, sizeof(keypair)); |
151 | 0 | explicit_bzero(&rnd, sizeof(rnd)); |
152 | 0 | return 0; |
153 | 0 | } |
154 | | |
155 | | int |
156 | | crypto_sign_mldsa44(uint8_t sig[MLDSA44_SIGBYTES], |
157 | | const uint8_t *msg, size_t msglen, |
158 | | const uint8_t *ctx, size_t ctxlen, |
159 | | const uint8_t sk[MLDSA44_SECRETKEYBYTES]) |
160 | 0 | { |
161 | 0 | uint8_t rnd[MLDSA44_SEEDBYTES]; |
162 | 0 | int r; |
163 | |
|
164 | 0 | arc4random_buf(rnd, sizeof(rnd)); |
165 | 0 | r = crypto_sign_mldsa44_seeded(sig, msg, msglen, ctx, ctxlen, sk, rnd); |
166 | 0 | explicit_bzero(rnd, sizeof(rnd)); |
167 | 0 | return r; |
168 | 0 | } |
169 | | |
170 | | int |
171 | | crypto_sign_mldsa44_seeded(uint8_t sig[MLDSA44_SIGBYTES], |
172 | | const uint8_t *msg, size_t msglen, |
173 | | const uint8_t *ctx, size_t ctxlen, |
174 | | const uint8_t sk[MLDSA44_SECRETKEYBYTES], |
175 | | const uint8_t seed[MLDSA44_SEEDBYTES]) |
176 | 0 | { |
177 | 0 | libcrux_mldsa44_sign_rnd rnd; |
178 | 0 | libcrux_mldsa44_sk sk_internal; |
179 | 0 | libcrux_mldsa44_message message = { msg, msglen }; |
180 | 0 | libcrux_mldsa44_message context = { ctx, ctxlen }; |
181 | 0 | libcrux_mldsa44_sign_result res; |
182 | 0 | int r = -1; |
183 | |
|
184 | 0 | memcpy(sk_internal.data, sk, MLDSA44_SECRETKEYBYTES); |
185 | 0 | memcpy(rnd.data, seed, sizeof(rnd.data)); |
186 | 0 | res = libcrux_ml_dsa_ml_dsa_44_portable_sign(&sk_internal, |
187 | 0 | message, context, rnd); |
188 | 0 | if (res.tag == LIBCRUX_RESULT_OK) { |
189 | 0 | memcpy(sig, res.val.case_Ok.data, MLDSA44_SIGBYTES); |
190 | 0 | r = 0; |
191 | 0 | } |
192 | |
|
193 | 0 | explicit_bzero(&sk_internal, sizeof(sk_internal)); |
194 | 0 | explicit_bzero(&res, sizeof(res)); |
195 | 0 | explicit_bzero(&rnd, sizeof(rnd)); |
196 | 0 | return r; |
197 | 0 | } |
198 | | |
199 | | int |
200 | | crypto_sign_mldsa44_verify(const uint8_t sig[MLDSA44_SIGBYTES], |
201 | | const uint8_t *msg, size_t msglen, |
202 | | const uint8_t *ctx, size_t ctxlen, |
203 | | const uint8_t pk[MLDSA44_PUBLICKEYBYTES]) |
204 | 0 | { |
205 | 0 | libcrux_mldsa44_pk pk_internal; |
206 | 0 | libcrux_mldsa44_signature sig_internal; |
207 | 0 | libcrux_mldsa44_message message = { msg, msglen }; |
208 | 0 | libcrux_mldsa44_message context = { ctx, ctxlen }; |
209 | 0 | libcrux_mldsa44_verify_result res; |
210 | |
|
211 | 0 | memcpy(pk_internal.data, pk, MLDSA44_PUBLICKEYBYTES); |
212 | 0 | memcpy(sig_internal.data, sig, MLDSA44_SIGBYTES); |
213 | 0 | res = libcrux_ml_dsa_ml_dsa_44_portable_verify(&pk_internal, |
214 | 0 | message, context, &sig_internal); |
215 | |
|
216 | 0 | return (res.tag == LIBCRUX_RESULT_OK) ? 0 : -1; |
217 | 0 | } |
218 | | |
219 | | /* ML-DSA 65 */ |
220 | | |
221 | | #if 0 |
222 | | int |
223 | | crypto_sign_mldsa65_keypair(uint8_t pk[MLDSA65_PUBLICKEYBYTES], |
224 | | uint8_t sk[MLDSA65_SECRETKEYBYTES]) |
225 | | { |
226 | | uint8_t rnd[MLDSA65_SEEDBYTES]; |
227 | | int r; |
228 | | |
229 | | arc4random_buf(rnd, sizeof(rnd)); |
230 | | r = crypto_sign_mldsa65_keypair_seeded(pk, sk, rnd); |
231 | | explicit_bzero(rnd, sizeof(rnd)); |
232 | | return r; |
233 | | } |
234 | | |
235 | | int |
236 | | crypto_sign_mldsa65_keypair_seeded(uint8_t pk[MLDSA65_PUBLICKEYBYTES], |
237 | | uint8_t sk[MLDSA65_SECRETKEYBYTES], const uint8_t seed[MLDSA65_SEEDBYTES]) |
238 | | { |
239 | | libcrux_mldsa65_keypair_rnd rnd; |
240 | | libcrux_mldsa65_keypair keypair; |
241 | | |
242 | | memcpy(rnd.data, seed, sizeof(rnd.data)); |
243 | | keypair = libcrux_ml_dsa_ml_dsa_65_portable_generate_key_pair(rnd); |
244 | | memcpy(pk, keypair.verification_key.data, MLDSA65_PUBLICKEYBYTES); |
245 | | memcpy(sk, keypair.signing_key.data, MLDSA65_SECRETKEYBYTES); |
246 | | |
247 | | explicit_bzero(&keypair, sizeof(keypair)); |
248 | | explicit_bzero(&rnd, sizeof(rnd)); |
249 | | return 0; |
250 | | } |
251 | | |
252 | | int |
253 | | crypto_sign_mldsa65(uint8_t sig[MLDSA65_SIGBYTES], |
254 | | const uint8_t *msg, size_t msglen, |
255 | | const uint8_t *ctx, size_t ctxlen, |
256 | | const uint8_t sk[MLDSA65_SECRETKEYBYTES]) |
257 | | { |
258 | | uint8_t rnd[MLDSA65_SEEDBYTES]; |
259 | | int r; |
260 | | |
261 | | arc4random_buf(rnd, sizeof(rnd)); |
262 | | r = crypto_sign_mldsa65_seeded(sig, msg, msglen, ctx, ctxlen, sk, rnd); |
263 | | explicit_bzero(rnd, sizeof(rnd)); |
264 | | return r; |
265 | | } |
266 | | |
267 | | int |
268 | | crypto_sign_mldsa65_seeded(uint8_t sig[MLDSA65_SIGBYTES], |
269 | | const uint8_t *msg, size_t msglen, |
270 | | const uint8_t *ctx, size_t ctxlen, |
271 | | const uint8_t sk[MLDSA65_SECRETKEYBYTES], |
272 | | const uint8_t seed[MLDSA65_SEEDBYTES]) |
273 | | { |
274 | | libcrux_mldsa65_sign_rnd rnd; |
275 | | libcrux_mldsa65_sk sk_internal; |
276 | | libcrux_mldsa65_message message = { msg, msglen }; |
277 | | libcrux_mldsa65_message context = { ctx, ctxlen }; |
278 | | libcrux_mldsa65_sign_result res; |
279 | | int r = -1; |
280 | | |
281 | | memcpy(sk_internal.data, sk, MLDSA65_SECRETKEYBYTES); |
282 | | memcpy(rnd.data, seed, sizeof(rnd.data)); |
283 | | res = libcrux_ml_dsa_ml_dsa_65_portable_sign(&sk_internal, |
284 | | message, context, rnd); |
285 | | if (res.tag == LIBCRUX_RESULT_OK) { |
286 | | memcpy(sig, res.val.case_Ok.data, MLDSA65_SIGBYTES); |
287 | | r = 0; |
288 | | } |
289 | | |
290 | | explicit_bzero(&sk_internal, sizeof(sk_internal)); |
291 | | explicit_bzero(&res, sizeof(res)); |
292 | | explicit_bzero(&rnd, sizeof(rnd)); |
293 | | return r; |
294 | | } |
295 | | |
296 | | int |
297 | | crypto_sign_mldsa65_verify(const uint8_t sig[MLDSA65_SIGBYTES], |
298 | | const uint8_t *msg, size_t msglen, |
299 | | const uint8_t *ctx, size_t ctxlen, |
300 | | const uint8_t pk[MLDSA65_PUBLICKEYBYTES]) |
301 | | { |
302 | | libcrux_mldsa65_pk pk_internal; |
303 | | libcrux_mldsa65_signature sig_internal; |
304 | | libcrux_mldsa65_message message = { msg, msglen }; |
305 | | libcrux_mldsa65_message context = { ctx, ctxlen }; |
306 | | libcrux_mldsa65_verify_result res; |
307 | | |
308 | | memcpy(pk_internal.data, pk, MLDSA65_PUBLICKEYBYTES); |
309 | | memcpy(sig_internal.data, sig, MLDSA65_SIGBYTES); |
310 | | res = libcrux_ml_dsa_ml_dsa_65_portable_verify(&pk_internal, |
311 | | message, context, &sig_internal); |
312 | | |
313 | | return (res.tag == LIBCRUX_RESULT_OK) ? 0 : -1; |
314 | | } |
315 | | #endif |
316 | | |
317 | | /* ML-DSA 87 */ |
318 | | |
319 | | #if 0 |
320 | | int |
321 | | crypto_sign_mldsa87_keypair(uint8_t pk[MLDSA87_PUBLICKEYBYTES], |
322 | | uint8_t sk[MLDSA87_SECRETKEYBYTES]) |
323 | | { |
324 | | uint8_t rnd[MLDSA87_SEEDBYTES]; |
325 | | int r; |
326 | | |
327 | | arc4random_buf(rnd, sizeof(rnd)); |
328 | | r = crypto_sign_mldsa87_keypair_seeded(pk, sk, rnd); |
329 | | explicit_bzero(rnd, sizeof(rnd)); |
330 | | return r; |
331 | | } |
332 | | |
333 | | int |
334 | | crypto_sign_mldsa87_keypair_seeded(uint8_t pk[MLDSA87_PUBLICKEYBYTES], |
335 | | uint8_t sk[MLDSA87_SECRETKEYBYTES], const uint8_t seed[MLDSA87_SEEDBYTES]) |
336 | | { |
337 | | libcrux_mldsa87_keypair_rnd rnd; |
338 | | libcrux_mldsa87_keypair keypair; |
339 | | |
340 | | memcpy(rnd.data, seed, sizeof(rnd.data)); |
341 | | keypair = libcrux_ml_dsa_ml_dsa_87_portable_generate_key_pair(rnd); |
342 | | memcpy(pk, keypair.verification_key.data, MLDSA87_PUBLICKEYBYTES); |
343 | | memcpy(sk, keypair.signing_key.data, MLDSA87_SECRETKEYBYTES); |
344 | | |
345 | | explicit_bzero(&keypair, sizeof(keypair)); |
346 | | explicit_bzero(&rnd, sizeof(rnd)); |
347 | | return 0; |
348 | | } |
349 | | |
350 | | int |
351 | | crypto_sign_mldsa87(uint8_t sig[MLDSA87_SIGBYTES], |
352 | | const uint8_t *msg, size_t msglen, |
353 | | const uint8_t *ctx, size_t ctxlen, |
354 | | const uint8_t sk[MLDSA87_SECRETKEYBYTES]) |
355 | | { |
356 | | uint8_t rnd[MLDSA87_SEEDBYTES]; |
357 | | int r; |
358 | | |
359 | | arc4random_buf(rnd, sizeof(rnd)); |
360 | | r = crypto_sign_mldsa87_seeded(sig, msg, msglen, ctx, ctxlen, sk, rnd); |
361 | | explicit_bzero(rnd, sizeof(rnd)); |
362 | | return r; |
363 | | } |
364 | | |
365 | | int |
366 | | crypto_sign_mldsa87_seeded(uint8_t sig[MLDSA87_SIGBYTES], |
367 | | const uint8_t *msg, size_t msglen, |
368 | | const uint8_t *ctx, size_t ctxlen, |
369 | | const uint8_t sk[MLDSA87_SECRETKEYBYTES], |
370 | | const uint8_t seed[MLDSA87_SEEDBYTES]) |
371 | | { |
372 | | libcrux_mldsa87_sign_rnd rnd; |
373 | | libcrux_mldsa87_sk sk_internal; |
374 | | libcrux_mldsa87_message message = { msg, msglen }; |
375 | | libcrux_mldsa87_message context = { ctx, ctxlen }; |
376 | | libcrux_mldsa87_sign_result res; |
377 | | int r = -1; |
378 | | |
379 | | memcpy(sk_internal.data, sk, MLDSA87_SECRETKEYBYTES); |
380 | | memcpy(rnd.data, seed, sizeof(rnd.data)); |
381 | | res = libcrux_ml_dsa_ml_dsa_87_portable_sign(&sk_internal, |
382 | | message, context, rnd); |
383 | | if (res.tag == LIBCRUX_RESULT_OK) { |
384 | | memcpy(sig, res.val.case_Ok.data, MLDSA87_SIGBYTES); |
385 | | r = 0; |
386 | | } |
387 | | |
388 | | explicit_bzero(&sk_internal, sizeof(sk_internal)); |
389 | | explicit_bzero(&res, sizeof(res)); |
390 | | explicit_bzero(&rnd, sizeof(rnd)); |
391 | | return r; |
392 | | } |
393 | | |
394 | | int |
395 | | crypto_sign_mldsa87_verify(const uint8_t sig[MLDSA87_SIGBYTES], |
396 | | const uint8_t *msg, size_t msglen, |
397 | | const uint8_t *ctx, size_t ctxlen, |
398 | | const uint8_t pk[MLDSA87_PUBLICKEYBYTES]) |
399 | | { |
400 | | libcrux_mldsa87_pk pk_internal; |
401 | | libcrux_mldsa87_signature sig_internal; |
402 | | libcrux_mldsa87_message message = { msg, msglen }; |
403 | | libcrux_mldsa87_message context = { ctx, ctxlen }; |
404 | | libcrux_mldsa87_verify_result res; |
405 | | |
406 | | memcpy(pk_internal.data, pk, MLDSA87_PUBLICKEYBYTES); |
407 | | memcpy(sig_internal.data, sig, MLDSA87_SIGBYTES); |
408 | | res = libcrux_ml_dsa_ml_dsa_87_portable_verify(&pk_internal, |
409 | | message, context, &sig_internal); |
410 | | |
411 | | return (res.tag == LIBCRUX_RESULT_OK) ? 0 : -1; |
412 | | } |
413 | | #endif |
414 | | |
415 | | void |
416 | | sha3_256(uint8_t digest[32], const uint8_t *data, size_t len) |
417 | 0 | { |
418 | 0 | Eurydice_borrow_slice_u8 input = { data, len }; |
419 | 0 | Eurydice_mut_borrow_slice_u8 output = { digest, 32 }; |
420 | 0 | libcrux_sha3_portable_sha256(output, input); |
421 | 0 | } |
422 | | |
423 | | void |
424 | | sha3_512(uint8_t digest[64], const uint8_t *data, size_t len) |
425 | 0 | { |
426 | 0 | Eurydice_borrow_slice_u8 input = { data, len }; |
427 | 0 | Eurydice_mut_borrow_slice_u8 output = { digest, 64 }; |
428 | 0 | libcrux_sha3_portable_sha512(output, input); |
429 | 0 | } |
430 | | #endif /* defined(USE_MLDSA) || defined(USE_MLKEM768X25519) */ |