summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/mlkem/mlkem768_encap_tests.c
diff options
context:
space:
mode:
authortb <>2024-12-26 00:04:24 +0000
committertb <>2024-12-26 00:04:24 +0000
commit31d1b04da9af806cdb66a2b49ed6490e67479eef (patch)
treef187d226245651988501e2fb8891081ff9eea9f2 /src/regress/lib/libcrypto/mlkem/mlkem768_encap_tests.c
parentfe8b80dbfd7a71d866da84cfdab5d2ce23feac28 (diff)
downloadopenbsd-31d1b04da9af806cdb66a2b49ed6490e67479eef.tar.gz
openbsd-31d1b04da9af806cdb66a2b49ed6490e67479eef.tar.bz2
openbsd-31d1b04da9af806cdb66a2b49ed6490e67479eef.zip
Overhaul ML-KEM regress once more
Implement a file parser that drives a state machine to extract the test data from the .txt files and manages the parsed data. Comments and empty lines are ignored. The code currently assumes that instruction lines are at the start of the file (which isn't generally true) and only supports two line types for now. This is good enough for all the ML-KEM tests but should be easy enough to extend. Once all data for a test case is parsed in the expected order, a test handler is called which can retrieve the test data via a simple API and throw warnings and errors with information on the test case line number, etc. Merge the tests into three programs: one parsing the .txt files and running the corresponding test cases, a unit test and the iteration tests. Deduplicate the actual test code and let the caller pass in an object containing the API functions, private keys and arrays that need to be different between the 768 version and the 1024 version. This way we don't have two sets of half a dozen .c files differing only in 3 or 4 occurrences of 768 and 1024. All this will also make it a lot easier to hook these tests into portable.
Diffstat (limited to 'src/regress/lib/libcrypto/mlkem/mlkem768_encap_tests.c')
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem768_encap_tests.c210
1 files changed, 0 insertions, 210 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem768_encap_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem768_encap_tests.c
deleted file mode 100644
index e2123f8de5..0000000000
--- a/src/regress/lib/libcrypto/mlkem/mlkem768_encap_tests.c
+++ /dev/null
@@ -1,210 +0,0 @@
1/* $OpenBSD: mlkem768_encap_tests.c,v 1.4 2024/12/20 00:32:15 tb Exp $ */
2/*
3 * Copyright (c) 2024 Google Inc.
4 * Copyright (c) 2024 Bob Beck <beck@obtuse.com>
5 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <assert.h>
21#include <err.h>
22#include <stdint.h>
23#include <stdio.h>
24#include <stdlib.h>
25
26#include "bytestring.h"
27#include "mlkem.h"
28
29#include "mlkem_internal.h"
30#include "mlkem_tests_util.h"
31
32static int
33MlkemEncapFileTest(CBB *entropy_cbb, CBB *pubkey_cbb, CBB *ciphertext_cbb,
34 CBB *shared_secret_cbb, int should_fail, size_t line)
35{
36 struct MLKEM768_public_key pub;
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[MLKEM768_CIPHERTEXT_BYTES];
43 CBS public_key_cbs;
44 int failed = 1;
45
46 if (!CBB_finish(entropy_cbb, &entropy, &entropy_len))
47 goto err;
48 if (!CBB_finish(pubkey_cbb, &public_key, &public_key_len))
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 (!MLKEM768_parse_public_key(&pub, &public_key_cbs)) {
58 if ((failed = !should_fail))
59 warnx("#%zu: parse_public_key", line);
60 goto err;
61 }
62 MLKEM768_encap_external_entropy(ciphertext_buf, shared_secret_buf,
63 &pub, entropy);
64
65 failed = compare_data(shared_secret, shared_secret_buf,
66 MLKEM_SHARED_SECRET_BYTES, line, "shared_secret");
67 failed |= compare_data(ciphertext, ciphertext_buf,
68 MLKEM768_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;
87}
88
89#define S_START 0
90#define S_COMMENT 1
91#define S_ENTROPY 2
92#define S_PUBLIC_KEY 3
93#define S_RESULT 4
94#define S_CIPHERTEXT 5
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}
114
115int
116main(int argc, char **argv)
117{
118 CBB entropy = { 0 }, public_key = { 0 }, ciphertext = { 0 }, shared_secret = { 0 };
119 int should_fail = 0;
120 const char *test;
121 size_t line;
122 char *buf = NULL;
123 size_t buflen = 0;
124 ssize_t len;
125 FILE *fp;
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, "can't open test file");
137
138 state = S_COMMENT;
139 line = 0;
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
153 switch (state) {
154 case S_START:
155 state = S_COMMENT;
156 break;
157 case S_COMMENT:
158 if (!CBS_get_u8(&cbs, &u8))
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);
163 state = S_ENTROPY;
164 break;
165 case S_ENTROPY:
166 if (!get_string_cbs(&cbs, "entropy: ", line, msg))
167 errx(1, "#%zu %s: get_string_cbs", line, msg);
168 hex_decode_cbs(&cbs, &entropy, line, msg);
169 state = S_PUBLIC_KEY;
170 break;
171 case S_PUBLIC_KEY:
172 if (!get_string_cbs(&cbs, "public_key = ", line, msg))
173 errx(1, "#%zu %s: get_string_cbs", line, msg);
174 hex_decode_cbs(&cbs, &public_key, line, msg);
175 state = S_RESULT;
176 break;
177 case S_RESULT:
178 if (!get_string_cbs(&cbs, "result: ", line, msg))
179 errx(1, "#%zu %s: get_string_cbs", line, msg);
180 should_fail = get_string_cbs(&cbs, "fail", line, msg);
181 state = S_CIPHERTEXT;
182 break;
183 case S_CIPHERTEXT:
184 if (!get_string_cbs(&cbs, "ciphertext: ", line, msg))
185 errx(1, "#%zu %s: get_string_cbs", line, msg);
186 hex_decode_cbs(&cbs, &ciphertext, line, msg);
187 state = S_SHARED_SECRET;
188 break;
189 case S_SHARED_SECRET:
190 if (!get_string_cbs(&cbs, "shared_secret: ", line, msg))
191 errx(1, "#%zu %s: get_string_cbs", line, msg);
192 hex_decode_cbs(&cbs, &shared_secret, line, msg);
193
194 failed |= MlkemEncapFileTest(&entropy, &public_key,
195 &ciphertext, &shared_secret, should_fail, line);
196
197 state = S_START;
198 break;
199 }
200 if (CBS_len(&cbs) > 0)
201 errx(1, "#%zu %s: CBS_len", line, msg);
202 }
203 free(buf);
204
205 if (ferror(fp))
206 err(1, NULL);
207 fclose(fp);
208
209 return failed;
210}