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 "secerr.h"
11 
12 #include "gtest/gtest.h"
13 #include "nss_scoped_ptrs.h"
14 #include "testvectors/cbc-vectors.h"
15 #include "util.h"
16 
17 namespace nss_test {
18 
19 static const uint8_t kInput[99] = {1, 2, 3};
20 static const uint8_t kKeyData[24] = {'K', 'E', 'Y'};
21 
GetIv()22 static SECItem* GetIv() {
23   static const uint8_t kIvData[16] = {'I', 'V'};
24   static const SECItem kIv = {siBuffer, const_cast<uint8_t*>(kIvData),
25                               static_cast<unsigned int>(sizeof(kIvData))};
26   return const_cast<SECItem*>(&kIv);
27 }
28 
29 class Pkcs11CbcPadTest : public ::testing::TestWithParam<CK_MECHANISM_TYPE> {
30  protected:
is_padded() const31   bool is_padded() const {
32     switch (GetParam()) {
33       case CKM_AES_CBC_PAD:
34       case CKM_DES3_CBC_PAD:
35         return true;
36 
37       case CKM_AES_CBC:
38       case CKM_DES3_CBC:
39         return false;
40 
41       default:
42         ADD_FAILURE() << "Unknown mechanism " << GetParam();
43     }
44     return false;
45   }
46 
GetUnpaddedMechanism() const47   uint32_t GetUnpaddedMechanism() const {
48     switch (GetParam()) {
49       case CKM_AES_CBC_PAD:
50         return CKM_AES_CBC;
51       case CKM_DES3_CBC_PAD:
52         return CKM_DES3_CBC;
53       default:
54         ADD_FAILURE() << "Unknown padded mechanism " << GetParam();
55     }
56     return 0;
57   }
58 
block_size() const59   size_t block_size() const {
60     return static_cast<size_t>(PK11_GetBlockSize(GetParam(), nullptr));
61   }
62 
GetInputLen(CK_ATTRIBUTE_TYPE op) const63   size_t GetInputLen(CK_ATTRIBUTE_TYPE op) const {
64     if (is_padded() && op == CKA_ENCRYPT) {
65       // Anything goes for encryption when padded.
66       return sizeof(kInput);
67     }
68 
69     // Otherwise, use a strict multiple of the block size.
70     size_t block_count = sizeof(kInput) / block_size();
71     EXPECT_LT(1U, block_count) << "need 2 blocks for tests";
72     return block_count * block_size();
73   }
74 
MakeKey(CK_ATTRIBUTE_TYPE op)75   ScopedPK11SymKey MakeKey(CK_ATTRIBUTE_TYPE op) {
76     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
77     EXPECT_NE(nullptr, slot);
78     if (!slot) {
79       return nullptr;
80     }
81 
82     unsigned int key_len = 0;
83     switch (GetParam()) {
84       case CKM_AES_CBC_PAD:
85       case CKM_AES_CBC:
86         key_len = 16;  // This doesn't do AES-256 to keep it simple.
87         break;
88 
89       case CKM_DES3_CBC_PAD:
90       case CKM_DES3_CBC:
91         key_len = 24;
92         break;
93 
94       default:
95         ADD_FAILURE() << "Unknown mechanism " << GetParam();
96         return nullptr;
97     }
98 
99     SECItem key_item = {siBuffer, const_cast<uint8_t*>(kKeyData), key_len};
100     PK11SymKey* p = PK11_ImportSymKey(slot.get(), GetParam(), PK11_OriginUnwrap,
101                                       op, &key_item, nullptr);
102     EXPECT_NE(nullptr, p);
103     return ScopedPK11SymKey(p);
104   }
105 
MakeContext(CK_ATTRIBUTE_TYPE op)106   ScopedPK11Context MakeContext(CK_ATTRIBUTE_TYPE op) {
107     ScopedPK11SymKey k = MakeKey(op);
108     PK11Context* ctx =
109         PK11_CreateContextBySymKey(GetParam(), op, k.get(), GetIv());
110     EXPECT_NE(nullptr, ctx);
111     return ScopedPK11Context(ctx);
112   }
113 };
114 
TEST_P(Pkcs11CbcPadTest,EncryptDecrypt)115 TEST_P(Pkcs11CbcPadTest, EncryptDecrypt) {
116   uint8_t encrypted[sizeof(kInput) + 64];  // Allow for padding and expansion.
117   size_t input_len = GetInputLen(CKA_ENCRYPT);
118 
119   ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
120   unsigned int encrypted_len = 0;
121   SECStatus rv =
122       PK11_Encrypt(ek.get(), GetParam(), GetIv(), encrypted, &encrypted_len,
123                    sizeof(encrypted), kInput, input_len);
124   ASSERT_EQ(SECSuccess, rv);
125   EXPECT_LE(input_len, static_cast<size_t>(encrypted_len));
126 
127   // Though the decrypted result can't be larger than the input we provided,
128   // NSS needs extra space to put the padding in.
129   uint8_t decrypted[sizeof(kInput) + 64];
130   unsigned int decrypted_len = 0;
131   ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
132   rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted, &decrypted_len,
133                     sizeof(decrypted), encrypted, encrypted_len);
134   ASSERT_EQ(SECSuccess, rv);
135   EXPECT_EQ(input_len, static_cast<size_t>(decrypted_len));
136   EXPECT_EQ(0, memcmp(kInput, decrypted, input_len));
137 }
138 
TEST_P(Pkcs11CbcPadTest,ContextEncryptDecrypt)139 TEST_P(Pkcs11CbcPadTest, ContextEncryptDecrypt) {
140   uint8_t encrypted[sizeof(kInput) + 64];  // Allow for padding and expansion.
141   size_t input_len = GetInputLen(CKA_ENCRYPT);
142 
143   ScopedPK11Context ectx = MakeContext(CKA_ENCRYPT);
144   int encrypted_len = 0;
145   SECStatus rv = PK11_CipherOp(ectx.get(), encrypted, &encrypted_len,
146                                sizeof(encrypted), kInput, input_len);
147   ASSERT_EQ(SECSuccess, rv);
148   EXPECT_LE(0, encrypted_len);  // Stupid signed parameters.
149 
150   unsigned int final_len = 0;
151   rv = PK11_CipherFinal(ectx.get(), encrypted + encrypted_len, &final_len,
152                         sizeof(encrypted) - encrypted_len);
153   ASSERT_EQ(SECSuccess, rv);
154   encrypted_len += final_len;
155   EXPECT_LE(input_len, static_cast<size_t>(encrypted_len));
156 
157   uint8_t decrypted[sizeof(kInput) + 64];
158   int decrypted_len = 0;
159   ScopedPK11Context dctx = MakeContext(CKA_DECRYPT);
160   rv = PK11_CipherOp(dctx.get(), decrypted, &decrypted_len, sizeof(decrypted),
161                      encrypted, encrypted_len);
162   ASSERT_EQ(SECSuccess, rv);
163   EXPECT_LE(0, decrypted_len);
164 
165   rv = PK11_CipherFinal(dctx.get(), decrypted + decrypted_len, &final_len,
166                         sizeof(decrypted) - decrypted_len);
167   ASSERT_EQ(SECSuccess, rv);
168   decrypted_len += final_len;
169   EXPECT_EQ(input_len, static_cast<size_t>(decrypted_len));
170   EXPECT_EQ(0, memcmp(kInput, decrypted, input_len));
171 }
172 
TEST_P(Pkcs11CbcPadTest,ContextEncryptDecryptTwoParts)173 TEST_P(Pkcs11CbcPadTest, ContextEncryptDecryptTwoParts) {
174   uint8_t encrypted[sizeof(kInput) + 64];
175   size_t input_len = GetInputLen(CKA_ENCRYPT);
176 
177   ScopedPK11Context ectx = MakeContext(CKA_ENCRYPT);
178   int first_len = 0;
179   SECStatus rv = PK11_CipherOp(ectx.get(), encrypted, &first_len,
180                                sizeof(encrypted), kInput, block_size());
181   ASSERT_EQ(SECSuccess, rv);
182   ASSERT_LE(0, first_len);
183 
184   int second_len = 0;
185   rv = PK11_CipherOp(ectx.get(), encrypted + first_len, &second_len,
186                      sizeof(encrypted) - first_len, kInput + block_size(),
187                      input_len - block_size());
188   ASSERT_EQ(SECSuccess, rv);
189   ASSERT_LE(0, second_len);
190 
191   unsigned int final_len = 0;
192   rv = PK11_CipherFinal(ectx.get(), encrypted + first_len + second_len,
193                         &final_len, sizeof(encrypted) - first_len - second_len);
194   ASSERT_EQ(SECSuccess, rv);
195   unsigned int encrypted_len = first_len + second_len + final_len;
196   ASSERT_LE(input_len, static_cast<size_t>(encrypted_len));
197 
198   // Now decrypt this in a similar fashion.
199   uint8_t decrypted[sizeof(kInput) + 64];
200   ScopedPK11Context dctx = MakeContext(CKA_DECRYPT);
201   rv = PK11_CipherOp(dctx.get(), decrypted, &first_len, sizeof(decrypted),
202                      encrypted, block_size());
203   ASSERT_EQ(SECSuccess, rv);
204   EXPECT_LE(0, first_len);
205 
206   rv = PK11_CipherOp(dctx.get(), decrypted + first_len, &second_len,
207                      sizeof(decrypted) - first_len, encrypted + block_size(),
208                      encrypted_len - block_size());
209   ASSERT_EQ(SECSuccess, rv);
210   EXPECT_LE(0, second_len);
211 
212   unsigned int decrypted_len = 0;
213   rv = PK11_CipherFinal(dctx.get(), decrypted + first_len + second_len,
214                         &decrypted_len,
215                         sizeof(decrypted) - first_len - second_len);
216   ASSERT_EQ(SECSuccess, rv);
217   decrypted_len += first_len + second_len;
218   EXPECT_EQ(input_len, static_cast<size_t>(decrypted_len));
219   EXPECT_EQ(0, memcmp(kInput, decrypted, input_len));
220 }
221 
TEST_P(Pkcs11CbcPadTest,FailDecryptSimple)222 TEST_P(Pkcs11CbcPadTest, FailDecryptSimple) {
223   ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
224   uint8_t output[sizeof(kInput) + 64];
225   unsigned int output_len = 999;
226   SECStatus rv =
227       PK11_Decrypt(dk.get(), GetParam(), GetIv(), output, &output_len,
228                    sizeof(output), kInput, GetInputLen(CKA_DECRYPT));
229   if (is_padded()) {
230     EXPECT_EQ(SECFailure, rv);
231     EXPECT_EQ(999U, output_len);
232   } else {
233     // Unpadded decryption can't really fail.
234     EXPECT_EQ(SECSuccess, rv);
235   }
236 }
237 
TEST_P(Pkcs11CbcPadTest,FailEncryptSimple)238 TEST_P(Pkcs11CbcPadTest, FailEncryptSimple) {
239   ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
240   uint8_t output[3];  // Too small for anything.
241   unsigned int output_len = 333;
242 
243   SECStatus rv =
244       PK11_Encrypt(ek.get(), GetParam(), GetIv(), output, &output_len,
245                    sizeof(output), kInput, GetInputLen(CKA_ENCRYPT));
246   EXPECT_EQ(SECFailure, rv);
247   EXPECT_EQ(333U, output_len);
248 }
249 
250 // It's a bit of a lie to put this in pk11_cbc_unittest, since we
251 // also test bounds checking in other modes. There doesn't seem
252 // to be an appropriately-generic place elsewhere.
TEST_F(Pkcs11CbcPadTest,FailEncryptShortParam)253 TEST_F(Pkcs11CbcPadTest, FailEncryptShortParam) {
254   SECStatus rv = SECFailure;
255   uint8_t encrypted[sizeof(kInput)];
256   unsigned int encrypted_len = 0;
257   size_t input_len = AES_BLOCK_SIZE;
258 
259   // CK_NSS_GCM_PARAMS is the largest param struct used across AES modes
260   uint8_t param_buf[sizeof(CK_NSS_GCM_PARAMS)];
261   SECItem param = {siBuffer, param_buf, sizeof(param_buf)};
262   SECItem key_item = {siBuffer, const_cast<uint8_t*>(kKeyData), 16};
263 
264   // Setup (we use the ECB key for other modes)
265   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
266   ASSERT_NE(nullptr, slot);
267   ScopedPK11SymKey key(PK11_ImportSymKey(slot.get(), CKM_AES_ECB,
268                                          PK11_OriginUnwrap, CKA_ENCRYPT,
269                                          &key_item, nullptr));
270   ASSERT_TRUE(key.get());
271 
272   // CTR should have a CK_AES_CTR_PARAMS
273   param.len = sizeof(CK_AES_CTR_PARAMS) - 1;
274   rv = PK11_Encrypt(key.get(), CKM_AES_CTR, &param, encrypted, &encrypted_len,
275                     sizeof(encrypted), kInput, input_len);
276   EXPECT_EQ(SECFailure, rv);
277 
278   param.len++;
279   reinterpret_cast<CK_AES_CTR_PARAMS*>(param.data)->ulCounterBits = 32;
280   rv = PK11_Encrypt(key.get(), CKM_AES_CTR, &param, encrypted, &encrypted_len,
281                     sizeof(encrypted), kInput, input_len);
282   EXPECT_EQ(SECSuccess, rv);
283 
284   // GCM should have a CK_NSS_GCM_PARAMS
285   param.len = sizeof(CK_NSS_GCM_PARAMS) - 1;
286   rv = PK11_Encrypt(key.get(), CKM_AES_GCM, &param, encrypted, &encrypted_len,
287                     sizeof(encrypted), kInput, input_len);
288   EXPECT_EQ(SECFailure, rv);
289 
290   param.len++;
291   reinterpret_cast<CK_NSS_GCM_PARAMS*>(param.data)->pIv = param_buf;
292   reinterpret_cast<CK_NSS_GCM_PARAMS*>(param.data)->ulIvLen = 12;
293   reinterpret_cast<CK_NSS_GCM_PARAMS*>(param.data)->pAAD = nullptr;
294   reinterpret_cast<CK_NSS_GCM_PARAMS*>(param.data)->ulAADLen = 0;
295   reinterpret_cast<CK_NSS_GCM_PARAMS*>(param.data)->ulTagBits = 128;
296   rv = PK11_Encrypt(key.get(), CKM_AES_GCM, &param, encrypted, &encrypted_len,
297                     sizeof(encrypted), kInput, input_len);
298   EXPECT_EQ(SECSuccess, rv);
299 
300   // CBC should have a 16B IV
301   param.len = AES_BLOCK_SIZE - 1;
302   rv = PK11_Encrypt(key.get(), CKM_AES_CBC, &param, encrypted, &encrypted_len,
303                     sizeof(encrypted), kInput, input_len);
304   EXPECT_EQ(SECFailure, rv);
305 
306   param.len++;
307   rv = PK11_Encrypt(key.get(), CKM_AES_CBC, &param, encrypted, &encrypted_len,
308                     sizeof(encrypted), kInput, input_len);
309   EXPECT_EQ(SECSuccess, rv);
310 
311   // CTS
312   param.len = AES_BLOCK_SIZE - 1;
313   rv = PK11_Encrypt(key.get(), CKM_AES_CTS, &param, encrypted, &encrypted_len,
314                     sizeof(encrypted), kInput, input_len);
315   EXPECT_EQ(SECFailure, rv);
316 
317   param.len++;
318   rv = PK11_Encrypt(key.get(), CKM_AES_CTS, &param, encrypted, &encrypted_len,
319                     sizeof(encrypted), kInput, input_len);
320   EXPECT_EQ(SECSuccess, rv);
321 }
322 
TEST_P(Pkcs11CbcPadTest,ContextFailDecryptSimple)323 TEST_P(Pkcs11CbcPadTest, ContextFailDecryptSimple) {
324   ScopedPK11Context dctx = MakeContext(CKA_DECRYPT);
325   uint8_t output[sizeof(kInput) + 64];
326   int output_len = 77;
327 
328   SECStatus rv = PK11_CipherOp(dctx.get(), output, &output_len, sizeof(output),
329                                kInput, GetInputLen(CKA_DECRYPT));
330   EXPECT_EQ(SECSuccess, rv);
331   EXPECT_LE(0, output_len) << "this is not an AEAD, so content leaks";
332 
333   unsigned int final_len = 88;
334   rv = PK11_CipherFinal(dctx.get(), output, &final_len, sizeof(output));
335   if (is_padded()) {
336     EXPECT_EQ(SECFailure, rv);
337     ASSERT_EQ(88U, final_len) << "final_len should be untouched";
338   } else {
339     // Unpadded decryption can't really fail.
340     EXPECT_EQ(SECSuccess, rv);
341   }
342 }
343 
TEST_P(Pkcs11CbcPadTest,ContextFailDecryptInvalidBlockSize)344 TEST_P(Pkcs11CbcPadTest, ContextFailDecryptInvalidBlockSize) {
345   ScopedPK11Context dctx = MakeContext(CKA_DECRYPT);
346   uint8_t output[sizeof(kInput) + 64];
347   int output_len = 888;
348 
349   SECStatus rv = PK11_CipherOp(dctx.get(), output, &output_len, sizeof(output),
350                                kInput, GetInputLen(CKA_DECRYPT) - 1);
351   EXPECT_EQ(SECFailure, rv);
352   // Because PK11_CipherOp is partial, it can return data on failure.
353   // This means that it needs to reset its output length to 0 when it starts.
354   EXPECT_EQ(0, output_len) << "output_len is reset";
355 }
356 
TEST_P(Pkcs11CbcPadTest,EncryptDecrypt_PaddingTooLong)357 TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_PaddingTooLong) {
358   if (!is_padded()) {
359     return;
360   }
361 
362   // Padding that's over the block size
363   const std::vector<uint8_t> input = {
364       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
367       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
368       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
369       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
370   std::vector<uint8_t> encrypted(input.size());
371   uint32_t encrypted_len = 0;
372 
373   ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
374   SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedMechanism(), GetIv(),
375                               encrypted.data(), &encrypted_len,
376                               encrypted.size(), input.data(), input.size());
377   ASSERT_EQ(SECSuccess, rv);
378   EXPECT_EQ(input.size(), encrypted_len);
379 
380   std::vector<uint8_t> decrypted(input.size());
381   uint32_t decrypted_len = 0;
382   ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
383   rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
384                     &decrypted_len, decrypted.size(), encrypted.data(),
385                     encrypted_len);
386   EXPECT_EQ(SECFailure, rv);
387   EXPECT_EQ(0U, decrypted_len);
388 }
389 
TEST_P(Pkcs11CbcPadTest,EncryptDecrypt_ShortPadding1)390 TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_ShortPadding1) {
391   if (!is_padded()) {
392     return;
393   }
394 
395   // Padding that's one byte short
396   const std::vector<uint8_t> input = {
397       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402       0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
403   std::vector<uint8_t> encrypted(input.size());
404   uint32_t encrypted_len = 0;
405 
406   ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
407   SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedMechanism(), GetIv(),
408                               encrypted.data(), &encrypted_len,
409                               encrypted.size(), input.data(), input.size());
410   ASSERT_EQ(SECSuccess, rv);
411   EXPECT_EQ(input.size(), encrypted_len);
412 
413   std::vector<uint8_t> decrypted(input.size());
414   uint32_t decrypted_len = 0;
415   ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
416   rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
417                     &decrypted_len, decrypted.size(), encrypted.data(),
418                     encrypted_len);
419   EXPECT_EQ(SECFailure, rv);
420   EXPECT_EQ(0U, decrypted_len);
421 }
422 
TEST_P(Pkcs11CbcPadTest,EncryptDecrypt_ShortPadding2)423 TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_ShortPadding2) {
424   if (!is_padded()) {
425     return;
426   }
427 
428   // Padding that's one byte short
429   const std::vector<uint8_t> input = {
430       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02};
436   std::vector<uint8_t> encrypted(input.size());
437   uint32_t encrypted_len = 0;
438 
439   ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
440   SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedMechanism(), GetIv(),
441                               encrypted.data(), &encrypted_len,
442                               encrypted.size(), input.data(), input.size());
443   ASSERT_EQ(SECSuccess, rv);
444   EXPECT_EQ(input.size(), encrypted_len);
445 
446   std::vector<uint8_t> decrypted(input.size());
447   uint32_t decrypted_len = 0;
448   ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
449   rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
450                     &decrypted_len, decrypted.size(), encrypted.data(),
451                     encrypted_len);
452   EXPECT_EQ(SECFailure, rv);
453   EXPECT_EQ(0U, decrypted_len);
454 }
455 
TEST_P(Pkcs11CbcPadTest,EncryptDecrypt_ZeroLengthPadding)456 TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_ZeroLengthPadding) {
457   if (!is_padded()) {
458     return;
459   }
460 
461   // Padding of length zero
462   const std::vector<uint8_t> input = {
463       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
469   std::vector<uint8_t> encrypted(input.size());
470   uint32_t encrypted_len = 0;
471 
472   ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
473   SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedMechanism(), GetIv(),
474                               encrypted.data(), &encrypted_len,
475                               encrypted.size(), input.data(), input.size());
476   ASSERT_EQ(SECSuccess, rv);
477   EXPECT_EQ(input.size(), encrypted_len);
478 
479   std::vector<uint8_t> decrypted(input.size());
480   uint32_t decrypted_len = 0;
481   ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
482   rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
483                     &decrypted_len, decrypted.size(), encrypted.data(),
484                     encrypted_len);
485   EXPECT_EQ(SECFailure, rv);
486   EXPECT_EQ(0U, decrypted_len);
487 }
488 
TEST_P(Pkcs11CbcPadTest,EncryptDecrypt_OverflowPadding)489 TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_OverflowPadding) {
490   if (!is_padded()) {
491     return;
492   }
493 
494   // Padding that's much longer than block size
495   const std::vector<uint8_t> input = {
496       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
497       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
498       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
499       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
500       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
501       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
502   std::vector<uint8_t> encrypted(input.size());
503   uint32_t encrypted_len = 0;
504 
505   ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
506   SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedMechanism(), GetIv(),
507                               encrypted.data(), &encrypted_len,
508                               encrypted.size(), input.data(), input.size());
509   ASSERT_EQ(SECSuccess, rv);
510   EXPECT_EQ(input.size(), encrypted_len);
511 
512   std::vector<uint8_t> decrypted(input.size());
513   uint32_t decrypted_len = 0;
514   ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
515   rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
516                     &decrypted_len, decrypted.size(), encrypted.data(),
517                     encrypted_len);
518   EXPECT_EQ(SECFailure, rv);
519   EXPECT_EQ(0U, decrypted_len);
520 }
521 
TEST_P(Pkcs11CbcPadTest,EncryptDecrypt_ShortValidPadding)522 TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_ShortValidPadding) {
523   if (!is_padded()) {
524     return;
525   }
526 
527   // Minimal valid padding
528   const std::vector<uint8_t> input = {
529       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
535   std::vector<uint8_t> encrypted(input.size());
536   uint32_t encrypted_len = 0;
537 
538   ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
539   SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedMechanism(), GetIv(),
540                               encrypted.data(), &encrypted_len,
541                               encrypted.size(), input.data(), input.size());
542   ASSERT_EQ(SECSuccess, rv);
543   EXPECT_EQ(input.size(), encrypted_len);
544 
545   std::vector<uint8_t> decrypted(input.size());
546   uint32_t decrypted_len = 0;
547   ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
548   rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
549                     &decrypted_len, decrypted.size(), encrypted.data(),
550                     encrypted_len);
551   EXPECT_EQ(SECSuccess, rv);
552   EXPECT_EQ(input.size() - 1, decrypted_len);
553   EXPECT_EQ(0, memcmp(decrypted.data(), input.data(), decrypted_len));
554 }
555 
556 INSTANTIATE_TEST_SUITE_P(EncryptDecrypt, Pkcs11CbcPadTest,
557                          ::testing::Values(CKM_AES_CBC_PAD, CKM_AES_CBC,
558                                            CKM_DES3_CBC_PAD, CKM_DES3_CBC));
559 
560 class Pkcs11AesCbcWycheproofTest
561     : public ::testing::TestWithParam<AesCbcTestVector> {
562  protected:
RunTest(const AesCbcTestVector vec)563   void RunTest(const AesCbcTestVector vec) {
564     bool valid = vec.valid;
565     std::string err = "Test #" + std::to_string(vec.id) + " failed";
566     std::vector<uint8_t> key = hex_string_to_bytes(vec.key);
567     std::vector<uint8_t> iv = hex_string_to_bytes(vec.iv);
568     std::vector<uint8_t> ciphertext = hex_string_to_bytes(vec.ciphertext);
569     std::vector<uint8_t> msg = hex_string_to_bytes(vec.msg);
570     std::vector<uint8_t> decrypted(vec.ciphertext.size());
571     unsigned int decrypted_len = 0;
572 
573     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
574     ASSERT_NE(nullptr, slot);
575 
576     // Don't provide a null pointer, even if the length is 0. We don't want to
577     // fail on trivial checks.
578     uint8_t tmp;
579     SECItem iv_item = {siBuffer, iv.data() ? iv.data() : &tmp,
580                        static_cast<unsigned int>(iv.size())};
581     SECItem key_item = {siBuffer, key.data() ? key.data() : &tmp,
582                         static_cast<unsigned int>(key.size())};
583 
584     PK11SymKey* pKey = PK11_ImportSymKey(slot.get(), kMech, PK11_OriginUnwrap,
585                                          CKA_ENCRYPT, &key_item, nullptr);
586     ASSERT_NE(nullptr, pKey);
587     ScopedPK11SymKey spKey = ScopedPK11SymKey(pKey);
588 
589     SECStatus rv = PK11_Decrypt(spKey.get(), kMech, &iv_item, decrypted.data(),
590                                 &decrypted_len, decrypted.size(),
591                                 ciphertext.data(), ciphertext.size());
592 
593     ASSERT_EQ(valid ? SECSuccess : SECFailure, rv) << err;
594     if (valid) {
595       EXPECT_EQ(msg.size(), static_cast<size_t>(decrypted_len)) << err;
596       EXPECT_EQ(0, memcmp(msg.data(), decrypted.data(), decrypted_len)) << err;
597     }
598   }
599 
600   const CK_MECHANISM_TYPE kMech = CKM_AES_CBC_PAD;
601 };
602 
TEST_P(Pkcs11AesCbcWycheproofTest,TestVectors)603 TEST_P(Pkcs11AesCbcWycheproofTest, TestVectors) { RunTest(GetParam()); }
604 
605 INSTANTIATE_TEST_SUITE_P(WycheproofTestVector, Pkcs11AesCbcWycheproofTest,
606                          ::testing::ValuesIn(kCbcWycheproofVectors));
607 
608 }  // namespace nss_test
609