tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pk11_cbc_unittest.cc (23468B)


      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 
     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:
     31  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 
     47  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 
     59  size_t block_size() const {
     60    return static_cast<size_t>(PK11_GetBlockSize(GetParam(), nullptr));
     61  }
     62 
     63  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 
     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 
    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 
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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:
    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 
    603 TEST_P(Pkcs11AesCbcWycheproofTest, TestVectors) { RunTest(GetParam()); }
    604 
    605 INSTANTIATE_TEST_SUITE_P(WycheproofTestVector, Pkcs11AesCbcWycheproofTest,
    606                         ::testing::ValuesIn(kCbcWycheproofVectors));
    607 
    608 }  // namespace nss_test