pk11_prf_unittest.cc (7230B)
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 11 #include "cpputil.h" 12 13 #include "gtest/gtest.h" 14 15 namespace nss_test { 16 17 const size_t kPmsSize = 48; 18 const size_t kMasterSecretSize = 48; 19 const size_t kPrfSeedSizeSha256 = 32; 20 const size_t kPrfSeedSizeTlsPrf = 36; 21 22 // This is not the right size for anything 23 const size_t kIncorrectSize = 17; 24 25 const uint8_t kPmsData[] = { 26 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 27 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 28 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 29 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f}; 30 31 const uint8_t kPrfSeed[] = { 32 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 33 0xfc, 0xfd, 0xfe, 0xff, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 34 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xd0, 0xd1, 0xd2, 0xd3}; 35 36 const uint8_t kExpectedOutputEmsSha256[] = { 37 0x75, 0xa7, 0xa5, 0x98, 0xef, 0xab, 0x90, 0xe7, 0x7c, 0x67, 0x80, 0xde, 38 0xab, 0x3a, 0x11, 0xf3, 0x5d, 0xb2, 0xf8, 0x47, 0xff, 0x09, 0x01, 0xec, 39 0xf8, 0x93, 0x89, 0xfc, 0x98, 0x2e, 0x6e, 0xf9, 0x2c, 0xf5, 0x9b, 0x04, 40 0x04, 0x6f, 0xd7, 0x28, 0x6e, 0xea, 0xe3, 0x83, 0xc4, 0x4a, 0xff, 0x03}; 41 42 const uint8_t kExpectedOutputEmsTlsPrf[] = { 43 0x06, 0xbf, 0x29, 0x86, 0x5d, 0xf3, 0x3e, 0x38, 0xfd, 0xfa, 0x91, 0x10, 44 0x2a, 0x20, 0xff, 0xd6, 0xb9, 0xd5, 0x72, 0x5a, 0x6d, 0x42, 0x20, 0x16, 45 0xde, 0xa4, 0xa0, 0x51, 0xe5, 0x53, 0xc1, 0x28, 0x04, 0x99, 0xbc, 0xb1, 46 0x2c, 0x9d, 0xe8, 0x0b, 0x18, 0xa2, 0x0e, 0x48, 0x52, 0x8d, 0x61, 0x13}; 47 48 class TlsPrfTest : public ::testing::Test { 49 public: 50 TlsPrfTest() 51 : params_({siBuffer, nullptr, 0}), 52 pms_item_({siBuffer, toUcharPtr(kPmsData), kPmsSize}), 53 key_mech_(0), 54 slot_(nullptr), 55 pms_(nullptr), 56 ms_(nullptr), 57 pms_version_({0, 0}) {} 58 59 ~TlsPrfTest() { 60 if (slot_) { 61 PK11_FreeSlot(slot_); 62 } 63 ClearTempVars(); 64 } 65 66 void ClearTempVars() { 67 if (pms_) { 68 PK11_FreeSymKey(pms_); 69 } 70 if (ms_) { 71 PK11_FreeSymKey(ms_); 72 } 73 } 74 75 void Init() { 76 params_.type = siBuffer; 77 78 pms_item_.type = siBuffer; 79 pms_item_.data = 80 const_cast<unsigned char*>(static_cast<const unsigned char*>(kPmsData)); 81 82 slot_ = PK11_GetInternalSlot(); 83 ASSERT_NE(nullptr, slot_); 84 } 85 86 void CheckForError(CK_MECHANISM_TYPE hash_mech, size_t seed_len, 87 size_t pms_len, size_t output_len) { 88 // Error tests don't depend on the derivation mechansim 89 Inner(CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, hash_mech, seed_len, pms_len, 90 output_len, nullptr, nullptr); 91 } 92 93 void ComputeAndVerifyMs(CK_MECHANISM_TYPE derive_mech, 94 CK_MECHANISM_TYPE hash_mech, CK_VERSION* version, 95 const uint8_t* expected) { 96 // Infer seed length from mechanism 97 int seed_len = 0; 98 switch (hash_mech) { 99 case CKM_TLS_PRF: 100 seed_len = kPrfSeedSizeTlsPrf; 101 break; 102 case CKM_SHA256: 103 seed_len = kPrfSeedSizeSha256; 104 break; 105 default: 106 ASSERT_TRUE(false); 107 } 108 109 Inner(derive_mech, hash_mech, seed_len, kPmsSize, 0, version, expected); 110 } 111 112 // Set output == nullptr to test when errors occur 113 void Inner(CK_MECHANISM_TYPE derive_mech, CK_MECHANISM_TYPE hash_mech, 114 size_t seed_len, size_t pms_len, size_t output_len, 115 CK_VERSION* version, const uint8_t* expected) { 116 ClearTempVars(); 117 118 // Infer the key mechanism from the hash type 119 switch (hash_mech) { 120 case CKM_TLS_PRF: 121 key_mech_ = CKM_TLS_KEY_AND_MAC_DERIVE; 122 break; 123 case CKM_SHA256: 124 key_mech_ = CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256; 125 break; 126 default: 127 ASSERT_TRUE(false); 128 } 129 130 // Import the params 131 CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS master_params = { 132 hash_mech, toUcharPtr(kPrfSeed), static_cast<CK_ULONG>(seed_len), 133 version}; 134 params_.data = reinterpret_cast<unsigned char*>(&master_params); 135 params_.len = sizeof(master_params); 136 137 // Import the PMS 138 pms_item_.len = pms_len; 139 pms_ = PK11_ImportSymKey(slot_, derive_mech, PK11_OriginUnwrap, CKA_DERIVE, 140 &pms_item_, NULL); 141 ASSERT_NE(nullptr, pms_); 142 143 // Compute the EMS 144 ms_ = PK11_DeriveWithFlags(pms_, derive_mech, ¶ms_, key_mech_, 145 CKA_DERIVE, output_len, CKF_SIGN | CKF_VERIFY); 146 147 // Verify the EMS has the expected value (null or otherwise) 148 if (!expected) { 149 EXPECT_EQ(nullptr, ms_); 150 } else { 151 ASSERT_NE(nullptr, ms_); 152 153 SECStatus rv = PK11_ExtractKeyValue(ms_); 154 ASSERT_EQ(SECSuccess, rv); 155 156 SECItem* msData = PK11_GetKeyData(ms_); 157 ASSERT_NE(nullptr, msData); 158 159 ASSERT_EQ(kMasterSecretSize, msData->len); 160 EXPECT_EQ(0, memcmp(msData->data, expected, kMasterSecretSize)); 161 } 162 } 163 164 protected: 165 SECItem params_; 166 SECItem pms_item_; 167 CK_MECHANISM_TYPE key_mech_; 168 PK11SlotInfo* slot_; 169 PK11SymKey* pms_; 170 PK11SymKey* ms_; 171 CK_VERSION pms_version_; 172 }; 173 174 TEST_F(TlsPrfTest, ExtendedMsParamErr) { 175 Init(); 176 177 // This should fail; it's the correct set from which the below are derived 178 // CheckForError(CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, CKM_TLS_PRF, 179 // kPrfSeedSizeTlsPrf, kPmsSize, 0); 180 181 // Output key size != 0, SSL3_MASTER_SECRET_LENGTH 182 CheckForError(CKM_TLS_PRF, kPrfSeedSizeTlsPrf, kPmsSize, kIncorrectSize); 183 184 // not-DH && pms size != SSL3_PMS_LENGTH 185 CheckForError(CKM_TLS_PRF, kPrfSeedSizeTlsPrf, kIncorrectSize, 0); 186 187 // CKM_TLS_PRF && seed length != MD5_LENGTH + SHA1_LENGTH 188 CheckForError(CKM_TLS_PRF, kIncorrectSize, kPmsSize, 0); 189 190 // !CKM_TLS_PRF && seed length != hash output length 191 CheckForError(CKM_SHA256, kIncorrectSize, kPmsSize, 0); 192 } 193 194 // Test matrix: 195 // 196 // DH RSA 197 // TLS_PRF 1 2 198 // SHA256 3 4 199 TEST_F(TlsPrfTest, ExtendedMsDhTlsPrf) { 200 Init(); 201 ComputeAndVerifyMs(CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH, CKM_TLS_PRF, 202 nullptr, kExpectedOutputEmsTlsPrf); 203 } 204 205 TEST_F(TlsPrfTest, ExtendedMsRsaTlsPrf) { 206 Init(); 207 ComputeAndVerifyMs(CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, CKM_TLS_PRF, 208 &pms_version_, kExpectedOutputEmsTlsPrf); 209 EXPECT_EQ(0, pms_version_.major); 210 EXPECT_EQ(1, pms_version_.minor); 211 } 212 213 TEST_F(TlsPrfTest, ExtendedMsDhSha256) { 214 Init(); 215 ComputeAndVerifyMs(CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH, CKM_SHA256, 216 nullptr, kExpectedOutputEmsSha256); 217 } 218 219 TEST_F(TlsPrfTest, ExtendedMsRsaSha256) { 220 Init(); 221 ComputeAndVerifyMs(CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, CKM_SHA256, 222 &pms_version_, kExpectedOutputEmsSha256); 223 EXPECT_EQ(0, pms_version_.major); 224 EXPECT_EQ(1, pms_version_.minor); 225 } 226 227 } // namespace nss_test