summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/mlkem/mlkem768_decap_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/mlkem768_decap_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/mlkem768_decap_tests.c')
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem768_decap_tests.c201
1 files changed, 134 insertions, 67 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem768_decap_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem768_decap_tests.c
index 96dc435c4d..a88e487494 100644
--- a/src/regress/lib/libcrypto/mlkem/mlkem768_decap_tests.c
+++ b/src/regress/lib/libcrypto/mlkem/mlkem768_decap_tests.c
@@ -1,7 +1,8 @@
1/* $OpenBSD: mlkem768_decap_tests.c,v 1.2 2024/12/14 19:16:24 tb Exp $ */ 1/* $OpenBSD: mlkem768_decap_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,113 +17,179 @@
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_tests_util.h" 29#include "mlkem_tests_util.h"
28 30
29static void 31static int
30MlkemDecapFileTest(CBS *c, CBS *k, CBS *dk, int should_fail) 32MlkemDecapFileTest(CBB *ciphertext_cbb, CBB *shared_secret_cbb,
33 CBB *private_key_cbb, int should_fail, size_t line)
31{ 34{
32 uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES];
33 struct MLKEM768_private_key priv; 35 struct MLKEM768_private_key priv;
34 int parse_ok, decap_ok; 36 uint8_t *ciphertext = NULL, *shared_secret = NULL, *private_key = NULL;
37 size_t ciphertext_len = 0, shared_secret_len = 0, private_key_len = 0;
38 uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES];
39 CBS private_key_cbs;
40 int failed = 1;
35 41
36 parse_ok = MLKEM768_parse_private_key(&priv, dk); 42 if (!CBB_finish(ciphertext_cbb, &ciphertext, &ciphertext_len))
37 if (!parse_ok) { 43 goto err;
38 TEST(!should_fail, "parse_private_key"); 44 if (!CBB_finish(shared_secret_cbb, &shared_secret, &shared_secret_len))
39 return; 45 goto err;
46 if (!CBB_finish(private_key_cbb, &private_key, &private_key_len))
47 goto err;
48
49 CBS_init(&private_key_cbs, private_key, private_key_len);
50
51 if (!MLKEM768_parse_private_key(&priv, &private_key_cbs)) {
52 if ((failed = !should_fail))
53 warnx("#%zu: parse_private_key", line);
54 goto err;
55 }
56 if (!MLKEM768_decap(shared_secret_buf, ciphertext, ciphertext_len,
57 &priv)) {
58 if ((failed = !should_fail))
59 warnx("#%zu: decap", line);
60 goto err;
40 } 61 }
41 decap_ok = MLKEM768_decap(shared_secret, CBS_data(c), CBS_len(c), 62
42 &priv); 63 failed = compare_data(shared_secret, shared_secret_buf,
43 if (!decap_ok) { 64 MLKEM_SHARED_SECRET_BYTES, line, "shared_secret");
44 TEST(!should_fail, "decap"); 65
45 return; 66 if (should_fail != failed) {
67 warnx("FAIL: #%zu: should_fail %d, failed %d",
68 line, should_fail, failed);
69 failed = 1;
46 } 70 }
47 TEST_DATAEQ(shared_secret, CBS_data(k), 71
48 MLKEM_SHARED_SECRET_BYTES, "shared_secret"); 72 err:
73 CBB_cleanup(ciphertext_cbb);
74 CBB_cleanup(shared_secret_cbb);
75 CBB_cleanup(private_key_cbb);
76 freezero(ciphertext, ciphertext_len);
77 freezero(shared_secret, shared_secret_len);
78 freezero(private_key, private_key_len);
79
80 return failed;
49} 81}
50 82
51#define S_START 0 83#define S_START 0
52#define S_COMMENT 1 84#define S_COMMENT 1
53#define S_PRIVATE_KEY 2 85#define S_PRIVATE_KEY 2
54#define S_CIPHERTEXT 3 86#define S_CIPHERTEXT 3
55#define S_RESULT 4 87#define S_RESULT 4
56#define S_SHARED_SECRET 5 88#define S_SHARED_SECRET 5
89
90#define S2S(x) case x: return #x
91
92static const char *
93state2str(int state)
94{
95 switch (state) {
96 S2S(S_START);
97 S2S(S_COMMENT);
98 S2S(S_PRIVATE_KEY);
99 S2S(S_CIPHERTEXT);
100 S2S(S_RESULT);
101 S2S(S_SHARED_SECRET);
102 default:
103 errx(1, "unknown state %d", state);
104 }
105}
57 106
58int 107int
59main(int argc, char **argv) 108main(int argc, char **argv)
60{ 109{
61 CBS ciphertext, shared_secret, private_key; 110 CBB ciphertext = { 0 }, shared_secret = { 0 }, private_key = { 0 };
62 const uint8_t *p = NULL;
63 int should_fail = 0; 111 int should_fail = 0;
64 char *buf; 112 const char *test;
113 size_t line = 0;
114 char *buf = NULL;
115 size_t buflen = 0;
116 ssize_t len;
65 FILE *fp; 117 FILE *fp;
66 int state; 118 int state;
119 int failed = 0;
120
121 if (argc < 2)
122 errx(1, "%s: missing test file", argv[0]);
123
124 test = argv[1];
125
126 if ((fp = fopen(test, "r")) == NULL)
127 err(1, "cant't open test file");
67 128
68 fprintf(stderr, "Testing decap 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; 129 state = S_COMMENT;
72 test_number = 1; 130 line = 0;
73 while (fgets(buf, 16*1024, fp) != NULL) { 131
132 while ((len = getline(&buf, &buflen, fp)) != -1) {
133 const char *msg = state2str(state);
134 CBS cbs;
135 uint8_t u8;
136
137 line++;
138 CBS_init(&cbs, buf, len);
139
140 if (!CBS_get_last_u8(&cbs, &u8))
141 errx(1, "#%zu %s: CBB_get_last_u8", line, msg);
142 assert(u8 == '\n');
143
74 switch (state) { 144 switch (state) {
75 case S_START: 145 case S_START:
76 if (strcmp(buf, "\n") != 0)
77 break;
78 state = S_COMMENT; 146 state = S_COMMENT;
79 break; 147 break;
80 case S_COMMENT: 148 case S_COMMENT:
81 if (strncmp(buf, "#", 1) != 0) 149 if (!CBS_get_u8(&cbs, &u8))
82 break; 150 errx(1, "#%zu %s: CBB_get_u8", line, msg);
151 assert(u8 == '#');
152 if (!CBS_skip(&cbs, CBS_len(&cbs)))
153 errx(1, "#%zu %s: CBB_skip", line, msg);
83 state = S_PRIVATE_KEY; 154 state = S_PRIVATE_KEY;
84 break; 155 break;
85 case S_PRIVATE_KEY: 156 case S_PRIVATE_KEY:
86 if (strncmp(buf, "private_key: ", 157 if (!get_string_cbs(&cbs, "private_key: ", line, msg))
87 strlen("private_key: ")) != 0) 158 errx(1, "#%zu %s: get_string_cbs", line, msg);
88 break; 159 hex_decode_cbs(&cbs, &private_key, line, msg);
89 grab_data(&private_key, buf, strlen("private_key: "));
90 p = CBS_data(&private_key);
91 state = S_CIPHERTEXT; 160 state = S_CIPHERTEXT;
92 break; 161 break;
93 case S_CIPHERTEXT: 162 case S_CIPHERTEXT:
94 if (strncmp(buf, "ciphertext: ", 163 if (!get_string_cbs(&cbs, "ciphertext: ", line, msg))
95 strlen("ciphertext: ")) != 0) 164 errx(1, "#%zu %s: get_string_cbs", line, msg);
96 break; 165 hex_decode_cbs(&cbs, &ciphertext, line, msg);
97 grab_data(&ciphertext, buf, strlen("ciphertext: "));
98 state = S_RESULT; 166 state = S_RESULT;
99 break; 167 break;
100 case S_RESULT: 168 case S_RESULT:
101 if (strncmp(buf, "result: pass", 169 if (!get_string_cbs(&cbs, "result: ", line, msg))
102 strlen("result: pass")) != 0) 170 errx(1, "#%zu %s: get_string_cbs", line, msg);
103 should_fail = 1; 171 should_fail = get_string_cbs(&cbs, "fail", line, msg);
104 else
105 should_fail = 0;
106 state = S_SHARED_SECRET; 172 state = S_SHARED_SECRET;
107 break; 173 break;
108 case S_SHARED_SECRET: 174 case S_SHARED_SECRET:
109 if (strncmp(buf, "shared_secret: ", 175 if (!get_string_cbs(&cbs, "shared_secret: ", line, msg))
110 strlen("shared_secret: ")) != 0) 176 errx(1, "#%zu %s: get_string_cbs", line, msg);
111 break; 177 hex_decode_cbs(&cbs, &shared_secret, line, msg);
112 grab_data(&shared_secret, buf, 178
113 strlen("shared_secret: ")); 179 failed |= MlkemDecapFileTest(&ciphertext, &shared_secret,
114 MlkemDecapFileTest(&ciphertext, &shared_secret, 180 &private_key, should_fail, line);
115 &private_key, should_fail); 181
116 free((void *)CBS_data(&ciphertext));
117 free((void *)CBS_data(&shared_secret));
118 free((void *)p);
119
120 test_number++;
121 state = S_START; 182 state = S_START;
122 break; 183 break;
123 } 184 }
185 if (CBS_len(&cbs) > 0)
186 errx(1, "#%zu %s: CBS_len", line, msg);
124 } 187 }
125
126 free(buf); 188 free(buf);
127 exit(failure); 189
190 if (ferror(fp))
191 err(1, NULL);
192 fclose(fp);
193
194 return failed;
128} 195}