summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c
diff options
context:
space:
mode:
authortb <>2024-12-20 00:07:12 +0000
committertb <>2024-12-20 00:07:12 +0000
commit8aaed9d4e73e75e021900f9a05721eacb93f999d (patch)
treef04653a882e3c8a90b00b8e6f900e4a225736db9 /src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c
parent4152a99459d7137840a7c9ad6477912d3da74426 (diff)
downloadopenbsd-8aaed9d4e73e75e021900f9a05721eacb93f999d.tar.gz
openbsd-8aaed9d4e73e75e021900f9a05721eacb93f999d.tar.bz2
openbsd-8aaed9d4e73e75e021900f9a05721eacb93f999d.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/mlkem768_keygen_tests.c')
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c198
1 files changed, 129 insertions, 69 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c
index 7214dd8a80..be1aff3d04 100644
--- a/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c
+++ b/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c
@@ -1,7 +1,8 @@
1/* $OpenBSD: mlkem768_keygen_tests.c,v 1.4 2024/12/17 07:20:10 tb Exp $ */ 1/* $OpenBSD: mlkem768_keygen_tests.c,v 1.5 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,115 +17,174 @@
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
27#include "mlkem_internal.h" 29#include "mlkem_internal.h"
28#include "mlkem_tests_util.h" 30#include "mlkem_tests_util.h"
29 31
30static int 32static int
31encode_private_key(const struct MLKEM768_private_key *priv, uint8_t **out_buf, 33MlkemKeygenFileTest(CBB *seed_cbb, CBB *public_key_cbb, CBB *private_key_cbb,
32 size_t *out_len) 34 size_t line)
33{
34 CBB cbb;
35 if (!CBB_init(&cbb, MLKEM768_PUBLIC_KEY_BYTES))
36 return 0;
37 if (!MLKEM768_marshal_private_key(&cbb, priv))
38 return 0;
39 if (!CBB_finish(&cbb, out_buf, out_len))
40 return 0;
41 CBB_cleanup(&cbb);
42 return 1;
43}
44
45static void
46MlkemKeygenFileTest(CBS *seed, CBS *public_key, CBS *private_key)
47{ 35{
48 struct MLKEM768_private_key priv; 36 struct MLKEM768_private_key priv;
37 uint8_t *seed = NULL, *public_key = NULL, *private_key = NULL;
38 size_t seed_len = 0, public_key_len = 0, private_key_len = 0;
49 uint8_t *encoded_private_key = NULL; 39 uint8_t *encoded_private_key = NULL;
50 uint8_t encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES]; 40 uint8_t encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES];
51 size_t len; 41 size_t len;
42 int failed = 1;
43
44 if (!CBB_finish(seed_cbb, &seed, &seed_len))
45 goto err;
46 if (!compare_length(MLKEM_SEED_BYTES, seed_len, line, "seed length"))
47 goto err;
48 if (!CBB_finish(public_key_cbb, &public_key, &public_key_len))
49 goto err;
50 if (!compare_length(MLKEM768_PUBLIC_KEY_BYTES, public_key_len, line,
51 "public key length"))
52 goto err;
53 if (!CBB_finish(private_key_cbb, &private_key, &private_key_len))
54 goto err;
55 if (!compare_length(MLKEM768_PUBLIC_KEY_BYTES, public_key_len, line,
56 "public key length"))
57 goto err;
52 58
53 TEST(CBS_len(seed) != MLKEM_SEED_BYTES, "seed len bogus");
54 TEST(CBS_len(private_key) != MLKEM768_PRIVATE_KEY_BYTES,
55 "expected private key len bogus");
56 TEST(CBS_len(public_key) != MLKEM768_PUBLIC_KEY_BYTES,
57 "expected public key len bogus");
58 MLKEM768_generate_key_external_entropy(encoded_public_key, &priv, 59 MLKEM768_generate_key_external_entropy(encoded_public_key, &priv,
59 CBS_data(seed)); 60 seed);
60 TEST(!encode_private_key(&priv, &encoded_private_key, 61 if (!mlkem768_encode_private_key(&priv, &encoded_private_key, &len)) {
61 &len), "encode_private_key"); 62 warnx("#%zu: encoded_private_key", line);
62 TEST(len != MLKEM768_PRIVATE_KEY_BYTES, "private key len bogus"); 63 goto err;
63 TEST_DATAEQ(encoded_public_key, CBS_data(public_key), 64 }
64 MLKEM768_PUBLIC_KEY_BYTES, "public key"); 65
65 TEST_DATAEQ(encoded_private_key, CBS_data(private_key), 66 if (!compare_length(MLKEM768_PRIVATE_KEY_BYTES, len, line,
66 MLKEM768_PRIVATE_KEY_BYTES, "private key"); 67 "private key length"))
68 goto err;
69
70 failed = compare_data(private_key, encoded_private_key,
71 MLKEM768_PRIVATE_KEY_BYTES, line, "private key");
72 failed |= compare_data(public_key, encoded_public_key,
73 MLKEM768_PUBLIC_KEY_BYTES, line, "public key");
74
75 err:
76 CBB_cleanup(seed_cbb);
77 CBB_cleanup(public_key_cbb);
78 CBB_cleanup(private_key_cbb);
79 freezero(seed, seed_len);
80 freezero(public_key, public_key_len);
81 freezero(private_key, private_key_len);
67 free(encoded_private_key); 82 free(encoded_private_key);
83
84 return failed;
68} 85}
69 86
70#define S_START 0 87#define S_START 0
71#define S_SEED 1 88#define S_COMMENT 1
72#define S_PUBLIC_KEY 2 89#define S_SEED 2
73#define S_PRIVATE_KEY 3 90#define S_PUBLIC_KEY 3
91#define S_PRIVATE_KEY 4
92
93#define S2S(x) case x: return #x
94
95static const char *
96state2str(int state)
97{
98 switch (state) {
99 S2S(S_START);
100 S2S(S_COMMENT);
101 S2S(S_SEED);
102 S2S(S_PUBLIC_KEY);
103 S2S(S_PRIVATE_KEY);
104 default:
105 errx(1, "unknown state %d", state);
106 }
107}
74 108
75int 109int
76main(int argc, char **argv) 110main(int argc, char **argv)
77{ 111{
78 CBS seed, public_key, private_key; 112 CBB seed = { 0 }, public_key = { 0 }, private_key = { 0 };
79 char *buf; 113 const char *test;
114 size_t line = 0;
115 char *buf = NULL;
116 size_t buflen = 0;
117 ssize_t len;
80 FILE *fp; 118 FILE *fp;
81 int state; 119 int state;
120 int failed = 0;
121
122 if (argc < 2)
123 errx(1, "%s: missing test file", argv[0]);
124
125 test = argv[1];
126
127 if ((fp = fopen(test, "r")) == NULL)
128 err(1, "cant't open test file");
129
130 state = S_COMMENT;
131 line = 0;
132
133 while ((len = getline(&buf, &buflen, fp)) != -1) {
134 const char *msg = state2str(state);
135 CBS cbs;
136 uint8_t u8;
137
138 line++;
139 CBS_init(&cbs, buf, len);
140
141 if (!CBS_get_last_u8(&cbs, &u8))
142 errx(1, "#%zu %s: CBB_get_last_u8", line, msg);
143 assert(u8 == '\n');
82 144
83 fprintf(stderr, "Testing keygen test vectors in %s\n", argv[1]);
84 TEST((fp = fopen(argv[1], "r")) == NULL, "can't open test file");
85 MALLOC(buf, 16*1024);
86 state = S_SEED;
87 test_number = 1;
88 while (fgets(buf, 16*1024, fp) != NULL) {
89 switch (state) { 145 switch (state) {
90 case S_START: 146 case S_START:
91 if (strcmp(buf, "\n") != 0) 147 state = S_COMMENT;
92 break; 148 break;
149 case S_COMMENT:
150 if (!CBS_get_u8(&cbs, &u8))
151 errx(1, "#%zu %s: CBB_get_u8", line, msg);
152 assert(u8 == '#');
153 if (!CBS_skip(&cbs, CBS_len(&cbs)))
154 errx(1, "#%zu %s: CBB_skip", line, msg);
93 state = S_SEED; 155 state = S_SEED;
94 break; 156 break;
95 case S_SEED: 157 case S_SEED:
96 if (strncmp(buf, "seed: ", strlen("seed: ")) != 0) { 158 if (!get_string_cbs(&cbs, "seed: ", line, msg))
97 break; 159 errx(1, "#%zu %s: get_string_cbs", line, msg);
98 } 160 hex_decode_cbs(&cbs, &seed, line, msg);
99 grab_data(&seed, buf, strlen("seed: "));
100 state = S_PUBLIC_KEY; 161 state = S_PUBLIC_KEY;
101 break; 162 break;
102 case S_PUBLIC_KEY: 163 case S_PUBLIC_KEY:
103 if (strncmp(buf, "public_key: ", 164 if (!get_string_cbs(&cbs, "public_key: ", line, msg))
104 strlen("public_key: ")) != 0) 165 errx(1, "#%zu %s: get_string_cbs", line, msg);
105 break; 166 hex_decode_cbs(&cbs, &public_key, line, msg);
106 grab_data(&public_key, buf, strlen("public_key: "));
107 state = S_PRIVATE_KEY; 167 state = S_PRIVATE_KEY;
108 break; 168 break;
109 case S_PRIVATE_KEY: 169 case S_PRIVATE_KEY:
110 if (strncmp(buf, "private_key: ", 170 if (!get_string_cbs(&cbs, "private_key: ", line, msg))
111 strlen("private_key: ")) != 0) 171 errx(1, "#%zu %s: get_string_cbs", line, msg);
112 break; 172 hex_decode_cbs(&cbs, &private_key, line, msg);
113 grab_data(&private_key, buf, strlen("private_key: "));
114 state = S_START;
115 173
116 MlkemKeygenFileTest(&seed, &public_key, &private_key); 174 failed |= MlkemKeygenFileTest(&seed, &public_key,
117 free((void *)CBS_data(&seed)); 175 &private_key, line);
118 free((void *)CBS_data(&public_key));
119 free((void *)CBS_data(&private_key));
120 176
121 test_number++;
122 state = S_START; 177 state = S_START;
123 break; 178 break;
124 } 179 }
180 if (CBS_len(&cbs) > 0)
181 errx(1, "#%zu %s: CBS_len", line, msg);
125 } 182 }
126
127 free(buf); 183 free(buf);
184
185 if (ferror(fp))
186 err(1, NULL);
128 fclose(fp); 187 fclose(fp);
129 exit(failure); 188
189 return failed;
130} 190}