summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/mlkem/mlkem1024_iteration_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libcrypto/mlkem/mlkem1024_iteration_test.c')
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem1024_iteration_test.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem1024_iteration_test.c b/src/regress/lib/libcrypto/mlkem/mlkem1024_iteration_test.c
new file mode 100644
index 0000000000..d44156e715
--- /dev/null
+++ b/src/regress/lib/libcrypto/mlkem/mlkem1024_iteration_test.c
@@ -0,0 +1,158 @@
1/* Copyright (c) 2024, Google Inc.
2 * Copyright (c) 2024, Bob Beck <beck@obtuse.com>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19
20#include "bytestring.h"
21
22#include "sha3_internal.h"
23#include "mlkem.h"
24#include "mlkem_internal.h"
25#include "mlkem_tests_util.h"
26
27static int
28encode_private_key(const struct MLKEM1024_private_key *priv, uint8_t **out_buf,
29 size_t *out_len)
30{
31 CBB cbb;
32 if (!CBB_init(&cbb, MLKEM1024_PUBLIC_KEY_BYTES))
33 return 0;
34 if (!MLKEM1024_marshal_private_key(&cbb, priv))
35 return 0;
36 if (!CBB_finish(&cbb, out_buf, out_len))
37 return 0;
38 CBB_cleanup(&cbb);
39 return 1;
40}
41
42/*
43 * The structure of this test is taken from
44 * https://github.com/C2SP/CCTV/blob/main/ML-KEM/README.md?ref=words.filippo.io#accumulated-pq-crystals-vectors
45 * but the final value has been updated to reflect the change from Kyber to
46 * ML-KEM.
47 *
48 * The deterministic RNG is a single SHAKE-128 instance with an empty input.
49 * (The RNG stream starts with 7f9c2ba4e88f827d616045507605853e.)
50 */
51
52static void
53MlkemIterativeTest()
54{
55 /* https://github.com/C2SP/CCTV/tree/main/ML-KEM */
56 /*
57 * The deterministic RNG is a single SHAKE-128 instance with an empty input.
58 * (The RNG stream starts with 7f9c2ba4e88f827d616045507605853e.)
59 */
60 const uint8_t kExpectedSeedStart[16] = {
61 0x7f, 0x9c, 0x2b, 0xa4, 0xe8, 0x8f, 0x82, 0x7d, 0x61, 0x60, 0x45,
62 0x50, 0x76, 0x05, 0x85, 0x3e
63 };
64
65 /*
66 * Filippo says:
67 * ML-KEM-1024: 47ac888fe61544efc0518f46094b4f8a600965fc89822acb06dc7169d24f3543
68 * but Boring believes this:
69 */
70 const uint8_t kExpectedAdam[32] = {
71 0xe3, 0xbf, 0x82, 0xb0, 0x13, 0x30, 0x7b, 0x2e, 0x9d, 0x47, 0xdd,
72 0xe7, 0x91, 0xff, 0x6d, 0xfc, 0x82, 0xe6, 0x94, 0xe6, 0x38, 0x24,
73 0x04, 0xab, 0xdb, 0x94, 0x8b, 0x90, 0x8b, 0x75, 0xba, 0xd5
74 };
75 uint8_t encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES];
76 uint8_t invalid_ciphertext[MLKEM1024_CIPHERTEXT_BYTES];
77 uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES];
78 uint8_t ciphertext[MLKEM1024_CIPHERTEXT_BYTES];
79 uint8_t encap_entropy[MLKEM_ENCAP_ENTROPY];
80 uint8_t seed[MLKEM_SEED_BYTES] = {0};
81 struct MLKEM1024_private_key priv;
82 struct MLKEM1024_public_key pub;
83 sha3_ctx drng, results;
84 uint8_t out[32];
85 int i;
86
87 shake128_init(&drng);
88 shake128_init(&results);
89
90 shake_xof(&drng);
91 for (i = 0; i < 10000; i++) {
92 uint8_t *encoded_private_key = NULL;
93 size_t encoded_private_key_len;
94
95 /*
96 * This should draw both d and z from DRNG concatenating in
97 * seed.
98 */
99 shake_out(&drng, seed, sizeof(seed));
100 if (i == 0) {
101 TEST_DATAEQ(seed, kExpectedSeedStart,
102 sizeof(kExpectedSeedStart), "seed start");
103 }
104
105 /* generate ek as encoded_public_key */
106 MLKEM1024_generate_key_external_entropy(encoded_public_key,
107 &priv, seed);
108 MLKEM1024_public_from_private(&pub, &priv);
109
110 /* hash in ek */
111 shake_update(&results, encoded_public_key,
112 sizeof(encoded_public_key));
113
114 /* marshal priv to dk as encoded_private_key */
115 TEST(!encode_private_key(&priv, &encoded_private_key,
116 &encoded_private_key_len), "encode_private_key");
117
118 /* hash in dk */
119 shake_update(&results, encoded_private_key,
120 encoded_private_key_len);
121
122 free(encoded_private_key);
123
124 /* draw m as encap entropy from DRNG */
125 shake_out(&drng, encap_entropy, sizeof(encap_entropy));
126
127 /* generate ct as ciphertext, k as shared_secret */
128 MLKEM1024_encap_external_entropy(ciphertext, shared_secret,
129 &pub, encap_entropy);
130
131 /* hash in ct */
132 shake_update(&results, ciphertext, sizeof(ciphertext));
133 /* hash in k */
134 shake_update(&results, shared_secret, sizeof(shared_secret));
135
136 /* draw ct as invalid_ciphertxt from DRNG */
137 shake_out(&drng, invalid_ciphertext,
138 sizeof(invalid_ciphertext));
139
140 /* generte k as shared secret from invalid ciphertext */
141 TEST(!MLKEM1024_decap(shared_secret, invalid_ciphertext,
142 sizeof(invalid_ciphertext), &priv), "decap failed!");
143
144 /* hash in k */
145 shake_update(&results, shared_secret, sizeof(shared_secret));
146 }
147 shake_xof(&results);
148 shake_out(&results, out, 32);
149
150 TEST_DATAEQ(out, kExpectedAdam, 32, "final result hash");
151}
152
153int
154main(int argc, char **argv)
155{
156 MlkemIterativeTest();
157 exit(failure);
158}