pk11_ike_unittest.cc (7862B)
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 #include "databuffer.h" 17 18 #include "testvectors/ike-sha1-vectors.h" 19 #include "testvectors/ike-sha256-vectors.h" 20 #include "testvectors/ike-sha384-vectors.h" 21 #include "testvectors/ike-sha512-vectors.h" 22 #include "testvectors/ike-aesxcbc-vectors.h" 23 24 namespace nss_test { 25 26 class Pkcs11IkeTest : public ::testing::TestWithParam< 27 std::tuple<IkeTestVector, CK_MECHANISM_TYPE>> { 28 protected: 29 ScopedPK11SymKey ImportKey(SECItem &ikm_item) { 30 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 31 if (!slot) { 32 ADD_FAILURE() << "Can't get slot"; 33 return nullptr; 34 } 35 ScopedPK11SymKey ikm( 36 PK11_ImportSymKey(slot.get(), CKM_GENERIC_SECRET_KEY_GEN, 37 PK11_OriginUnwrap, CKA_DERIVE, &ikm_item, nullptr)); 38 return ikm; 39 } 40 41 void RunVectorTest(const IkeTestVector &vec, CK_MECHANISM_TYPE prf_mech) { 42 std::string msg = "Test #" + std::to_string(vec.id) + " failed"; 43 std::vector<uint8_t> vec_ikm = hex_string_to_bytes(vec.ikm); 44 std::vector<uint8_t> vec_okm = hex_string_to_bytes(vec.okm); 45 std::vector<uint8_t> vec_gxykm = hex_string_to_bytes(vec.gxykm); 46 std::vector<uint8_t> vec_prevkm = hex_string_to_bytes(vec.prevkm); 47 std::vector<uint8_t> vec_Ni = hex_string_to_bytes(vec.Ni); 48 std::vector<uint8_t> vec_Nr = hex_string_to_bytes(vec.Nr); 49 std::vector<uint8_t> vec_seed_data = hex_string_to_bytes(vec.seed_data); 50 SECItem ikm_item = {siBuffer, vec_ikm.data(), 51 static_cast<unsigned int>(vec_ikm.size())}; 52 SECItem okm_item = {siBuffer, vec_okm.data(), 53 static_cast<unsigned int>(vec_okm.size())}; 54 SECItem prevkm_item = {siBuffer, vec_prevkm.data(), 55 static_cast<unsigned int>(vec_prevkm.size())}; 56 SECItem gxykm_item = {siBuffer, vec_gxykm.data(), 57 static_cast<unsigned int>(vec_gxykm.size())}; 58 CK_MECHANISM_TYPE derive_mech = CKM_IKE_PRF_DERIVE; 59 ScopedPK11SymKey gxy_key = nullptr; 60 ScopedPK11SymKey prev_key = nullptr; 61 ScopedPK11SymKey ikm = ImportKey(ikm_item); 62 63 // IKE_PRF structure (used in cases 1, 2 and 3) 64 CK_IKE_PRF_DERIVE_PARAMS ike_prf_params = { 65 prf_mech, 66 CK_FALSE, 67 CK_FALSE, 68 vec_Ni.data(), 69 static_cast<CK_ULONG>(vec_Ni.size()), 70 vec_Nr.data(), 71 static_cast<CK_ULONG>(vec_Nr.size()), 72 CK_INVALID_HANDLE}; 73 74 // IKE_V1_PRF, used to derive session keys. 75 CK_IKE1_PRF_DERIVE_PARAMS ike_v1_prf_params = { 76 prf_mech, false, 77 CK_INVALID_HANDLE, CK_INVALID_HANDLE, 78 vec_Ni.data(), static_cast<CK_ULONG>(vec_Ni.size()), 79 vec_Nr.data(), static_cast<CK_ULONG>(vec_Nr.size()), 80 vec.key_number}; 81 82 // IKE_V1_EXTENDED, do quick mode (all session keys in one call). 83 CK_IKE1_EXTENDED_DERIVE_PARAMS ike1_extended_derive_params_quick = { 84 prf_mech, CK_FALSE, CK_INVALID_HANDLE, vec_seed_data.data(), 85 static_cast<CK_ULONG>(vec_seed_data.size())}; 86 87 // IKE_V1_EXTENDED, used for long session keys in ike_v1 88 CK_MECHANISM_TYPE ike1_extended_derive_params = prf_mech; 89 90 // IKE_V2_PRF_PLUS, used to generate session keys in ike v2 91 CK_IKE2_PRF_PLUS_DERIVE_PARAMS ike2_prf_plus_params = { 92 prf_mech, CK_FALSE, CK_INVALID_HANDLE, vec_seed_data.data(), 93 static_cast<CK_ULONG>(vec_seed_data.size())}; 94 95 SECItem params_item = {siBuffer, (unsigned char *)&ike_prf_params, 96 sizeof(ike_prf_params)}; 97 98 switch (vec.test_type) { 99 case IkeTestType::ikeGxy: 100 ike_prf_params.bDataAsKey = true; 101 break; 102 case IkeTestType::ikeV1Psk: 103 break; 104 case IkeTestType::ikeV2Rekey: 105 ike_prf_params.bRekey = true; 106 gxy_key = ImportKey(gxykm_item); 107 ike_prf_params.hNewKey = PK11_GetSymKeyHandle(gxy_key.get()); 108 break; 109 case IkeTestType::ikeV1: 110 derive_mech = CKM_IKE1_PRF_DERIVE; 111 params_item.data = (unsigned char *)&ike_v1_prf_params; 112 params_item.len = sizeof(ike_v1_prf_params); 113 gxy_key = ImportKey(gxykm_item); 114 ike_v1_prf_params.hKeygxy = PK11_GetSymKeyHandle(gxy_key.get()); 115 if (prevkm_item.len != 0) { 116 prev_key = ImportKey(prevkm_item); 117 ike_v1_prf_params.bHasPrevKey = true; 118 ike_v1_prf_params.hPrevKey = PK11_GetSymKeyHandle(prev_key.get()); 119 } 120 break; 121 case IkeTestType::ikeV1AppB: 122 derive_mech = CKM_IKE1_EXTENDED_DERIVE; 123 params_item.data = (unsigned char *)&ike1_extended_derive_params; 124 params_item.len = sizeof(ike1_extended_derive_params); 125 break; 126 case IkeTestType::ikeV1AppBQuick: 127 derive_mech = CKM_IKE1_EXTENDED_DERIVE; 128 params_item.data = (unsigned char *)&ike1_extended_derive_params_quick; 129 params_item.len = sizeof(ike1_extended_derive_params_quick); 130 if (gxykm_item.len != 0) { 131 gxy_key = ImportKey(gxykm_item); 132 ike1_extended_derive_params_quick.bHasKeygxy = true; 133 ike1_extended_derive_params_quick.hKeygxy = 134 PK11_GetSymKeyHandle(gxy_key.get()); 135 } 136 break; 137 case IkeTestType::ikePlus: 138 derive_mech = CKM_IKE2_PRF_PLUS_DERIVE; 139 params_item.data = (unsigned char *)&ike2_prf_plus_params; 140 params_item.len = sizeof(ike2_prf_plus_params); 141 break; 142 default: 143 ADD_FAILURE() << msg; 144 return; 145 } 146 ASSERT_NE(nullptr, ikm) << msg; 147 148 ScopedPK11SymKey okm = ScopedPK11SymKey( 149 PK11_Derive(ikm.get(), derive_mech, ¶ms_item, 150 CKM_GENERIC_SECRET_KEY_GEN, CKA_DERIVE, vec.size)); 151 if (vec.valid) { 152 ASSERT_NE(nullptr, okm.get()) << msg; 153 ASSERT_EQ(SECSuccess, PK11_ExtractKeyValue(okm.get())) << msg; 154 SECItem *outItem = PK11_GetKeyData(okm.get()); 155 SECItem nullItem = {siBuffer, NULL, 0}; 156 if (outItem == NULL) { 157 outItem = &nullItem; 158 } 159 ASSERT_EQ(0, SECITEM_CompareItem(&okm_item, PK11_GetKeyData(okm.get()))) 160 << msg << std::endl 161 << " expect:" << DataBuffer(okm_item.data, okm_item.len) << std::endl 162 << " calc'd:" << DataBuffer(outItem->data, outItem->len) << std::endl; 163 } else { 164 ASSERT_EQ(nullptr, okm.get()) << msg; 165 } 166 } 167 }; 168 169 TEST_P(Pkcs11IkeTest, IkeproofVectors) { 170 RunVectorTest(std::get<0>(GetParam()), std::get<1>(GetParam())); 171 } 172 173 INSTANTIATE_TEST_SUITE_P( 174 IkeSha1, Pkcs11IkeTest, 175 ::testing::Combine(::testing::ValuesIn(kIkeSha1ProofVectors), 176 ::testing::Values(CKM_SHA_1_HMAC))); 177 INSTANTIATE_TEST_SUITE_P( 178 IkeSha256, Pkcs11IkeTest, 179 ::testing::Combine(::testing::ValuesIn(kIkeSha256ProofVectors), 180 ::testing::Values(CKM_SHA256_HMAC))); 181 182 INSTANTIATE_TEST_SUITE_P( 183 IkeSha384, Pkcs11IkeTest, 184 ::testing::Combine(::testing::ValuesIn(kIkeSha384ProofVectors), 185 ::testing::Values(CKM_SHA384_HMAC))); 186 187 INSTANTIATE_TEST_SUITE_P( 188 IkeSha512, Pkcs11IkeTest, 189 ::testing::Combine(::testing::ValuesIn(kIkeSha512ProofVectors), 190 ::testing::Values(CKM_SHA512_HMAC))); 191 192 INSTANTIATE_TEST_SUITE_P( 193 IkeAESXCBC, Pkcs11IkeTest, 194 ::testing::Combine(::testing::ValuesIn(kIkeAesXcbcProofVectors), 195 ::testing::Values(CKM_AES_XCBC_MAC))); 196 197 } // namespace nss_test