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, ¶m, 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, ¶m, 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, ¶m, 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, ¶m, 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, ¶m, 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, ¶m, 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, ¶m, 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, ¶m, 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