tor-browser

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

pk11_encrypt_derive_unittest.cc (7544B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "pk11pub.h"
      6 #include "nssutil.h"
      7 #include <stdio.h>
      8 #include "prerror.h"
      9 #include "nss.h"
     10 #include "gtest/gtest.h"
     11 #include "nss_scoped_ptrs.h"
     12 #include "cpputil.h"
     13 #include "databuffer.h"
     14 #include "util.h"
     15 
     16 #define MAX_KEY_SIZE 24
     17 
     18 namespace nss_test {
     19 
     20 static const uint8_t kIv[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
     21                              0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     22                              0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
     23 static const uint8_t kInput[] = {
     24    0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0xff, 0xee, 0xdd, 0xcc,
     25    0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00};
     26 
     27 class EncryptDeriveTest
     28    : public ::testing::Test,
     29      public ::testing::WithParamInterface<CK_MECHANISM_TYPE> {
     30 public:
     31  void TestEncryptDerive() {
     32    ScopedPK11SymKey derived_key(PK11_Derive(key_.get(), derive_mech(),
     33                                             derive_param(), encrypt_mech(),
     34                                             CKA_DECRYPT, keysize()));
     35    ASSERT_TRUE(derived_key);
     36 
     37    uint8_t derived_key_data[MAX_KEY_SIZE];
     38    ASSERT_GE(sizeof(derived_key_data), keysize());
     39    GetKeyData(derived_key, derived_key_data, keysize());
     40    RemoveChecksum(derived_key_data);
     41 
     42    uint8_t reference_key_data[MAX_KEY_SIZE];
     43    unsigned int reference_len = 0;
     44    SECStatus rv = PK11_Encrypt(key_.get(), encrypt_mech(), encrypt_param(),
     45                                reference_key_data, &reference_len, keysize(),
     46                                kInput, keysize());
     47    ASSERT_EQ(SECSuccess, rv);
     48    ASSERT_EQ(keysize(), static_cast<size_t>(reference_len));
     49    RemoveChecksum(reference_key_data);
     50 
     51    EXPECT_EQ(DataBuffer(reference_key_data, keysize()),
     52              DataBuffer(derived_key_data, keysize()));
     53  }
     54 
     55 protected:
     56  unsigned int keysize() const { return 16; }
     57 
     58 private:
     59  CK_MECHANISM_TYPE encrypt_mech() const { return GetParam(); }
     60 
     61  CK_MECHANISM_TYPE derive_mech() const {
     62    switch (encrypt_mech()) {
     63      case CKM_DES3_ECB:
     64        return CKM_DES3_ECB_ENCRYPT_DATA;
     65      case CKM_DES3_CBC:
     66        return CKM_DES3_CBC_ENCRYPT_DATA;
     67      case CKM_AES_ECB:
     68        return CKM_AES_ECB_ENCRYPT_DATA;
     69      case CKM_AES_CBC:
     70        return CKM_AES_CBC_ENCRYPT_DATA;
     71      case CKM_CAMELLIA_ECB:
     72        return CKM_CAMELLIA_ECB_ENCRYPT_DATA;
     73      case CKM_CAMELLIA_CBC:
     74        return CKM_CAMELLIA_CBC_ENCRYPT_DATA;
     75 #ifndef NSS_DISABLE_DEPRECATED_SEED
     76      case CKM_SEED_ECB:
     77        return CKM_SEED_ECB_ENCRYPT_DATA;
     78      case CKM_SEED_CBC:
     79        return CKM_SEED_CBC_ENCRYPT_DATA;
     80 #endif
     81      default:
     82        ADD_FAILURE() << "Unknown mechanism";
     83        break;
     84    }
     85    return CKM_INVALID_MECHANISM;
     86  }
     87 
     88  SECItem* derive_param() const {
     89    static CK_AES_CBC_ENCRYPT_DATA_PARAMS aes_data;
     90    static CK_DES_CBC_ENCRYPT_DATA_PARAMS des_data;
     91    static CK_KEY_DERIVATION_STRING_DATA string_data;
     92    static SECItem param = {siBuffer, NULL, 0};
     93 
     94    switch (encrypt_mech()) {
     95      case CKM_DES3_ECB:
     96      case CKM_AES_ECB:
     97      case CKM_CAMELLIA_ECB:
     98 #ifndef NSS_DISABLE_DEPRECATED_SEED
     99      case CKM_SEED_ECB:
    100 #endif
    101        string_data.pData = toUcharPtr(kInput);
    102        string_data.ulLen = keysize();
    103        param.data = reinterpret_cast<uint8_t*>(&string_data);
    104        param.len = sizeof(string_data);
    105        break;
    106 
    107      case CKM_DES3_CBC:
    108        des_data.pData = toUcharPtr(kInput);
    109        des_data.length = keysize();
    110        PORT_Memcpy(des_data.iv, kIv, 8);
    111        param.data = reinterpret_cast<uint8_t*>(&des_data);
    112        param.len = sizeof(des_data);
    113        break;
    114 
    115      case CKM_AES_CBC:
    116      case CKM_CAMELLIA_CBC:
    117 #ifndef NSS_DISABLE_DEPRECATED_SEED
    118      case CKM_SEED_CBC:
    119 #endif
    120        aes_data.pData = toUcharPtr(kInput);
    121        aes_data.length = keysize();
    122        PORT_Memcpy(aes_data.iv, kIv, keysize());
    123        param.data = reinterpret_cast<uint8_t*>(&aes_data);
    124        param.len = sizeof(aes_data);
    125        break;
    126 
    127      default:
    128        ADD_FAILURE() << "Unknown mechanism";
    129        break;
    130    }
    131    return &param;
    132  }
    133 
    134  SECItem* encrypt_param() const {
    135    static SECItem param = {siBuffer, NULL, 0};
    136 
    137    switch (encrypt_mech()) {
    138      case CKM_DES3_ECB:
    139      case CKM_AES_ECB:
    140      case CKM_CAMELLIA_ECB:
    141 #ifndef NSS_DISABLE_DEPRECATED_SEED
    142      case CKM_SEED_ECB:
    143 #endif
    144        // No parameter needed here.
    145        break;
    146 
    147      case CKM_DES3_CBC:
    148      case CKM_AES_CBC:
    149      case CKM_CAMELLIA_CBC:
    150 #ifndef NSS_DISABLE_DEPRECATED_SEED
    151      case CKM_SEED_CBC:
    152 #endif
    153        param.data = toUcharPtr(kIv);
    154        param.len = keysize();
    155        break;
    156 
    157      default:
    158        ADD_FAILURE() << "Unknown mechanism";
    159        break;
    160    }
    161    return &param;
    162  }
    163 
    164  virtual void SetUp() {
    165    slot_.reset(PK11_GetBestSlot(derive_mech(), NULL));
    166    ASSERT_TRUE(slot_);
    167 
    168    key_.reset(PK11_TokenKeyGenWithFlags(slot_.get(), encrypt_mech(), NULL,
    169                                         keysize(), NULL,
    170                                         CKF_ENCRYPT | CKF_DERIVE, 0, NULL));
    171    ASSERT_TRUE(key_);
    172  }
    173 
    174  void GetKeyData(ScopedPK11SymKey& key, uint8_t* buf, size_t max_len) const {
    175    ASSERT_EQ(SECSuccess, PK11_ExtractKeyValue(key.get()));
    176    SECItem* data = PK11_GetKeyData(key.get());
    177    ASSERT_TRUE(data);
    178    ASSERT_EQ(max_len, static_cast<size_t>(data->len));
    179    PORT_Memcpy(buf, data->data, data->len);
    180  }
    181 
    182  // Remove checksum if the key is a 3DES key.
    183  void RemoveChecksum(uint8_t* key_data) const {
    184    if (encrypt_mech() != CKM_DES3_CBC && encrypt_mech() != CKM_DES3_ECB) {
    185      return;
    186    }
    187    for (size_t i = 0; i < keysize(); ++i) {
    188      key_data[i] &= 0xfe;
    189    }
    190  }
    191 
    192  ScopedPK11SlotInfo slot_;
    193  ScopedPK11SymKey key_;
    194 };
    195 
    196 TEST_P(EncryptDeriveTest, Test) { TestEncryptDerive(); }
    197 
    198 static const CK_MECHANISM_TYPE kEncryptDeriveMechanisms[] = {CKM_DES3_ECB,
    199                                                             CKM_DES3_CBC,
    200                                                             CKM_AES_ECB,
    201                                                             CKM_AES_ECB,
    202                                                             CKM_AES_CBC,
    203                                                             CKM_CAMELLIA_ECB,
    204                                                             CKM_CAMELLIA_CBC
    205 #ifndef NSS_DISABLE_DEPRECATED_SEED
    206                                                             ,
    207                                                             CKM_SEED_ECB,
    208                                                             CKM_SEED_CBC
    209 #endif
    210 };
    211 
    212 INSTANTIATE_TEST_SUITE_P(EncryptDeriveTests, EncryptDeriveTest,
    213                         ::testing::ValuesIn(kEncryptDeriveMechanisms));
    214 
    215 // This class handles the case where 3DES takes a 192-bit key
    216 // where all 24 octets will be used.
    217 class EncryptDerive3Test : public EncryptDeriveTest {
    218 protected:
    219  unsigned int keysize() const { return 24; }
    220 };
    221 
    222 TEST_P(EncryptDerive3Test, Test) { TestEncryptDerive(); }
    223 
    224 static const CK_MECHANISM_TYPE kDES3EncryptDeriveMechanisms[] = {CKM_DES3_ECB,
    225                                                                 CKM_DES3_CBC};
    226 
    227 INSTANTIATE_TEST_SUITE_P(Encrypt3DeriveTests, EncryptDerive3Test,
    228                         ::testing::ValuesIn(kDES3EncryptDeriveMechanisms));
    229 
    230 }  // namespace nss_test