1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include <memory>
8 #include "nss.h"
9 #include "pk11pub.h"
10 #include "pk11priv.h"
11 #include "secerr.h"
12 #include "sechash.h"
13
14 #include "nss_scoped_ptrs.h"
15
16 #include "testvectors/gcm-vectors.h"
17 #include "gtest/gtest.h"
18 #include "util.h"
19
20 namespace nss_test {
21
22 class Pkcs11AesGcmTest : public ::testing::TestWithParam<AesGcmKatValue> {
23 protected:
RunTest(const AesGcmKatValue vec)24 void RunTest(const AesGcmKatValue vec) {
25 std::vector<uint8_t> key = hex_string_to_bytes(vec.key);
26 std::vector<uint8_t> iv = hex_string_to_bytes(vec.iv);
27 std::vector<uint8_t> plaintext = hex_string_to_bytes(vec.plaintext);
28 std::vector<uint8_t> aad = hex_string_to_bytes(vec.additional_data);
29 std::vector<uint8_t> result = hex_string_to_bytes(vec.result);
30 bool invalid_ct = vec.invalid_ct;
31 bool invalid_iv = vec.invalid_iv;
32 std::string msg = "Test #" + std::to_string(vec.id) + " failed";
33 // Ignore GHASH-only vectors.
34 if (key.empty()) {
35 return;
36 }
37
38 // Prepare AEAD params.
39 CK_NSS_GCM_PARAMS gcm_params;
40 gcm_params.pIv = iv.data();
41 gcm_params.ulIvLen = iv.size();
42 gcm_params.pAAD = aad.data();
43 gcm_params.ulAADLen = aad.size();
44 gcm_params.ulTagBits = 128;
45
46 SECItem params = {siBuffer, reinterpret_cast<unsigned char*>(&gcm_params),
47 sizeof(gcm_params)};
48
49 ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
50 SECItem key_item = {siBuffer, key.data(),
51 static_cast<unsigned int>(key.size())};
52
53 // Import key.
54 ScopedPK11SymKey sym_key(PK11_ImportSymKey(
55 slot.get(), mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, nullptr));
56 ASSERT_TRUE(!!sym_key) << msg;
57
58 // Encrypt with bogus parameters.
59 unsigned int output_len = 0;
60 std::vector<uint8_t> output(plaintext.size() + gcm_params.ulTagBits / 8);
61 // "maxout" must be at least "inlen + tagBytes", or, in this case:
62 // "output.size()" must be at least "plaintext.size() + tagBytes"
63 gcm_params.ulTagBits = 128;
64 SECStatus rv =
65 PK11_Encrypt(sym_key.get(), mech, ¶ms, output.data(), &output_len,
66 output.size() - 10, plaintext.data(), plaintext.size());
67 EXPECT_EQ(SECFailure, rv);
68 EXPECT_EQ(0U, output_len);
69
70 // The valid values for tag size in AES_GCM are:
71 // 32, 64, 96, 104, 112, 120 and 128.
72 gcm_params.ulTagBits = 110;
73 rv = PK11_Encrypt(sym_key.get(), mech, ¶ms, output.data(), &output_len,
74 output.size(), plaintext.data(), plaintext.size());
75 EXPECT_EQ(SECFailure, rv);
76 EXPECT_EQ(0U, output_len);
77
78 // Encrypt.
79 gcm_params.ulTagBits = 128;
80 rv = PK11_Encrypt(sym_key.get(), mech, ¶ms, output.data(), &output_len,
81 output.size(), plaintext.data(), plaintext.size());
82 if (invalid_iv) {
83 EXPECT_EQ(SECFailure, rv) << msg;
84 EXPECT_EQ(0U, output_len);
85 return;
86 }
87 EXPECT_EQ(SECSuccess, rv) << msg;
88
89 ASSERT_EQ(output_len, output.size()) << msg;
90
91 // Check ciphertext and tag.
92 if (invalid_ct) {
93 EXPECT_NE(result, output) << msg;
94 } else {
95 EXPECT_EQ(result, output) << msg;
96 }
97
98 // Decrypt.
99 unsigned int decrypted_len = 0;
100 // The PK11 AES API is stupid, it expects an explicit IV and thus wants
101 // a block more of available output memory.
102 std::vector<uint8_t> decrypted(output.size());
103 rv = PK11_Decrypt(sym_key.get(), mech, ¶ms, decrypted.data(),
104 &decrypted_len, decrypted.size(), output.data(),
105 output_len);
106 EXPECT_EQ(SECSuccess, rv) << msg;
107 ASSERT_EQ(decrypted_len, plaintext.size()) << msg;
108
109 // Check the plaintext.
110 EXPECT_EQ(plaintext,
111 std::vector<uint8_t>(decrypted.begin(),
112 decrypted.begin() + decrypted_len))
113 << msg;
114 }
115
EncryptWithIV(std::vector<uint8_t> & iv)116 SECStatus EncryptWithIV(std::vector<uint8_t>& iv) {
117 // Generate a random key.
118 ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
119 ScopedPK11SymKey sym_key(
120 PK11_KeyGen(slot.get(), mech, nullptr, 16, nullptr));
121 EXPECT_TRUE(!!sym_key);
122
123 std::vector<uint8_t> data(17);
124 std::vector<uint8_t> output(33);
125 std::vector<uint8_t> aad(0);
126
127 // Prepare AEAD params.
128 CK_NSS_GCM_PARAMS gcm_params;
129 gcm_params.pIv = iv.data();
130 gcm_params.ulIvLen = iv.size();
131 gcm_params.pAAD = aad.data();
132 gcm_params.ulAADLen = aad.size();
133 gcm_params.ulTagBits = 128;
134
135 SECItem params = {siBuffer, reinterpret_cast<unsigned char*>(&gcm_params),
136 sizeof(gcm_params)};
137
138 // Try to encrypt.
139 unsigned int output_len = 0;
140 return PK11_Encrypt(sym_key.get(), mech, ¶ms, output.data(),
141 &output_len, output.size(), data.data(), data.size());
142 }
143
MessageInterfaceTest(int iterations,int ivFixedBits,CK_GENERATOR_FUNCTION ivGen,PRBool separateTag)144 SECStatus MessageInterfaceTest(int iterations, int ivFixedBits,
145 CK_GENERATOR_FUNCTION ivGen,
146 PRBool separateTag) {
147 // Generate a random key.
148 ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
149 EXPECT_NE(nullptr, slot);
150 ScopedPK11SymKey sym_key(
151 PK11_KeyGen(slot.get(), mech, nullptr, 16, nullptr));
152 EXPECT_NE(nullptr, sym_key);
153
154 const int kTagSize = 16;
155 int cipher_simulated_size;
156 int output_len_message = 0;
157 int output_len_simulated = 0;
158 unsigned int output_len_v24 = 0;
159
160 std::vector<uint8_t> plainIn(17);
161 std::vector<uint8_t> plainOut_message(17);
162 std::vector<uint8_t> plainOut_simulated(17);
163 std::vector<uint8_t> plainOut_v24(17);
164 std::vector<uint8_t> iv(16);
165 std::vector<uint8_t> iv_init(16);
166 std::vector<uint8_t> iv_simulated(16);
167 std::vector<uint8_t> cipher_message(33);
168 std::vector<uint8_t> cipher_simulated(33);
169 std::vector<uint8_t> cipher_v24(33);
170 std::vector<uint8_t> aad(16);
171 std::vector<uint8_t> tag_message(16);
172 std::vector<uint8_t> tag_simulated(16);
173
174 // Prepare AEAD v2.40 params.
175 CK_GCM_PARAMS_V3 gcm_params;
176 gcm_params.pIv = iv.data();
177 gcm_params.ulIvLen = iv.size();
178 gcm_params.ulIvBits = iv.size() * 8;
179 gcm_params.pAAD = aad.data();
180 gcm_params.ulAADLen = aad.size();
181 gcm_params.ulTagBits = kTagSize * 8;
182
183 // Prepare AEAD MESSAGE params.
184 CK_GCM_MESSAGE_PARAMS gcm_message_params;
185 gcm_message_params.pIv = iv.data();
186 gcm_message_params.ulIvLen = iv.size();
187 gcm_message_params.ulTagBits = kTagSize * 8;
188 gcm_message_params.ulIvFixedBits = ivFixedBits;
189 gcm_message_params.ivGenerator = ivGen;
190 if (separateTag) {
191 gcm_message_params.pTag = tag_message.data();
192 } else {
193 gcm_message_params.pTag = cipher_message.data() + plainIn.size();
194 }
195
196 // Prepare AEAD MESSAGE params for simulated case
197 CK_GCM_MESSAGE_PARAMS gcm_simulated_params;
198 gcm_simulated_params = gcm_message_params;
199 if (separateTag) {
200 // The simulated case, we have to allocate temp bufs for separate
201 // tags, make sure that works in both the encrypt and the decrypt
202 // cases.
203 gcm_simulated_params.pTag = tag_simulated.data();
204 cipher_simulated_size = cipher_simulated.size() - kTagSize;
205 } else {
206 gcm_simulated_params.pTag = cipher_simulated.data() + plainIn.size();
207 cipher_simulated_size = cipher_simulated.size();
208 }
209 /* when we are using CKG_GENERATE_RANDOM, don't independently generate
210 * the IV in the simulated case. Since the IV's would be random, none of
211 * the generated results would be the same. Just use the IV we generated
212 * in message interface */
213 if (ivGen == CKG_GENERATE_RANDOM) {
214 gcm_simulated_params.ivGenerator = CKG_NO_GENERATE;
215 } else {
216 gcm_simulated_params.pIv = iv_simulated.data();
217 }
218
219 SECItem params = {siBuffer, reinterpret_cast<unsigned char*>(&gcm_params),
220 sizeof(gcm_params)};
221 SECItem empty = {siBuffer, NULL, 0};
222
223 // initialize our plain text, IV and aad.
224 EXPECT_EQ(PK11_GenerateRandom(plainIn.data(), plainIn.size()), SECSuccess);
225 EXPECT_EQ(PK11_GenerateRandom(aad.data(), aad.size()), SECSuccess);
226 EXPECT_EQ(PK11_GenerateRandom(iv_init.data(), iv_init.size()), SECSuccess);
227 iv_simulated = iv_init; // vector assignment actually copies data
228 iv = iv_init;
229
230 // Initialize message encrypt context
231 ScopedPK11Context encrypt_message_context(PK11_CreateContextBySymKey(
232 mech, CKA_NSS_MESSAGE | CKA_ENCRYPT, sym_key.get(), &empty));
233 EXPECT_NE(nullptr, encrypt_message_context);
234 if (!encrypt_message_context) {
235 return SECFailure;
236 }
237 EXPECT_FALSE(_PK11_ContextGetAEADSimulation(encrypt_message_context.get()));
238
239 // Initialize simulated encrypt context
240 ScopedPK11Context encrypt_simulated_context(PK11_CreateContextBySymKey(
241 mech, CKA_NSS_MESSAGE | CKA_ENCRYPT, sym_key.get(), &empty));
242 EXPECT_NE(nullptr, encrypt_simulated_context);
243 if (!encrypt_simulated_context) {
244 return SECFailure;
245 }
246 EXPECT_EQ(SECSuccess,
247 _PK11_ContextSetAEADSimulation(encrypt_simulated_context.get()));
248
249 // Initialize message decrypt context
250 ScopedPK11Context decrypt_message_context(PK11_CreateContextBySymKey(
251 mech, CKA_NSS_MESSAGE | CKA_DECRYPT, sym_key.get(), &empty));
252 EXPECT_NE(nullptr, decrypt_message_context);
253 if (!decrypt_message_context) {
254 return SECFailure;
255 }
256 EXPECT_FALSE(_PK11_ContextGetAEADSimulation(decrypt_message_context.get()));
257
258 // Initialize simulated decrypt context
259 ScopedPK11Context decrypt_simulated_context(PK11_CreateContextBySymKey(
260 mech, CKA_NSS_MESSAGE | CKA_DECRYPT, sym_key.get(), &empty));
261 EXPECT_NE(nullptr, decrypt_simulated_context);
262 if (!decrypt_simulated_context) {
263 return SECFailure;
264 }
265 EXPECT_EQ(SECSuccess,
266 _PK11_ContextSetAEADSimulation(decrypt_simulated_context.get()));
267
268 // Now walk down our iterations. Each method of calculating the operation
269 // should agree at each step.
270 for (int i = 0; i < iterations; i++) {
271 SECStatus rv;
272 /* recopy the initial vector each time */
273 iv_simulated = iv_init;
274 iv = iv_init;
275
276 // First encrypt. We don't test the error code here, because
277 // we may be testing error conditions with this function (namely
278 // do we fail if we try to generate to many Random IV's).
279 rv =
280 PK11_AEADRawOp(encrypt_message_context.get(), &gcm_message_params,
281 sizeof(gcm_message_params), aad.data(), aad.size(),
282 cipher_message.data(), &output_len_message,
283 cipher_message.size(), plainIn.data(), plainIn.size());
284 if (rv != SECSuccess) {
285 return rv;
286 }
287 rv =
288 PK11_AEADRawOp(encrypt_simulated_context.get(), &gcm_simulated_params,
289 sizeof(gcm_simulated_params), aad.data(), aad.size(),
290 cipher_simulated.data(), &output_len_simulated,
291 cipher_simulated_size, plainIn.data(), plainIn.size());
292 if (rv != SECSuccess) {
293 return rv;
294 }
295 // make sure simulated and message is the same
296 EXPECT_EQ(output_len_message, output_len_simulated);
297 EXPECT_EQ(0, memcmp(cipher_message.data(), cipher_simulated.data(),
298 output_len_message));
299 EXPECT_EQ(0, memcmp(gcm_message_params.pTag, gcm_simulated_params.pTag,
300 kTagSize));
301 EXPECT_EQ(0, memcmp(iv.data(), gcm_simulated_params.pIv, iv.size()));
302 // make sure v2.40 is the same. it inherits the generated iv from
303 // encrypt_message_context.
304 EXPECT_EQ(SECSuccess,
305 PK11_Encrypt(sym_key.get(), mech, ¶ms, cipher_v24.data(),
306 &output_len_v24, cipher_v24.size(), plainIn.data(),
307 plainIn.size()));
308 EXPECT_EQ(output_len_message, (int)output_len_v24 - kTagSize);
309 EXPECT_EQ(0, memcmp(cipher_message.data(), cipher_v24.data(),
310 output_len_message));
311 EXPECT_EQ(0, memcmp(gcm_message_params.pTag,
312 cipher_v24.data() + output_len_message, kTagSize));
313 // now make sure we can decrypt
314 EXPECT_EQ(SECSuccess,
315 PK11_AEADRawOp(decrypt_message_context.get(),
316 &gcm_message_params, sizeof(gcm_message_params),
317 aad.data(), aad.size(), plainOut_message.data(),
318 &output_len_message, plainOut_message.size(),
319 cipher_message.data(), output_len_message));
320 EXPECT_EQ(output_len_message, (int)plainIn.size());
321 EXPECT_EQ(
322 0, memcmp(plainOut_message.data(), plainIn.data(), plainIn.size()));
323 EXPECT_EQ(
324 SECSuccess,
325 PK11_AEADRawOp(decrypt_simulated_context.get(), &gcm_simulated_params,
326 sizeof(gcm_simulated_params), aad.data(), aad.size(),
327 plainOut_simulated.data(), &output_len_simulated,
328 plainOut_simulated.size(), cipher_message.data(),
329 output_len_simulated));
330 EXPECT_EQ(output_len_simulated, (int)plainIn.size());
331 EXPECT_EQ(
332 0, memcmp(plainOut_simulated.data(), plainIn.data(), plainIn.size()));
333 if (separateTag) {
334 // in the separateTag case, we need to copy the tag back to the
335 // end of the cipher_message.data() before using the v2.4 interface
336 memcpy(cipher_message.data() + output_len_message,
337 gcm_message_params.pTag, kTagSize);
338 }
339 EXPECT_EQ(SECSuccess,
340 PK11_Decrypt(sym_key.get(), mech, ¶ms, plainOut_v24.data(),
341 &output_len_v24, plainOut_v24.size(),
342 cipher_message.data(), output_len_v24));
343 EXPECT_EQ(output_len_v24, plainIn.size());
344 EXPECT_EQ(0, memcmp(plainOut_v24.data(), plainIn.data(), plainIn.size()));
345 }
346 return SECSuccess;
347 }
348
349 const CK_MECHANISM_TYPE mech = CKM_AES_GCM;
350 };
351
TEST_P(Pkcs11AesGcmTest,TestVectors)352 TEST_P(Pkcs11AesGcmTest, TestVectors) { RunTest(GetParam()); }
353
354 INSTANTIATE_TEST_SUITE_P(NISTTestVector, Pkcs11AesGcmTest,
355 ::testing::ValuesIn(kGcmKatValues));
356
357 INSTANTIATE_TEST_SUITE_P(WycheproofTestVector, Pkcs11AesGcmTest,
358 ::testing::ValuesIn(kGcmWycheproofVectors));
359
TEST_F(Pkcs11AesGcmTest,ZeroLengthIV)360 TEST_F(Pkcs11AesGcmTest, ZeroLengthIV) {
361 std::vector<uint8_t> iv(0);
362 EXPECT_EQ(SECFailure, EncryptWithIV(iv));
363 }
364
TEST_F(Pkcs11AesGcmTest,AllZeroIV)365 TEST_F(Pkcs11AesGcmTest, AllZeroIV) {
366 std::vector<uint8_t> iv(16, 0);
367 EXPECT_EQ(SECSuccess, EncryptWithIV(iv));
368 }
369
TEST_F(Pkcs11AesGcmTest,TwelveByteZeroIV)370 TEST_F(Pkcs11AesGcmTest, TwelveByteZeroIV) {
371 std::vector<uint8_t> iv(12, 0);
372 EXPECT_EQ(SECSuccess, EncryptWithIV(iv));
373 }
374
375 // basic message interface it's the most common configuration
TEST_F(Pkcs11AesGcmTest,MessageInterfaceBasic)376 TEST_F(Pkcs11AesGcmTest, MessageInterfaceBasic) {
377 EXPECT_EQ(SECSuccess,
378 MessageInterfaceTest(16, 0, CKG_GENERATE_COUNTER, PR_FALSE));
379 }
380
381 // basic interface, but return the tags in a separate buffer. This triggers
382 // different behaviour in the simulated case, which has to buffer the
383 // intermediate values in a separate buffer.
TEST_F(Pkcs11AesGcmTest,MessageInterfaceSeparateTags)384 TEST_F(Pkcs11AesGcmTest, MessageInterfaceSeparateTags) {
385 EXPECT_EQ(SECSuccess,
386 MessageInterfaceTest(16, 0, CKG_GENERATE_COUNTER, PR_TRUE));
387 }
388
389 // test the case where we are only allowing a portion of the iv to be generated
TEST_F(Pkcs11AesGcmTest,MessageInterfaceIVMask)390 TEST_F(Pkcs11AesGcmTest, MessageInterfaceIVMask) {
391 EXPECT_EQ(SECSuccess,
392 MessageInterfaceTest(16, 124, CKG_GENERATE_COUNTER, PR_FALSE));
393 }
394
395 // test the case where we using the tls1.3 iv generation
TEST_F(Pkcs11AesGcmTest,MessageInterfaceXorCounter)396 TEST_F(Pkcs11AesGcmTest, MessageInterfaceXorCounter) {
397 EXPECT_EQ(SECSuccess,
398 MessageInterfaceTest(16, 0, CKG_GENERATE_COUNTER_XOR, PR_FALSE));
399 }
400
401 // test the case where we overflow the counter (requires restricted iv)
402 // 128-124 = 4 bits;
TEST_F(Pkcs11AesGcmTest,MessageInterfaceCounterOverflow)403 TEST_F(Pkcs11AesGcmTest, MessageInterfaceCounterOverflow) {
404 EXPECT_EQ(SECFailure,
405 MessageInterfaceTest(17, 124, CKG_GENERATE_COUNTER, PR_FALSE));
406 }
407
408 // overflow the tla1.2 iv case
TEST_F(Pkcs11AesGcmTest,MessageInterfaceXorCounterOverflow)409 TEST_F(Pkcs11AesGcmTest, MessageInterfaceXorCounterOverflow) {
410 EXPECT_EQ(SECFailure,
411 MessageInterfaceTest(17, 124, CKG_GENERATE_COUNTER_XOR, PR_FALSE));
412 }
413
414 // test random generation of the IV (uses an aligned restricted iv)
TEST_F(Pkcs11AesGcmTest,MessageInterfaceRandomIV)415 TEST_F(Pkcs11AesGcmTest, MessageInterfaceRandomIV) {
416 EXPECT_EQ(SECSuccess,
417 MessageInterfaceTest(16, 56, CKG_GENERATE_RANDOM, PR_FALSE));
418 }
419
420 // test the case where we try to generate too many random IVs for the size of
421 // our our restricted IV (notice for counters, we can generate 16 IV with
422 // 4 bits, but for random we need at least 72 bits to generate 16 IVs).
423 // 128-56 = 72 bits
TEST_F(Pkcs11AesGcmTest,MessageInterfaceRandomOverflow)424 TEST_F(Pkcs11AesGcmTest, MessageInterfaceRandomOverflow) {
425 EXPECT_EQ(SECFailure,
426 MessageInterfaceTest(17, 56, CKG_GENERATE_RANDOM, PR_FALSE));
427 }
428 } // namespace nss_test
429