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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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