summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c
diff options
context:
space:
mode:
authortb <>2024-12-20 00:07:12 +0000
committertb <>2024-12-20 00:07:12 +0000
commitb1838090ad769162b2ea08f33254c67d084bb22f (patch)
treef04653a882e3c8a90b00b8e6f900e4a225736db9 /src/regress/lib/libcrypto/mlkem/mlkem1024_encap_tests.c
parent86a35b733e7f43fa01b1c83b3c582855e18ef432 (diff)
downloadopenbsd-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.c221
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
29static void 32static int
30MlkemEncapFileTest(CBS *entropy, CBS *public_key, CBS *expected_ciphertext, 33MlkemEncapFileTest(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
99static const char *
100state2str(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
58int 115int
59main(int argc, char **argv) 116main(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}