summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/mlkem/mlkem768_nist_decap_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libcrypto/mlkem/mlkem768_nist_decap_tests.c')
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem768_nist_decap_tests.c210
1 files changed, 146 insertions, 64 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem768_nist_decap_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem768_nist_decap_tests.c
index 0778c921b6..c72ad5c388 100644
--- a/src/regress/lib/libcrypto/mlkem/mlkem768_nist_decap_tests.c
+++ b/src/regress/lib/libcrypto/mlkem/mlkem768_nist_decap_tests.c
@@ -1,7 +1,8 @@
1/* $OpenBSD: mlkem768_nist_decap_tests.c,v 1.2 2024/12/14 19:16:24 tb Exp $ */ 1/* $OpenBSD: mlkem768_nist_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,96 +17,177 @@
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 void 32static int
31MlkemNistDecapFileTest(CBS *c, CBS *k, CBS *dk) 33MlkemNistDecapFileTest(CBB *c_cbb, CBB *k_cbb, CBS *dk, size_t line)
32{ 34{
35 uint8_t *c = NULL, *k = NULL;
36 size_t c_len = 0, k_len = 0;
33 uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES]; 37 uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES];
34 struct MLKEM768_private_key priv; 38 struct MLKEM768_private_key priv;
39 int failed = 1;
35 40
36 TEST(CBS_len(dk) != MLKEM768_PRIVATE_KEY_BYTES, 41 if (!CBB_finish(c_cbb, &c, &c_len))
37 "private key len bogus"); 42 goto err;
38 TEST(CBS_len(k) != MLKEM_SHARED_SECRET_BYTES, 43 if (!CBB_finish(k_cbb, &k, &k_len))
39 "shared secret len bogus"); 44 goto err;
40 45
41 TEST(!MLKEM768_parse_private_key(&priv, dk), "parse_private_key"); 46 if (!compare_length(MLKEM768_PRIVATE_KEY_BYTES, CBS_len(dk), line,
42 TEST(!MLKEM768_decap(shared_secret, CBS_data(c), CBS_len(c), &priv), 47 "private key len bogus"))
43 "decap"); 48 goto err;
44 TEST_DATAEQ(shared_secret, CBS_data(k), 49 if (!compare_length(MLKEM_SHARED_SECRET_BYTES, k_len, line,
45 MLKEM_SHARED_SECRET_BYTES, "shared_secret"); 50 "shared secret len bogus"))
51 goto err;
52
53 if (!MLKEM768_parse_private_key(&priv, dk)) {
54 warnx("#%zu MLKEM768_parse_private_key", line);
55 goto err;
56 }
57 if (!MLKEM768_decap(shared_secret, c, c_len, &priv)) {
58 warnx("#%zu MLKEM768_decap", line);
59 goto err;
60 }
61
62 failed = compare_data(shared_secret, k, k_len, line, "shared_secret");
63
64 err:
65 CBB_cleanup(c_cbb);
66 CBB_cleanup(k_cbb);
67 freezero(c, c_len);
68 freezero(k, k_len);
69
70 return failed;
46} 71}
47 72
48#define S_START 0 73#define S_START 0
49#define S_CIPHERTEXT 1 74#define S_C 1
50#define S_SHARED_SECRET 2 75#define S_K 2
51#define S_PRIVATE_KEY 3 76#define S_EMPTY 3
77
78#define S2S(x) case x: return #x
79
80static const char *
81state2str(int state)
82{
83 switch (state) {
84 S2S(S_START);
85 S2S(S_C);
86 S2S(S_K);
87 S2S(S_EMPTY);
88 default:
89 errx(1, "unknown state %d", state);
90 }
91}
52 92
53int 93int
54main(int argc, char **argv) 94main(int argc, char **argv)
55{ 95{
56 CBS ciphertext, shared_secret, private_key; 96 CBB dk_cbb = { 0 }, c = { 0 }, k = { 0 };
57 const uint8_t *p; 97 CBS instr;
58 char *buf; 98 uint8_t *dk = NULL;
99 size_t dk_len = 0;
100 uint8_t bracket, newline;
101 const char *test;
102 size_t line;
103 char *buf = NULL;
104 size_t buflen = 0;
105 ssize_t len;
59 FILE *fp; 106 FILE *fp;
60 int state; 107 int state;
108 int failed = 0;
109
110 if (argc < 2)
111 errx(1, "%s: missing test file", argv[0]);
112
113 test = argv[1];
114
115 if ((fp = fopen(test, "r")) == NULL)
116 err(1, "cant't open test file");
117
118 if ((len = getline(&buf, &buflen, fp)) == -1)
119 err(1, "failed to read instruction line");
120
121 /*
122 * The private key is enclosed in brackets in an "instruction line".
123 */
124 line = 1;
125 CBS_init(&instr, buf, len);
126 if (!CBS_get_u8(&instr, &bracket))
127 err(1, "failed to parse instruction line '['");
128 assert(bracket == '[');
129 if (!CBS_get_last_u8(&instr, &newline))
130 errx(1, "failed to parse instruction line '\\n'");
131 assert(newline == '\n');
132 if (!CBS_get_last_u8(&instr, &bracket))
133 errx(1, "failed to parse instruction line ']'");
134 assert(bracket == ']');
135 if (!get_string_cbs(&instr, "dk: ", line, "private key"))
136 errx(1, "failed to read instruction line 'dk: '");
137 hex_decode_cbs(&instr, &dk_cbb, line, "private key");
138 assert(CBS_len(&instr) == 0);
139
140 if (!CBB_finish(&dk_cbb, &dk, &dk_len))
141 errx(1, "CBB finish instruction line");
142
143 state = S_START;
144
145 while ((len = getline(&buf, &buflen, fp)) != -1) {
146 const char *msg = state2str(state);
147 CBS cbs, dk_cbs;
148 uint8_t u8;
149
150 line++;
151 CBS_init(&cbs, buf, len);
152
153 if (!CBS_get_last_u8(&cbs, &u8))
154 errx(1, "#%zu %s: CBB_get_last_u8", line, msg);
155 assert(u8 == '\n');
61 156
62 fprintf(stderr, "Testing NIST decap test vectors in %s\n", argv[1]);
63 TEST((fp = fopen(argv[1], "r")) == NULL, "can't open test file");
64 MALLOC(buf, 16*1024);
65 state = S_CIPHERTEXT;
66 test_number = 1;
67 while (fgets(buf, 16*1024, fp) != NULL) {
68 switch (state) { 157 switch (state) {
69 case S_START: 158 case S_START:
70 if (strcmp(buf, "\n") != 0) 159 state = S_C;
71 break;
72 state = S_CIPHERTEXT;
73 break; 160 break;
74 case S_CIPHERTEXT: 161 case S_C:
75 if (strncmp(buf, "ciphertext: ", 162 if (!get_string_cbs(&cbs, "c: ", line, msg))
76 strlen("ciphertext: ")) != 0) { 163 errx(1, "#%zu %s: get_string_cbs", line, msg);
77 break; 164 hex_decode_cbs(&cbs, &c, line, msg);
78 } 165 state = S_K;
79 grab_data(&ciphertext, buf, strlen("ciphertext: "));
80 state = S_SHARED_SECRET;
81 break; 166 break;
82 case S_SHARED_SECRET: 167 case S_K:
83 if (strncmp(buf, "shared_secret: ", 168 if (!get_string_cbs(&cbs, "k: ", line, msg))
84 strlen("shared_secret: ")) != 0) 169 errx(1, "#%zu %s: get_string_cbs", line, msg);
85 break; 170 hex_decode_cbs(&cbs, &k, line, msg);
86 grab_data(&shared_secret, buf, 171 state = S_EMPTY;
87 strlen("shared_secret: "));
88 state = S_PRIVATE_KEY;
89 break; 172 break;
90 case S_PRIVATE_KEY: 173 case S_EMPTY:
91 if (strncmp(buf, "private_key: ", 174 CBS_init(&dk_cbs, dk, dk_len);
92 strlen("private_key: ")) != 0) 175
93 break; 176 failed |= MlkemNistDecapFileTest(&c, &k, &dk_cbs, line);
94 grab_data(&private_key, buf, strlen("private_key: ")); 177
95 p = CBS_data(&private_key); 178 state = S_C;
96
97 MlkemNistDecapFileTest(&ciphertext, &shared_secret,
98 &private_key);
99 free((void *)CBS_data(&ciphertext));
100 free((void *)CBS_data(&shared_secret));
101 free((void *)p);
102
103 state = S_START;
104 test_number++;
105 break; 179 break;
106 } 180 }
181 if (CBS_len(&cbs) > 0)
182 errx(1, "#%zu %s: CBS_len", line, msg);
107 } 183 }
108
109 free(buf); 184 free(buf);
110 exit(failure); 185
186 if (ferror(fp))
187 err(1, NULL);
188 fclose(fp);
189
190 freezero(dk, dk_len);
191
192 return failed;
111} 193}