pk11_symkey_unittest.cc (5659B)
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 "gtest/gtest.h" 6 #include "nss_scoped_ptrs.h" 7 8 #include <assert.h> 9 #include <limits.h> 10 #include <prinit.h> 11 #include <nss.h> 12 #include <pk11pub.h> 13 14 namespace nss_test { 15 16 uint8_t kKeyData[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; 17 SECItem kFull = {siBuffer, (unsigned char *)kKeyData, 16}; 18 SECItem kLeftHalf = {siBuffer, (unsigned char *)kKeyData, 8}; 19 SECItem kRightHalf = {siBuffer, (unsigned char *)kKeyData + 8, 8}; 20 21 class Pkcs11SymKeyTest : public ::testing::Test { 22 protected: 23 PK11SymKey *ImportSymKey(PK11SlotInfo *slot, SECItem *key_data) { 24 PK11SymKey *out = PK11_ImportSymKey(slot, CKM_NULL, PK11_OriginUnwrap, 25 CKA_DERIVE, key_data, nullptr); 26 EXPECT_NE(nullptr, out); 27 return out; 28 } 29 30 void CheckKeyData(SECItem &expected, PK11SymKey *actual) { 31 ASSERT_NE(nullptr, actual); 32 33 SECStatus rv = PK11_ExtractKeyValue(actual); 34 ASSERT_EQ(SECSuccess, rv); 35 36 SECItem *keyData = PK11_GetKeyData(actual); 37 ASSERT_NE(nullptr, keyData); 38 ASSERT_NE(nullptr, keyData->data); 39 ASSERT_EQ(expected.len, keyData->len); 40 ASSERT_EQ(0, memcmp(expected.data, keyData->data, keyData->len)); 41 } 42 43 void SetSensitive(PK11SymKey *key) { 44 ASSERT_NE(nullptr, key); 45 46 CK_BBOOL cktrue = CK_TRUE; 47 SECItem attrValue = {siBuffer, &cktrue, sizeof(CK_BBOOL)}; 48 EXPECT_EQ(SECSuccess, PK11_WriteRawAttribute(PK11_TypeSymKey, key, 49 CKA_SENSITIVE, &attrValue)); 50 } 51 52 void CheckIsSensitive(PK11SymKey *key) { 53 ASSERT_NE(nullptr, key); 54 55 StackSECItem attrValue; 56 ASSERT_EQ(SECSuccess, PK11_ReadRawAttribute(PK11_TypeSymKey, key, 57 CKA_SENSITIVE, &attrValue)); 58 ASSERT_EQ(attrValue.len, sizeof(CK_BBOOL)); 59 EXPECT_EQ(*(CK_BBOOL *)attrValue.data, CK_TRUE); 60 } 61 62 void SetNotExtractable(PK11SymKey *key) { 63 ASSERT_NE(nullptr, key); 64 65 CK_BBOOL ckfalse = CK_FALSE; 66 SECItem attrValue = {siBuffer, &ckfalse, sizeof(CK_BBOOL)}; 67 EXPECT_EQ(SECSuccess, PK11_WriteRawAttribute(PK11_TypeSymKey, key, 68 CKA_EXTRACTABLE, &attrValue)); 69 } 70 71 void CheckIsNotExtractable(PK11SymKey *key) { 72 ASSERT_NE(nullptr, key); 73 74 StackSECItem attrValue; 75 ASSERT_EQ(SECSuccess, PK11_ReadRawAttribute(PK11_TypeSymKey, key, 76 CKA_EXTRACTABLE, &attrValue)); 77 ASSERT_EQ(attrValue.len, sizeof(CK_BBOOL)); 78 EXPECT_EQ(*(CK_BBOOL *)attrValue.data, CK_FALSE); 79 } 80 }; 81 82 TEST_F(Pkcs11SymKeyTest, ConcatSymKeyTest) { 83 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 84 ASSERT_NE(nullptr, slot); 85 86 ScopedPK11SymKey left(ImportSymKey(slot.get(), &kLeftHalf)); 87 88 ScopedPK11SymKey right(ImportSymKey(slot.get(), &kRightHalf)); 89 90 ScopedPK11SymKey key( 91 PK11_ConcatSymKeys(left.get(), right.get(), CKM_HKDF_DERIVE, CKA_DERIVE)); 92 CheckKeyData(kFull, key.get()); 93 } 94 95 // Test that the derived key is sensitive if either input is. 96 TEST_F(Pkcs11SymKeyTest, SensitiveConcatSymKeyTest) { 97 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 98 ASSERT_NE(nullptr, slot); 99 100 ScopedPK11SymKey left(ImportSymKey(slot.get(), &kLeftHalf)); 101 SetSensitive(left.get()); 102 103 ScopedPK11SymKey right(ImportSymKey(slot.get(), &kRightHalf)); 104 105 ScopedPK11SymKey key( 106 PK11_ConcatSymKeys(left.get(), right.get(), CKM_HKDF_DERIVE, CKA_DERIVE)); 107 CheckIsSensitive(key.get()); 108 109 // Again with left and right swapped 110 ScopedPK11SymKey key2( 111 PK11_ConcatSymKeys(right.get(), left.get(), CKM_HKDF_DERIVE, CKA_DERIVE)); 112 CheckIsSensitive(key2.get()); 113 } 114 115 // Test that the derived key is extractable if either input is. 116 TEST_F(Pkcs11SymKeyTest, NotExtractableConcatSymKeyTest) { 117 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 118 ASSERT_NE(nullptr, slot); 119 120 ScopedPK11SymKey left(ImportSymKey(slot.get(), &kLeftHalf)); 121 SetNotExtractable(left.get()); 122 123 ScopedPK11SymKey right(ImportSymKey(slot.get(), &kRightHalf)); 124 125 ScopedPK11SymKey key( 126 PK11_ConcatSymKeys(left.get(), right.get(), CKM_HKDF_DERIVE, CKA_DERIVE)); 127 CheckIsNotExtractable(key.get()); 128 129 ScopedPK11SymKey key2( 130 PK11_ConcatSymKeys(right.get(), left.get(), CKM_HKDF_DERIVE, CKA_DERIVE)); 131 CheckIsNotExtractable(key2.get()); 132 } 133 134 // Test that keys can be concatenated on the key slot. 135 TEST_F(Pkcs11SymKeyTest, KeySlotConcatSymKeyTest) { 136 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 137 ASSERT_NE(nullptr, slot); 138 139 ScopedPK11SymKey left(ImportSymKey(slot.get(), &kLeftHalf)); 140 141 ScopedPK11SymKey right(ImportSymKey(slot.get(), &kRightHalf)); 142 143 ScopedPK11SymKey key( 144 PK11_ConcatSymKeys(left.get(), right.get(), CKM_HKDF_DERIVE, CKA_DERIVE)); 145 CheckKeyData(kFull, key.get()); 146 } 147 148 // Test that keys in different slots are moved to the same slot for derivation. 149 // The PK11SymKey.data fields are set in PK11_ImportSymKey, so this just 150 // re-imports the key data. 151 TEST_F(Pkcs11SymKeyTest, CrossSlotConcatSymKeyTest) { 152 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 153 ASSERT_NE(nullptr, slot); 154 155 ScopedPK11SlotInfo slot2(PK11_GetInternalKeySlot()); 156 ASSERT_NE(nullptr, slot2); 157 158 EXPECT_NE(slot, slot2); 159 160 ScopedPK11SymKey left(ImportSymKey(slot.get(), &kLeftHalf)); 161 162 ScopedPK11SymKey right(ImportSymKey(slot2.get(), &kRightHalf)); 163 164 ScopedPK11SymKey key( 165 PK11_ConcatSymKeys(left.get(), right.get(), CKM_HKDF_DERIVE, CKA_DERIVE)); 166 CheckKeyData(kFull, key.get()); 167 } 168 169 } // namespace nss_test