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