1 /* Copyright (c) 2023, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <vector>
16
17 #include <string.h>
18
19 #include <gtest/gtest.h>
20
21 #include <openssl/bytestring.h>
22 #include <openssl/ctrdrbg.h>
23 #define OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER
24 #include <openssl/experimental/kyber.h>
25
26 #include "../test/file_test.h"
27 #include "../test/test_util.h"
28 #include "../keccak/internal.h"
29 #include "./internal.h"
30
31
32 template <typename T>
Marshal(int (* marshal_func)(CBB *,const T *),const T * t)33 static std::vector<uint8_t> Marshal(int (*marshal_func)(CBB *, const T *),
34 const T *t) {
35 bssl::ScopedCBB cbb;
36 uint8_t *encoded;
37 size_t encoded_len;
38 if (!CBB_init(cbb.get(), 1) || //
39 !marshal_func(cbb.get(), t) || //
40 !CBB_finish(cbb.get(), &encoded, &encoded_len)) {
41 abort();
42 }
43
44 std::vector<uint8_t> ret(encoded, encoded + encoded_len);
45 OPENSSL_free(encoded);
46 return ret;
47 }
48
TEST(KyberTest,Basic)49 TEST(KyberTest, Basic) {
50 // This function makes several Kyber keys, which runs up against stack limits.
51 // Heap-allocate them instead.
52
53 uint8_t encoded_public_key[KYBER_PUBLIC_KEY_BYTES];
54 auto priv = std::make_unique<KYBER_private_key>();
55 KYBER_generate_key(encoded_public_key, priv.get());
56
57 uint8_t first_two_bytes[2];
58 OPENSSL_memcpy(first_two_bytes, encoded_public_key, sizeof(first_two_bytes));
59 OPENSSL_memset(encoded_public_key, 0xff, sizeof(first_two_bytes));
60 CBS encoded_public_key_cbs;
61 CBS_init(&encoded_public_key_cbs, encoded_public_key,
62 sizeof(encoded_public_key));
63 auto pub = std::make_unique<KYBER_public_key>();
64 // Parsing should fail because the first coefficient is >= kPrime;
65 ASSERT_FALSE(KYBER_parse_public_key(pub.get(), &encoded_public_key_cbs));
66
67 OPENSSL_memcpy(encoded_public_key, first_two_bytes, sizeof(first_two_bytes));
68 CBS_init(&encoded_public_key_cbs, encoded_public_key,
69 sizeof(encoded_public_key));
70 ASSERT_TRUE(KYBER_parse_public_key(pub.get(), &encoded_public_key_cbs));
71 EXPECT_EQ(CBS_len(&encoded_public_key_cbs), 0u);
72
73 EXPECT_EQ(Bytes(encoded_public_key),
74 Bytes(Marshal(KYBER_marshal_public_key, pub.get())));
75
76 auto pub2 = std::make_unique<KYBER_public_key>();
77 KYBER_public_from_private(pub2.get(), priv.get());
78 EXPECT_EQ(Bytes(encoded_public_key),
79 Bytes(Marshal(KYBER_marshal_public_key, pub2.get())));
80
81 std::vector<uint8_t> encoded_private_key(
82 Marshal(KYBER_marshal_private_key, priv.get()));
83 EXPECT_EQ(encoded_private_key.size(), size_t{KYBER_PRIVATE_KEY_BYTES});
84
85 OPENSSL_memcpy(first_two_bytes, encoded_private_key.data(),
86 sizeof(first_two_bytes));
87 OPENSSL_memset(encoded_private_key.data(), 0xff, sizeof(first_two_bytes));
88 CBS cbs;
89 CBS_init(&cbs, encoded_private_key.data(), encoded_private_key.size());
90 auto priv2 = std::make_unique<KYBER_private_key>();
91 // Parsing should fail because the first coefficient is >= kPrime.
92 ASSERT_FALSE(KYBER_parse_private_key(priv2.get(), &cbs));
93
94 OPENSSL_memcpy(encoded_private_key.data(), first_two_bytes,
95 sizeof(first_two_bytes));
96 CBS_init(&cbs, encoded_private_key.data(), encoded_private_key.size());
97 ASSERT_TRUE(KYBER_parse_private_key(priv2.get(), &cbs));
98 EXPECT_EQ(Bytes(encoded_private_key),
99 Bytes(Marshal(KYBER_marshal_private_key, priv2.get())));
100
101 uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES];
102 uint8_t shared_secret1[KYBER_SHARED_SECRET_BYTES];
103 uint8_t shared_secret2[KYBER_SHARED_SECRET_BYTES];
104 KYBER_encap(ciphertext, shared_secret1, pub.get());
105 KYBER_decap(shared_secret2, ciphertext, priv.get());
106 EXPECT_EQ(Bytes(shared_secret1), Bytes(shared_secret2));
107 KYBER_decap(shared_secret2, ciphertext, priv2.get());
108 EXPECT_EQ(Bytes(shared_secret1), Bytes(shared_secret2));
109 }
110
KyberFileTest(FileTest * t)111 static void KyberFileTest(FileTest *t) {
112 std::vector<uint8_t> seed, public_key_expected, private_key_expected,
113 ciphertext_expected, shared_secret_expected, given_generate_entropy,
114 given_encap_entropy_pre_hash;
115 t->IgnoreAttribute("count");
116 ASSERT_TRUE(t->GetBytes(&seed, "seed"));
117 ASSERT_TRUE(t->GetBytes(&public_key_expected, "pk"));
118 ASSERT_TRUE(t->GetBytes(&private_key_expected, "sk"));
119 ASSERT_TRUE(t->GetBytes(&ciphertext_expected, "ct"));
120 ASSERT_TRUE(t->GetBytes(&shared_secret_expected, "ss"));
121 ASSERT_TRUE(t->GetBytes(&given_generate_entropy, "generateEntropy"));
122 ASSERT_TRUE(
123 t->GetBytes(&given_encap_entropy_pre_hash, "encapEntropyPreHash"));
124
125 KYBER_private_key priv;
126 uint8_t encoded_private_key[KYBER_PRIVATE_KEY_BYTES];
127 KYBER_public_key pub;
128 uint8_t encoded_public_key[KYBER_PUBLIC_KEY_BYTES];
129 uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES];
130 uint8_t gen_key_entropy[KYBER_GENERATE_KEY_ENTROPY];
131 uint8_t encap_entropy[KYBER_ENCAP_ENTROPY];
132 uint8_t encapsulated_key[KYBER_SHARED_SECRET_BYTES];
133 uint8_t decapsulated_key[KYBER_SHARED_SECRET_BYTES];
134 // The test vectors provide a CTR-DRBG seed which is used to generate the
135 // input entropy.
136 ASSERT_EQ(seed.size(), size_t{CTR_DRBG_ENTROPY_LEN});
137 {
138 bssl::UniquePtr<CTR_DRBG_STATE> state(
139 CTR_DRBG_new(seed.data(), nullptr, 0));
140 ASSERT_TRUE(state);
141 ASSERT_TRUE(
142 CTR_DRBG_generate(state.get(), gen_key_entropy, 32, nullptr, 0));
143 ASSERT_TRUE(
144 CTR_DRBG_generate(state.get(), gen_key_entropy + 32, 32, nullptr, 0));
145 ASSERT_TRUE(CTR_DRBG_generate(state.get(), encap_entropy,
146 KYBER_ENCAP_ENTROPY, nullptr, 0));
147 }
148
149 EXPECT_EQ(Bytes(gen_key_entropy), Bytes(given_generate_entropy));
150 EXPECT_EQ(Bytes(encap_entropy), Bytes(given_encap_entropy_pre_hash));
151
152 BORINGSSL_keccak(encap_entropy, sizeof(encap_entropy), encap_entropy,
153 sizeof(encap_entropy), boringssl_sha3_256);
154
155 KYBER_generate_key_external_entropy(encoded_public_key, &priv,
156 gen_key_entropy);
157 CBB cbb;
158 CBB_init_fixed(&cbb, encoded_private_key, sizeof(encoded_private_key));
159 ASSERT_TRUE(KYBER_marshal_private_key(&cbb, &priv));
160 CBS encoded_public_key_cbs;
161 CBS_init(&encoded_public_key_cbs, encoded_public_key,
162 sizeof(encoded_public_key));
163 ASSERT_TRUE(KYBER_parse_public_key(&pub, &encoded_public_key_cbs));
164 KYBER_encap_external_entropy(ciphertext, encapsulated_key, &pub,
165 encap_entropy);
166 KYBER_decap(decapsulated_key, ciphertext, &priv);
167
168 EXPECT_EQ(Bytes(encapsulated_key), Bytes(decapsulated_key));
169 EXPECT_EQ(Bytes(private_key_expected), Bytes(encoded_private_key));
170 EXPECT_EQ(Bytes(public_key_expected), Bytes(encoded_public_key));
171 EXPECT_EQ(Bytes(ciphertext_expected), Bytes(ciphertext));
172 EXPECT_EQ(Bytes(shared_secret_expected), Bytes(encapsulated_key));
173
174 uint8_t corrupted_ciphertext[KYBER_CIPHERTEXT_BYTES];
175 OPENSSL_memcpy(corrupted_ciphertext, ciphertext, KYBER_CIPHERTEXT_BYTES);
176 corrupted_ciphertext[3] ^= 0x40;
177 uint8_t corrupted_decapsulated_key[KYBER_SHARED_SECRET_BYTES];
178 KYBER_decap(corrupted_decapsulated_key, corrupted_ciphertext, &priv);
179 // It would be nice to have actual test vectors for the failure case, but the
180 // NIST submission currently does not include those, so we are just testing
181 // for inequality.
182 EXPECT_NE(Bytes(encapsulated_key), Bytes(corrupted_decapsulated_key));
183 }
184
TEST(KyberTest,TestVectors)185 TEST(KyberTest, TestVectors) {
186 FileTestGTest("crypto/kyber/kyber_tests.txt", KyberFileTest);
187 }
188