diff options
Diffstat (limited to '')
-rw-r--r-- | src/regress/lib/libcrypto/bn/bn_mul_div.c | 15 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/Makefile | 4 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c | 180 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_tests.c | 299 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c | 161 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h | 63 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_unittest.c | 302 |
7 files changed, 414 insertions, 610 deletions
diff --git a/src/regress/lib/libcrypto/bn/bn_mul_div.c b/src/regress/lib/libcrypto/bn/bn_mul_div.c index 625d5e318e..dbad01004e 100644 --- a/src/regress/lib/libcrypto/bn/bn_mul_div.c +++ b/src/regress/lib/libcrypto/bn/bn_mul_div.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_mul_div.c,v 1.7 2023/06/21 07:18:10 jsing Exp $ */ | 1 | /* $OpenBSD: bn_mul_div.c,v 1.8 2025/08/12 10:29:35 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -233,6 +233,13 @@ struct benchmark benchmarks[] = { | |||
233 | .b_bits = 256, | 233 | .b_bits = 256, |
234 | }, | 234 | }, |
235 | { | 235 | { |
236 | .desc = "BN_mul (384 bit x 384 bit)", | ||
237 | .setup = benchmark_bn_mul_setup, | ||
238 | .run_once = benchmark_bn_mul_run_once, | ||
239 | .a_bits = 384, | ||
240 | .b_bits = 384, | ||
241 | }, | ||
242 | { | ||
236 | .desc = "BN_mul (512 bit x 512 bit)", | 243 | .desc = "BN_mul (512 bit x 512 bit)", |
237 | .setup = benchmark_bn_mul_setup, | 244 | .setup = benchmark_bn_mul_setup, |
238 | .run_once = benchmark_bn_mul_run_once, | 245 | .run_once = benchmark_bn_mul_run_once, |
@@ -294,6 +301,12 @@ struct benchmark benchmarks[] = { | |||
294 | .a_bits = 256, | 301 | .a_bits = 256, |
295 | }, | 302 | }, |
296 | { | 303 | { |
304 | .desc = "BN_sqr (384 bit)", | ||
305 | .setup = benchmark_bn_sqr_setup, | ||
306 | .run_once = benchmark_bn_sqr_run_once, | ||
307 | .a_bits = 384, | ||
308 | }, | ||
309 | { | ||
297 | .desc = "BN_sqr (512 bit)", | 310 | .desc = "BN_sqr (512 bit)", |
298 | .setup = benchmark_bn_sqr_setup, | 311 | .setup = benchmark_bn_sqr_setup, |
299 | .run_once = benchmark_bn_sqr_run_once, | 312 | .run_once = benchmark_bn_sqr_run_once, |
diff --git a/src/regress/lib/libcrypto/mlkem/Makefile b/src/regress/lib/libcrypto/mlkem/Makefile index a08623c90a..3acaf78e63 100644 --- a/src/regress/lib/libcrypto/mlkem/Makefile +++ b/src/regress/lib/libcrypto/mlkem/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile,v 1.9 2024/12/29 20:14:15 tb Exp $ | 1 | # $OpenBSD: Makefile,v 1.10 2025/08/15 14:46:37 tb Exp $ |
2 | 2 | ||
3 | REGRESS_SLOW_TARGETS += run-regress-mlkem_iteration_tests | 3 | REGRESS_SLOW_TARGETS += run-regress-mlkem_iteration_tests |
4 | 4 | ||
@@ -22,7 +22,7 @@ run-regress-mlkem_tests: mlkem_tests | |||
22 | ./mlkem_tests $f ${.CURDIR}/$f.txt | 22 | ./mlkem_tests $f ${.CURDIR}/$f.txt |
23 | .endfor | 23 | .endfor |
24 | 24 | ||
25 | SRCS_mlkem_tests = mlkem_tests.c mlkem_tests_util.c parse_test_file.c | 25 | SRCS_mlkem_tests = mlkem_tests.c parse_test_file.c |
26 | SRCS_mlkem_iteration_tests = mlkem_iteration_tests.c mlkem_tests_util.c | 26 | SRCS_mlkem_iteration_tests = mlkem_iteration_tests.c mlkem_tests_util.c |
27 | SRCS_mlkem_unittest = mlkem_unittest.c mlkem_tests_util.c | 27 | SRCS_mlkem_unittest = mlkem_unittest.c mlkem_tests_util.c |
28 | 28 | ||
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c index b93243023c..053f8e1222 100644 --- a/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c +++ b/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mlkem_iteration_tests.c,v 1.5 2025/05/20 00:33:41 beck Exp $ */ | 1 | /* $OpenBSD: mlkem_iteration_tests.c,v 1.8 2025/08/17 19:26:35 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024 Google Inc. | 3 | * Copyright (c) 2024 Google Inc. |
4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> | 4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> |
@@ -22,7 +22,7 @@ | |||
22 | #include <stdio.h> | 22 | #include <stdio.h> |
23 | #include <stdlib.h> | 23 | #include <stdlib.h> |
24 | 24 | ||
25 | #include "mlkem.h" | 25 | #include <openssl/mlkem.h> |
26 | 26 | ||
27 | #include "mlkem_internal.h" | 27 | #include "mlkem_internal.h" |
28 | #include "mlkem_tests_util.h" | 28 | #include "mlkem_tests_util.h" |
@@ -63,46 +63,49 @@ const uint8_t kExpectedAdam1024[32] = { | |||
63 | 0x04, 0xab, 0xdb, 0x94, 0x8b, 0x90, 0x8b, 0x75, 0xba, 0xd5 | 63 | 0x04, 0xab, 0xdb, 0x94, 0x8b, 0x90, 0x8b, 0x75, 0xba, 0xd5 |
64 | }; | 64 | }; |
65 | 65 | ||
66 | struct iteration_ctx { | ||
67 | uint8_t *encoded_public_key; | ||
68 | size_t encoded_public_key_len; | ||
69 | uint8_t *ciphertext; | ||
70 | size_t ciphertext_len; | ||
71 | uint8_t *invalid_ciphertext; | ||
72 | size_t invalid_ciphertext_len; | ||
73 | void *priv; | ||
74 | void *pub; | ||
75 | |||
76 | mlkem_marshal_private_key_fn marshal_private_key; | ||
77 | mlkem_encap_external_entropy_fn encap_external_entropy; | ||
78 | mlkem_generate_key_external_entropy_fn generate_key_external_entropy; | ||
79 | mlkem_public_from_private_fn public_from_private; | ||
80 | mlkem_decap_fn decap; | ||
81 | |||
82 | const uint8_t *start; | ||
83 | size_t start_len; | ||
84 | |||
85 | const uint8_t *expected; | ||
86 | size_t expected_len; | ||
87 | }; | ||
88 | |||
89 | static int | 66 | static int |
90 | MlkemIterativeTest(struct iteration_ctx *ctx) | 67 | MlkemIterativeTest(int rank) |
91 | { | 68 | { |
92 | uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES]; | 69 | const uint8_t *start, *expected; |
70 | size_t start_len; | ||
93 | uint8_t encap_entropy[MLKEM_ENCAP_ENTROPY]; | 71 | uint8_t encap_entropy[MLKEM_ENCAP_ENTROPY]; |
94 | uint8_t seed[MLKEM_SEED_BYTES] = {0}; | 72 | uint8_t seed[MLKEM_SEED_LENGTH] = {0}; |
73 | uint8_t *shared_secret = NULL; | ||
95 | sha3_ctx drng, results; | 74 | sha3_ctx drng, results; |
96 | uint8_t out[32]; | 75 | uint8_t out[32]; |
97 | int i; | 76 | int i; |
98 | 77 | ||
78 | start = kExpectedSeedStart; | ||
79 | start_len = sizeof(kExpectedSeedStart); | ||
80 | switch(rank){ | ||
81 | case RANK768: | ||
82 | expected = kExpectedAdam768; | ||
83 | break; | ||
84 | case RANK1024: | ||
85 | expected = kExpectedAdam1024; | ||
86 | break; | ||
87 | default: | ||
88 | errx(1, "invalid rank %d", rank); | ||
89 | } | ||
90 | |||
99 | shake128_init(&drng); | 91 | shake128_init(&drng); |
100 | shake128_init(&results); | 92 | shake128_init(&results); |
101 | 93 | ||
102 | shake_xof(&drng); | 94 | shake_xof(&drng); |
103 | for (i = 0; i < 10000; i++) { | 95 | for (i = 0; i < 10000; i++) { |
104 | uint8_t *encoded_private_key = NULL; | 96 | uint8_t *encoded_public_key = NULL, *ciphertext = NULL, |
105 | size_t encoded_private_key_len; | 97 | *encoded_private_key = NULL, *invalid_ciphertext = NULL; |
98 | size_t encoded_public_key_len, ciphertext_len, | ||
99 | encoded_private_key_len, invalid_ciphertext_len; | ||
100 | MLKEM_private_key *priv; | ||
101 | MLKEM_public_key *pub; | ||
102 | size_t s_len = 0; | ||
103 | |||
104 | /* allocate keys for this iteration */ | ||
105 | if ((priv = MLKEM_private_key_new(rank)) == NULL) | ||
106 | errx(1, "malloc"); | ||
107 | if ((pub = MLKEM_public_key_new(rank)) == NULL) | ||
108 | errx(1, "malloc"); | ||
106 | 109 | ||
107 | /* | 110 | /* |
108 | * This should draw both d and z from DRNG concatenating in | 111 | * This should draw both d and z from DRNG concatenating in |
@@ -110,120 +113,91 @@ MlkemIterativeTest(struct iteration_ctx *ctx) | |||
110 | */ | 113 | */ |
111 | shake_out(&drng, seed, sizeof(seed)); | 114 | shake_out(&drng, seed, sizeof(seed)); |
112 | if (i == 0) { | 115 | if (i == 0) { |
113 | if (compare_data(seed, ctx->start, ctx->start_len, | 116 | if (compare_data(seed, start, start_len, |
114 | "seed start") != 0) | 117 | "seed start") != 0) |
115 | errx(1, "compare_data"); | 118 | errx(1, "compare_data"); |
116 | } | 119 | } |
117 | 120 | ||
118 | /* generate ek as encoded_public_key */ | 121 | /* generate ek as encoded_public_key */ |
119 | if (!ctx->generate_key_external_entropy(ctx->encoded_public_key, | 122 | if (!MLKEM_generate_key_external_entropy(priv, |
120 | ctx->priv, seed)) { | 123 | &encoded_public_key, &encoded_public_key_len, |
124 | seed)) | ||
121 | errx(1, "generate_key_external_entropy"); | 125 | errx(1, "generate_key_external_entropy"); |
122 | } | 126 | |
123 | ctx->public_from_private(ctx->pub, ctx->priv); | 127 | if (!MLKEM_public_from_private(priv, pub)) |
128 | errx(1, "public_from_private"); | ||
124 | 129 | ||
125 | /* hash in ek */ | 130 | /* hash in ek */ |
126 | shake_update(&results, ctx->encoded_public_key, | 131 | shake_update(&results, encoded_public_key, |
127 | ctx->encoded_public_key_len); | 132 | encoded_public_key_len); |
128 | 133 | ||
129 | /* marshal priv to dk as encoded_private_key */ | 134 | /* marshal priv to dk as encoded_private_key */ |
130 | if (!ctx->marshal_private_key(ctx->priv, &encoded_private_key, | 135 | if (!MLKEM_marshal_private_key(priv, &encoded_private_key, |
131 | &encoded_private_key_len)) | 136 | &encoded_private_key_len)) |
132 | errx(1, "encode private key"); | 137 | errx(1, "marshal private key"); |
133 | 138 | ||
134 | /* hash in dk */ | 139 | /* hash in dk */ |
135 | shake_update(&results, encoded_private_key, | 140 | shake_update(&results, encoded_private_key, |
136 | encoded_private_key_len); | 141 | encoded_private_key_len); |
137 | 142 | ||
138 | free(encoded_private_key); | 143 | freezero(encoded_private_key, encoded_private_key_len); |
139 | 144 | ||
140 | /* draw m as encap entropy from DRNG */ | 145 | /* draw m as encap entropy from DRNG */ |
141 | shake_out(&drng, encap_entropy, sizeof(encap_entropy)); | 146 | shake_out(&drng, encap_entropy, sizeof(encap_entropy)); |
142 | 147 | ||
143 | /* generate ct as ciphertext, k as shared_secret */ | 148 | /* generate ct as ciphertext, k as shared_secret */ |
144 | ctx->encap_external_entropy(ctx->ciphertext, shared_secret, | 149 | if (!MLKEM_encap_external_entropy(pub, encap_entropy, |
145 | ctx->pub, encap_entropy); | 150 | &ciphertext, &ciphertext_len, &shared_secret, &s_len)) |
151 | errx(1, "encap_external_entropy"); | ||
146 | 152 | ||
147 | /* hash in ct */ | 153 | /* hash in ct */ |
148 | shake_update(&results, ctx->ciphertext, ctx->ciphertext_len); | 154 | shake_update(&results, ciphertext, ciphertext_len); |
149 | /* hash in k */ | 155 | /* hash in k */ |
150 | shake_update(&results, shared_secret, sizeof(shared_secret)); | 156 | shake_update(&results, shared_secret, s_len); |
157 | |||
158 | freezero(shared_secret, s_len); | ||
159 | shared_secret = NULL; | ||
160 | |||
161 | invalid_ciphertext_len = ciphertext_len; | ||
162 | if ((invalid_ciphertext = calloc(1, invalid_ciphertext_len)) | ||
163 | == NULL) | ||
164 | errx(1, "malloc"); | ||
151 | 165 | ||
152 | /* draw ct as invalid_ciphertxt from DRNG */ | 166 | /* draw ct as invalid_ciphertxt from DRNG */ |
153 | shake_out(&drng, ctx->invalid_ciphertext, | 167 | shake_out(&drng, invalid_ciphertext, invalid_ciphertext_len); |
154 | ctx->invalid_ciphertext_len); | ||
155 | 168 | ||
156 | /* generate k as shared secret from invalid ciphertext */ | 169 | /* generate k as shared secret from invalid ciphertext */ |
157 | if (!ctx->decap(shared_secret, ctx->invalid_ciphertext, | 170 | if (!MLKEM_decap(priv, invalid_ciphertext, |
158 | ctx->invalid_ciphertext_len, ctx->priv)) | 171 | invalid_ciphertext_len, &shared_secret, &s_len)) |
159 | errx(1, "decap failed"); | 172 | errx(1, "decap failed, iteration %d", i); |
160 | 173 | ||
161 | /* hash in k */ | 174 | /* hash in k */ |
162 | shake_update(&results, shared_secret, sizeof(shared_secret)); | 175 | shake_update(&results, shared_secret, s_len); |
176 | |||
177 | freezero(shared_secret, s_len); | ||
178 | shared_secret = NULL; | ||
179 | freezero(invalid_ciphertext, invalid_ciphertext_len); | ||
180 | invalid_ciphertext = NULL; | ||
181 | |||
182 | /* free keys and intermediate products for this iteration */ | ||
183 | MLKEM_private_key_free(priv); | ||
184 | MLKEM_public_key_free(pub); | ||
185 | freezero(encoded_public_key, encoded_public_key_len); | ||
186 | freezero(ciphertext, ciphertext_len); | ||
163 | } | 187 | } |
164 | shake_xof(&results); | 188 | shake_xof(&results); |
165 | shake_out(&results, out, sizeof(out)); | 189 | shake_out(&results, out, sizeof(out)); |
166 | 190 | ||
167 | return compare_data(ctx->expected, out, sizeof(out), "final result hash"); | 191 | return compare_data(expected, out, sizeof(out), "final result hash"); |
168 | } | 192 | } |
169 | 193 | ||
170 | int | 194 | int |
171 | main(void) | 195 | main(void) |
172 | { | 196 | { |
173 | uint8_t encoded_public_key768[MLKEM768_PUBLIC_KEY_BYTES]; | ||
174 | uint8_t ciphertext768[MLKEM768_CIPHERTEXT_BYTES]; | ||
175 | uint8_t invalid_ciphertext768[MLKEM768_CIPHERTEXT_BYTES]; | ||
176 | struct MLKEM768_private_key priv768; | ||
177 | struct MLKEM768_public_key pub768; | ||
178 | struct iteration_ctx iteration768 = { | ||
179 | .encoded_public_key = encoded_public_key768, | ||
180 | .encoded_public_key_len = sizeof(encoded_public_key768), | ||
181 | .ciphertext = ciphertext768, | ||
182 | .ciphertext_len = sizeof(ciphertext768), | ||
183 | .invalid_ciphertext = invalid_ciphertext768, | ||
184 | .invalid_ciphertext_len = sizeof(invalid_ciphertext768), | ||
185 | .priv = &priv768, | ||
186 | .pub = &pub768, | ||
187 | .encap_external_entropy = mlkem768_encap_external_entropy, | ||
188 | .marshal_private_key = mlkem768_marshal_private_key, | ||
189 | .generate_key_external_entropy = | ||
190 | mlkem768_generate_key_external_entropy, | ||
191 | .public_from_private = mlkem768_public_from_private, | ||
192 | .decap = mlkem768_decap, | ||
193 | .start = kExpectedSeedStart, | ||
194 | .start_len = sizeof(kExpectedSeedStart), | ||
195 | .expected = kExpectedAdam768, | ||
196 | .expected_len = sizeof(kExpectedAdam768), | ||
197 | }; | ||
198 | uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES]; | ||
199 | uint8_t ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES]; | ||
200 | uint8_t invalid_ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES]; | ||
201 | struct MLKEM1024_private_key priv1024; | ||
202 | struct MLKEM1024_public_key pub1024; | ||
203 | struct iteration_ctx iteration1024 = { | ||
204 | .encoded_public_key = encoded_public_key1024, | ||
205 | .encoded_public_key_len = sizeof(encoded_public_key1024), | ||
206 | .ciphertext = ciphertext1024, | ||
207 | .ciphertext_len = sizeof(ciphertext1024), | ||
208 | .invalid_ciphertext = invalid_ciphertext1024, | ||
209 | .invalid_ciphertext_len = sizeof(invalid_ciphertext1024), | ||
210 | .priv = &priv1024, | ||
211 | .pub = &pub1024, | ||
212 | .encap_external_entropy = mlkem1024_encap_external_entropy, | ||
213 | .marshal_private_key = mlkem1024_marshal_private_key, | ||
214 | .generate_key_external_entropy = | ||
215 | mlkem1024_generate_key_external_entropy, | ||
216 | .public_from_private = mlkem1024_public_from_private, | ||
217 | .decap = mlkem1024_decap, | ||
218 | .start = kExpectedSeedStart, | ||
219 | .start_len = sizeof(kExpectedSeedStart), | ||
220 | .expected = kExpectedAdam1024, | ||
221 | .expected_len = sizeof(kExpectedAdam1024), | ||
222 | }; | ||
223 | int failed = 0; | 197 | int failed = 0; |
224 | 198 | ||
225 | failed |= MlkemIterativeTest(&iteration768); | 199 | failed |= MlkemIterativeTest(RANK768); |
226 | failed |= MlkemIterativeTest(&iteration1024); | 200 | failed |= MlkemIterativeTest(RANK1024); |
227 | 201 | ||
228 | return failed; | 202 | return failed; |
229 | } | 203 | } |
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests.c index 8e04dc6ad2..361467afd0 100644 --- a/src/regress/lib/libcrypto/mlkem/mlkem_tests.c +++ b/src/regress/lib/libcrypto/mlkem/mlkem_tests.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mlkem_tests.c,v 1.6 2025/05/20 00:33:41 beck Exp $ */ | 1 | /* $OpenBSD: mlkem_tests.c,v 1.10 2025/08/15 21:47:39 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024 Google Inc. | 3 | * Copyright (c) 2024 Google Inc. |
4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> |
@@ -23,12 +23,11 @@ | |||
23 | #include <stdlib.h> | 23 | #include <stdlib.h> |
24 | #include <string.h> | 24 | #include <string.h> |
25 | 25 | ||
26 | #include "bytestring.h" | 26 | #include <openssl/mlkem.h> |
27 | #include "mlkem.h" | ||
28 | 27 | ||
28 | #include "bytestring.h" | ||
29 | #include "mlkem_internal.h" | 29 | #include "mlkem_internal.h" |
30 | 30 | ||
31 | #include "mlkem_tests_util.h" | ||
32 | #include "parse_test_file.h" | 31 | #include "parse_test_file.h" |
33 | 32 | ||
34 | enum test_type { | 33 | enum test_type { |
@@ -39,11 +38,7 @@ enum test_type { | |||
39 | struct decap_ctx { | 38 | struct decap_ctx { |
40 | struct parse *parse_ctx; | 39 | struct parse *parse_ctx; |
41 | 40 | ||
42 | void *private_key; | 41 | int rank; |
43 | size_t private_key_len; | ||
44 | |||
45 | mlkem_parse_private_key_fn parse_private_key; | ||
46 | mlkem_decap_fn decap; | ||
47 | }; | 42 | }; |
48 | 43 | ||
49 | enum decap_states { | 44 | enum decap_states { |
@@ -102,8 +97,10 @@ static int | |||
102 | MlkemDecapFileTest(struct decap_ctx *decap) | 97 | MlkemDecapFileTest(struct decap_ctx *decap) |
103 | { | 98 | { |
104 | struct parse *p = decap->parse_ctx; | 99 | struct parse *p = decap->parse_ctx; |
105 | uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES]; | 100 | MLKEM_private_key *priv_key = NULL; |
106 | CBS ciphertext, shared_secret, private_key; | 101 | CBS ciphertext, shared_secret, private_key; |
102 | uint8_t *shared_secret_buf = NULL; | ||
103 | size_t shared_secret_buf_len = 0; | ||
107 | int should_fail; | 104 | int should_fail; |
108 | int failed = 1; | 105 | int failed = 1; |
109 | 106 | ||
@@ -112,21 +109,31 @@ MlkemDecapFileTest(struct decap_ctx *decap) | |||
112 | parse_get_cbs(p, DECAP_PRIVATE_KEY, &private_key); | 109 | parse_get_cbs(p, DECAP_PRIVATE_KEY, &private_key); |
113 | parse_get_int(p, DECAP_RESULT, &should_fail); | 110 | parse_get_int(p, DECAP_RESULT, &should_fail); |
114 | 111 | ||
115 | if (!decap->parse_private_key(decap->private_key, | 112 | if ((priv_key = MLKEM_private_key_new(decap->rank)) == NULL) |
113 | parse_errx(p, "MLKEM_private_key_new"); | ||
114 | |||
115 | if (!MLKEM_parse_private_key(priv_key, | ||
116 | CBS_data(&private_key), CBS_len(&private_key))) { | 116 | CBS_data(&private_key), CBS_len(&private_key))) { |
117 | if ((failed = !should_fail)) | 117 | if ((failed = !should_fail)) |
118 | parse_info(p, "parse private key"); | 118 | parse_info(p, "parse private key"); |
119 | goto err; | 119 | goto err; |
120 | } | 120 | } |
121 | if (!decap->decap(shared_secret_buf, | 121 | if (!MLKEM_decap(priv_key, CBS_data(&ciphertext), CBS_len(&ciphertext), |
122 | CBS_data(&ciphertext), CBS_len(&ciphertext), decap->private_key)) { | 122 | &shared_secret_buf, &shared_secret_buf_len)) { |
123 | if ((failed = !should_fail)) | 123 | if ((failed = !should_fail)) |
124 | parse_info(p, "decap"); | 124 | parse_info(p, "decap"); |
125 | goto err; | 125 | goto err; |
126 | } | 126 | } |
127 | 127 | ||
128 | if (shared_secret_buf_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
129 | if ((failed = !should_fail)) | ||
130 | parse_info(p, "shared secret length %zu != %d", | ||
131 | shared_secret_buf_len, MLKEM_SHARED_SECRET_LENGTH); | ||
132 | goto err; | ||
133 | } | ||
134 | |||
128 | failed = !parse_data_equal(p, "shared_secret", &shared_secret, | 135 | failed = !parse_data_equal(p, "shared_secret", &shared_secret, |
129 | shared_secret_buf, sizeof(shared_secret_buf)); | 136 | shared_secret_buf, shared_secret_buf_len); |
130 | 137 | ||
131 | if (should_fail != failed) { | 138 | if (should_fail != failed) { |
132 | parse_info(p, "FAIL: should_fail %d, failed %d", | 139 | parse_info(p, "FAIL: should_fail %d, failed %d", |
@@ -135,6 +142,9 @@ MlkemDecapFileTest(struct decap_ctx *decap) | |||
135 | } | 142 | } |
136 | 143 | ||
137 | err: | 144 | err: |
145 | MLKEM_private_key_free(priv_key); | ||
146 | freezero(shared_secret_buf, shared_secret_buf_len); | ||
147 | |||
138 | return failed; | 148 | return failed; |
139 | } | 149 | } |
140 | 150 | ||
@@ -193,36 +203,49 @@ static int | |||
193 | MlkemNistDecapFileTest(struct decap_ctx *decap) | 203 | MlkemNistDecapFileTest(struct decap_ctx *decap) |
194 | { | 204 | { |
195 | struct parse *p = decap->parse_ctx; | 205 | struct parse *p = decap->parse_ctx; |
196 | uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES]; | 206 | MLKEM_private_key *priv_key = NULL; |
197 | CBS dk, c, k; | 207 | CBS dk, c, k; |
208 | uint8_t *shared_secret = NULL; | ||
209 | size_t shared_secret_len = 0; | ||
198 | int failed = 1; | 210 | int failed = 1; |
199 | 211 | ||
200 | parse_instruction_get_cbs(p, NIST_DECAP_DK, &dk); | 212 | parse_instruction_get_cbs(p, NIST_DECAP_DK, &dk); |
201 | parse_get_cbs(p, NIST_DECAP_C, &c); | 213 | parse_get_cbs(p, NIST_DECAP_C, &c); |
202 | parse_get_cbs(p, NIST_DECAP_K, &k); | 214 | parse_get_cbs(p, NIST_DECAP_K, &k); |
203 | 215 | ||
216 | if ((priv_key = MLKEM_private_key_new(decap->rank)) == NULL) | ||
217 | parse_errx(p, "MLKEM_private_key_new"); | ||
218 | |||
204 | if (!parse_length_equal(p, "private key", | 219 | if (!parse_length_equal(p, "private key", |
205 | decap->private_key_len, CBS_len(&dk))) | 220 | MLKEM_private_key_encoded_length(priv_key), CBS_len(&dk))) |
206 | goto err; | 221 | goto err; |
207 | if (!parse_length_equal(p, "shared secret", | 222 | if (!parse_length_equal(p, "shared secret", |
208 | MLKEM_SHARED_SECRET_BYTES, CBS_len(&k))) | 223 | MLKEM_SHARED_SECRET_LENGTH, CBS_len(&k))) |
209 | goto err; | 224 | goto err; |
210 | 225 | ||
211 | if (!decap->parse_private_key(decap->private_key, CBS_data(&dk), | 226 | if (!MLKEM_parse_private_key(priv_key, CBS_data(&dk), CBS_len(&dk))) { |
212 | CBS_len(&dk))) { | ||
213 | parse_info(p, "parse private key"); | 227 | parse_info(p, "parse private key"); |
214 | goto err; | 228 | goto err; |
215 | } | 229 | } |
216 | if (!decap->decap(shared_secret, CBS_data(&c), CBS_len(&c), | 230 | if (!MLKEM_decap(priv_key, CBS_data(&c), CBS_len(&c), |
217 | decap->private_key)) { | 231 | &shared_secret, &shared_secret_len)) { |
218 | parse_info(p, "decap"); | 232 | parse_info(p, "decap"); |
219 | goto err; | 233 | goto err; |
220 | } | 234 | } |
221 | 235 | ||
236 | if (shared_secret_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
237 | parse_info(p, "shared secret length %zu != %d", | ||
238 | shared_secret_len, MLKEM_SHARED_SECRET_LENGTH); | ||
239 | goto err; | ||
240 | } | ||
241 | |||
222 | failed = !parse_data_equal(p, "shared secret", &k, | 242 | failed = !parse_data_equal(p, "shared secret", &k, |
223 | shared_secret, MLKEM_SHARED_SECRET_BYTES); | 243 | shared_secret, shared_secret_len); |
224 | 244 | ||
225 | err: | 245 | err: |
246 | MLKEM_private_key_free(priv_key); | ||
247 | freezero(shared_secret, shared_secret_len); | ||
248 | |||
226 | return failed; | 249 | return failed; |
227 | } | 250 | } |
228 | 251 | ||
@@ -246,46 +269,24 @@ static const struct test_parse nist_decap_parse = { | |||
246 | }; | 269 | }; |
247 | 270 | ||
248 | static int | 271 | static int |
249 | mlkem_decap_tests(const char *fn, size_t size, enum test_type test_type) | 272 | mlkem_decap_tests(const char *fn, int rank, enum test_type test_type) |
250 | { | 273 | { |
251 | struct MLKEM768_private_key private_key768; | 274 | struct decap_ctx decap = { |
252 | struct decap_ctx decap768 = { | 275 | .rank = rank, |
253 | .private_key = &private_key768, | ||
254 | .private_key_len = MLKEM768_PRIVATE_KEY_BYTES, | ||
255 | |||
256 | .parse_private_key = mlkem768_parse_private_key, | ||
257 | .decap = mlkem768_decap, | ||
258 | }; | 276 | }; |
259 | struct MLKEM1024_private_key private_key1024; | ||
260 | struct decap_ctx decap1024 = { | ||
261 | .private_key = &private_key1024, | ||
262 | .private_key_len = MLKEM1024_PRIVATE_KEY_BYTES, | ||
263 | 277 | ||
264 | .parse_private_key = mlkem1024_parse_private_key, | 278 | if (test_type == TEST_TYPE_NORMAL) |
265 | .decap = mlkem1024_decap, | 279 | return parse_test_file(fn, &decap_parse, &decap); |
266 | }; | 280 | if (test_type == TEST_TYPE_NIST) |
267 | 281 | return parse_test_file(fn, &nist_decap_parse, &decap); | |
268 | if (size == 768 && test_type == TEST_TYPE_NORMAL) | ||
269 | return parse_test_file(fn, &decap_parse, &decap768); | ||
270 | if (size == 768 && test_type == TEST_TYPE_NIST) | ||
271 | return parse_test_file(fn, &nist_decap_parse, &decap768); | ||
272 | if (size == 1024 && test_type == TEST_TYPE_NORMAL) | ||
273 | return parse_test_file(fn, &decap_parse, &decap1024); | ||
274 | if (size == 1024 && test_type == TEST_TYPE_NIST) | ||
275 | return parse_test_file(fn, &nist_decap_parse, &decap1024); | ||
276 | 282 | ||
277 | errx(1, "unknown decap test: size %zu, type %d", size, test_type); | 283 | errx(1, "unknown decap test: rank %d, type %d", rank, test_type); |
278 | } | 284 | } |
279 | 285 | ||
280 | struct encap_ctx { | 286 | struct encap_ctx { |
281 | struct parse *parse_ctx; | 287 | struct parse *parse_ctx; |
282 | 288 | ||
283 | void *public_key; | 289 | int rank; |
284 | uint8_t *ciphertext; | ||
285 | size_t ciphertext_len; | ||
286 | |||
287 | mlkem_parse_public_key_fn parse_public_key; | ||
288 | mlkem_encap_external_entropy_fn encap_external_entropy; | ||
289 | }; | 290 | }; |
290 | 291 | ||
291 | enum encap_states { | 292 | enum encap_states { |
@@ -351,8 +352,12 @@ static int | |||
351 | MlkemEncapFileTest(struct encap_ctx *encap) | 352 | MlkemEncapFileTest(struct encap_ctx *encap) |
352 | { | 353 | { |
353 | struct parse *p = encap->parse_ctx; | 354 | struct parse *p = encap->parse_ctx; |
354 | uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES]; | 355 | MLKEM_public_key *pub_key = NULL; |
355 | CBS entropy, public_key, ciphertext, shared_secret; | 356 | CBS entropy, public_key, ciphertext, shared_secret; |
357 | uint8_t *ciphertext_buf = NULL; | ||
358 | size_t ciphertext_buf_len = 0; | ||
359 | uint8_t *shared_secret_buf = NULL; | ||
360 | size_t shared_secret_buf_len = 0; | ||
356 | int should_fail; | 361 | int should_fail; |
357 | int failed = 1; | 362 | int failed = 1; |
358 | 363 | ||
@@ -362,19 +367,34 @@ MlkemEncapFileTest(struct encap_ctx *encap) | |||
362 | parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret); | 367 | parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret); |
363 | parse_get_int(p, ENCAP_RESULT, &should_fail); | 368 | parse_get_int(p, ENCAP_RESULT, &should_fail); |
364 | 369 | ||
365 | if (!encap->parse_public_key(encap->public_key, CBS_data(&public_key), | 370 | if ((pub_key = MLKEM_public_key_new(encap->rank)) == NULL) |
366 | CBS_len(&public_key))) { | 371 | parse_errx(p, "MLKEM_public_key_new"); |
372 | |||
373 | if (!MLKEM_parse_public_key(pub_key, | ||
374 | CBS_data(&public_key), CBS_len(&public_key))) { | ||
367 | if ((failed = !should_fail)) | 375 | if ((failed = !should_fail)) |
368 | parse_info(p, "parse public key"); | 376 | parse_info(p, "parse public key"); |
369 | goto err; | 377 | goto err; |
370 | } | 378 | } |
371 | encap->encap_external_entropy(encap->ciphertext, shared_secret_buf, | 379 | if (!MLKEM_encap_external_entropy(pub_key, CBS_data(&entropy), |
372 | encap->public_key, CBS_data(&entropy)); | 380 | &ciphertext_buf, &ciphertext_buf_len, |
381 | &shared_secret_buf, &shared_secret_buf_len)) { | ||
382 | if ((failed = !should_fail)) | ||
383 | parse_info(p, "encap_external_entropy"); | ||
384 | goto err; | ||
385 | } | ||
386 | |||
387 | if (shared_secret_buf_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
388 | if ((failed = !should_fail)) | ||
389 | parse_info(p, "shared secret length %zu != %d", | ||
390 | shared_secret_buf_len, MLKEM_SHARED_SECRET_LENGTH); | ||
391 | goto err; | ||
392 | } | ||
373 | 393 | ||
374 | failed = !parse_data_equal(p, "shared_secret", &shared_secret, | 394 | failed = !parse_data_equal(p, "shared_secret", &shared_secret, |
375 | shared_secret_buf, sizeof(shared_secret_buf)); | 395 | shared_secret_buf, shared_secret_buf_len); |
376 | failed |= !parse_data_equal(p, "ciphertext", &ciphertext, | 396 | failed |= !parse_data_equal(p, "ciphertext", &ciphertext, |
377 | encap->ciphertext, encap->ciphertext_len); | 397 | ciphertext_buf, ciphertext_buf_len); |
378 | 398 | ||
379 | if (should_fail != failed) { | 399 | if (should_fail != failed) { |
380 | parse_info(p, "FAIL: should_fail %d, failed %d", | 400 | parse_info(p, "FAIL: should_fail %d, failed %d", |
@@ -383,6 +403,10 @@ MlkemEncapFileTest(struct encap_ctx *encap) | |||
383 | } | 403 | } |
384 | 404 | ||
385 | err: | 405 | err: |
406 | MLKEM_public_key_free(pub_key); | ||
407 | freezero(ciphertext_buf, ciphertext_buf_len); | ||
408 | freezero(shared_secret_buf, shared_secret_buf_len); | ||
409 | |||
386 | return failed; | 410 | return failed; |
387 | } | 411 | } |
388 | 412 | ||
@@ -403,48 +427,19 @@ static const struct test_parse encap_parse = { | |||
403 | }; | 427 | }; |
404 | 428 | ||
405 | static int | 429 | static int |
406 | mlkem_encap_tests(const char *fn, size_t size) | 430 | mlkem_encap_tests(const char *fn, int rank) |
407 | { | 431 | { |
408 | struct MLKEM768_public_key public_key768; | 432 | struct encap_ctx encap = { |
409 | uint8_t ciphertext768[MLKEM768_CIPHERTEXT_BYTES]; | 433 | .rank = rank, |
410 | struct encap_ctx encap768 = { | ||
411 | .public_key = &public_key768, | ||
412 | .ciphertext = ciphertext768, | ||
413 | .ciphertext_len = sizeof(ciphertext768), | ||
414 | |||
415 | .parse_public_key = mlkem768_parse_public_key, | ||
416 | .encap_external_entropy = mlkem768_encap_external_entropy, | ||
417 | }; | ||
418 | struct MLKEM1024_public_key public_key1024; | ||
419 | uint8_t ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES]; | ||
420 | struct encap_ctx encap1024 = { | ||
421 | .public_key = &public_key1024, | ||
422 | .ciphertext = ciphertext1024, | ||
423 | .ciphertext_len = sizeof(ciphertext1024), | ||
424 | |||
425 | .parse_public_key = mlkem1024_parse_public_key, | ||
426 | .encap_external_entropy = mlkem1024_encap_external_entropy, | ||
427 | }; | 434 | }; |
428 | 435 | ||
429 | if (size == 768) | 436 | return parse_test_file(fn, &encap_parse, &encap); |
430 | return parse_test_file(fn, &encap_parse, &encap768); | ||
431 | if (size == 1024) | ||
432 | return parse_test_file(fn, &encap_parse, &encap1024); | ||
433 | |||
434 | errx(1, "unknown encap test: size %zu", size); | ||
435 | } | 437 | } |
436 | 438 | ||
437 | struct keygen_ctx { | 439 | struct keygen_ctx { |
438 | struct parse *parse_ctx; | 440 | struct parse *parse_ctx; |
439 | 441 | ||
440 | void *private_key; | 442 | int rank; |
441 | void *encoded_public_key; | ||
442 | size_t encoded_public_key_len; | ||
443 | size_t private_key_len; | ||
444 | size_t public_key_len; | ||
445 | |||
446 | mlkem_generate_key_external_entropy_fn generate_key_external_entropy; | ||
447 | mlkem_marshal_private_key_fn marshal_private_key; | ||
448 | }; | 443 | }; |
449 | 444 | ||
450 | enum keygen_states { | 445 | enum keygen_states { |
@@ -495,27 +490,38 @@ static int | |||
495 | MlkemKeygenFileTest(struct keygen_ctx *keygen) | 490 | MlkemKeygenFileTest(struct keygen_ctx *keygen) |
496 | { | 491 | { |
497 | struct parse *p = keygen->parse_ctx; | 492 | struct parse *p = keygen->parse_ctx; |
493 | MLKEM_private_key *priv_key = NULL; | ||
498 | CBS seed, public_key, private_key; | 494 | CBS seed, public_key, private_key; |
499 | uint8_t *encoded_private_key = NULL; | 495 | uint8_t *encoded_private_key = NULL; |
500 | size_t encoded_private_key_len = 0; | 496 | size_t encoded_private_key_len = 0; |
497 | uint8_t *encoded_public_key = NULL; | ||
498 | size_t encoded_public_key_len = 0; | ||
501 | int failed = 1; | 499 | int failed = 1; |
502 | 500 | ||
503 | parse_get_cbs(p, KEYGEN_SEED, &seed); | 501 | parse_get_cbs(p, KEYGEN_SEED, &seed); |
504 | parse_get_cbs(p, KEYGEN_PUBLIC_KEY, &public_key); | 502 | parse_get_cbs(p, KEYGEN_PUBLIC_KEY, &public_key); |
505 | parse_get_cbs(p, KEYGEN_PRIVATE_KEY, &private_key); | 503 | parse_get_cbs(p, KEYGEN_PRIVATE_KEY, &private_key); |
506 | 504 | ||
507 | if (!parse_length_equal(p, "seed", MLKEM_SEED_BYTES, CBS_len(&seed))) | 505 | if (!parse_length_equal(p, "seed", MLKEM_SEED_LENGTH, CBS_len(&seed))) |
508 | goto err; | 506 | goto err; |
507 | |||
508 | if ((priv_key = MLKEM_private_key_new(keygen->rank)) == NULL) | ||
509 | parse_errx(p, "MLKEM_public_key_free"); | ||
510 | |||
511 | if (!MLKEM_generate_key_external_entropy(priv_key, | ||
512 | &encoded_public_key, &encoded_public_key_len, CBS_data(&seed))) { | ||
513 | parse_info(p, "generate_key_external_entropy"); | ||
514 | goto err; | ||
515 | } | ||
516 | |||
509 | if (!parse_length_equal(p, "public key", | 517 | if (!parse_length_equal(p, "public key", |
510 | keygen->public_key_len, CBS_len(&public_key))) | 518 | encoded_public_key_len, CBS_len(&public_key))) |
511 | goto err; | 519 | goto err; |
512 | if (!parse_length_equal(p, "private key", | 520 | if (!parse_length_equal(p, "private key", |
513 | keygen->private_key_len, CBS_len(&private_key))) | 521 | MLKEM_private_key_encoded_length(priv_key), CBS_len(&private_key))) |
514 | goto err; | 522 | goto err; |
515 | 523 | ||
516 | keygen->generate_key_external_entropy(keygen->encoded_public_key, | 524 | if (!MLKEM_marshal_private_key(priv_key, |
517 | keygen->private_key, CBS_data(&seed)); | ||
518 | if (!keygen->marshal_private_key(keygen->private_key, | ||
519 | &encoded_private_key, &encoded_private_key_len)) { | 525 | &encoded_private_key, &encoded_private_key_len)) { |
520 | parse_info(p, "encode private key"); | 526 | parse_info(p, "encode private key"); |
521 | goto err; | 527 | goto err; |
@@ -524,10 +530,12 @@ MlkemKeygenFileTest(struct keygen_ctx *keygen) | |||
524 | failed = !parse_data_equal(p, "private key", &private_key, | 530 | failed = !parse_data_equal(p, "private key", &private_key, |
525 | encoded_private_key, encoded_private_key_len); | 531 | encoded_private_key, encoded_private_key_len); |
526 | failed |= !parse_data_equal(p, "public key", &public_key, | 532 | failed |= !parse_data_equal(p, "public key", &public_key, |
527 | keygen->encoded_public_key, keygen->encoded_public_key_len); | 533 | encoded_public_key, encoded_public_key_len); |
528 | 534 | ||
529 | err: | 535 | err: |
536 | MLKEM_private_key_free(priv_key); | ||
530 | freezero(encoded_private_key, encoded_private_key_len); | 537 | freezero(encoded_private_key, encoded_private_key_len); |
538 | freezero(encoded_public_key, encoded_public_key_len); | ||
531 | 539 | ||
532 | return failed; | 540 | return failed; |
533 | } | 541 | } |
@@ -587,12 +595,15 @@ static int | |||
587 | MlkemNistKeygenFileTest(struct keygen_ctx *keygen) | 595 | MlkemNistKeygenFileTest(struct keygen_ctx *keygen) |
588 | { | 596 | { |
589 | struct parse *p = keygen->parse_ctx; | 597 | struct parse *p = keygen->parse_ctx; |
598 | MLKEM_private_key *priv_key = NULL; | ||
590 | CBB seed_cbb; | 599 | CBB seed_cbb; |
591 | CBS z, d, ek, dk; | 600 | CBS z, d, ek, dk; |
592 | uint8_t seed[MLKEM_SEED_BYTES]; | 601 | uint8_t seed[MLKEM_SEED_LENGTH]; |
593 | size_t seed_len; | 602 | size_t seed_len; |
594 | uint8_t *encoded_private_key = NULL; | 603 | uint8_t *encoded_private_key = NULL; |
595 | size_t encoded_private_key_len = 0; | 604 | size_t encoded_private_key_len = 0; |
605 | uint8_t *encoded_public_key = NULL; | ||
606 | size_t encoded_public_key_len = 0; | ||
596 | int failed = 1; | 607 | int failed = 1; |
597 | 608 | ||
598 | parse_get_cbs(p, NIST_KEYGEN_Z, &z); | 609 | parse_get_cbs(p, NIST_KEYGEN_Z, &z); |
@@ -609,24 +620,33 @@ MlkemNistKeygenFileTest(struct keygen_ctx *keygen) | |||
609 | if (!CBB_finish(&seed_cbb, NULL, &seed_len)) | 620 | if (!CBB_finish(&seed_cbb, NULL, &seed_len)) |
610 | parse_errx(p, "CBB_finish"); | 621 | parse_errx(p, "CBB_finish"); |
611 | 622 | ||
612 | if (!parse_length_equal(p, "bogus z or d", MLKEM_SEED_BYTES, seed_len)) | 623 | if (!parse_length_equal(p, "bogus z or d", MLKEM_SEED_LENGTH, seed_len)) |
613 | goto err; | 624 | goto err; |
614 | 625 | ||
615 | keygen->generate_key_external_entropy(keygen->encoded_public_key, | 626 | if ((priv_key = MLKEM_private_key_new(keygen->rank)) == NULL) |
616 | keygen->private_key, seed); | 627 | parse_errx(p, "MLKEM_private_key_new"); |
617 | if (!keygen->marshal_private_key(keygen->private_key, | 628 | |
629 | if (!MLKEM_generate_key_external_entropy(priv_key, | ||
630 | &encoded_public_key, &encoded_public_key_len, seed)) { | ||
631 | parse_info(p, "MLKEM_generate_key_external_entropy"); | ||
632 | goto err; | ||
633 | } | ||
634 | |||
635 | if (!MLKEM_marshal_private_key(priv_key, | ||
618 | &encoded_private_key, &encoded_private_key_len)) { | 636 | &encoded_private_key, &encoded_private_key_len)) { |
619 | parse_info(p, "encode private key"); | 637 | parse_info(p, "encode private key"); |
620 | goto err; | 638 | goto err; |
621 | } | 639 | } |
622 | 640 | ||
623 | failed = !parse_data_equal(p, "public key", &ek, | 641 | failed = !parse_data_equal(p, "public key", &ek, |
624 | keygen->encoded_public_key, keygen->encoded_public_key_len); | 642 | encoded_public_key, encoded_public_key_len); |
625 | failed |= !parse_data_equal(p, "private key", &dk, | 643 | failed |= !parse_data_equal(p, "private key", &dk, |
626 | encoded_private_key, encoded_private_key_len); | 644 | encoded_private_key, encoded_private_key_len); |
627 | 645 | ||
628 | err: | 646 | err: |
647 | MLKEM_private_key_free(priv_key); | ||
629 | freezero(encoded_private_key, encoded_private_key_len); | 648 | freezero(encoded_private_key, encoded_private_key_len); |
649 | freezero(encoded_public_key, encoded_public_key_len); | ||
630 | 650 | ||
631 | return failed; | 651 | return failed; |
632 | } | 652 | } |
@@ -648,74 +668,45 @@ static const struct test_parse nist_keygen_parse = { | |||
648 | }; | 668 | }; |
649 | 669 | ||
650 | static int | 670 | static int |
651 | mlkem_keygen_tests(const char *fn, size_t size, enum test_type test_type) | 671 | mlkem_keygen_tests(const char *fn, int rank, enum test_type test_type) |
652 | { | 672 | { |
653 | struct MLKEM768_private_key private_key768; | 673 | struct keygen_ctx keygen = { |
654 | uint8_t encoded_public_key768[MLKEM768_PUBLIC_KEY_BYTES]; | 674 | .rank = rank, |
655 | struct keygen_ctx keygen768 = { | ||
656 | .private_key = &private_key768, | ||
657 | .encoded_public_key = encoded_public_key768, | ||
658 | .encoded_public_key_len = sizeof(encoded_public_key768), | ||
659 | .private_key_len = MLKEM768_PRIVATE_KEY_BYTES, | ||
660 | .public_key_len = MLKEM768_PUBLIC_KEY_BYTES, | ||
661 | |||
662 | .generate_key_external_entropy = | ||
663 | mlkem768_generate_key_external_entropy, | ||
664 | .marshal_private_key = | ||
665 | mlkem768_marshal_private_key, | ||
666 | }; | ||
667 | struct MLKEM1024_private_key private_key1024; | ||
668 | uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES]; | ||
669 | struct keygen_ctx keygen1024 = { | ||
670 | .private_key = &private_key1024, | ||
671 | .encoded_public_key = encoded_public_key1024, | ||
672 | .encoded_public_key_len = sizeof(encoded_public_key1024), | ||
673 | .private_key_len = MLKEM1024_PRIVATE_KEY_BYTES, | ||
674 | .public_key_len = MLKEM1024_PUBLIC_KEY_BYTES, | ||
675 | |||
676 | .generate_key_external_entropy = | ||
677 | mlkem1024_generate_key_external_entropy, | ||
678 | .marshal_private_key = | ||
679 | mlkem1024_marshal_private_key, | ||
680 | }; | 675 | }; |
681 | 676 | ||
682 | if (size == 768 && test_type == TEST_TYPE_NORMAL) | 677 | if (test_type == TEST_TYPE_NORMAL) |
683 | return parse_test_file(fn, &keygen_parse, &keygen768); | 678 | return parse_test_file(fn, &keygen_parse, &keygen); |
684 | if (size == 768 && test_type == TEST_TYPE_NIST) | 679 | if (test_type == TEST_TYPE_NIST) |
685 | return parse_test_file(fn, &nist_keygen_parse, &keygen768); | 680 | return parse_test_file(fn, &nist_keygen_parse, &keygen); |
686 | if (size == 1024 && test_type == TEST_TYPE_NORMAL) | ||
687 | return parse_test_file(fn, &keygen_parse, &keygen1024); | ||
688 | if (size == 1024 && test_type == TEST_TYPE_NIST) | ||
689 | return parse_test_file(fn, &nist_keygen_parse, &keygen1024); | ||
690 | 681 | ||
691 | errx(1, "unknown keygen test: size %zu, type %d", size, test_type); | 682 | errx(1, "unknown keygen test: rank %d, type %d", rank, test_type); |
692 | } | 683 | } |
693 | 684 | ||
694 | static int | 685 | static int |
695 | run_mlkem_test(const char *test, const char *fn) | 686 | run_mlkem_test(const char *test, const char *fn) |
696 | { | 687 | { |
697 | if (strcmp(test, "mlkem768_decap_tests") == 0) | 688 | if (strcmp(test, "mlkem768_decap_tests") == 0) |
698 | return mlkem_decap_tests(fn, 768, TEST_TYPE_NORMAL); | 689 | return mlkem_decap_tests(fn, RANK768, TEST_TYPE_NORMAL); |
699 | if (strcmp(test, "mlkem768_nist_decap_tests") == 0) | 690 | if (strcmp(test, "mlkem768_nist_decap_tests") == 0) |
700 | return mlkem_decap_tests(fn, 768, TEST_TYPE_NIST); | 691 | return mlkem_decap_tests(fn, RANK768, TEST_TYPE_NIST); |
701 | if (strcmp(test, "mlkem1024_decap_tests") == 0) | 692 | if (strcmp(test, "mlkem1024_decap_tests") == 0) |
702 | return mlkem_decap_tests(fn, 1024, TEST_TYPE_NORMAL); | 693 | return mlkem_decap_tests(fn, RANK1024, TEST_TYPE_NORMAL); |
703 | if (strcmp(test, "mlkem1024_nist_decap_tests") == 0) | 694 | if (strcmp(test, "mlkem1024_nist_decap_tests") == 0) |
704 | return mlkem_decap_tests(fn, 1024, TEST_TYPE_NIST); | 695 | return mlkem_decap_tests(fn, RANK1024, TEST_TYPE_NIST); |
705 | 696 | ||
706 | if (strcmp(test, "mlkem768_encap_tests") == 0) | 697 | if (strcmp(test, "mlkem768_encap_tests") == 0) |
707 | return mlkem_encap_tests(fn, 768); | 698 | return mlkem_encap_tests(fn, RANK768); |
708 | if (strcmp(test, "mlkem1024_encap_tests") == 0) | 699 | if (strcmp(test, "mlkem1024_encap_tests") == 0) |
709 | return mlkem_encap_tests(fn, 1024); | 700 | return mlkem_encap_tests(fn, RANK1024); |
710 | 701 | ||
711 | if (strcmp(test, "mlkem768_keygen_tests") == 0) | 702 | if (strcmp(test, "mlkem768_keygen_tests") == 0) |
712 | return mlkem_keygen_tests(fn, 768, TEST_TYPE_NORMAL); | 703 | return mlkem_keygen_tests(fn, RANK768, TEST_TYPE_NORMAL); |
713 | if (strcmp(test, "mlkem768_nist_keygen_tests") == 0) | 704 | if (strcmp(test, "mlkem768_nist_keygen_tests") == 0) |
714 | return mlkem_keygen_tests(fn, 768, TEST_TYPE_NIST); | 705 | return mlkem_keygen_tests(fn, RANK768, TEST_TYPE_NIST); |
715 | if (strcmp(test, "mlkem1024_keygen_tests") == 0) | 706 | if (strcmp(test, "mlkem1024_keygen_tests") == 0) |
716 | return mlkem_keygen_tests(fn, 1024, TEST_TYPE_NORMAL); | 707 | return mlkem_keygen_tests(fn, RANK1024, TEST_TYPE_NORMAL); |
717 | if (strcmp(test, "mlkem1024_nist_keygen_tests") == 0) | 708 | if (strcmp(test, "mlkem1024_nist_keygen_tests") == 0) |
718 | return mlkem_keygen_tests(fn, 1024, TEST_TYPE_NIST); | 709 | return mlkem_keygen_tests(fn, RANK1024, TEST_TYPE_NIST); |
719 | 710 | ||
720 | errx(1, "unknown test %s (test file %s)", test, fn); | 711 | errx(1, "unknown test %s (test file %s)", test, fn); |
721 | } | 712 | } |
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c index 68bd5d4871..d2e0fbd7c7 100644 --- a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c +++ b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mlkem_tests_util.c,v 1.8 2025/05/20 00:33:41 beck Exp $ */ | 1 | /* $OpenBSD: mlkem_tests_util.c,v 1.10 2025/08/15 14:47:54 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024 Google Inc. | 3 | * Copyright (c) 2024 Google Inc. |
4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> | 4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> |
@@ -22,11 +22,6 @@ | |||
22 | #include <stdio.h> | 22 | #include <stdio.h> |
23 | #include <string.h> | 23 | #include <string.h> |
24 | 24 | ||
25 | #include "bytestring.h" | ||
26 | #include "mlkem.h" | ||
27 | |||
28 | #include "mlkem_internal.h" | ||
29 | |||
30 | #include "mlkem_tests_util.h" | 25 | #include "mlkem_tests_util.h" |
31 | 26 | ||
32 | static void | 27 | static void |
@@ -59,157 +54,3 @@ compare_data(const uint8_t *want, const uint8_t *got, size_t len, const char *ms | |||
59 | 54 | ||
60 | return 1; | 55 | return 1; |
61 | } | 56 | } |
62 | |||
63 | int | ||
64 | mlkem768_marshal_private_key(const void *private_key, uint8_t **out_buf, | ||
65 | size_t *out_len) | ||
66 | { | ||
67 | return MLKEM768_marshal_private_key(private_key, out_buf, out_len); | ||
68 | } | ||
69 | |||
70 | int | ||
71 | mlkem768_marshal_public_key(const void *public_key, uint8_t **out_buf, | ||
72 | size_t *out_len) | ||
73 | { | ||
74 | return MLKEM768_marshal_public_key(out_buf, out_len, public_key); | ||
75 | } | ||
76 | |||
77 | int | ||
78 | mlkem1024_marshal_private_key(const void *private_key, uint8_t **out_buf, | ||
79 | size_t *out_len) | ||
80 | { | ||
81 | return MLKEM1024_marshal_private_key(private_key, out_buf, out_len); | ||
82 | } | ||
83 | |||
84 | int | ||
85 | mlkem1024_marshal_public_key(const void *public_key, uint8_t **out_buf, | ||
86 | size_t *out_len) | ||
87 | { | ||
88 | return MLKEM1024_marshal_public_key(out_buf, out_len, public_key); | ||
89 | } | ||
90 | |||
91 | int | ||
92 | mlkem768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
93 | const uint8_t *ciphertext, size_t ciphertext_len, const void *private_key) | ||
94 | { | ||
95 | return MLKEM768_decap(out_shared_secret, ciphertext, ciphertext_len, | ||
96 | private_key); | ||
97 | } | ||
98 | |||
99 | void | ||
100 | mlkem768_encap(uint8_t *out_ciphertext, | ||
101 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
102 | const void *public_key) | ||
103 | { | ||
104 | MLKEM768_encap(out_ciphertext, out_shared_secret, public_key); | ||
105 | } | ||
106 | |||
107 | void | ||
108 | mlkem768_encap_external_entropy(uint8_t *out_ciphertext, | ||
109 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
110 | const void *public_key, const uint8_t entropy[MLKEM_ENCAP_ENTROPY]) | ||
111 | { | ||
112 | MLKEM768_encap_external_entropy(out_ciphertext, out_shared_secret, | ||
113 | public_key, entropy); | ||
114 | } | ||
115 | |||
116 | int | ||
117 | mlkem768_generate_key(uint8_t *out_encoded_public_key, | ||
118 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key) | ||
119 | { | ||
120 | return MLKEM768_generate_key(out_encoded_public_key, optional_out_seed, | ||
121 | out_private_key); | ||
122 | } | ||
123 | |||
124 | int | ||
125 | mlkem768_generate_key_external_entropy(uint8_t *out_encoded_public_key, | ||
126 | void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]) | ||
127 | { | ||
128 | return MLKEM768_generate_key_external_entropy(out_encoded_public_key, | ||
129 | out_private_key, entropy); | ||
130 | } | ||
131 | |||
132 | int | ||
133 | mlkem768_parse_private_key(void *out_private_key, const uint8_t *private_key, | ||
134 | size_t private_key_len) | ||
135 | { | ||
136 | return MLKEM768_parse_private_key(out_private_key, private_key, | ||
137 | private_key_len); | ||
138 | } | ||
139 | |||
140 | int | ||
141 | mlkem768_parse_public_key(void *out_public_key, const uint8_t *public_key, | ||
142 | size_t public_key_len) | ||
143 | { | ||
144 | return MLKEM768_parse_public_key(out_public_key, public_key, | ||
145 | public_key_len); | ||
146 | } | ||
147 | |||
148 | void | ||
149 | mlkem768_public_from_private(void *out_public_key, const void *private_key) | ||
150 | { | ||
151 | MLKEM768_public_from_private(out_public_key, private_key); | ||
152 | } | ||
153 | |||
154 | int | ||
155 | mlkem1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
156 | const uint8_t *ciphertext, size_t ciphertext_len, const void *private_key) | ||
157 | { | ||
158 | return MLKEM1024_decap(out_shared_secret, ciphertext, ciphertext_len, | ||
159 | private_key); | ||
160 | } | ||
161 | |||
162 | void | ||
163 | mlkem1024_encap(uint8_t *out_ciphertext, | ||
164 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
165 | const void *public_key) | ||
166 | { | ||
167 | MLKEM1024_encap(out_ciphertext, out_shared_secret, public_key); | ||
168 | } | ||
169 | |||
170 | void | ||
171 | mlkem1024_encap_external_entropy(uint8_t *out_ciphertext, | ||
172 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
173 | const void *public_key, const uint8_t entropy[MLKEM_ENCAP_ENTROPY]) | ||
174 | { | ||
175 | MLKEM1024_encap_external_entropy(out_ciphertext, out_shared_secret, | ||
176 | public_key, entropy); | ||
177 | } | ||
178 | |||
179 | int | ||
180 | mlkem1024_generate_key(uint8_t *out_encoded_public_key, | ||
181 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key) | ||
182 | { | ||
183 | return MLKEM1024_generate_key(out_encoded_public_key, optional_out_seed, | ||
184 | out_private_key); | ||
185 | } | ||
186 | |||
187 | int | ||
188 | mlkem1024_generate_key_external_entropy(uint8_t *out_encoded_public_key, | ||
189 | void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]) | ||
190 | { | ||
191 | return MLKEM1024_generate_key_external_entropy(out_encoded_public_key, | ||
192 | out_private_key, entropy); | ||
193 | } | ||
194 | |||
195 | int | ||
196 | mlkem1024_parse_private_key(void *out_private_key, const uint8_t *private_key, | ||
197 | size_t private_key_len) | ||
198 | { | ||
199 | return MLKEM1024_parse_private_key(out_private_key, private_key, | ||
200 | private_key_len); | ||
201 | } | ||
202 | |||
203 | void | ||
204 | mlkem1024_public_from_private(void *out_public_key, const void *private_key) | ||
205 | { | ||
206 | MLKEM1024_public_from_private(out_public_key, private_key); | ||
207 | } | ||
208 | |||
209 | int | ||
210 | mlkem1024_parse_public_key(void *out_public_key, const uint8_t *public_key, | ||
211 | size_t public_key_len) | ||
212 | { | ||
213 | return MLKEM1024_parse_public_key(out_public_key, public_key, | ||
214 | public_key_len); | ||
215 | } | ||
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h index 1235309f60..514a309112 100644 --- a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h +++ b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mlkem_tests_util.h,v 1.7 2025/05/20 00:33:41 beck Exp $ */ | 1 | /* $OpenBSD: mlkem_tests_util.h,v 1.9 2025/08/15 14:47:54 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> | 3 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> |
4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> |
@@ -22,68 +22,7 @@ | |||
22 | #include <stddef.h> | 22 | #include <stddef.h> |
23 | #include <stdint.h> | 23 | #include <stdint.h> |
24 | 24 | ||
25 | #include "bytestring.h" | ||
26 | |||
27 | #include "mlkem.h" | ||
28 | #include "mlkem_internal.h" | ||
29 | |||
30 | int compare_data(const uint8_t *want, const uint8_t *got, size_t len, | 25 | int compare_data(const uint8_t *want, const uint8_t *got, size_t len, |
31 | const char *msg); | 26 | const char *msg); |
32 | 27 | ||
33 | int mlkem768_marshal_private_key(const void *priv, uint8_t **out_buf, | ||
34 | size_t *out_len); | ||
35 | int mlkem768_marshal_public_key(const void *pub, uint8_t **out_buf, | ||
36 | size_t *out_len); | ||
37 | int mlkem1024_marshal_private_key(const void *priv, uint8_t **out_buf, | ||
38 | size_t *out_len); | ||
39 | int mlkem1024_marshal_public_key(const void *pub, uint8_t **out_buf, | ||
40 | size_t *out_len); | ||
41 | |||
42 | int mlkem768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
43 | const uint8_t *ciphertext, size_t ciphertext_len, const void *priv); | ||
44 | void mlkem768_encap(uint8_t *out_ciphertext, | ||
45 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub); | ||
46 | void mlkem768_encap_external_entropy(uint8_t *out_ciphertext, | ||
47 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub, | ||
48 | const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); | ||
49 | int mlkem768_generate_key(uint8_t *out_encoded_public_key, | ||
50 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key); | ||
51 | int mlkem768_generate_key_external_entropy(uint8_t *out_encoded_public_key, | ||
52 | void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]); | ||
53 | int mlkem768_parse_private_key(void *priv, const uint8_t *in, size_t in_len); | ||
54 | int mlkem768_parse_public_key(void *pub, const uint8_t *in, size_t in_len); | ||
55 | void mlkem768_public_from_private(void *out_public_key, const void *private_key); | ||
56 | |||
57 | int mlkem1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
58 | const uint8_t *ciphertext, size_t ciphertext_len, const void *priv); | ||
59 | void mlkem1024_encap(uint8_t *out_ciphertext, | ||
60 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub); | ||
61 | void mlkem1024_encap_external_entropy(uint8_t *out_ciphertext, | ||
62 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub, | ||
63 | const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); | ||
64 | int mlkem1024_generate_key(uint8_t *out_encoded_public_key, | ||
65 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key); | ||
66 | int mlkem1024_generate_key_external_entropy(uint8_t *out_encoded_public_key, | ||
67 | void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]); | ||
68 | int mlkem1024_parse_private_key(void *priv, const uint8_t *in, size_t in_len); | ||
69 | int mlkem1024_parse_public_key(void *pub, const uint8_t *in, size_t in_len); | ||
70 | void mlkem1024_public_from_private(void *out_public_key, const void *private_key); | ||
71 | |||
72 | typedef int (*mlkem_marshal_private_key_fn)(const void *, uint8_t **, size_t *); | ||
73 | typedef int (*mlkem_marshal_public_key_fn)(const void *, uint8_t **, size_t *); | ||
74 | typedef int (*mlkem_decap_fn)(uint8_t [MLKEM_SHARED_SECRET_BYTES], | ||
75 | const uint8_t *, size_t, const void *); | ||
76 | typedef void (*mlkem_encap_fn)(uint8_t *, uint8_t [MLKEM_SHARED_SECRET_BYTES], | ||
77 | const void *); | ||
78 | typedef void (*mlkem_encap_external_entropy_fn)(uint8_t *, | ||
79 | uint8_t [MLKEM_SHARED_SECRET_BYTES], const void *, | ||
80 | const uint8_t [MLKEM_ENCAP_ENTROPY]); | ||
81 | typedef int (*mlkem_generate_key_fn)(uint8_t *, uint8_t *, void *); | ||
82 | typedef int (*mlkem_generate_key_external_entropy_fn)(uint8_t *, void *, | ||
83 | const uint8_t [MLKEM_SEED_BYTES]); | ||
84 | typedef int (*mlkem_parse_private_key_fn)(void *, const uint8_t *, size_t); | ||
85 | typedef int (*mlkem_parse_public_key_fn)(void *, const uint8_t *, size_t); | ||
86 | typedef void (*mlkem_public_from_private_fn)(void *out_public_key, | ||
87 | const void *private_key); | ||
88 | |||
89 | #endif /* MLKEM_TEST_UTIL_H */ | 28 | #endif /* MLKEM_TEST_UTIL_H */ |
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c b/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c index adb1c47d8e..f802324189 100644 --- a/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c +++ b/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mlkem_unittest.c,v 1.11 2025/05/21 03:46:20 tb Exp $ */ | 1 | /* $OpenBSD: mlkem_unittest.c,v 1.15 2025/08/17 19:26:35 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024 Google Inc. | 3 | * Copyright (c) 2024 Google Inc. |
4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> | 4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> |
@@ -22,100 +22,166 @@ | |||
22 | #include <stdlib.h> | 22 | #include <stdlib.h> |
23 | #include <string.h> | 23 | #include <string.h> |
24 | 24 | ||
25 | #include "bytestring.h" | 25 | #include <openssl/mlkem.h> |
26 | #include "mlkem.h" | ||
27 | 26 | ||
27 | #include "mlkem_internal.h" | ||
28 | #include "mlkem_tests_util.h" | 28 | #include "mlkem_tests_util.h" |
29 | 29 | ||
30 | struct unittest_ctx { | ||
31 | void *priv; | ||
32 | void *pub; | ||
33 | void *priv2; | ||
34 | void *pub2; | ||
35 | uint8_t *encoded_public_key; | ||
36 | size_t encoded_public_key_len; | ||
37 | uint8_t *ciphertext; | ||
38 | size_t ciphertext_len; | ||
39 | mlkem_decap_fn decap; | ||
40 | mlkem_encap_fn encap; | ||
41 | mlkem_generate_key_fn generate_key; | ||
42 | mlkem_parse_private_key_fn parse_private_key; | ||
43 | mlkem_parse_public_key_fn parse_public_key; | ||
44 | mlkem_marshal_private_key_fn marshal_private_key; | ||
45 | mlkem_marshal_public_key_fn marshal_public_key; | ||
46 | mlkem_public_from_private_fn public_from_private; | ||
47 | }; | ||
48 | |||
49 | static int | 30 | static int |
50 | MlKemUnitTest(struct unittest_ctx *ctx) | 31 | MlKemUnitTest(int rank) |
51 | { | 32 | { |
52 | uint8_t shared_secret1[MLKEM_SHARED_SECRET_BYTES]; | 33 | MLKEM_private_key *priv = NULL, *priv2 = NULL, *priv3 = NULL; |
53 | uint8_t shared_secret2[MLKEM_SHARED_SECRET_BYTES]; | 34 | MLKEM_public_key *pub = NULL, *pub2 = NULL, *pub3 = NULL; |
35 | uint8_t *encoded_public_key = NULL, *ciphertext = NULL, | ||
36 | *shared_secret2 = NULL, *shared_secret1 = NULL, | ||
37 | *encoded_private_key = NULL, *tmp_buf = NULL, *seed_buf = NULL; | ||
38 | size_t encoded_public_key_len, ciphertext_len, | ||
39 | encoded_private_key_len, tmp_buf_len; | ||
54 | uint8_t first_two_bytes[2]; | 40 | uint8_t first_two_bytes[2]; |
55 | uint8_t *encoded_private_key = NULL, *tmp_buf = NULL; | 41 | size_t s_len = 0; |
56 | size_t encoded_private_key_len, tmp_buf_len; | ||
57 | int failed = 0; | 42 | int failed = 0; |
58 | 43 | ||
59 | if (!ctx->generate_key(ctx->encoded_public_key, NULL, ctx->priv)) { | 44 | if ((pub = MLKEM_public_key_new(rank)) == NULL) { |
45 | warnx("public_key_new"); | ||
46 | failed |= 1; | ||
47 | } | ||
48 | |||
49 | if ((pub2 = MLKEM_public_key_new(rank)) == NULL) { | ||
50 | warnx("public_key_new"); | ||
51 | failed |= 1; | ||
52 | } | ||
53 | |||
54 | if ((priv = MLKEM_private_key_new(rank)) == NULL) { | ||
55 | warnx("private_key_new"); | ||
56 | failed |= 1; | ||
57 | } | ||
58 | |||
59 | if ((priv2 = MLKEM_private_key_new(rank)) == NULL) { | ||
60 | warnx("private_key_new"); | ||
61 | failed |= 1; | ||
62 | } | ||
63 | |||
64 | if (!MLKEM_generate_key(priv, &encoded_public_key, | ||
65 | &encoded_public_key_len, &seed_buf, &s_len)) { | ||
60 | warnx("generate_key failed"); | 66 | warnx("generate_key failed"); |
61 | failed |= 1; | 67 | failed |= 1; |
62 | } | 68 | } |
63 | 69 | ||
64 | memcpy(first_two_bytes, ctx->encoded_public_key, sizeof(first_two_bytes)); | 70 | if (s_len != MLKEM_SEED_LENGTH) { |
65 | memset(ctx->encoded_public_key, 0xff, sizeof(first_two_bytes)); | 71 | warnx("seed length %zu != %d", s_len, MLKEM_SEED_LENGTH); |
72 | failed |= 1; | ||
73 | } | ||
74 | |||
75 | if ((priv3 = MLKEM_private_key_new(rank)) == NULL) { | ||
76 | warnx("private_key_new"); | ||
77 | failed |= 1; | ||
78 | } | ||
79 | |||
80 | if ((pub3 = MLKEM_public_key_new(rank)) == NULL) { | ||
81 | warnx("public_key_new"); | ||
82 | failed |= 1; | ||
83 | } | ||
84 | |||
85 | if (!MLKEM_private_key_from_seed(priv3, seed_buf, s_len)) { | ||
86 | warnx("private_key_from_seed failed"); | ||
87 | failed |= 1; | ||
88 | } | ||
89 | |||
90 | free(seed_buf); | ||
91 | seed_buf = NULL; | ||
92 | |||
93 | if (!MLKEM_public_from_private(priv3, pub3)) { | ||
94 | warnx("public_from_private"); | ||
95 | failed |= 1; | ||
96 | } | ||
97 | |||
98 | memcpy(first_two_bytes, encoded_public_key, sizeof(first_two_bytes)); | ||
99 | memset(encoded_public_key, 0xff, sizeof(first_two_bytes)); | ||
66 | 100 | ||
67 | /* Parsing should fail because the first coefficient is >= kPrime. */ | 101 | /* Parsing should fail because the first coefficient is >= kPrime. */ |
68 | if (ctx->parse_public_key(ctx->pub, ctx->encoded_public_key, | 102 | if (MLKEM_parse_public_key(pub, encoded_public_key, |
69 | ctx->encoded_public_key_len)) { | 103 | encoded_public_key_len)) { |
70 | warnx("parse_public_key should have failed"); | 104 | warnx("parse_public_key should have failed"); |
71 | failed |= 1; | 105 | failed |= 1; |
72 | } | 106 | } |
73 | 107 | ||
74 | memcpy(ctx->encoded_public_key, first_two_bytes, sizeof(first_two_bytes)); | 108 | memcpy(encoded_public_key, first_two_bytes, sizeof(first_two_bytes)); |
75 | if (!ctx->parse_public_key(ctx->pub, ctx->encoded_public_key, | 109 | |
76 | ctx->encoded_public_key_len)) { | 110 | MLKEM_public_key_free(pub); |
77 | warnx("MLKEM768_parse_public_key"); | 111 | if ((pub = MLKEM_public_key_new(rank)) == NULL) { |
112 | warnx("public_key_new"); | ||
113 | failed |= 1; | ||
114 | } | ||
115 | if (!MLKEM_parse_public_key(pub, encoded_public_key, | ||
116 | encoded_public_key_len)) { | ||
117 | warnx("MLKEM_parse_public_key"); | ||
118 | failed |= 1; | ||
119 | } | ||
120 | |||
121 | if (!MLKEM_marshal_public_key(pub, &tmp_buf, &tmp_buf_len)) { | ||
122 | warnx("marshal_public_key"); | ||
123 | failed |= 1; | ||
124 | } | ||
125 | if (encoded_public_key_len != tmp_buf_len) { | ||
126 | warnx("encoded public key lengths differ %d != %d", | ||
127 | (int) encoded_public_key_len, (int) tmp_buf_len); | ||
128 | failed |= 1; | ||
129 | } | ||
130 | |||
131 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, | ||
132 | "encoded public keys") != 0) { | ||
133 | warnx("compare_data"); | ||
78 | failed |= 1; | 134 | failed |= 1; |
79 | } | 135 | } |
136 | free(tmp_buf); | ||
137 | tmp_buf = NULL; | ||
138 | tmp_buf_len = 0; | ||
80 | 139 | ||
81 | if (!ctx->marshal_public_key(ctx->pub, &tmp_buf, &tmp_buf_len)) { | 140 | if (!MLKEM_marshal_public_key(pub3, &tmp_buf, &tmp_buf_len)) { |
82 | warnx("marshal_public_key"); | 141 | warnx("marshal_public_key"); |
83 | failed |= 1; | 142 | failed |= 1; |
84 | } | 143 | } |
85 | if (ctx->encoded_public_key_len != tmp_buf_len) { | 144 | if (encoded_public_key_len != tmp_buf_len) { |
86 | warnx("encoded public key lengths differ"); | 145 | warnx("encoded public key lengths differ %d != %d", |
146 | (int) encoded_public_key_len, (int) tmp_buf_len); | ||
87 | failed |= 1; | 147 | failed |= 1; |
88 | } | 148 | } |
89 | 149 | ||
90 | if (compare_data(ctx->encoded_public_key, tmp_buf, tmp_buf_len, | 150 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, |
91 | "encoded public keys") != 0) { | 151 | "encoded public keys") != 0) { |
92 | warnx("compare_data"); | 152 | warnx("compare_data"); |
93 | failed |= 1; | 153 | failed |= 1; |
94 | } | 154 | } |
95 | free(tmp_buf); | 155 | free(tmp_buf); |
96 | tmp_buf = NULL; | 156 | tmp_buf = NULL; |
157 | tmp_buf_len = 0; | ||
97 | 158 | ||
98 | ctx->public_from_private(ctx->pub2, ctx->priv); | 159 | if (!MLKEM_public_from_private(priv, pub2)) { |
99 | if (!ctx->marshal_public_key(ctx->pub2, &tmp_buf, &tmp_buf_len)) { | 160 | warnx("public_from_private"); |
161 | failed |= 1; | ||
162 | } | ||
163 | if (!MLKEM_marshal_public_key(pub2, &tmp_buf, &tmp_buf_len)) { | ||
100 | warnx("marshal_public_key"); | 164 | warnx("marshal_public_key"); |
101 | failed |= 1; | 165 | failed |= 1; |
102 | } | 166 | } |
103 | if (ctx->encoded_public_key_len != tmp_buf_len) { | 167 | if (encoded_public_key_len != tmp_buf_len) { |
104 | warnx("encoded public key lengths differ"); | 168 | warnx("encoded public key lengths differ %d %d", |
169 | (int) encoded_public_key_len, (int) tmp_buf_len); | ||
105 | failed |= 1; | 170 | failed |= 1; |
106 | } | 171 | } |
107 | 172 | ||
108 | if (compare_data(ctx->encoded_public_key, tmp_buf, tmp_buf_len, | 173 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, |
109 | "encoded public keys") != 0) { | 174 | "encoded public keys") != 0) { |
110 | warnx("compare_data"); | 175 | warnx("compare_data"); |
111 | failed |= 1; | 176 | failed |= 1; |
112 | } | 177 | } |
113 | free(tmp_buf); | 178 | free(tmp_buf); |
114 | tmp_buf = NULL; | 179 | tmp_buf = NULL; |
180 | tmp_buf_len = 0; | ||
115 | 181 | ||
116 | if (!ctx->marshal_private_key(ctx->priv, &encoded_private_key, | 182 | if (!MLKEM_marshal_private_key(priv, &encoded_private_key, |
117 | &encoded_private_key_len)) { | 183 | &encoded_private_key_len)) { |
118 | warnx("mlkem768_encode_private_key"); | 184 | warnx("marshal_private_key"); |
119 | failed |= 1; | 185 | failed |= 1; |
120 | } | 186 | } |
121 | 187 | ||
@@ -123,27 +189,34 @@ MlKemUnitTest(struct unittest_ctx *ctx) | |||
123 | memset(encoded_private_key, 0xff, sizeof(first_two_bytes)); | 189 | memset(encoded_private_key, 0xff, sizeof(first_two_bytes)); |
124 | 190 | ||
125 | /* Parsing should fail because the first coefficient is >= kPrime. */ | 191 | /* Parsing should fail because the first coefficient is >= kPrime. */ |
126 | if (ctx->parse_private_key(ctx->priv2, encoded_private_key, | 192 | if (MLKEM_parse_private_key(priv2, encoded_private_key, |
127 | encoded_private_key_len)) { | 193 | encoded_private_key_len)) { |
128 | warnx("MLKEM768_parse_private_key should have failed"); | 194 | warnx("parse_private_key should have failed"); |
129 | failed |= 1; | 195 | failed |= 1; |
130 | } | 196 | } |
131 | 197 | ||
132 | memcpy(encoded_private_key, first_two_bytes, sizeof(first_two_bytes)); | 198 | memcpy(encoded_private_key, first_two_bytes, sizeof(first_two_bytes)); |
133 | 199 | ||
134 | if (!ctx->parse_private_key(ctx->priv2, encoded_private_key, | 200 | MLKEM_private_key_free(priv2); |
201 | priv2 = NULL; | ||
202 | |||
203 | if ((priv2 = MLKEM_private_key_new(rank)) == NULL) { | ||
204 | warnx("private_key_new"); | ||
205 | failed |= 1; | ||
206 | } | ||
207 | if (!MLKEM_parse_private_key(priv2, encoded_private_key, | ||
135 | encoded_private_key_len)) { | 208 | encoded_private_key_len)) { |
136 | warnx("MLKEM768_parse_private_key"); | 209 | warnx("parse_private_key"); |
137 | failed |= 1; | 210 | failed |= 1; |
138 | } | 211 | } |
139 | 212 | ||
140 | if (!ctx->marshal_private_key(ctx->priv2, &tmp_buf, &tmp_buf_len)) { | 213 | if (!MLKEM_marshal_private_key(priv2, &tmp_buf, &tmp_buf_len)) { |
141 | warnx("encode_private_key"); | 214 | warnx("marshal_private_key"); |
142 | failed |= 1; | 215 | failed |= 1; |
143 | } | 216 | } |
144 | 217 | ||
145 | if (encoded_private_key_len != tmp_buf_len) { | 218 | if (encoded_private_key_len != tmp_buf_len) { |
146 | warnx("encode private key lengths differ"); | 219 | warnx("encoded private key lengths differ"); |
147 | failed |= 1; | 220 | failed |= 1; |
148 | } | 221 | } |
149 | 222 | ||
@@ -156,106 +229,79 @@ MlKemUnitTest(struct unittest_ctx *ctx) | |||
156 | free(tmp_buf); | 229 | free(tmp_buf); |
157 | tmp_buf = NULL; | 230 | tmp_buf = NULL; |
158 | 231 | ||
159 | ctx->encap(ctx->ciphertext, shared_secret1, ctx->pub); | 232 | if (!MLKEM_encap(pub, &ciphertext, &ciphertext_len, &shared_secret1, |
160 | if (!ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len, | 233 | &s_len)) { |
161 | ctx->priv)) { | 234 | warnx("encap failed using pub"); |
235 | failed |= 1; | ||
236 | } | ||
237 | |||
238 | if (s_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
239 | warnx("seed length %zu != %d", s_len, | ||
240 | MLKEM_SHARED_SECRET_LENGTH); | ||
241 | failed |= 1; | ||
242 | } | ||
243 | |||
244 | if (!MLKEM_decap(priv, ciphertext, ciphertext_len, | ||
245 | &shared_secret2, &s_len)) { | ||
162 | warnx("decap() failed using priv"); | 246 | warnx("decap() failed using priv"); |
163 | failed |= 1; | 247 | failed |= 1; |
164 | } | 248 | } |
165 | if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES, | 249 | |
250 | if (s_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
251 | warnx("seed length %zu != %d", s_len, | ||
252 | MLKEM_SHARED_SECRET_LENGTH); | ||
253 | failed |= 1; | ||
254 | } | ||
255 | |||
256 | if (compare_data(shared_secret1, shared_secret2, s_len, | ||
166 | "shared secrets with priv") != 0) { | 257 | "shared secrets with priv") != 0) { |
167 | warnx("compare_data"); | 258 | warnx("compare_data"); |
168 | failed |= 1; | 259 | failed |= 1; |
169 | } | 260 | } |
170 | 261 | ||
171 | if (!ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len, | 262 | free(shared_secret2); |
172 | ctx->priv2)) { | 263 | shared_secret2 = NULL; |
264 | |||
265 | if (!MLKEM_decap(priv2, ciphertext, ciphertext_len, | ||
266 | &shared_secret2, &s_len)){ | ||
173 | warnx("decap() failed using priv2"); | 267 | warnx("decap() failed using priv2"); |
174 | failed |= 1; | 268 | failed |= 1; |
175 | } | 269 | } |
176 | if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES, | 270 | |
271 | if (s_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
272 | warnx("seed length %zu != %d", s_len, | ||
273 | MLKEM_SHARED_SECRET_LENGTH); | ||
274 | failed |= 1; | ||
275 | } | ||
276 | |||
277 | if (compare_data(shared_secret1, shared_secret2, s_len, | ||
177 | "shared secrets with priv2") != 0) { | 278 | "shared secrets with priv2") != 0) { |
178 | warnx("compare_data"); | 279 | warnx("compare_data"); |
179 | failed |= 1; | 280 | failed |= 1; |
180 | } | 281 | } |
181 | 282 | ||
283 | MLKEM_public_key_free(pub); | ||
284 | MLKEM_public_key_free(pub2); | ||
285 | MLKEM_public_key_free(pub3); | ||
286 | MLKEM_private_key_free(priv); | ||
287 | MLKEM_private_key_free(priv2); | ||
288 | MLKEM_private_key_free(priv3); | ||
289 | free(encoded_public_key); | ||
290 | free(ciphertext); | ||
182 | free(encoded_private_key); | 291 | free(encoded_private_key); |
292 | free(shared_secret1); | ||
293 | free(shared_secret2); | ||
183 | 294 | ||
184 | return failed; | 295 | return failed; |
185 | } | 296 | } |
186 | 297 | ||
187 | static int | ||
188 | mlkem768_unittest(void) | ||
189 | { | ||
190 | struct MLKEM768_private_key mlkem768_priv, mlkem768_priv2; | ||
191 | struct MLKEM768_public_key mlkem768_pub, mlkem768_pub2; | ||
192 | uint8_t mlkem768_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES]; | ||
193 | uint8_t mlkem768_ciphertext[MLKEM768_CIPHERTEXT_BYTES]; | ||
194 | struct unittest_ctx mlkem768_test = { | ||
195 | .priv = &mlkem768_priv, | ||
196 | .pub = &mlkem768_pub, | ||
197 | .priv2 = &mlkem768_priv2, | ||
198 | .pub2 = &mlkem768_pub2, | ||
199 | .encoded_public_key = mlkem768_encoded_public_key, | ||
200 | .encoded_public_key_len = sizeof(mlkem768_encoded_public_key), | ||
201 | .ciphertext = mlkem768_ciphertext, | ||
202 | .ciphertext_len = sizeof(mlkem768_ciphertext), | ||
203 | .decap = mlkem768_decap, | ||
204 | .encap = mlkem768_encap, | ||
205 | .generate_key = mlkem768_generate_key, | ||
206 | .parse_private_key = mlkem768_parse_private_key, | ||
207 | .parse_public_key = mlkem768_parse_public_key, | ||
208 | .marshal_private_key = mlkem768_marshal_private_key, | ||
209 | .marshal_public_key = mlkem768_marshal_public_key, | ||
210 | .public_from_private = mlkem768_public_from_private, | ||
211 | }; | ||
212 | |||
213 | return MlKemUnitTest(&mlkem768_test); | ||
214 | } | ||
215 | |||
216 | static int | ||
217 | mlkem1024_unittest(void) | ||
218 | { | ||
219 | struct MLKEM1024_private_key mlkem1024_priv, mlkem1024_priv2; | ||
220 | struct MLKEM1024_public_key mlkem1024_pub, mlkem1024_pub2; | ||
221 | uint8_t mlkem1024_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES]; | ||
222 | uint8_t mlkem1024_ciphertext[MLKEM1024_CIPHERTEXT_BYTES]; | ||
223 | struct unittest_ctx mlkem1024_test = { | ||
224 | .priv = &mlkem1024_priv, | ||
225 | .pub = &mlkem1024_pub, | ||
226 | .priv2 = &mlkem1024_priv2, | ||
227 | .pub2 = &mlkem1024_pub2, | ||
228 | .encoded_public_key = mlkem1024_encoded_public_key, | ||
229 | .encoded_public_key_len = sizeof(mlkem1024_encoded_public_key), | ||
230 | .ciphertext = mlkem1024_ciphertext, | ||
231 | .ciphertext_len = sizeof(mlkem1024_ciphertext), | ||
232 | .decap = mlkem1024_decap, | ||
233 | .encap = mlkem1024_encap, | ||
234 | .generate_key = mlkem1024_generate_key, | ||
235 | .parse_private_key = mlkem1024_parse_private_key, | ||
236 | .parse_public_key = mlkem1024_parse_public_key, | ||
237 | .marshal_private_key = mlkem1024_marshal_private_key, | ||
238 | .marshal_public_key = mlkem1024_marshal_public_key, | ||
239 | .public_from_private = mlkem1024_public_from_private, | ||
240 | }; | ||
241 | |||
242 | return MlKemUnitTest(&mlkem1024_test); | ||
243 | } | ||
244 | |||
245 | int | 298 | int |
246 | main(void) | 299 | main(void) |
247 | { | 300 | { |
248 | int failed = 0; | 301 | int failed = 0; |
249 | 302 | ||
250 | /* | 303 | failed |= MlKemUnitTest(RANK768); |
251 | * XXX - this is split into two helper functions since having a few | 304 | failed |= MlKemUnitTest(RANK1024); |
252 | * ML-KEM key blobs on the stack makes Emscripten's stack explode, | ||
253 | * leading to inscrutable silent failures unless ASAN is enabled. | ||
254 | * Go figure. | ||
255 | */ | ||
256 | |||
257 | failed |= mlkem768_unittest(); | ||
258 | failed |= mlkem1024_unittest(); | ||
259 | 305 | ||
260 | return failed; | 306 | return failed; |
261 | } | 307 | } |