tor-browser

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

pk11_hkdf_unittest.cc (7318B)


      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 "blapi.h"
      9 #include "gtest/gtest.h"
     10 #include "nss.h"
     11 #include "nss_scoped_ptrs.h"
     12 #include "pk11pub.h"
     13 #include "secerr.h"
     14 #include "sechash.h"
     15 #include "util.h"
     16 
     17 #include "testvectors/hkdf-sha1-vectors.h"
     18 #include "testvectors/hkdf-sha256-vectors.h"
     19 #include "testvectors/hkdf-sha384-vectors.h"
     20 #include "testvectors/hkdf-sha512-vectors.h"
     21 
     22 namespace nss_test {
     23 
     24 enum class HkdfTestType {
     25  legacy,        /* CKM_NSS_HKDF_SHA... */
     26  derive,        /* CKM_HKDF_DERIVE, ikm as secret key, salt as data. */
     27  deriveDataKey, /* CKM_HKDF_DERIVE, ikm as data, salt as data. */
     28  saltDerive,    /* CKM_HKDF_DERIVE, [ikm, salt] as secret key, salt as key. */
     29  saltDeriveDataKey, /* CKM_HKDF_DERIVE, [ikm, salt] as data, salt as key. */
     30  hkdfData           /* CKM_HKDF_DATA, ikm as data, salt as data. */
     31 };
     32 static const HkdfTestType kHkdfTestTypesAll[] = {
     33    HkdfTestType::legacy,
     34    HkdfTestType::derive,
     35    HkdfTestType::deriveDataKey,
     36    HkdfTestType::saltDerive,
     37    HkdfTestType::saltDeriveDataKey,
     38    HkdfTestType::hkdfData,
     39 };
     40 
     41 class Pkcs11HkdfTest
     42    : public ::testing::TestWithParam<
     43          std::tuple<HkdfTestVector, HkdfTestType, CK_MECHANISM_TYPE>> {
     44 protected:
     45  CK_MECHANISM_TYPE Pk11MechToVendorMech(CK_MECHANISM_TYPE pk11_mech) {
     46    switch (pk11_mech) {
     47      case CKM_SHA_1:
     48        return CKM_NSS_HKDF_SHA1;
     49      case CKM_SHA256:
     50        return CKM_NSS_HKDF_SHA256;
     51      case CKM_SHA384:
     52        return CKM_NSS_HKDF_SHA384;
     53      case CKM_SHA512:
     54        return CKM_NSS_HKDF_SHA512;
     55      default:
     56        ADD_FAILURE() << "Unknown hash mech";
     57        return CKM_INVALID_MECHANISM;
     58    }
     59  }
     60 
     61  ScopedPK11SymKey ImportKey(SECItem &ikm_item, bool import_as_data) {
     62    ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
     63    if (!slot) {
     64      ADD_FAILURE() << "Can't get slot";
     65      return nullptr;
     66    }
     67 
     68    ScopedPK11SymKey ikm;
     69    if (import_as_data) {
     70      ikm.reset(PK11_ImportDataKey(slot.get(), CKM_HKDF_KEY_GEN,
     71                                   PK11_OriginUnwrap, CKA_SIGN, &ikm_item,
     72                                   nullptr));
     73    } else {
     74      ikm.reset(PK11_ImportSymKey(slot.get(), CKM_GENERIC_SECRET_KEY_GEN,
     75                                  PK11_OriginUnwrap, CKA_SIGN, &ikm_item,
     76                                  nullptr));
     77    }
     78    return ikm;
     79  }
     80 
     81  void RunWycheproofTest(const HkdfTestVector &vec, HkdfTestType test_type,
     82                         CK_MECHANISM_TYPE hash_mech) {
     83    std::string msg = "Test #" + std::to_string(vec.id) + " failed";
     84    std::vector<uint8_t> vec_ikm = hex_string_to_bytes(vec.ikm);
     85    std::vector<uint8_t> vec_okm = hex_string_to_bytes(vec.okm);
     86    std::vector<uint8_t> vec_info = hex_string_to_bytes(vec.info);
     87    std::vector<uint8_t> vec_salt = hex_string_to_bytes(vec.salt);
     88    SECItem ikm_item = {siBuffer, vec_ikm.data(),
     89                        static_cast<unsigned int>(vec_ikm.size())};
     90    SECItem okm_item = {siBuffer, vec_okm.data(),
     91                        static_cast<unsigned int>(vec_okm.size())};
     92    SECItem salt_item = {siBuffer, vec_salt.data(),
     93                         static_cast<unsigned int>(vec_salt.size())};
     94    CK_MECHANISM_TYPE derive_mech = CKM_HKDF_DERIVE;
     95    ScopedPK11SymKey salt_key = nullptr;
     96    ScopedPK11SymKey ikm = nullptr;
     97 
     98    // Legacy vendor mech params
     99    CK_NSS_HKDFParams nss_hkdf_params = {
    100        true, vec_salt.data(), static_cast<unsigned int>(vec_salt.size()),
    101        true, vec_info.data(), static_cast<unsigned int>(vec_info.size())};
    102 
    103    // PKCS #11 v3.0
    104    CK_HKDF_PARAMS hkdf_params = {
    105        true,
    106        true,
    107        hash_mech,
    108        vec_salt.size() ? CKF_HKDF_SALT_DATA : CKF_HKDF_SALT_NULL,
    109        vec_salt.size() ? vec_salt.data() : nullptr,
    110        static_cast<unsigned int>(vec_salt.size()),
    111        CK_INVALID_HANDLE,
    112        vec_info.data(),
    113        static_cast<unsigned int>(vec_info.size())};
    114    SECItem params_item = {siBuffer, (unsigned char *)&hkdf_params,
    115                           sizeof(hkdf_params)};
    116 
    117    switch (test_type) {
    118      case HkdfTestType::legacy:
    119        derive_mech = Pk11MechToVendorMech(hash_mech);
    120        params_item.data = (uint8_t *)&nss_hkdf_params;
    121        params_item.len = sizeof(nss_hkdf_params);
    122        ikm = ImportKey(ikm_item, false);
    123        break;
    124      case HkdfTestType::derive:
    125        ikm = ImportKey(ikm_item, false);
    126        break;
    127      case HkdfTestType::deriveDataKey:
    128        ikm = ImportKey(ikm_item, true);
    129        break;
    130      case HkdfTestType::saltDerive:
    131        ikm = ImportKey(ikm_item, false);
    132        salt_key = ImportKey(salt_item, false);
    133        break;
    134      case HkdfTestType::saltDeriveDataKey:
    135        ikm = ImportKey(ikm_item, true);
    136        salt_key = ImportKey(salt_item, true);
    137        break;
    138      case HkdfTestType::hkdfData:
    139        derive_mech = CKM_HKDF_DATA;
    140        ikm = ImportKey(ikm_item, true);
    141        break;
    142      default:
    143        ADD_FAILURE() << msg;
    144        return;
    145    }
    146    ASSERT_NE(nullptr, ikm) << msg;
    147 
    148    if (test_type == HkdfTestType::saltDerive ||
    149        test_type == HkdfTestType::saltDeriveDataKey) {
    150      ASSERT_NE(nullptr, salt_key) << msg;
    151      hkdf_params.ulSaltType = CKF_HKDF_SALT_KEY;
    152      hkdf_params.ulSaltLen = 0;
    153      hkdf_params.pSalt = NULL;
    154      hkdf_params.hSaltKey = PK11_GetSymKeyHandle(salt_key.get());
    155    }
    156 
    157    ScopedPK11SymKey okm = ScopedPK11SymKey(
    158        PK11_Derive(ikm.get(), derive_mech, &params_item,
    159                    CKM_GENERIC_SECRET_KEY_GEN, CKA_DERIVE, vec.size));
    160    if (vec.valid) {
    161      ASSERT_NE(nullptr, okm.get()) << msg;
    162      ASSERT_EQ(SECSuccess, PK11_ExtractKeyValue(okm.get())) << msg;
    163      ASSERT_EQ(0, SECITEM_CompareItem(&okm_item, PK11_GetKeyData(okm.get())))
    164          << msg;
    165    } else {
    166      ASSERT_EQ(nullptr, okm.get()) << msg;
    167    }
    168  }
    169 };
    170 
    171 TEST_P(Pkcs11HkdfTest, WycheproofVectors) {
    172  RunWycheproofTest(std::get<0>(GetParam()), std::get<1>(GetParam()),
    173                    std::get<2>(GetParam()));
    174 }
    175 
    176 INSTANTIATE_TEST_SUITE_P(
    177    HkdfSha1, Pkcs11HkdfTest,
    178    ::testing::Combine(::testing::ValuesIn(kHkdfSha1WycheproofVectors),
    179                       ::testing::ValuesIn(kHkdfTestTypesAll),
    180                       ::testing::Values(CKM_SHA_1)));
    181 
    182 INSTANTIATE_TEST_SUITE_P(
    183    HkdfSha256, Pkcs11HkdfTest,
    184    ::testing::Combine(::testing::ValuesIn(kHkdfSha256WycheproofVectors),
    185                       ::testing::ValuesIn(kHkdfTestTypesAll),
    186                       ::testing::Values(CKM_SHA256)));
    187 
    188 INSTANTIATE_TEST_SUITE_P(
    189    HkdfSha384, Pkcs11HkdfTest,
    190    ::testing::Combine(::testing::ValuesIn(kHkdfSha384WycheproofVectors),
    191                       ::testing::ValuesIn(kHkdfTestTypesAll),
    192                       ::testing::Values(CKM_SHA384)));
    193 
    194 INSTANTIATE_TEST_SUITE_P(
    195    HkdfSha512, Pkcs11HkdfTest,
    196    ::testing::Combine(::testing::ValuesIn(kHkdfSha512WycheproofVectors),
    197                       ::testing::ValuesIn(kHkdfTestTypesAll),
    198                       ::testing::Values(CKM_SHA512)));
    199 }  // namespace nss_test