diff options
Diffstat (limited to '')
-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 | 297 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c | 213 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h | 63 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_unittest.c | 318 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/parse_test_file.c | 13 |
7 files changed, 421 insertions, 667 deletions
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 5a61248090..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.2 2024/12/26 07:26:45 tb 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_encode_private_key_fn encode_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,118 +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 | 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, |
121 | ctx->public_from_private(ctx->pub, ctx->priv); | 124 | seed)) |
125 | errx(1, "generate_key_external_entropy"); | ||
126 | |||
127 | if (!MLKEM_public_from_private(priv, pub)) | ||
128 | errx(1, "public_from_private"); | ||
122 | 129 | ||
123 | /* hash in ek */ | 130 | /* hash in ek */ |
124 | shake_update(&results, ctx->encoded_public_key, | 131 | shake_update(&results, encoded_public_key, |
125 | ctx->encoded_public_key_len); | 132 | encoded_public_key_len); |
126 | 133 | ||
127 | /* marshal priv to dk as encoded_private_key */ | 134 | /* marshal priv to dk as encoded_private_key */ |
128 | if (!ctx->encode_private_key(ctx->priv, &encoded_private_key, | 135 | if (!MLKEM_marshal_private_key(priv, &encoded_private_key, |
129 | &encoded_private_key_len)) | 136 | &encoded_private_key_len)) |
130 | errx(1, "encode private key"); | 137 | errx(1, "marshal private key"); |
131 | 138 | ||
132 | /* hash in dk */ | 139 | /* hash in dk */ |
133 | shake_update(&results, encoded_private_key, | 140 | shake_update(&results, encoded_private_key, |
134 | encoded_private_key_len); | 141 | encoded_private_key_len); |
135 | 142 | ||
136 | free(encoded_private_key); | 143 | freezero(encoded_private_key, encoded_private_key_len); |
137 | 144 | ||
138 | /* draw m as encap entropy from DRNG */ | 145 | /* draw m as encap entropy from DRNG */ |
139 | shake_out(&drng, encap_entropy, sizeof(encap_entropy)); | 146 | shake_out(&drng, encap_entropy, sizeof(encap_entropy)); |
140 | 147 | ||
141 | /* generate ct as ciphertext, k as shared_secret */ | 148 | /* generate ct as ciphertext, k as shared_secret */ |
142 | ctx->encap_external_entropy(ctx->ciphertext, shared_secret, | 149 | if (!MLKEM_encap_external_entropy(pub, encap_entropy, |
143 | ctx->pub, encap_entropy); | 150 | &ciphertext, &ciphertext_len, &shared_secret, &s_len)) |
151 | errx(1, "encap_external_entropy"); | ||
144 | 152 | ||
145 | /* hash in ct */ | 153 | /* hash in ct */ |
146 | shake_update(&results, ctx->ciphertext, ctx->ciphertext_len); | 154 | shake_update(&results, ciphertext, ciphertext_len); |
147 | /* hash in k */ | 155 | /* hash in k */ |
148 | 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"); | ||
149 | 165 | ||
150 | /* draw ct as invalid_ciphertxt from DRNG */ | 166 | /* draw ct as invalid_ciphertxt from DRNG */ |
151 | shake_out(&drng, ctx->invalid_ciphertext, | 167 | shake_out(&drng, invalid_ciphertext, invalid_ciphertext_len); |
152 | ctx->invalid_ciphertext_len); | ||
153 | 168 | ||
154 | /* generate k as shared secret from invalid ciphertext */ | 169 | /* generate k as shared secret from invalid ciphertext */ |
155 | if (!ctx->decap(shared_secret, ctx->invalid_ciphertext, | 170 | if (!MLKEM_decap(priv, invalid_ciphertext, |
156 | ctx->invalid_ciphertext_len, ctx->priv)) | 171 | invalid_ciphertext_len, &shared_secret, &s_len)) |
157 | errx(1, "decap failed"); | 172 | errx(1, "decap failed, iteration %d", i); |
158 | 173 | ||
159 | /* hash in k */ | 174 | /* hash in k */ |
160 | 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); | ||
161 | } | 187 | } |
162 | shake_xof(&results); | 188 | shake_xof(&results); |
163 | shake_out(&results, out, sizeof(out)); | 189 | shake_out(&results, out, sizeof(out)); |
164 | 190 | ||
165 | return compare_data(ctx->expected, out, sizeof(out), "final result hash"); | 191 | return compare_data(expected, out, sizeof(out), "final result hash"); |
166 | } | 192 | } |
167 | 193 | ||
168 | int | 194 | int |
169 | main(void) | 195 | main(void) |
170 | { | 196 | { |
171 | uint8_t encoded_public_key768[MLKEM768_PUBLIC_KEY_BYTES]; | ||
172 | uint8_t ciphertext768[MLKEM768_CIPHERTEXT_BYTES]; | ||
173 | uint8_t invalid_ciphertext768[MLKEM768_CIPHERTEXT_BYTES]; | ||
174 | struct MLKEM768_private_key priv768; | ||
175 | struct MLKEM768_public_key pub768; | ||
176 | struct iteration_ctx iteration768 = { | ||
177 | .encoded_public_key = encoded_public_key768, | ||
178 | .encoded_public_key_len = sizeof(encoded_public_key768), | ||
179 | .ciphertext = ciphertext768, | ||
180 | .ciphertext_len = sizeof(ciphertext768), | ||
181 | .invalid_ciphertext = invalid_ciphertext768, | ||
182 | .invalid_ciphertext_len = sizeof(invalid_ciphertext768), | ||
183 | .priv = &priv768, | ||
184 | .pub = &pub768, | ||
185 | .encap_external_entropy = mlkem768_encap_external_entropy, | ||
186 | .encode_private_key = mlkem768_encode_private_key, | ||
187 | .generate_key_external_entropy = | ||
188 | mlkem768_generate_key_external_entropy, | ||
189 | .public_from_private = mlkem768_public_from_private, | ||
190 | .decap = mlkem768_decap, | ||
191 | .start = kExpectedSeedStart, | ||
192 | .start_len = sizeof(kExpectedSeedStart), | ||
193 | .expected = kExpectedAdam768, | ||
194 | .expected_len = sizeof(kExpectedAdam768), | ||
195 | }; | ||
196 | uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES]; | ||
197 | uint8_t ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES]; | ||
198 | uint8_t invalid_ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES]; | ||
199 | struct MLKEM1024_private_key priv1024; | ||
200 | struct MLKEM1024_public_key pub1024; | ||
201 | struct iteration_ctx iteration1024 = { | ||
202 | .encoded_public_key = encoded_public_key1024, | ||
203 | .encoded_public_key_len = sizeof(encoded_public_key1024), | ||
204 | .ciphertext = ciphertext1024, | ||
205 | .ciphertext_len = sizeof(ciphertext1024), | ||
206 | .invalid_ciphertext = invalid_ciphertext1024, | ||
207 | .invalid_ciphertext_len = sizeof(invalid_ciphertext1024), | ||
208 | .priv = &priv1024, | ||
209 | .pub = &pub1024, | ||
210 | .encap_external_entropy = mlkem1024_encap_external_entropy, | ||
211 | .encode_private_key = mlkem1024_encode_private_key, | ||
212 | .generate_key_external_entropy = | ||
213 | mlkem1024_generate_key_external_entropy, | ||
214 | .public_from_private = mlkem1024_public_from_private, | ||
215 | .decap = mlkem1024_decap, | ||
216 | .start = kExpectedSeedStart, | ||
217 | .start_len = sizeof(kExpectedSeedStart), | ||
218 | .expected = kExpectedAdam1024, | ||
219 | .expected_len = sizeof(kExpectedAdam1024), | ||
220 | }; | ||
221 | int failed = 0; | 197 | int failed = 0; |
222 | 198 | ||
223 | failed |= MlkemIterativeTest(&iteration768); | 199 | failed |= MlkemIterativeTest(RANK768); |
224 | failed |= MlkemIterativeTest(&iteration1024); | 200 | failed |= MlkemIterativeTest(RANK1024); |
225 | 201 | ||
226 | return failed; | 202 | return failed; |
227 | } | 203 | } |
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests.c index 2801a58890..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.2 2024/12/26 00:10:19 tb 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,20 +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, &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 | if ((failed = !should_fail)) | 117 | if ((failed = !should_fail)) |
117 | parse_info(p, "parse private key"); | 118 | parse_info(p, "parse private key"); |
118 | goto err; | 119 | goto err; |
119 | } | 120 | } |
120 | if (!decap->decap(shared_secret_buf, | 121 | if (!MLKEM_decap(priv_key, CBS_data(&ciphertext), CBS_len(&ciphertext), |
121 | CBS_data(&ciphertext), CBS_len(&ciphertext), decap->private_key)) { | 122 | &shared_secret_buf, &shared_secret_buf_len)) { |
122 | if ((failed = !should_fail)) | 123 | if ((failed = !should_fail)) |
123 | parse_info(p, "decap"); | 124 | parse_info(p, "decap"); |
124 | goto err; | 125 | goto err; |
125 | } | 126 | } |
126 | 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 | |||
127 | failed = !parse_data_equal(p, "shared_secret", &shared_secret, | 135 | failed = !parse_data_equal(p, "shared_secret", &shared_secret, |
128 | shared_secret_buf, sizeof(shared_secret_buf)); | 136 | shared_secret_buf, shared_secret_buf_len); |
129 | 137 | ||
130 | if (should_fail != failed) { | 138 | if (should_fail != failed) { |
131 | parse_info(p, "FAIL: should_fail %d, failed %d", | 139 | parse_info(p, "FAIL: should_fail %d, failed %d", |
@@ -134,6 +142,9 @@ MlkemDecapFileTest(struct decap_ctx *decap) | |||
134 | } | 142 | } |
135 | 143 | ||
136 | err: | 144 | err: |
145 | MLKEM_private_key_free(priv_key); | ||
146 | freezero(shared_secret_buf, shared_secret_buf_len); | ||
147 | |||
137 | return failed; | 148 | return failed; |
138 | } | 149 | } |
139 | 150 | ||
@@ -192,35 +203,49 @@ static int | |||
192 | MlkemNistDecapFileTest(struct decap_ctx *decap) | 203 | MlkemNistDecapFileTest(struct decap_ctx *decap) |
193 | { | 204 | { |
194 | struct parse *p = decap->parse_ctx; | 205 | struct parse *p = decap->parse_ctx; |
195 | uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES]; | 206 | MLKEM_private_key *priv_key = NULL; |
196 | CBS dk, c, k; | 207 | CBS dk, c, k; |
208 | uint8_t *shared_secret = NULL; | ||
209 | size_t shared_secret_len = 0; | ||
197 | int failed = 1; | 210 | int failed = 1; |
198 | 211 | ||
199 | parse_instruction_get_cbs(p, NIST_DECAP_DK, &dk); | 212 | parse_instruction_get_cbs(p, NIST_DECAP_DK, &dk); |
200 | parse_get_cbs(p, NIST_DECAP_C, &c); | 213 | parse_get_cbs(p, NIST_DECAP_C, &c); |
201 | parse_get_cbs(p, NIST_DECAP_K, &k); | 214 | parse_get_cbs(p, NIST_DECAP_K, &k); |
202 | 215 | ||
216 | if ((priv_key = MLKEM_private_key_new(decap->rank)) == NULL) | ||
217 | parse_errx(p, "MLKEM_private_key_new"); | ||
218 | |||
203 | if (!parse_length_equal(p, "private key", | 219 | if (!parse_length_equal(p, "private key", |
204 | decap->private_key_len, CBS_len(&dk))) | 220 | MLKEM_private_key_encoded_length(priv_key), CBS_len(&dk))) |
205 | goto err; | 221 | goto err; |
206 | if (!parse_length_equal(p, "shared secret", | 222 | if (!parse_length_equal(p, "shared secret", |
207 | MLKEM_SHARED_SECRET_BYTES, CBS_len(&k))) | 223 | MLKEM_SHARED_SECRET_LENGTH, CBS_len(&k))) |
208 | goto err; | 224 | goto err; |
209 | 225 | ||
210 | if (!decap->parse_private_key(decap->private_key, &dk)) { | 226 | if (!MLKEM_parse_private_key(priv_key, CBS_data(&dk), CBS_len(&dk))) { |
211 | parse_info(p, "parse private key"); | 227 | parse_info(p, "parse private key"); |
212 | goto err; | 228 | goto err; |
213 | } | 229 | } |
214 | if (!decap->decap(shared_secret, CBS_data(&c), CBS_len(&c), | 230 | if (!MLKEM_decap(priv_key, CBS_data(&c), CBS_len(&c), |
215 | decap->private_key)) { | 231 | &shared_secret, &shared_secret_len)) { |
216 | parse_info(p, "decap"); | 232 | parse_info(p, "decap"); |
217 | goto err; | 233 | goto err; |
218 | } | 234 | } |
219 | 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 | |||
220 | failed = !parse_data_equal(p, "shared secret", &k, | 242 | failed = !parse_data_equal(p, "shared secret", &k, |
221 | shared_secret, MLKEM_SHARED_SECRET_BYTES); | 243 | shared_secret, shared_secret_len); |
222 | 244 | ||
223 | err: | 245 | err: |
246 | MLKEM_private_key_free(priv_key); | ||
247 | freezero(shared_secret, shared_secret_len); | ||
248 | |||
224 | return failed; | 249 | return failed; |
225 | } | 250 | } |
226 | 251 | ||
@@ -244,46 +269,24 @@ static const struct test_parse nist_decap_parse = { | |||
244 | }; | 269 | }; |
245 | 270 | ||
246 | static int | 271 | static int |
247 | 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) |
248 | { | 273 | { |
249 | struct MLKEM768_private_key private_key768; | 274 | struct decap_ctx decap = { |
250 | struct decap_ctx decap768 = { | 275 | .rank = rank, |
251 | .private_key = &private_key768, | ||
252 | .private_key_len = MLKEM768_PRIVATE_KEY_BYTES, | ||
253 | |||
254 | .parse_private_key = mlkem768_parse_private_key, | ||
255 | .decap = mlkem768_decap, | ||
256 | }; | 276 | }; |
257 | struct MLKEM1024_private_key private_key1024; | ||
258 | struct decap_ctx decap1024 = { | ||
259 | .private_key = &private_key1024, | ||
260 | .private_key_len = MLKEM1024_PRIVATE_KEY_BYTES, | ||
261 | 277 | ||
262 | .parse_private_key = mlkem1024_parse_private_key, | 278 | if (test_type == TEST_TYPE_NORMAL) |
263 | .decap = mlkem1024_decap, | 279 | return parse_test_file(fn, &decap_parse, &decap); |
264 | }; | 280 | if (test_type == TEST_TYPE_NIST) |
265 | 281 | return parse_test_file(fn, &nist_decap_parse, &decap); | |
266 | if (size == 768 && test_type == TEST_TYPE_NORMAL) | ||
267 | return parse_test_file(fn, &decap_parse, &decap768); | ||
268 | if (size == 768 && test_type == TEST_TYPE_NIST) | ||
269 | return parse_test_file(fn, &nist_decap_parse, &decap768); | ||
270 | if (size == 1024 && test_type == TEST_TYPE_NORMAL) | ||
271 | return parse_test_file(fn, &decap_parse, &decap1024); | ||
272 | if (size == 1024 && test_type == TEST_TYPE_NIST) | ||
273 | return parse_test_file(fn, &nist_decap_parse, &decap1024); | ||
274 | 282 | ||
275 | 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); |
276 | } | 284 | } |
277 | 285 | ||
278 | struct encap_ctx { | 286 | struct encap_ctx { |
279 | struct parse *parse_ctx; | 287 | struct parse *parse_ctx; |
280 | 288 | ||
281 | void *public_key; | 289 | int rank; |
282 | uint8_t *ciphertext; | ||
283 | size_t ciphertext_len; | ||
284 | |||
285 | mlkem_parse_public_key_fn parse_public_key; | ||
286 | mlkem_encap_external_entropy_fn encap_external_entropy; | ||
287 | }; | 290 | }; |
288 | 291 | ||
289 | enum encap_states { | 292 | enum encap_states { |
@@ -349,8 +352,12 @@ static int | |||
349 | MlkemEncapFileTest(struct encap_ctx *encap) | 352 | MlkemEncapFileTest(struct encap_ctx *encap) |
350 | { | 353 | { |
351 | struct parse *p = encap->parse_ctx; | 354 | struct parse *p = encap->parse_ctx; |
352 | uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES]; | 355 | MLKEM_public_key *pub_key = NULL; |
353 | 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; | ||
354 | int should_fail; | 361 | int should_fail; |
355 | int failed = 1; | 362 | int failed = 1; |
356 | 363 | ||
@@ -360,18 +367,34 @@ MlkemEncapFileTest(struct encap_ctx *encap) | |||
360 | parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret); | 367 | parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret); |
361 | parse_get_int(p, ENCAP_RESULT, &should_fail); | 368 | parse_get_int(p, ENCAP_RESULT, &should_fail); |
362 | 369 | ||
363 | if (!encap->parse_public_key(encap->public_key, &public_key)) { | 370 | if ((pub_key = MLKEM_public_key_new(encap->rank)) == NULL) |
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))) { | ||
364 | if ((failed = !should_fail)) | 375 | if ((failed = !should_fail)) |
365 | parse_info(p, "parse public key"); | 376 | parse_info(p, "parse public key"); |
366 | goto err; | 377 | goto err; |
367 | } | 378 | } |
368 | encap->encap_external_entropy(encap->ciphertext, shared_secret_buf, | 379 | if (!MLKEM_encap_external_entropy(pub_key, CBS_data(&entropy), |
369 | 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 | } | ||
370 | 393 | ||
371 | failed = !parse_data_equal(p, "shared_secret", &shared_secret, | 394 | failed = !parse_data_equal(p, "shared_secret", &shared_secret, |
372 | shared_secret_buf, sizeof(shared_secret_buf)); | 395 | shared_secret_buf, shared_secret_buf_len); |
373 | failed |= !parse_data_equal(p, "ciphertext", &ciphertext, | 396 | failed |= !parse_data_equal(p, "ciphertext", &ciphertext, |
374 | encap->ciphertext, encap->ciphertext_len); | 397 | ciphertext_buf, ciphertext_buf_len); |
375 | 398 | ||
376 | if (should_fail != failed) { | 399 | if (should_fail != failed) { |
377 | parse_info(p, "FAIL: should_fail %d, failed %d", | 400 | parse_info(p, "FAIL: should_fail %d, failed %d", |
@@ -380,6 +403,10 @@ MlkemEncapFileTest(struct encap_ctx *encap) | |||
380 | } | 403 | } |
381 | 404 | ||
382 | 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 | |||
383 | return failed; | 410 | return failed; |
384 | } | 411 | } |
385 | 412 | ||
@@ -400,48 +427,19 @@ static const struct test_parse encap_parse = { | |||
400 | }; | 427 | }; |
401 | 428 | ||
402 | static int | 429 | static int |
403 | mlkem_encap_tests(const char *fn, size_t size) | 430 | mlkem_encap_tests(const char *fn, int rank) |
404 | { | 431 | { |
405 | struct MLKEM768_public_key public_key768; | 432 | struct encap_ctx encap = { |
406 | uint8_t ciphertext768[MLKEM768_CIPHERTEXT_BYTES]; | 433 | .rank = rank, |
407 | struct encap_ctx encap768 = { | ||
408 | .public_key = &public_key768, | ||
409 | .ciphertext = ciphertext768, | ||
410 | .ciphertext_len = sizeof(ciphertext768), | ||
411 | |||
412 | .parse_public_key = mlkem768_parse_public_key, | ||
413 | .encap_external_entropy = mlkem768_encap_external_entropy, | ||
414 | }; | ||
415 | struct MLKEM1024_public_key public_key1024; | ||
416 | uint8_t ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES]; | ||
417 | struct encap_ctx encap1024 = { | ||
418 | .public_key = &public_key1024, | ||
419 | .ciphertext = ciphertext1024, | ||
420 | .ciphertext_len = sizeof(ciphertext1024), | ||
421 | |||
422 | .parse_public_key = mlkem1024_parse_public_key, | ||
423 | .encap_external_entropy = mlkem1024_encap_external_entropy, | ||
424 | }; | 434 | }; |
425 | 435 | ||
426 | if (size == 768) | 436 | return parse_test_file(fn, &encap_parse, &encap); |
427 | return parse_test_file(fn, &encap_parse, &encap768); | ||
428 | if (size == 1024) | ||
429 | return parse_test_file(fn, &encap_parse, &encap1024); | ||
430 | |||
431 | errx(1, "unknown encap test: size %zu", size); | ||
432 | } | 437 | } |
433 | 438 | ||
434 | struct keygen_ctx { | 439 | struct keygen_ctx { |
435 | struct parse *parse_ctx; | 440 | struct parse *parse_ctx; |
436 | 441 | ||
437 | void *private_key; | 442 | int rank; |
438 | void *encoded_public_key; | ||
439 | size_t encoded_public_key_len; | ||
440 | size_t private_key_len; | ||
441 | size_t public_key_len; | ||
442 | |||
443 | mlkem_generate_key_external_entropy_fn generate_key_external_entropy; | ||
444 | mlkem_encode_private_key_fn encode_private_key; | ||
445 | }; | 443 | }; |
446 | 444 | ||
447 | enum keygen_states { | 445 | enum keygen_states { |
@@ -492,27 +490,38 @@ static int | |||
492 | MlkemKeygenFileTest(struct keygen_ctx *keygen) | 490 | MlkemKeygenFileTest(struct keygen_ctx *keygen) |
493 | { | 491 | { |
494 | struct parse *p = keygen->parse_ctx; | 492 | struct parse *p = keygen->parse_ctx; |
493 | MLKEM_private_key *priv_key = NULL; | ||
495 | CBS seed, public_key, private_key; | 494 | CBS seed, public_key, private_key; |
496 | uint8_t *encoded_private_key = NULL; | 495 | uint8_t *encoded_private_key = NULL; |
497 | 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; | ||
498 | int failed = 1; | 499 | int failed = 1; |
499 | 500 | ||
500 | parse_get_cbs(p, KEYGEN_SEED, &seed); | 501 | parse_get_cbs(p, KEYGEN_SEED, &seed); |
501 | parse_get_cbs(p, KEYGEN_PUBLIC_KEY, &public_key); | 502 | parse_get_cbs(p, KEYGEN_PUBLIC_KEY, &public_key); |
502 | parse_get_cbs(p, KEYGEN_PRIVATE_KEY, &private_key); | 503 | parse_get_cbs(p, KEYGEN_PRIVATE_KEY, &private_key); |
503 | 504 | ||
504 | 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))) |
505 | 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 | |||
506 | if (!parse_length_equal(p, "public key", | 517 | if (!parse_length_equal(p, "public key", |
507 | keygen->public_key_len, CBS_len(&public_key))) | 518 | encoded_public_key_len, CBS_len(&public_key))) |
508 | goto err; | 519 | goto err; |
509 | if (!parse_length_equal(p, "private key", | 520 | if (!parse_length_equal(p, "private key", |
510 | keygen->private_key_len, CBS_len(&private_key))) | 521 | MLKEM_private_key_encoded_length(priv_key), CBS_len(&private_key))) |
511 | goto err; | 522 | goto err; |
512 | 523 | ||
513 | keygen->generate_key_external_entropy(keygen->encoded_public_key, | 524 | if (!MLKEM_marshal_private_key(priv_key, |
514 | keygen->private_key, CBS_data(&seed)); | ||
515 | if (!keygen->encode_private_key(keygen->private_key, | ||
516 | &encoded_private_key, &encoded_private_key_len)) { | 525 | &encoded_private_key, &encoded_private_key_len)) { |
517 | parse_info(p, "encode private key"); | 526 | parse_info(p, "encode private key"); |
518 | goto err; | 527 | goto err; |
@@ -521,10 +530,12 @@ MlkemKeygenFileTest(struct keygen_ctx *keygen) | |||
521 | failed = !parse_data_equal(p, "private key", &private_key, | 530 | failed = !parse_data_equal(p, "private key", &private_key, |
522 | encoded_private_key, encoded_private_key_len); | 531 | encoded_private_key, encoded_private_key_len); |
523 | failed |= !parse_data_equal(p, "public key", &public_key, | 532 | failed |= !parse_data_equal(p, "public key", &public_key, |
524 | keygen->encoded_public_key, keygen->encoded_public_key_len); | 533 | encoded_public_key, encoded_public_key_len); |
525 | 534 | ||
526 | err: | 535 | err: |
536 | MLKEM_private_key_free(priv_key); | ||
527 | 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); | ||
528 | 539 | ||
529 | return failed; | 540 | return failed; |
530 | } | 541 | } |
@@ -584,12 +595,15 @@ static int | |||
584 | MlkemNistKeygenFileTest(struct keygen_ctx *keygen) | 595 | MlkemNistKeygenFileTest(struct keygen_ctx *keygen) |
585 | { | 596 | { |
586 | struct parse *p = keygen->parse_ctx; | 597 | struct parse *p = keygen->parse_ctx; |
598 | MLKEM_private_key *priv_key = NULL; | ||
587 | CBB seed_cbb; | 599 | CBB seed_cbb; |
588 | CBS z, d, ek, dk; | 600 | CBS z, d, ek, dk; |
589 | uint8_t seed[MLKEM_SEED_BYTES]; | 601 | uint8_t seed[MLKEM_SEED_LENGTH]; |
590 | size_t seed_len; | 602 | size_t seed_len; |
591 | uint8_t *encoded_private_key = NULL; | 603 | uint8_t *encoded_private_key = NULL; |
592 | 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; | ||
593 | int failed = 1; | 607 | int failed = 1; |
594 | 608 | ||
595 | parse_get_cbs(p, NIST_KEYGEN_Z, &z); | 609 | parse_get_cbs(p, NIST_KEYGEN_Z, &z); |
@@ -606,24 +620,33 @@ MlkemNistKeygenFileTest(struct keygen_ctx *keygen) | |||
606 | if (!CBB_finish(&seed_cbb, NULL, &seed_len)) | 620 | if (!CBB_finish(&seed_cbb, NULL, &seed_len)) |
607 | parse_errx(p, "CBB_finish"); | 621 | parse_errx(p, "CBB_finish"); |
608 | 622 | ||
609 | 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)) |
610 | goto err; | 624 | goto err; |
611 | 625 | ||
612 | keygen->generate_key_external_entropy(keygen->encoded_public_key, | 626 | if ((priv_key = MLKEM_private_key_new(keygen->rank)) == NULL) |
613 | keygen->private_key, seed); | 627 | parse_errx(p, "MLKEM_private_key_new"); |
614 | if (!keygen->encode_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, | ||
615 | &encoded_private_key, &encoded_private_key_len)) { | 636 | &encoded_private_key, &encoded_private_key_len)) { |
616 | parse_info(p, "encode private key"); | 637 | parse_info(p, "encode private key"); |
617 | goto err; | 638 | goto err; |
618 | } | 639 | } |
619 | 640 | ||
620 | failed = !parse_data_equal(p, "public key", &ek, | 641 | failed = !parse_data_equal(p, "public key", &ek, |
621 | keygen->encoded_public_key, keygen->encoded_public_key_len); | 642 | encoded_public_key, encoded_public_key_len); |
622 | failed |= !parse_data_equal(p, "private key", &dk, | 643 | failed |= !parse_data_equal(p, "private key", &dk, |
623 | encoded_private_key, encoded_private_key_len); | 644 | encoded_private_key, encoded_private_key_len); |
624 | 645 | ||
625 | err: | 646 | err: |
647 | MLKEM_private_key_free(priv_key); | ||
626 | 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); | ||
627 | 650 | ||
628 | return failed; | 651 | return failed; |
629 | } | 652 | } |
@@ -645,73 +668,45 @@ static const struct test_parse nist_keygen_parse = { | |||
645 | }; | 668 | }; |
646 | 669 | ||
647 | static int | 670 | static int |
648 | 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) |
649 | { | 672 | { |
650 | struct MLKEM768_private_key private_key768; | 673 | struct keygen_ctx keygen = { |
651 | uint8_t encoded_public_key768[MLKEM768_PUBLIC_KEY_BYTES]; | 674 | .rank = rank, |
652 | struct keygen_ctx keygen768 = { | ||
653 | .private_key = &private_key768, | ||
654 | .encoded_public_key = encoded_public_key768, | ||
655 | .encoded_public_key_len = sizeof(encoded_public_key768), | ||
656 | .private_key_len = MLKEM768_PRIVATE_KEY_BYTES, | ||
657 | .public_key_len = MLKEM768_PUBLIC_KEY_BYTES, | ||
658 | .generate_key_external_entropy = | ||
659 | mlkem768_generate_key_external_entropy, | ||
660 | .encode_private_key = | ||
661 | mlkem768_encode_private_key, | ||
662 | }; | ||
663 | struct MLKEM1024_private_key private_key1024; | ||
664 | uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES]; | ||
665 | struct keygen_ctx keygen1024 = { | ||
666 | .private_key = &private_key1024, | ||
667 | .encoded_public_key = encoded_public_key1024, | ||
668 | .encoded_public_key_len = sizeof(encoded_public_key1024), | ||
669 | .private_key_len = MLKEM1024_PRIVATE_KEY_BYTES, | ||
670 | .public_key_len = MLKEM1024_PUBLIC_KEY_BYTES, | ||
671 | |||
672 | .generate_key_external_entropy = | ||
673 | mlkem1024_generate_key_external_entropy, | ||
674 | .encode_private_key = | ||
675 | mlkem1024_encode_private_key, | ||
676 | }; | 675 | }; |
677 | 676 | ||
678 | if (size == 768 && test_type == TEST_TYPE_NORMAL) | 677 | if (test_type == TEST_TYPE_NORMAL) |
679 | return parse_test_file(fn, &keygen_parse, &keygen768); | 678 | return parse_test_file(fn, &keygen_parse, &keygen); |
680 | if (size == 768 && test_type == TEST_TYPE_NIST) | 679 | if (test_type == TEST_TYPE_NIST) |
681 | return parse_test_file(fn, &nist_keygen_parse, &keygen768); | 680 | return parse_test_file(fn, &nist_keygen_parse, &keygen); |
682 | if (size == 1024 && test_type == TEST_TYPE_NORMAL) | ||
683 | return parse_test_file(fn, &keygen_parse, &keygen1024); | ||
684 | if (size == 1024 && test_type == TEST_TYPE_NIST) | ||
685 | return parse_test_file(fn, &nist_keygen_parse, &keygen1024); | ||
686 | 681 | ||
687 | 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); |
688 | } | 683 | } |
689 | 684 | ||
690 | static int | 685 | static int |
691 | run_mlkem_test(const char *test, const char *fn) | 686 | run_mlkem_test(const char *test, const char *fn) |
692 | { | 687 | { |
693 | if (strcmp(test, "mlkem768_decap_tests") == 0) | 688 | if (strcmp(test, "mlkem768_decap_tests") == 0) |
694 | return mlkem_decap_tests(fn, 768, TEST_TYPE_NORMAL); | 689 | return mlkem_decap_tests(fn, RANK768, TEST_TYPE_NORMAL); |
695 | if (strcmp(test, "mlkem768_nist_decap_tests") == 0) | 690 | if (strcmp(test, "mlkem768_nist_decap_tests") == 0) |
696 | return mlkem_decap_tests(fn, 768, TEST_TYPE_NIST); | 691 | return mlkem_decap_tests(fn, RANK768, TEST_TYPE_NIST); |
697 | if (strcmp(test, "mlkem1024_decap_tests") == 0) | 692 | if (strcmp(test, "mlkem1024_decap_tests") == 0) |
698 | return mlkem_decap_tests(fn, 1024, TEST_TYPE_NORMAL); | 693 | return mlkem_decap_tests(fn, RANK1024, TEST_TYPE_NORMAL); |
699 | if (strcmp(test, "mlkem1024_nist_decap_tests") == 0) | 694 | if (strcmp(test, "mlkem1024_nist_decap_tests") == 0) |
700 | return mlkem_decap_tests(fn, 1024, TEST_TYPE_NIST); | 695 | return mlkem_decap_tests(fn, RANK1024, TEST_TYPE_NIST); |
701 | 696 | ||
702 | if (strcmp(test, "mlkem768_encap_tests") == 0) | 697 | if (strcmp(test, "mlkem768_encap_tests") == 0) |
703 | return mlkem_encap_tests(fn, 768); | 698 | return mlkem_encap_tests(fn, RANK768); |
704 | if (strcmp(test, "mlkem1024_encap_tests") == 0) | 699 | if (strcmp(test, "mlkem1024_encap_tests") == 0) |
705 | return mlkem_encap_tests(fn, 1024); | 700 | return mlkem_encap_tests(fn, RANK1024); |
706 | 701 | ||
707 | if (strcmp(test, "mlkem768_keygen_tests") == 0) | 702 | if (strcmp(test, "mlkem768_keygen_tests") == 0) |
708 | return mlkem_keygen_tests(fn, 768, TEST_TYPE_NORMAL); | 703 | return mlkem_keygen_tests(fn, RANK768, TEST_TYPE_NORMAL); |
709 | if (strcmp(test, "mlkem768_nist_keygen_tests") == 0) | 704 | if (strcmp(test, "mlkem768_nist_keygen_tests") == 0) |
710 | return mlkem_keygen_tests(fn, 768, TEST_TYPE_NIST); | 705 | return mlkem_keygen_tests(fn, RANK768, TEST_TYPE_NIST); |
711 | if (strcmp(test, "mlkem1024_keygen_tests") == 0) | 706 | if (strcmp(test, "mlkem1024_keygen_tests") == 0) |
712 | return mlkem_keygen_tests(fn, 1024, TEST_TYPE_NORMAL); | 707 | return mlkem_keygen_tests(fn, RANK1024, TEST_TYPE_NORMAL); |
713 | if (strcmp(test, "mlkem1024_nist_keygen_tests") == 0) | 708 | if (strcmp(test, "mlkem1024_nist_keygen_tests") == 0) |
714 | return mlkem_keygen_tests(fn, 1024, TEST_TYPE_NIST); | 709 | return mlkem_keygen_tests(fn, RANK1024, TEST_TYPE_NIST); |
715 | 710 | ||
716 | errx(1, "unknown test %s (test file %s)", test, fn); | 711 | errx(1, "unknown test %s (test file %s)", test, fn); |
717 | } | 712 | } |
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c index 1bb2ed3a8b..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.5 2024/12/26 00:04:24 tb 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,209 +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_encode_private_key(const void *private_key, uint8_t **out_buf, | ||
65 | size_t *out_len) | ||
66 | { | ||
67 | CBB cbb; | ||
68 | int ret = 0; | ||
69 | |||
70 | if (!CBB_init(&cbb, MLKEM768_PUBLIC_KEY_BYTES)) | ||
71 | goto err; | ||
72 | if (!MLKEM768_marshal_private_key(&cbb, private_key)) | ||
73 | goto err; | ||
74 | if (!CBB_finish(&cbb, out_buf, out_len)) | ||
75 | goto err; | ||
76 | |||
77 | ret = 1; | ||
78 | |||
79 | err: | ||
80 | CBB_cleanup(&cbb); | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | int | ||
86 | mlkem768_encode_public_key(const void *public_key, uint8_t **out_buf, | ||
87 | size_t *out_len) | ||
88 | { | ||
89 | CBB cbb; | ||
90 | int ret = 0; | ||
91 | |||
92 | if (!CBB_init(&cbb, MLKEM768_PUBLIC_KEY_BYTES)) | ||
93 | goto err; | ||
94 | if (!MLKEM768_marshal_public_key(&cbb, public_key)) | ||
95 | goto err; | ||
96 | if (!CBB_finish(&cbb, out_buf, out_len)) | ||
97 | goto err; | ||
98 | |||
99 | ret = 1; | ||
100 | |||
101 | err: | ||
102 | CBB_cleanup(&cbb); | ||
103 | |||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | int | ||
108 | mlkem1024_encode_private_key(const void *private_key, uint8_t **out_buf, | ||
109 | size_t *out_len) | ||
110 | { | ||
111 | CBB cbb; | ||
112 | int ret = 0; | ||
113 | |||
114 | if (!CBB_init(&cbb, MLKEM1024_PUBLIC_KEY_BYTES)) | ||
115 | goto err; | ||
116 | if (!MLKEM1024_marshal_private_key(&cbb, private_key)) | ||
117 | goto err; | ||
118 | if (!CBB_finish(&cbb, out_buf, out_len)) | ||
119 | goto err; | ||
120 | |||
121 | ret = 1; | ||
122 | |||
123 | err: | ||
124 | CBB_cleanup(&cbb); | ||
125 | |||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | int | ||
130 | mlkem1024_encode_public_key(const void *public_key, uint8_t **out_buf, | ||
131 | size_t *out_len) | ||
132 | { | ||
133 | CBB cbb; | ||
134 | int ret = 0; | ||
135 | |||
136 | if (!CBB_init(&cbb, MLKEM1024_PUBLIC_KEY_BYTES)) | ||
137 | goto err; | ||
138 | if (!MLKEM1024_marshal_public_key(&cbb, public_key)) | ||
139 | goto err; | ||
140 | if (!CBB_finish(&cbb, out_buf, out_len)) | ||
141 | goto err; | ||
142 | |||
143 | ret = 1; | ||
144 | |||
145 | err: | ||
146 | CBB_cleanup(&cbb); | ||
147 | |||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | int | ||
152 | mlkem768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
153 | const uint8_t *ciphertext, size_t ciphertext_len, const void *private_key) | ||
154 | { | ||
155 | return MLKEM768_decap(out_shared_secret, ciphertext, ciphertext_len, | ||
156 | private_key); | ||
157 | } | ||
158 | |||
159 | void | ||
160 | mlkem768_encap(uint8_t *out_ciphertext, | ||
161 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
162 | const void *public_key) | ||
163 | { | ||
164 | MLKEM768_encap(out_ciphertext, out_shared_secret, public_key); | ||
165 | } | ||
166 | |||
167 | void | ||
168 | mlkem768_encap_external_entropy(uint8_t *out_ciphertext, | ||
169 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
170 | const void *public_key, const uint8_t entropy[MLKEM_ENCAP_ENTROPY]) | ||
171 | { | ||
172 | MLKEM768_encap_external_entropy(out_ciphertext, out_shared_secret, | ||
173 | public_key, entropy); | ||
174 | } | ||
175 | |||
176 | void | ||
177 | mlkem768_generate_key(uint8_t *out_encoded_public_key, | ||
178 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key) | ||
179 | { | ||
180 | MLKEM768_generate_key(out_encoded_public_key, optional_out_seed, | ||
181 | out_private_key); | ||
182 | } | ||
183 | |||
184 | void | ||
185 | mlkem768_generate_key_external_entropy(uint8_t *out_encoded_public_key, | ||
186 | void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]) | ||
187 | { | ||
188 | MLKEM768_generate_key_external_entropy(out_encoded_public_key, | ||
189 | out_private_key, entropy); | ||
190 | } | ||
191 | |||
192 | int | ||
193 | mlkem768_parse_private_key(void *out_private_key, CBS *private_key_cbs) | ||
194 | { | ||
195 | return MLKEM768_parse_private_key(out_private_key, private_key_cbs); | ||
196 | } | ||
197 | |||
198 | int | ||
199 | mlkem768_parse_public_key(void *out_public_key, CBS *public_key_cbs) | ||
200 | { | ||
201 | return MLKEM768_parse_public_key(out_public_key, public_key_cbs); | ||
202 | } | ||
203 | |||
204 | void | ||
205 | mlkem768_public_from_private(void *out_public_key, const void *private_key) | ||
206 | { | ||
207 | MLKEM768_public_from_private(out_public_key, private_key); | ||
208 | } | ||
209 | |||
210 | int | ||
211 | mlkem1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
212 | const uint8_t *ciphertext, size_t ciphertext_len, const void *private_key) | ||
213 | { | ||
214 | return MLKEM1024_decap(out_shared_secret, ciphertext, ciphertext_len, | ||
215 | private_key); | ||
216 | } | ||
217 | |||
218 | void | ||
219 | mlkem1024_encap(uint8_t *out_ciphertext, | ||
220 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
221 | const void *public_key) | ||
222 | { | ||
223 | MLKEM1024_encap(out_ciphertext, out_shared_secret, public_key); | ||
224 | } | ||
225 | |||
226 | void | ||
227 | mlkem1024_encap_external_entropy(uint8_t *out_ciphertext, | ||
228 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
229 | const void *public_key, const uint8_t entropy[MLKEM_ENCAP_ENTROPY]) | ||
230 | { | ||
231 | MLKEM1024_encap_external_entropy(out_ciphertext, out_shared_secret, | ||
232 | public_key, entropy); | ||
233 | } | ||
234 | |||
235 | void | ||
236 | mlkem1024_generate_key(uint8_t *out_encoded_public_key, | ||
237 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key) | ||
238 | { | ||
239 | MLKEM1024_generate_key(out_encoded_public_key, optional_out_seed, | ||
240 | out_private_key); | ||
241 | } | ||
242 | |||
243 | void | ||
244 | mlkem1024_generate_key_external_entropy(uint8_t *out_encoded_public_key, | ||
245 | void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]) | ||
246 | { | ||
247 | MLKEM1024_generate_key_external_entropy(out_encoded_public_key, | ||
248 | out_private_key, entropy); | ||
249 | } | ||
250 | |||
251 | int | ||
252 | mlkem1024_parse_private_key(void *out_private_key, CBS *private_key_cbs) | ||
253 | { | ||
254 | return MLKEM1024_parse_private_key(out_private_key, private_key_cbs); | ||
255 | } | ||
256 | |||
257 | void | ||
258 | mlkem1024_public_from_private(void *out_public_key, const void *private_key) | ||
259 | { | ||
260 | MLKEM1024_public_from_private(out_public_key, private_key); | ||
261 | } | ||
262 | |||
263 | int | ||
264 | mlkem1024_parse_public_key(void *out_public_key, CBS *public_key_cbs) | ||
265 | { | ||
266 | return MLKEM1024_parse_public_key(out_public_key, public_key_cbs); | ||
267 | } | ||
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h index 7fbe6f76a9..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.4 2024/12/26 00:04:24 tb 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_encode_private_key(const void *priv, uint8_t **out_buf, | ||
34 | size_t *out_len); | ||
35 | int mlkem768_encode_public_key(const void *pub, uint8_t **out_buf, | ||
36 | size_t *out_len); | ||
37 | int mlkem1024_encode_private_key(const void *priv, uint8_t **out_buf, | ||
38 | size_t *out_len); | ||
39 | int mlkem1024_encode_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 | void mlkem768_generate_key(uint8_t *out_encoded_public_key, | ||
50 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key); | ||
51 | void 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, CBS *private_key_cbs); | ||
54 | int mlkem768_parse_public_key(void *pub, CBS *in); | ||
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 | void mlkem1024_generate_key(uint8_t *out_encoded_public_key, | ||
65 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key); | ||
66 | void 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, CBS *private_key_cbs); | ||
69 | int mlkem1024_parse_public_key(void *pub, CBS *in); | ||
70 | void mlkem1024_public_from_private(void *out_public_key, const void *private_key); | ||
71 | |||
72 | typedef int (*mlkem_encode_private_key_fn)(const void *, uint8_t **, size_t *); | ||
73 | typedef int (*mlkem_encode_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 void (*mlkem_generate_key_fn)(uint8_t *, uint8_t *, void *); | ||
82 | typedef void (*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 *, CBS *); | ||
85 | typedef int (*mlkem_parse_public_key_fn)(void *, CBS *); | ||
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 23b3d8b261..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.6 2024/12/26 12:35:25 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,132 +22,201 @@ | |||
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_encode_private_key_fn encode_private_key; | ||
45 | mlkem_encode_public_key_fn encode_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 | CBS cbs; | ||
58 | int failed = 0; | 42 | int failed = 0; |
59 | 43 | ||
60 | 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)) { | ||
66 | warnx("generate_key failed"); | ||
67 | failed |= 1; | ||
68 | } | ||
69 | |||
70 | if (s_len != MLKEM_SEED_LENGTH) { | ||
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 | } | ||
61 | 84 | ||
62 | memcpy(first_two_bytes, ctx->encoded_public_key, sizeof(first_two_bytes)); | 85 | if (!MLKEM_private_key_from_seed(priv3, seed_buf, s_len)) { |
63 | memset(ctx->encoded_public_key, 0xff, sizeof(first_two_bytes)); | 86 | warnx("private_key_from_seed failed"); |
87 | failed |= 1; | ||
88 | } | ||
89 | |||
90 | free(seed_buf); | ||
91 | seed_buf = NULL; | ||
64 | 92 | ||
65 | CBS_init(&cbs, ctx->encoded_public_key, ctx->encoded_public_key_len); | 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, &cbs)) { | 102 | if (MLKEM_parse_public_key(pub, encoded_public_key, |
103 | encoded_public_key_len)) { | ||
69 | warnx("parse_public_key should have failed"); | 104 | warnx("parse_public_key should have failed"); |
70 | failed |= 1; | 105 | failed |= 1; |
71 | } | 106 | } |
72 | 107 | ||
73 | memcpy(ctx->encoded_public_key, first_two_bytes, sizeof(first_two_bytes)); | 108 | memcpy(encoded_public_key, first_two_bytes, sizeof(first_two_bytes)); |
74 | CBS_init(&cbs, ctx->encoded_public_key, ctx->encoded_public_key_len); | 109 | |
75 | if (!ctx->parse_public_key(ctx->pub, &cbs)) { | 110 | MLKEM_public_key_free(pub); |
76 | 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"); | ||
77 | failed |= 1; | 118 | failed |= 1; |
78 | } | 119 | } |
79 | 120 | ||
80 | if (CBS_len(&cbs) != 0u) { | 121 | if (!MLKEM_marshal_public_key(pub, &tmp_buf, &tmp_buf_len)) { |
81 | warnx("CBS_len must be 0"); | 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); | ||
82 | failed |= 1; | 128 | failed |= 1; |
83 | } | 129 | } |
84 | 130 | ||
85 | if (!ctx->encode_public_key(ctx->pub, &tmp_buf, &tmp_buf_len)) { | 131 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, |
86 | warnx("encode_public_key"); | 132 | "encoded public keys") != 0) { |
133 | warnx("compare_data"); | ||
87 | failed |= 1; | 134 | failed |= 1; |
88 | } | 135 | } |
89 | if (ctx->encoded_public_key_len != tmp_buf_len) { | 136 | free(tmp_buf); |
90 | warnx("encoded public key lengths differ"); | 137 | tmp_buf = NULL; |
138 | tmp_buf_len = 0; | ||
139 | |||
140 | if (!MLKEM_marshal_public_key(pub3, &tmp_buf, &tmp_buf_len)) { | ||
141 | warnx("marshal_public_key"); | ||
142 | failed |= 1; | ||
143 | } | ||
144 | if (encoded_public_key_len != tmp_buf_len) { | ||
145 | warnx("encoded public key lengths differ %d != %d", | ||
146 | (int) encoded_public_key_len, (int) tmp_buf_len); | ||
91 | failed |= 1; | 147 | failed |= 1; |
92 | } | 148 | } |
93 | 149 | ||
94 | if (compare_data(ctx->encoded_public_key, tmp_buf, tmp_buf_len, | 150 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, |
95 | "encoded public keys") != 0) { | 151 | "encoded public keys") != 0) { |
96 | warnx("compare_data"); | 152 | warnx("compare_data"); |
97 | failed |= 1; | 153 | failed |= 1; |
98 | } | 154 | } |
99 | free(tmp_buf); | 155 | free(tmp_buf); |
100 | tmp_buf = NULL; | 156 | tmp_buf = NULL; |
157 | tmp_buf_len = 0; | ||
101 | 158 | ||
102 | ctx->public_from_private(ctx->pub2, ctx->priv); | 159 | if (!MLKEM_public_from_private(priv, pub2)) { |
103 | if (!ctx->encode_public_key(ctx->pub2, &tmp_buf, &tmp_buf_len)) { | 160 | warnx("public_from_private"); |
104 | warnx("encode_public_key"); | 161 | failed |= 1; |
162 | } | ||
163 | if (!MLKEM_marshal_public_key(pub2, &tmp_buf, &tmp_buf_len)) { | ||
164 | warnx("marshal_public_key"); | ||
105 | failed |= 1; | 165 | failed |= 1; |
106 | } | 166 | } |
107 | if (ctx->encoded_public_key_len != tmp_buf_len) { | 167 | if (encoded_public_key_len != tmp_buf_len) { |
108 | 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); | ||
109 | failed |= 1; | 170 | failed |= 1; |
110 | } | 171 | } |
111 | 172 | ||
112 | if (compare_data(ctx->encoded_public_key, tmp_buf, tmp_buf_len, | 173 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, |
113 | "encoded public keys") != 0) { | 174 | "encoded public keys") != 0) { |
114 | warnx("compare_data"); | 175 | warnx("compare_data"); |
115 | failed |= 1; | 176 | failed |= 1; |
116 | } | 177 | } |
117 | free(tmp_buf); | 178 | free(tmp_buf); |
118 | tmp_buf = NULL; | 179 | tmp_buf = NULL; |
180 | tmp_buf_len = 0; | ||
119 | 181 | ||
120 | if (!ctx->encode_private_key(ctx->priv, &encoded_private_key, | 182 | if (!MLKEM_marshal_private_key(priv, &encoded_private_key, |
121 | &encoded_private_key_len)) { | 183 | &encoded_private_key_len)) { |
122 | warnx("mlkem768_encode_private_key"); | 184 | warnx("marshal_private_key"); |
123 | failed |= 1; | 185 | failed |= 1; |
124 | } | 186 | } |
125 | 187 | ||
126 | memcpy(first_two_bytes, encoded_private_key, sizeof(first_two_bytes)); | 188 | memcpy(first_two_bytes, encoded_private_key, sizeof(first_two_bytes)); |
127 | memset(encoded_private_key, 0xff, sizeof(first_two_bytes)); | 189 | memset(encoded_private_key, 0xff, sizeof(first_two_bytes)); |
128 | CBS_init(&cbs, encoded_private_key, encoded_private_key_len); | ||
129 | 190 | ||
130 | /* Parsing should fail because the first coefficient is >= kPrime. */ | 191 | /* Parsing should fail because the first coefficient is >= kPrime. */ |
131 | if (ctx->parse_private_key(ctx->priv2, &cbs)) { | 192 | if (MLKEM_parse_private_key(priv2, encoded_private_key, |
132 | warnx("MLKEM768_parse_private_key should have failed"); | 193 | encoded_private_key_len)) { |
194 | warnx("parse_private_key should have failed"); | ||
133 | failed |= 1; | 195 | failed |= 1; |
134 | } | 196 | } |
135 | 197 | ||
136 | memcpy(encoded_private_key, first_two_bytes, sizeof(first_two_bytes)); | 198 | memcpy(encoded_private_key, first_two_bytes, sizeof(first_two_bytes)); |
137 | CBS_init(&cbs, encoded_private_key, encoded_private_key_len); | ||
138 | 199 | ||
139 | if (!ctx->parse_private_key(ctx->priv2, &cbs)) { | 200 | MLKEM_private_key_free(priv2); |
140 | warnx("MLKEM768_parse_private_key"); | 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, | ||
208 | encoded_private_key_len)) { | ||
209 | warnx("parse_private_key"); | ||
141 | failed |= 1; | 210 | failed |= 1; |
142 | } | 211 | } |
143 | 212 | ||
144 | if (!ctx->encode_private_key(ctx->priv2, &tmp_buf, &tmp_buf_len)) { | 213 | if (!MLKEM_marshal_private_key(priv2, &tmp_buf, &tmp_buf_len)) { |
145 | warnx("encode_private_key"); | 214 | warnx("marshal_private_key"); |
146 | failed |= 1; | 215 | failed |= 1; |
147 | } | 216 | } |
148 | 217 | ||
149 | if (encoded_private_key_len != tmp_buf_len) { | 218 | if (encoded_private_key_len != tmp_buf_len) { |
150 | warnx("encode private key lengths differ"); | 219 | warnx("encoded private key lengths differ"); |
151 | failed |= 1; | 220 | failed |= 1; |
152 | } | 221 | } |
153 | 222 | ||
@@ -160,100 +229,79 @@ MlKemUnitTest(struct unittest_ctx *ctx) | |||
160 | free(tmp_buf); | 229 | free(tmp_buf); |
161 | tmp_buf = NULL; | 230 | tmp_buf = NULL; |
162 | 231 | ||
163 | ctx->encap(ctx->ciphertext, shared_secret1, ctx->pub); | 232 | if (!MLKEM_encap(pub, &ciphertext, &ciphertext_len, &shared_secret1, |
164 | ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len, | 233 | &s_len)) { |
165 | ctx->priv); | 234 | warnx("encap failed using pub"); |
166 | if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES, | 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)) { | ||
246 | warnx("decap() failed using priv"); | ||
247 | failed |= 1; | ||
248 | } | ||
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, | ||
167 | "shared secrets with priv") != 0) { | 257 | "shared secrets with priv") != 0) { |
168 | warnx("compare_data"); | 258 | warnx("compare_data"); |
169 | failed |= 1; | 259 | failed |= 1; |
170 | } | 260 | } |
171 | 261 | ||
172 | ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len, | 262 | free(shared_secret2); |
173 | ctx->priv2); | 263 | shared_secret2 = NULL; |
174 | if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES, | 264 | |
265 | if (!MLKEM_decap(priv2, ciphertext, ciphertext_len, | ||
266 | &shared_secret2, &s_len)){ | ||
267 | warnx("decap() failed using priv2"); | ||
268 | failed |= 1; | ||
269 | } | ||
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, | ||
175 | "shared secrets with priv2") != 0) { | 278 | "shared secrets with priv2") != 0) { |
176 | warnx("compare_data"); | 279 | warnx("compare_data"); |
177 | failed |= 1; | 280 | failed |= 1; |
178 | } | 281 | } |
179 | 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); | ||
180 | free(encoded_private_key); | 291 | free(encoded_private_key); |
292 | free(shared_secret1); | ||
293 | free(shared_secret2); | ||
181 | 294 | ||
182 | return failed; | 295 | return failed; |
183 | } | 296 | } |
184 | 297 | ||
185 | static int | ||
186 | mlkem768_unittest(void) | ||
187 | { | ||
188 | struct MLKEM768_private_key mlkem768_priv, mlkem768_priv2; | ||
189 | struct MLKEM768_public_key mlkem768_pub, mlkem768_pub2; | ||
190 | uint8_t mlkem768_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES]; | ||
191 | uint8_t mlkem768_ciphertext[MLKEM768_CIPHERTEXT_BYTES]; | ||
192 | struct unittest_ctx mlkem768_test = { | ||
193 | .priv = &mlkem768_priv, | ||
194 | .pub = &mlkem768_pub, | ||
195 | .priv2 = &mlkem768_priv2, | ||
196 | .pub2 = &mlkem768_pub2, | ||
197 | .encoded_public_key = mlkem768_encoded_public_key, | ||
198 | .encoded_public_key_len = sizeof(mlkem768_encoded_public_key), | ||
199 | .ciphertext = mlkem768_ciphertext, | ||
200 | .ciphertext_len = sizeof(mlkem768_ciphertext), | ||
201 | .decap = mlkem768_decap, | ||
202 | .encap = mlkem768_encap, | ||
203 | .generate_key = mlkem768_generate_key, | ||
204 | .parse_private_key = mlkem768_parse_private_key, | ||
205 | .parse_public_key = mlkem768_parse_public_key, | ||
206 | .encode_private_key = mlkem768_encode_private_key, | ||
207 | .encode_public_key = mlkem768_encode_public_key, | ||
208 | .public_from_private = mlkem768_public_from_private, | ||
209 | }; | ||
210 | |||
211 | return MlKemUnitTest(&mlkem768_test); | ||
212 | } | ||
213 | |||
214 | static int | ||
215 | mlkem1024_unittest(void) | ||
216 | { | ||
217 | struct MLKEM1024_private_key mlkem1024_priv, mlkem1024_priv2; | ||
218 | struct MLKEM1024_public_key mlkem1024_pub, mlkem1024_pub2; | ||
219 | uint8_t mlkem1024_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES]; | ||
220 | uint8_t mlkem1024_ciphertext[MLKEM1024_CIPHERTEXT_BYTES]; | ||
221 | struct unittest_ctx mlkem1024_test = { | ||
222 | .priv = &mlkem1024_priv, | ||
223 | .pub = &mlkem1024_pub, | ||
224 | .priv2 = &mlkem1024_priv2, | ||
225 | .pub2 = &mlkem1024_pub2, | ||
226 | .encoded_public_key = mlkem1024_encoded_public_key, | ||
227 | .encoded_public_key_len = sizeof(mlkem1024_encoded_public_key), | ||
228 | .ciphertext = mlkem1024_ciphertext, | ||
229 | .ciphertext_len = sizeof(mlkem1024_ciphertext), | ||
230 | .decap = mlkem1024_decap, | ||
231 | .encap = mlkem1024_encap, | ||
232 | .generate_key = mlkem1024_generate_key, | ||
233 | .parse_private_key = mlkem1024_parse_private_key, | ||
234 | .parse_public_key = mlkem1024_parse_public_key, | ||
235 | .encode_private_key = mlkem1024_encode_private_key, | ||
236 | .encode_public_key = mlkem1024_encode_public_key, | ||
237 | .public_from_private = mlkem1024_public_from_private, | ||
238 | }; | ||
239 | |||
240 | return MlKemUnitTest(&mlkem1024_test); | ||
241 | } | ||
242 | |||
243 | int | 298 | int |
244 | main(void) | 299 | main(void) |
245 | { | 300 | { |
246 | int failed = 0; | 301 | int failed = 0; |
247 | 302 | ||
248 | /* | 303 | failed |= MlKemUnitTest(RANK768); |
249 | * XXX - this is split into two helper functions since having a few | 304 | failed |= MlKemUnitTest(RANK1024); |
250 | * ML-KEM key blobs on the stack makes Emscripten's stack explode, | ||
251 | * leading to inscrutable silent failures unles ASAN is enabled. | ||
252 | * Go figure. | ||
253 | */ | ||
254 | |||
255 | failed |= mlkem768_unittest(); | ||
256 | failed |= mlkem1024_unittest(); | ||
257 | 305 | ||
258 | return failed; | 306 | return failed; |
259 | } | 307 | } |
diff --git a/src/regress/lib/libcrypto/mlkem/parse_test_file.c b/src/regress/lib/libcrypto/mlkem/parse_test_file.c index 19f03439e2..9f3e5f3a1a 100644 --- a/src/regress/lib/libcrypto/mlkem/parse_test_file.c +++ b/src/regress/lib/libcrypto/mlkem/parse_test_file.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: parse_test_file.c,v 1.3 2024/12/27 11:17:48 tb Exp $ */ | 1 | /* $OpenBSD: parse_test_file.c,v 1.6 2025/06/03 10:29:37 tb Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> |
@@ -47,6 +47,8 @@ static void | |||
47 | line_data_clear(struct line_data *ld) | 47 | line_data_clear(struct line_data *ld) |
48 | { | 48 | { |
49 | freezero(ld->data, ld->data_len); | 49 | freezero(ld->data, ld->data_len); |
50 | /* The dereference isn't enough for silly old gcc 14. */ | ||
51 | assert(ld != NULL); | ||
50 | explicit_bzero(ld, sizeof(*ld)); | 52 | explicit_bzero(ld, sizeof(*ld)); |
51 | } | 53 | } |
52 | 54 | ||
@@ -644,7 +646,8 @@ parse_reinit(struct parse *p) | |||
644 | p->state.running_test_case = 0; | 646 | p->state.running_test_case = 0; |
645 | parse_line_data_clear(p); | 647 | parse_line_data_clear(p); |
646 | tctx->finish(p->ctx); | 648 | tctx->finish(p->ctx); |
647 | tctx->init(p->ctx, p); | 649 | if (!tctx->init(p->ctx, p)) |
650 | parse_errx(p, "init failed"); | ||
648 | } | 651 | } |
649 | 652 | ||
650 | static int | 653 | static int |
@@ -706,7 +709,8 @@ parse_init(struct parse *p, const char *fn, const struct test_parse *tctx, | |||
706 | parse_state_init(&p->state, tctx->num_states, tctx->num_instructions); | 709 | parse_state_init(&p->state, tctx->num_states, tctx->num_instructions); |
707 | p->tctx = tctx; | 710 | p->tctx = tctx; |
708 | p->ctx = ctx; | 711 | p->ctx = ctx; |
709 | tctx->init(ctx, p); | 712 | if (!tctx->init(p->ctx, p)) |
713 | parse_errx(p, "init failed"); | ||
710 | } | 714 | } |
711 | 715 | ||
712 | static int | 716 | static int |
@@ -732,7 +736,10 @@ parse_next_line(struct parse *p) | |||
732 | static void | 736 | static void |
733 | parse_finish(struct parse *p) | 737 | parse_finish(struct parse *p) |
734 | { | 738 | { |
739 | const struct test_parse *tctx = p->tctx; | ||
740 | |||
735 | parse_state_finish(&p->state); | 741 | parse_state_finish(&p->state); |
742 | tctx->finish(p->ctx); | ||
736 | 743 | ||
737 | free(p->buf); | 744 | free(p->buf); |
738 | 745 | ||