diff options
author | tb <> | 2024-12-20 00:07:12 +0000 |
---|---|---|
committer | tb <> | 2024-12-20 00:07:12 +0000 |
commit | b1838090ad769162b2ea08f33254c67d084bb22f (patch) | |
tree | f04653a882e3c8a90b00b8e6f900e4a225736db9 /src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c | |
parent | 86a35b733e7f43fa01b1c83b3c582855e18ef432 (diff) | |
download | openbsd-b1838090ad769162b2ea08f33254c67d084bb22f.tar.gz openbsd-b1838090ad769162b2ea08f33254c67d084bb22f.tar.bz2 openbsd-b1838090ad769162b2ea08f33254c67d084bb22f.zip |
Rework and fix the mlkem tests
Make proper use of CBB and CBS. If a CBS ever owns data, you're holding
it wrong. Ditch gross macros, sscanf, and globals. The use of fgets is
annoying here, so replace it with getline, which be provided by portable
if needed.
Most importantly, make the tests actually signal failure rather than
only printing an error. Fix the state machines in a few of them. Some
tests didn't parse the .txt file at all. Others mostly did but didn't
actually test what they were supposed to be testing. Such failures
were hidden by the way the tests were written.
This basically needed a complete revamp. It still isn't pretty and much
of it could be deduplicated, but I only have so much time alotted on this
blue planet.
Diffstat (limited to 'src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c')
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c | 221 |
1 files changed, 148 insertions, 73 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c index 83924ba6d2..06b00a4b75 100644 --- a/src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c +++ b/src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* $OpenBSD: mlkem1024_encap_tests.c,v 1.2 2024/12/14 19:16:24 tb Exp $ */ | 1 | /* $OpenBSD: mlkem1024_encap_tests.c,v 1.3 2024/12/20 00:07:12 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> |
5 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> | ||
5 | * | 6 | * |
6 | * Permission to use, copy, modify, and/or distribute this software for any | 7 | * Permission to use, copy, modify, and/or distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above | 8 | * purpose with or without fee is hereby granted, provided that the above |
@@ -16,120 +17,194 @@ | |||
16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 17 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ | 18 | */ |
18 | 19 | ||
20 | #include <assert.h> | ||
21 | #include <err.h> | ||
19 | #include <stdint.h> | 22 | #include <stdint.h> |
20 | #include <stdio.h> | 23 | #include <stdio.h> |
21 | #include <stdlib.h> | 24 | #include <stdlib.h> |
22 | #include <string.h> | ||
23 | 25 | ||
24 | #include <openssl/bytestring.h> | 26 | #include "bytestring.h" |
25 | #include <openssl/mlkem.h> | 27 | #include "mlkem.h" |
26 | 28 | ||
29 | #include "mlkem_internal.h" | ||
27 | #include "mlkem_tests_util.h" | 30 | #include "mlkem_tests_util.h" |
28 | 31 | ||
29 | static void | 32 | static int |
30 | MlkemEncapFileTest(CBS *entropy, CBS *public_key, CBS *expected_ciphertext, | 33 | MlkemEncapFileTest(CBB *entropy_cbb, CBB *pubkey_cbb, CBB *ciphertext_cbb, |
31 | CBS *expected_shared_secret, int should_fail) | 34 | CBB *shared_secret_cbb, int should_fail, size_t line) |
32 | { | 35 | { |
33 | uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES]; | ||
34 | uint8_t ciphertext[MLKEM1024_CIPHERTEXT_BYTES]; | ||
35 | struct MLKEM1024_public_key pub; | 36 | struct MLKEM1024_public_key pub; |
36 | int parse_ok; | 37 | uint8_t *entropy = NULL, *public_key = NULL, *ciphertext = NULL; |
38 | uint8_t *shared_secret = NULL; | ||
39 | size_t entropy_len = 0, public_key_len = 0, ciphertext_len = 0; | ||
40 | size_t shared_secret_len = 0; | ||
41 | uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES]; | ||
42 | uint8_t ciphertext_buf[MLKEM1024_CIPHERTEXT_BYTES]; | ||
43 | CBS public_key_cbs; | ||
44 | int failed = 1; | ||
37 | 45 | ||
38 | parse_ok = MLKEM1024_parse_public_key(&pub, public_key); | 46 | if (!CBB_finish(entropy_cbb, &entropy, &entropy_len)) |
39 | if (!parse_ok) { | 47 | goto err; |
40 | TEST(!should_fail, "parse_public_key"); | 48 | if (!CBB_finish(pubkey_cbb, &public_key, &public_key_len)) |
41 | return; | 49 | goto err; |
50 | if (!CBB_finish(ciphertext_cbb, &ciphertext, &ciphertext_len)) | ||
51 | goto err; | ||
52 | if (!CBB_finish(shared_secret_cbb, &shared_secret, &shared_secret_len)) | ||
53 | goto err; | ||
54 | |||
55 | CBS_init(&public_key_cbs, public_key, public_key_len); | ||
56 | |||
57 | if (!MLKEM1024_parse_public_key(&pub, &public_key_cbs)) { | ||
58 | if ((failed = !should_fail)) | ||
59 | warnx("#%zu: parse_public_key", line); | ||
60 | goto err; | ||
42 | } | 61 | } |
43 | MLKEM1024_encap(ciphertext, shared_secret, &pub); | 62 | MLKEM1024_encap_external_entropy(ciphertext_buf, shared_secret_buf, |
44 | TEST_DATAEQ(shared_secret, CBS_data(expected_shared_secret), | 63 | &pub, entropy); |
45 | MLKEM_SHARED_SECRET_BYTES, "shared_secret"); | 64 | |
46 | TEST_DATAEQ(ciphertext, CBS_data(expected_ciphertext), | 65 | failed = compare_data(shared_secret, shared_secret_buf, |
47 | MLKEM1024_CIPHERTEXT_BYTES, "shared_secret"); | 66 | MLKEM_SHARED_SECRET_BYTES, line, "shared_secret"); |
67 | failed |= compare_data(ciphertext, ciphertext_buf, | ||
68 | MLKEM1024_CIPHERTEXT_BYTES, line, "ciphertext"); | ||
69 | |||
70 | if (should_fail != failed) { | ||
71 | warnx("FAIL: #%zu: should_fail %d, failed %d", | ||
72 | line, should_fail, failed); | ||
73 | failed = 1; | ||
74 | } | ||
75 | |||
76 | err: | ||
77 | CBB_cleanup(entropy_cbb); | ||
78 | CBB_cleanup(pubkey_cbb); | ||
79 | CBB_cleanup(ciphertext_cbb); | ||
80 | CBB_cleanup(shared_secret_cbb); | ||
81 | freezero(entropy, entropy_len); | ||
82 | freezero(public_key, public_key_len); | ||
83 | freezero(ciphertext, ciphertext_len); | ||
84 | freezero(shared_secret, shared_secret_len); | ||
85 | |||
86 | return failed; | ||
48 | } | 87 | } |
49 | 88 | ||
50 | #define S_START 0 | 89 | #define S_START 0 |
51 | #define S_COMMENT 1 | 90 | #define S_COMMENT 1 |
52 | #define S_ENTROPY 2 | 91 | #define S_ENTROPY 2 |
53 | #define S_PUBLIC_KEY 3 | 92 | #define S_PUBLIC_KEY 3 |
54 | #define S_RESULT 4 | 93 | #define S_RESULT 4 |
55 | #define S_CIPHERTEXT 5 | 94 | #define S_CIPHERTEXT 5 |
56 | #define S_SHARED_SECRET 6 | 95 | #define S_SHARED_SECRET 6 |
96 | |||
97 | #define S2S(x) case x: return #x | ||
98 | |||
99 | static const char * | ||
100 | state2str(int state) | ||
101 | { | ||
102 | switch (state) { | ||
103 | S2S(S_START); | ||
104 | S2S(S_COMMENT); | ||
105 | S2S(S_ENTROPY); | ||
106 | S2S(S_PUBLIC_KEY); | ||
107 | S2S(S_RESULT); | ||
108 | S2S(S_CIPHERTEXT); | ||
109 | S2S(S_SHARED_SECRET); | ||
110 | default: | ||
111 | errx(1, "unknown state %d", state); | ||
112 | } | ||
113 | } | ||
57 | 114 | ||
58 | int | 115 | int |
59 | main(int argc, char **argv) | 116 | main(int argc, char **argv) |
60 | { | 117 | { |
61 | CBS entropy, public_key, ciphertext, shared_secret; | 118 | CBB entropy = { 0 }, public_key = { 0 }, ciphertext = { 0 }, shared_secret = { 0 }; |
62 | const uint8_t *p = NULL; | ||
63 | int should_fail = 0; | 119 | int should_fail = 0; |
64 | char *buf; | 120 | const char *test; |
121 | size_t line; | ||
122 | char *buf = NULL; | ||
123 | size_t buflen = 0; | ||
124 | ssize_t len; | ||
65 | FILE *fp; | 125 | FILE *fp; |
66 | int state; | 126 | int state; |
127 | int failed = 0; | ||
128 | |||
129 | if (argc < 2) | ||
130 | errx(1, "%s: missing test file", argv[0]); | ||
131 | |||
132 | test = argv[1]; | ||
133 | line = 0; | ||
134 | |||
135 | if ((fp = fopen(test, "r")) == NULL) | ||
136 | err(1, "cant't open test file"); | ||
67 | 137 | ||
68 | fprintf(stderr, "Testing encap test vectors in %s\n", argv[1]); | ||
69 | TEST((fp = fopen(argv[1], "r")) == NULL, "can't open test file"); | ||
70 | MALLOC(buf, 16*1024); | ||
71 | state = S_COMMENT; | 138 | state = S_COMMENT; |
72 | test_number = 1; | 139 | line = 0; |
73 | while (fgets(buf, 16*1024, fp) != NULL) { | 140 | |
141 | while ((len = getline(&buf, &buflen, fp)) != -1) { | ||
142 | const char *msg = state2str(state); | ||
143 | CBS cbs; | ||
144 | uint8_t u8; | ||
145 | |||
146 | line++; | ||
147 | CBS_init(&cbs, buf, len); | ||
148 | |||
149 | if (!CBS_get_last_u8(&cbs, &u8)) | ||
150 | errx(1, "#%zu %s: CBB_get_last_u8", line, msg); | ||
151 | assert(u8 == '\n'); | ||
152 | |||
74 | switch (state) { | 153 | switch (state) { |
75 | case S_START: | 154 | case S_START: |
76 | if (strcmp(buf, "\n") != 0) | ||
77 | break; | ||
78 | state = S_COMMENT; | 155 | state = S_COMMENT; |
79 | break; | 156 | break; |
80 | case S_COMMENT: | 157 | case S_COMMENT: |
81 | if (strncmp(buf, "#", 1) != 0) | 158 | if (!CBS_get_u8(&cbs, &u8)) |
82 | break; | 159 | errx(1, "#%zu %s: CBB_get_u8", line, msg); |
160 | assert(u8 == '#'); | ||
161 | if (!CBS_skip(&cbs, CBS_len(&cbs))) | ||
162 | errx(1, "#%zu %s: CBB_skip", line, msg); | ||
83 | state = S_ENTROPY; | 163 | state = S_ENTROPY; |
84 | break; | 164 | break; |
85 | case S_ENTROPY: | 165 | case S_ENTROPY: |
86 | if (strncmp(buf, "entropy: ", strlen("entropy: ")) != 0) | 166 | if (!get_string_cbs(&cbs, "entropy: ", line, msg)) |
87 | break; | 167 | errx(1, "#%zu %s: get_string_cbs", line, msg); |
88 | grab_data(&entropy, buf, strlen("entropy: ")); | 168 | hex_decode_cbs(&cbs, &entropy, line, msg); |
89 | p = CBS_data(&entropy); | ||
90 | state = S_PUBLIC_KEY; | 169 | state = S_PUBLIC_KEY; |
91 | break; | 170 | break; |
92 | case S_PUBLIC_KEY: | 171 | case S_PUBLIC_KEY: |
93 | if (strncmp(buf, "public_key: ", | 172 | if (!get_string_cbs(&cbs, "public_key = ", line, msg)) |
94 | strlen("public_key: ")) != 0) | 173 | errx(1, "#%zu %s: get_string_cbs", line, msg); |
95 | break; | 174 | hex_decode_cbs(&cbs, &public_key, line, msg); |
96 | grab_data(&public_key, buf, strlen("public_key: ")); | ||
97 | p = CBS_data(&public_key); | ||
98 | state = S_RESULT; | 175 | state = S_RESULT; |
99 | break; | 176 | break; |
100 | case S_RESULT: | 177 | case S_RESULT: |
101 | if (strncmp(buf, "result: pass", | 178 | if (!get_string_cbs(&cbs, "result: ", line, msg)) |
102 | strlen("result: pass")) != 0) | 179 | errx(1, "#%zu %s: get_string_cbs", line, msg); |
103 | should_fail = 1; | 180 | should_fail = get_string_cbs(&cbs, "fail", line, msg); |
104 | else | ||
105 | should_fail = 0; | ||
106 | state = S_CIPHERTEXT; | 181 | state = S_CIPHERTEXT; |
107 | break; | 182 | break; |
108 | case S_CIPHERTEXT: | 183 | case S_CIPHERTEXT: |
109 | if (strncmp(buf, "ciphertext: ", | 184 | if (!get_string_cbs(&cbs, "ciphertext: ", line, msg)) |
110 | strlen("ciphertext: ")) != 0) | 185 | errx(1, "#%zu %s: get_string_cbs", line, msg); |
111 | break; | 186 | hex_decode_cbs(&cbs, &ciphertext, line, msg); |
112 | grab_data(&ciphertext, buf, strlen("ciphertext: ")); | 187 | state = S_SHARED_SECRET; |
113 | state = S_RESULT; | ||
114 | break; | 188 | break; |
115 | case S_SHARED_SECRET: | 189 | case S_SHARED_SECRET: |
116 | if (strncmp(buf, "shared_secret: ", | 190 | if (!get_string_cbs(&cbs, "shared_secret: ", line, msg)) |
117 | strlen("shared_secret: ")) != 0) | 191 | errx(1, "#%zu %s: get_string_cbs", line, msg); |
118 | break; | 192 | hex_decode_cbs(&cbs, &shared_secret, line, msg); |
119 | grab_data(&shared_secret, buf, | 193 | |
120 | strlen("shared_secret: ")); | 194 | failed |= MlkemEncapFileTest(&entropy, &public_key, |
121 | MlkemEncapFileTest(&entropy, &public_key, &ciphertext, | 195 | &ciphertext, &shared_secret, should_fail, line); |
122 | &shared_secret, should_fail); | 196 | |
123 | free((void *)CBS_data(&ciphertext)); | ||
124 | free((void *)CBS_data(&shared_secret)); | ||
125 | free((void *)p); | ||
126 | |||
127 | test_number++; | ||
128 | state = S_START; | 197 | state = S_START; |
129 | break; | 198 | break; |
130 | } | 199 | } |
200 | if (CBS_len(&cbs) > 0) | ||
201 | errx(1, "#%zu %s: CBS_len", line, msg); | ||
131 | } | 202 | } |
132 | |||
133 | free(buf); | 203 | free(buf); |
134 | exit(failure); | 204 | |
205 | if (ferror(fp)) | ||
206 | err(1, NULL); | ||
207 | fclose(fp); | ||
208 | |||
209 | return failed; | ||
135 | } | 210 | } |