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 "sechash.h"
12 #include "secerr.h"
13 
14 #include "cpputil.h"
15 #include "nss_scoped_ptrs.h"
16 
17 #include "testvectors/chachapoly-vectors.h"
18 #include "gtest/gtest.h"
19 
20 namespace nss_test {
21 
22 static const CK_MECHANISM_TYPE kMech = CKM_NSS_CHACHA20_POLY1305;
23 static const CK_MECHANISM_TYPE kMechXor = CKM_NSS_CHACHA20_CTR;
24 // Some test data for simple tests.
25 static const uint8_t kKeyData[32] = {'k'};
26 static const uint8_t kCtrNonce[16] = {'c', 0, 0, 0, 'n'};
27 static const uint8_t kData[16] = {'d'};
28 
29 class Pkcs11ChaCha20Poly1305Test
30     : public ::testing::TestWithParam<ChaChaTestVector> {
31  public:
EncryptDecrypt(const ScopedPK11SymKey & key,const bool invalid_iv,const bool invalid_tag,const uint8_t * data,size_t data_len,const uint8_t * aad,size_t aad_len,const uint8_t * iv,size_t iv_len,const uint8_t * ct=nullptr,size_t ct_len=0)32   void EncryptDecrypt(const ScopedPK11SymKey& key, const bool invalid_iv,
33                       const bool invalid_tag, const uint8_t* data,
34                       size_t data_len, const uint8_t* aad, size_t aad_len,
35                       const uint8_t* iv, size_t iv_len,
36                       const uint8_t* ct = nullptr, size_t ct_len = 0) {
37     // Prepare AEAD params.
38     CK_NSS_AEAD_PARAMS aead_params;
39     aead_params.pNonce = toUcharPtr(iv);
40     aead_params.ulNonceLen = iv_len;
41     aead_params.pAAD = toUcharPtr(aad);
42     aead_params.ulAADLen = aad_len;
43     aead_params.ulTagLen = 16;
44 
45     SECItem params = {siBuffer, reinterpret_cast<unsigned char*>(&aead_params),
46                       sizeof(aead_params)};
47 
48     // Encrypt with bad parameters (TagLen is too long).
49     unsigned int encrypted_len = 0;
50     std::vector<uint8_t> encrypted(data_len + aead_params.ulTagLen);
51     aead_params.ulTagLen = 158072;
52     SECStatus rv =
53         PK11_Encrypt(key.get(), kMech, &params, encrypted.data(),
54                      &encrypted_len, encrypted.size(), data, data_len);
55     EXPECT_EQ(SECFailure, rv);
56     EXPECT_EQ(0U, encrypted_len);
57 
58     // Encrypt with bad parameters (TagLen is too short).
59     aead_params.ulTagLen = 2;
60     rv = PK11_Encrypt(key.get(), kMech, &params, encrypted.data(),
61                       &encrypted_len, encrypted.size(), data, data_len);
62     EXPECT_EQ(SECFailure, rv);
63     EXPECT_EQ(0U, encrypted_len);
64 
65     // Encrypt.
66     aead_params.ulTagLen = 16;
67     rv = PK11_Encrypt(key.get(), kMech, &params, encrypted.data(),
68                       &encrypted_len, encrypted.size(), data, data_len);
69 
70     // Return if encryption failure was expected due to invalid IV.
71     // Without valid ciphertext, all further tests can be skipped.
72     if (invalid_iv) {
73       EXPECT_EQ(rv, SECFailure);
74       EXPECT_EQ(0U, encrypted_len)
75           << "encrypted_len is unmodified after failure";
76       return;
77     }
78 
79     EXPECT_EQ(rv, SECSuccess);
80     EXPECT_EQ(encrypted.size(), static_cast<size_t>(encrypted_len));
81 
82     // Check ciphertext and tag.
83     if (ct) {
84       ASSERT_EQ(ct_len, encrypted_len);
85       EXPECT_TRUE(!memcmp(ct, encrypted.data(), encrypted.size() - 16));
86       EXPECT_TRUE(!memcmp(ct, encrypted.data(), encrypted.size()) !=
87                   invalid_tag);
88     }
89 
90     // Get the *estimated* plaintext length. This value should
91     // never be zero as it could lead to a NULL outPtr being
92     // passed to a subsequent decryption call (for AEAD we
93     // must authenticate even when the pt is zero-length).
94     unsigned int decrypt_bytes_needed = 0;
95     rv = PK11_Decrypt(key.get(), kMech, &params, nullptr, &decrypt_bytes_needed,
96                       0, encrypted.data(), encrypted_len);
97     EXPECT_EQ(rv, SECSuccess);
98     EXPECT_GT(decrypt_bytes_needed, data_len);
99 
100     // Now decrypt it
101     std::vector<uint8_t> decrypted(decrypt_bytes_needed);
102     unsigned int decrypted_len = 0;
103     rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
104                       &decrypted_len, decrypted.size(), encrypted.data(),
105                       encrypted.size());
106     EXPECT_EQ(rv, SECSuccess);
107 
108     // Check the plaintext.
109     ASSERT_EQ(data_len, decrypted_len);
110     EXPECT_TRUE(!memcmp(data, decrypted.data(), decrypted_len));
111 
112     // Decrypt with bogus data.
113     // Skip if there's no data to modify.
114     if (encrypted_len > 0) {
115       decrypted_len = 0;
116       std::vector<uint8_t> bogus_ciphertext(encrypted);
117       bogus_ciphertext[0] ^= 0xff;
118       rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
119                         &decrypted_len, decrypted.size(),
120                         bogus_ciphertext.data(), encrypted_len);
121       EXPECT_EQ(rv, SECFailure);
122       EXPECT_EQ(0U, decrypted_len);
123     }
124 
125     // Decrypt with bogus tag.
126     // Skip if there's no tag to modify.
127     if (encrypted_len > 0) {
128       decrypted_len = 0;
129       std::vector<uint8_t> bogus_tag(encrypted);
130       bogus_tag[encrypted_len - 1] ^= 0xff;
131       rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
132                         &decrypted_len, decrypted.size(), bogus_tag.data(),
133                         encrypted_len);
134       EXPECT_EQ(rv, SECFailure);
135       EXPECT_EQ(0U, decrypted_len);
136     }
137 
138     // Decrypt with bogus IV.
139     // iv_len == 0 is invalid and should be caught earlier.
140     // Still skip, if there's no IV to modify.
141     if (iv_len != 0) {
142       decrypted_len = 0;
143       SECItem bogus_params(params);
144       CK_NSS_AEAD_PARAMS bogusAeadParams(aead_params);
145       bogus_params.data = reinterpret_cast<unsigned char*>(&bogusAeadParams);
146 
147       std::vector<uint8_t> bogusIV(iv, iv + iv_len);
148       bogusAeadParams.pNonce = toUcharPtr(bogusIV.data());
149       bogusIV[0] ^= 0xff;
150 
151       rv = PK11_Decrypt(key.get(), kMech, &bogus_params, decrypted.data(),
152                         &decrypted_len, data_len, encrypted.data(),
153                         encrypted.size());
154       EXPECT_EQ(rv, SECFailure);
155       EXPECT_EQ(0U, decrypted_len);
156     }
157 
158     // Decrypt with bogus additional data.
159     // Skip when AAD was empty and can't be modified.
160     // Alternatively we could generate random aad.
161     if (aad_len != 0) {
162       decrypted_len = 0;
163       SECItem bogus_params(params);
164       CK_NSS_AEAD_PARAMS bogus_aead_params(aead_params);
165       bogus_params.data = reinterpret_cast<unsigned char*>(&bogus_aead_params);
166 
167       std::vector<uint8_t> bogus_aad(aad, aad + aad_len);
168       bogus_aead_params.pAAD = toUcharPtr(bogus_aad.data());
169       bogus_aad[0] ^= 0xff;
170 
171       rv = PK11_Decrypt(key.get(), kMech, &bogus_params, decrypted.data(),
172                         &decrypted_len, data_len, encrypted.data(),
173                         encrypted.size());
174       EXPECT_EQ(rv, SECFailure);
175       EXPECT_EQ(0U, decrypted_len);
176     }
177   }
178 
EncryptDecrypt(const ChaChaTestVector testvector)179   void EncryptDecrypt(const ChaChaTestVector testvector) {
180     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
181     SECItem keyItem = {siBuffer, toUcharPtr(testvector.key.data()),
182                        static_cast<unsigned int>(testvector.key.size())};
183 
184     // Import key.
185     ScopedPK11SymKey key(PK11_ImportSymKey(slot.get(), kMech, PK11_OriginUnwrap,
186                                            CKA_ENCRYPT, &keyItem, nullptr));
187     EXPECT_TRUE(!!key);
188 
189     // Check.
190     EncryptDecrypt(key, testvector.invalid_iv, testvector.invalid_tag,
191                    testvector.plaintext.data(), testvector.plaintext.size(),
192                    testvector.aad.data(), testvector.aad.size(),
193                    testvector.iv.data(), testvector.iv.size(),
194                    testvector.ciphertext.data(), testvector.ciphertext.size());
195   }
196 
MessageInterfaceTest(CK_MECHANISM_TYPE mech,int iterations,PRBool separateTag)197   void MessageInterfaceTest(CK_MECHANISM_TYPE mech, int iterations,
198                             PRBool separateTag) {
199     // Generate a random key.
200     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
201     ASSERT_NE(nullptr, slot);
202     ScopedPK11SymKey sym_key(
203         PK11_KeyGen(slot.get(), mech, nullptr, 32, nullptr));
204     ASSERT_NE(nullptr, sym_key);
205 
206     int tagSize = 16;
207     int cipher_simulated_size;
208     int output_len_message = 0;
209     int output_len_simulated = 0;
210     unsigned int output_len_v24 = 0;
211 
212     std::vector<uint8_t> plainIn(17);
213     std::vector<uint8_t> plainOut_message(17);
214     std::vector<uint8_t> plainOut_simulated(17);
215     std::vector<uint8_t> plainOut_v24(17);
216     std::vector<uint8_t> nonce(12);
217     std::vector<uint8_t> cipher_message(33);
218     std::vector<uint8_t> cipher_simulated(33);
219     std::vector<uint8_t> cipher_v24(33);
220     std::vector<uint8_t> aad(16);
221     std::vector<uint8_t> tag_message(16);
222     std::vector<uint8_t> tag_simulated(16);
223 
224     // Prepare AEAD v2.40 params.
225     CK_SALSA20_CHACHA20_POLY1305_PARAMS chacha_params;
226     chacha_params.pNonce = nonce.data();
227     chacha_params.ulNonceLen = nonce.size();
228     chacha_params.pAAD = aad.data();
229     chacha_params.ulAADLen = aad.size();
230 
231     // Prepare AEAD MESSAGE params.
232     CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS chacha_message_params;
233     chacha_message_params.pNonce = nonce.data();
234     chacha_message_params.ulNonceLen = nonce.size();
235     if (separateTag) {
236       chacha_message_params.pTag = tag_message.data();
237     } else {
238       chacha_message_params.pTag = cipher_message.data() + plainIn.size();
239     }
240 
241     // Prepare AEAD MESSAGE params for simulated case
242     CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS chacha_simulated_params;
243     chacha_simulated_params = chacha_message_params;
244     if (separateTag) {
245       // The simulated case, we have to allocate temp bufs for separate
246       // tags, make sure that works in both the encrypt and the decrypt
247       // cases.
248       chacha_simulated_params.pTag = tag_simulated.data();
249       cipher_simulated_size = cipher_simulated.size() - tagSize;
250     } else {
251       chacha_simulated_params.pTag = cipher_simulated.data() + plainIn.size();
252       cipher_simulated_size = cipher_simulated.size();
253     }
254     SECItem params = {siBuffer,
255                       reinterpret_cast<unsigned char*>(&chacha_params),
256                       sizeof(chacha_params)};
257     SECItem empty = {siBuffer, NULL, 0};
258 
259     // initialize our plain text, IV and aad.
260     ASSERT_EQ(PK11_GenerateRandom(plainIn.data(), plainIn.size()), SECSuccess);
261     ASSERT_EQ(PK11_GenerateRandom(aad.data(), aad.size()), SECSuccess);
262 
263     // Initialize message encrypt context
264     ScopedPK11Context encrypt_message_context(PK11_CreateContextBySymKey(
265         mech, CKA_NSS_MESSAGE | CKA_ENCRYPT, sym_key.get(), &empty));
266     ASSERT_NE(nullptr, encrypt_message_context);
267     ASSERT_FALSE(_PK11_ContextGetAEADSimulation(encrypt_message_context.get()));
268 
269     // Initialize simulated encrypt context
270     ScopedPK11Context encrypt_simulated_context(PK11_CreateContextBySymKey(
271         mech, CKA_NSS_MESSAGE | CKA_ENCRYPT, sym_key.get(), &empty));
272     ASSERT_NE(nullptr, encrypt_simulated_context);
273     ASSERT_EQ(SECSuccess,
274               _PK11_ContextSetAEADSimulation(encrypt_simulated_context.get()));
275 
276     // Initialize message decrypt context
277     ScopedPK11Context decrypt_message_context(PK11_CreateContextBySymKey(
278         mech, CKA_NSS_MESSAGE | CKA_DECRYPT, sym_key.get(), &empty));
279     ASSERT_NE(nullptr, decrypt_message_context);
280     ASSERT_FALSE(_PK11_ContextGetAEADSimulation(decrypt_message_context.get()));
281 
282     // Initialize simulated decrypt context
283     ScopedPK11Context decrypt_simulated_context(PK11_CreateContextBySymKey(
284         mech, CKA_NSS_MESSAGE | CKA_DECRYPT, sym_key.get(), &empty));
285     ASSERT_NE(nullptr, decrypt_simulated_context);
286     EXPECT_EQ(SECSuccess,
287               _PK11_ContextSetAEADSimulation(decrypt_simulated_context.get()));
288 
289     // Now walk down our iterations. Each method of calculating the operation
290     // should agree at each step.
291     for (int i = 0; i < iterations; i++) {
292       // get a unique nonce for each iteration
293       EXPECT_EQ(PK11_GenerateRandom(nonce.data(), nonce.size()), SECSuccess);
294       EXPECT_EQ(SECSuccess,
295                 PK11_AEADRawOp(
296                     encrypt_message_context.get(), &chacha_message_params,
297                     sizeof(chacha_message_params), aad.data(), aad.size(),
298                     cipher_message.data(), &output_len_message,
299                     cipher_message.size(), plainIn.data(), plainIn.size()));
300       EXPECT_EQ(SECSuccess,
301                 PK11_AEADRawOp(
302                     encrypt_simulated_context.get(), &chacha_simulated_params,
303                     sizeof(chacha_simulated_params), aad.data(), aad.size(),
304                     cipher_simulated.data(), &output_len_simulated,
305                     cipher_simulated_size, plainIn.data(), plainIn.size()));
306       // make sure simulated and message is the same
307       EXPECT_EQ(output_len_message, output_len_simulated);
308       EXPECT_EQ(0, memcmp(cipher_message.data(), cipher_simulated.data(),
309                           output_len_message));
310       EXPECT_EQ(0, memcmp(chacha_message_params.pTag,
311                           chacha_simulated_params.pTag, tagSize));
312       // make sure v2.40 is the same.
313       EXPECT_EQ(SECSuccess,
314                 PK11_Encrypt(sym_key.get(), mech, &params, cipher_v24.data(),
315                              &output_len_v24, cipher_v24.size(), plainIn.data(),
316                              plainIn.size()));
317       EXPECT_EQ(output_len_message, (int)output_len_v24 - tagSize);
318       EXPECT_EQ(0, memcmp(cipher_message.data(), cipher_v24.data(),
319                           output_len_message));
320       EXPECT_EQ(0, memcmp(chacha_message_params.pTag,
321                           cipher_v24.data() + output_len_message, tagSize));
322       // now make sure we can decrypt
323       EXPECT_EQ(
324           SECSuccess,
325           PK11_AEADRawOp(decrypt_message_context.get(), &chacha_message_params,
326                          sizeof(chacha_message_params), aad.data(), aad.size(),
327                          plainOut_message.data(), &output_len_message,
328                          plainOut_message.size(), cipher_message.data(),
329                          output_len_message));
330       EXPECT_EQ(output_len_message, (int)plainIn.size());
331       EXPECT_EQ(
332           0, memcmp(plainOut_message.data(), plainIn.data(), plainIn.size()));
333       EXPECT_EQ(SECSuccess,
334                 PK11_AEADRawOp(decrypt_simulated_context.get(),
335                                &chacha_simulated_params,
336                                sizeof(chacha_simulated_params), aad.data(),
337                                aad.size(), plainOut_simulated.data(),
338                                &output_len_simulated, plainOut_simulated.size(),
339                                cipher_message.data(), output_len_simulated));
340       EXPECT_EQ(output_len_simulated, (int)plainIn.size());
341       EXPECT_EQ(
342           0, memcmp(plainOut_simulated.data(), plainIn.data(), plainIn.size()));
343       if (separateTag) {
344         // in the separateTag case, we need to copy the tag back to the
345         // end of the cipher_message.data() before using the v2.4 interface
346         memcpy(cipher_message.data() + output_len_message,
347                chacha_message_params.pTag, tagSize);
348       }
349       EXPECT_EQ(SECSuccess,
350                 PK11_Decrypt(sym_key.get(), mech, &params, plainOut_v24.data(),
351                              &output_len_v24, plainOut_v24.size(),
352                              cipher_message.data(), output_len_v24));
353       EXPECT_EQ(output_len_v24, plainIn.size());
354       EXPECT_EQ(0, memcmp(plainOut_v24.data(), plainIn.data(), plainIn.size()));
355     }
356     return;
357   }
358 
359  protected:
360 };
361 
TEST_F(Pkcs11ChaCha20Poly1305Test,GenerateEncryptDecrypt)362 TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateEncryptDecrypt) {
363   // Generate a random key.
364   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
365   ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
366   EXPECT_TRUE(!!key);
367 
368   // Generate random data.
369   std::vector<uint8_t> input(512);
370   SECStatus rv =
371       PK11_GenerateRandomOnSlot(slot.get(), input.data(), input.size());
372   EXPECT_EQ(rv, SECSuccess);
373 
374   // Generate random AAD.
375   std::vector<uint8_t> aad(16);
376   rv = PK11_GenerateRandomOnSlot(slot.get(), aad.data(), aad.size());
377   EXPECT_EQ(rv, SECSuccess);
378 
379   // Generate random IV.
380   std::vector<uint8_t> iv(12);
381   rv = PK11_GenerateRandomOnSlot(slot.get(), iv.data(), iv.size());
382   EXPECT_EQ(rv, SECSuccess);
383 
384   // Check.
385   EncryptDecrypt(key, false, false, input.data(), input.size(), aad.data(),
386                  aad.size(), iv.data(), iv.size());
387 }
388 
TEST_F(Pkcs11ChaCha20Poly1305Test,Xor)389 TEST_F(Pkcs11ChaCha20Poly1305Test, Xor) {
390   static const uint8_t kExpected[sizeof(kData)] = {
391       0xd8, 0x15, 0xd3, 0xb3, 0xe9, 0x34, 0x3b, 0x7a,
392       0x24, 0xf6, 0x5f, 0xd7, 0x95, 0x3d, 0xd3, 0x51};
393 
394   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
395   SECItem keyItem = {siBuffer, toUcharPtr(kKeyData),
396                      static_cast<unsigned int>(sizeof(kKeyData))};
397   ScopedPK11SymKey key(PK11_ImportSymKey(
398       slot.get(), kMechXor, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr));
399   EXPECT_TRUE(!!key);
400 
401   SECItem ctrNonceItem = {siBuffer, toUcharPtr(kCtrNonce),
402                           static_cast<unsigned int>(sizeof(kCtrNonce))};
403   uint8_t encrypted[sizeof(kData)];
404   unsigned int encrypted_len = 88;  // This should be overwritten.
405   SECStatus rv =
406       PK11_Encrypt(key.get(), kMechXor, &ctrNonceItem, encrypted,
407                    &encrypted_len, sizeof(encrypted), kData, sizeof(kData));
408   ASSERT_EQ(SECSuccess, rv);
409   ASSERT_EQ(sizeof(kExpected), static_cast<size_t>(encrypted_len));
410   EXPECT_EQ(0, memcmp(kExpected, encrypted, sizeof(kExpected)));
411 
412   // Decrypting has the same effect.
413   rv = PK11_Decrypt(key.get(), kMechXor, &ctrNonceItem, encrypted,
414                     &encrypted_len, sizeof(encrypted), kData, sizeof(kData));
415   ASSERT_EQ(SECSuccess, rv);
416   ASSERT_EQ(sizeof(kData), static_cast<size_t>(encrypted_len));
417   EXPECT_EQ(0, memcmp(kExpected, encrypted, sizeof(kExpected)));
418 
419   // Operating in reverse too.
420   rv = PK11_Encrypt(key.get(), kMechXor, &ctrNonceItem, encrypted,
421                     &encrypted_len, sizeof(encrypted), kExpected,
422                     sizeof(kExpected));
423   ASSERT_EQ(SECSuccess, rv);
424   ASSERT_EQ(sizeof(kExpected), static_cast<size_t>(encrypted_len));
425   EXPECT_EQ(0, memcmp(kData, encrypted, sizeof(kData)));
426 }
427 
428 // This test just ensures that a key can be generated for use with the XOR
429 // function.  The result is random and therefore cannot be checked.
TEST_F(Pkcs11ChaCha20Poly1305Test,GenerateXor)430 TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateXor) {
431   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
432   ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
433   EXPECT_TRUE(!!key);
434 
435   std::vector<uint8_t> iv(16);
436   SECStatus rv = PK11_GenerateRandomOnSlot(slot.get(), iv.data(), iv.size());
437   EXPECT_EQ(SECSuccess, rv);
438 
439   SECItem ctrNonceItem = {siBuffer, toUcharPtr(iv.data()),
440                           static_cast<unsigned int>(iv.size())};
441   uint8_t encrypted[sizeof(kData)];
442   unsigned int encrypted_len = 88;  // This should be overwritten.
443   rv = PK11_Encrypt(key.get(), kMechXor, &ctrNonceItem, encrypted,
444                     &encrypted_len, sizeof(encrypted), kData, sizeof(kData));
445   ASSERT_EQ(SECSuccess, rv);
446   ASSERT_EQ(sizeof(kData), static_cast<size_t>(encrypted_len));
447 }
448 
TEST_F(Pkcs11ChaCha20Poly1305Test,XorInvalidParams)449 TEST_F(Pkcs11ChaCha20Poly1305Test, XorInvalidParams) {
450   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
451   ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
452   EXPECT_TRUE(!!key);
453 
454   SECItem ctrNonceItem = {siBuffer, toUcharPtr(kCtrNonce),
455                           static_cast<unsigned int>(sizeof(kCtrNonce)) - 1};
456   uint8_t encrypted[sizeof(kData)];
457   unsigned int encrypted_len = 88;
458   SECStatus rv =
459       PK11_Encrypt(key.get(), kMechXor, &ctrNonceItem, encrypted,
460                    &encrypted_len, sizeof(encrypted), kData, sizeof(kData));
461   EXPECT_EQ(SECFailure, rv);
462 
463   ctrNonceItem.data = nullptr;
464   rv = PK11_Encrypt(key.get(), kMechXor, &ctrNonceItem, encrypted,
465                     &encrypted_len, sizeof(encrypted), kData, sizeof(kData));
466   EXPECT_EQ(SECFailure, rv);
467   EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
468 }
469 
TEST_P(Pkcs11ChaCha20Poly1305Test,TestVectors)470 TEST_P(Pkcs11ChaCha20Poly1305Test, TestVectors) { EncryptDecrypt(GetParam()); }
471 
472 INSTANTIATE_TEST_SUITE_P(NSSTestVector, Pkcs11ChaCha20Poly1305Test,
473                          ::testing::ValuesIn(kChaCha20Vectors));
474 
475 INSTANTIATE_TEST_SUITE_P(WycheproofTestVector, Pkcs11ChaCha20Poly1305Test,
476                          ::testing::ValuesIn(kChaCha20WycheproofVectors));
477 
478 // basic message interface it's the most common configuration
TEST_F(Pkcs11ChaCha20Poly1305Test,ChaCha201305MessageInterfaceBasic)479 TEST_F(Pkcs11ChaCha20Poly1305Test, ChaCha201305MessageInterfaceBasic) {
480   MessageInterfaceTest(CKM_CHACHA20_POLY1305, 16, PR_FALSE);
481 }
482 
483 // basic interface, but return the tags in a separate buffer. This triggers
484 // different behaviour in the simulated case, which has to buffer the
485 // intermediate values in a separate buffer.
TEST_F(Pkcs11ChaCha20Poly1305Test,ChaCha20Poly1305MessageInterfaceSeparateTags)486 TEST_F(Pkcs11ChaCha20Poly1305Test,
487        ChaCha20Poly1305MessageInterfaceSeparateTags) {
488   MessageInterfaceTest(CKM_CHACHA20_POLY1305, 16, PR_TRUE);
489 }
490 
491 }  // namespace nss_test
492