pk11_kbkdf.cc (8420B)
1 /* -*- Mode: C++; tab-width: 2; 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 #include "secerr.h" 11 #include "sechash.h" 12 #include "stdio.h" 13 14 #include "blapi.h" 15 16 #include "gtest/gtest.h" 17 #include "nss_scoped_ptrs.h" 18 #include "util.h" 19 20 namespace nss_test { 21 class Pkcs11KbkdfTest : public ::testing::Test { 22 protected: 23 ScopedPK11SymKey ImportKey(CK_MECHANISM_TYPE mech, SECItem *key_item) { 24 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 25 if (!slot) { 26 ADD_FAILURE() << "Can't get slot"; 27 return nullptr; 28 } 29 30 ScopedPK11SymKey result(PK11_ImportSymKey( 31 slot.get(), mech, PK11_OriginUnwrap, CKA_SIGN, key_item, nullptr)); 32 33 return result; 34 } 35 36 void RunKDF(CK_MECHANISM_TYPE kdfMech, CK_SP800_108_KDF_PARAMS_PTR kdfParams, 37 CK_BYTE_PTR inputKey, unsigned int inputKeyLen, 38 CK_BYTE_PTR expectedKey, unsigned int expectedKeyLen, 39 CK_BYTE_PTR expectedAdditional, 40 unsigned int expectedAdditionalLen) { 41 SECItem keyItem = {siBuffer, inputKey, inputKeyLen}; 42 ScopedPK11SymKey p11Key = ImportKey(kdfParams->prfType, &keyItem); 43 44 ASSERT_NE(kdfParams, nullptr); 45 SECItem paramsItem = {siBuffer, (unsigned char *)kdfParams, 46 sizeof(*kdfParams)}; 47 48 ScopedPK11SymKey result(PK11_Derive(p11Key.get(), kdfMech, ¶msItem, 49 CKM_SHA512_HMAC, CKA_SIGN, 50 expectedKeyLen)); 51 ASSERT_NE(result, nullptr); 52 53 ASSERT_EQ(PK11_ExtractKeyValue(result.get()), SECSuccess); 54 55 /* We don't need to free this -- it is just a reference... */ 56 SECItem *actualItem = PK11_GetKeyData(result.get()); 57 ASSERT_NE(actualItem, nullptr); 58 59 SECItem expectedItem = {siBuffer, expectedKey, expectedKeyLen}; 60 ASSERT_EQ(SECITEM_CompareItem(actualItem, &expectedItem), 0); 61 62 /* Extract the additional key. */ 63 if (expectedAdditional == NULL || kdfParams->ulAdditionalDerivedKeys != 1) { 64 return; 65 } 66 67 ScopedPK11SlotInfo slot(PK11_GetSlotFromKey(result.get())); 68 69 CK_OBJECT_HANDLE_PTR keyHandle = kdfParams->pAdditionalDerivedKeys[0].phKey; 70 ScopedPK11SymKey additionalKey( 71 PK11_SymKeyFromHandle(slot.get(), result.get(), PK11_OriginDerive, 72 CKM_SHA512_HMAC, *keyHandle, PR_FALSE, NULL)); 73 74 ASSERT_EQ(PK11_ExtractKeyValue(additionalKey.get()), SECSuccess); 75 76 /* We don't need to free this -- it is just a reference... */ 77 actualItem = PK11_GetKeyData(additionalKey.get()); 78 ASSERT_NE(actualItem, nullptr); 79 80 expectedItem = {siBuffer, expectedAdditional, expectedAdditionalLen}; 81 ASSERT_EQ(SECITEM_CompareItem(actualItem, &expectedItem), 0); 82 } 83 }; 84 85 TEST_F(Pkcs11KbkdfTest, TestAdditionalKey) { 86 /* Test number 11 of NIST CAVP vectors for Counter mode KDF, with counter 87 * after a fixed input (AES/128 CMAC). Resulting key (of size 256 bits) 88 * split into two 128-bit chunks since that aligns with a PRF invocation 89 * boundary. */ 90 CK_BYTE inputKey[] = {0x23, 0xeb, 0x06, 0x5b, 0xe1, 0x27, 0xa8, 0x81, 91 0xe3, 0x5a, 0x65, 0x14, 0xd4, 0x35, 0x67, 0x9f}; 92 CK_BYTE expectedKey[] = {0xea, 0x4e, 0xbb, 0xb4, 0xef, 0xff, 0x4b, 0x01, 93 0x68, 0x40, 0x12, 0xed, 0x8f, 0xf9, 0xc6, 0x4e}; 94 CK_BYTE expectedAdditional[] = {0x70, 0xae, 0x38, 0x19, 0x7c, 0x36, 95 0x44, 0x5a, 0x6c, 0x80, 0x4a, 0x0e, 96 0x44, 0x81, 0x9a, 0xc3}; 97 98 CK_SP800_108_COUNTER_FORMAT iterator = {CK_FALSE, 8}; 99 CK_BYTE fixedData[] = { 100 0xe6, 0x79, 0x86, 0x1a, 0x61, 0x34, 0x65, 0xa6, 0x73, 0x85, 0x37, 0x26, 101 0x71, 0xb1, 0x07, 0xe6, 0xb8, 0x95, 0xa2, 0xf6, 0x40, 0x43, 0xc9, 0x34, 102 0xff, 0x42, 0x56, 0xa7, 0xe6, 0x3c, 0xfb, 0x8b, 0xfa, 0xcc, 0x21, 0x24, 103 0x25, 0x1c, 0x90, 0xfa, 0x67, 0x0d, 0x45, 0x74, 0x5c, 0x1c, 0x35, 0xda, 104 0x9b, 0x6e, 0x05, 0xaf, 0x77, 0xea, 0x9c, 0x4a, 0xd4, 0x86, 0xfd, 0x1a}; 105 106 CK_PRF_DATA_PARAM dataParams[] = { 107 {CK_SP800_108_BYTE_ARRAY, fixedData, 108 sizeof(fixedData) / sizeof(*fixedData)}, 109 {CK_SP800_108_ITERATION_VARIABLE, &iterator, sizeof(iterator)}}; 110 111 CK_KEY_TYPE ckGeneric = CKK_GENERIC_SECRET; 112 CK_OBJECT_CLASS ckClass = CKO_SECRET_KEY; 113 CK_ULONG derivedLength = 16; 114 115 CK_ATTRIBUTE derivedTemplate[] = { 116 {CKA_CLASS, &ckClass, sizeof(ckClass)}, 117 {CKA_KEY_TYPE, &ckGeneric, sizeof(ckGeneric)}, 118 {CKA_VALUE_LEN, &derivedLength, sizeof(derivedLength)}}; 119 120 CK_OBJECT_HANDLE keyHandle; 121 CK_DERIVED_KEY derivedKey = { 122 derivedTemplate, sizeof(derivedTemplate) / sizeof(*derivedTemplate), 123 &keyHandle}; 124 125 CK_SP800_108_KDF_PARAMS kdfParams = {CKM_AES_CMAC, 126 sizeof(dataParams) / sizeof(*dataParams), 127 dataParams, 1, &derivedKey}; 128 129 RunKDF(CKM_SP800_108_COUNTER_KDF, &kdfParams, inputKey, 130 sizeof(inputKey) / sizeof(*inputKey), expectedKey, 131 sizeof(expectedKey) / sizeof(*expectedKey), expectedAdditional, 132 sizeof(expectedAdditional) / sizeof(*expectedAdditional)); 133 } 134 135 TEST_F(Pkcs11KbkdfTest, TestPRFs) { 136 // Table 161 of PKCS#11 v3.0 / Table 192 of PKCS#11 v3.1. 137 CK_SP800_108_PRF_TYPE allowedPRFs[] = { 138 CKM_SHA_1_HMAC, 139 CKM_SHA224_HMAC, 140 CKM_SHA256_HMAC, 141 CKM_SHA384_HMAC, 142 CKM_SHA512_HMAC, 143 CKM_SHA3_224_HMAC, 144 CKM_SHA3_256_HMAC, 145 CKM_SHA3_384_HMAC, 146 CKM_SHA3_512_HMAC, 147 /* CKM_DES3_CMAC, */ 148 CKM_AES_CMAC, 149 }; 150 CK_SP800_108_PRF_TYPE disallowedPRFs[] = { 151 CKM_MD2_HMAC, 152 CKM_MD5_HMAC, 153 CKM_RIPEMD128_HMAC, 154 CKM_RIPEMD160_HMAC, 155 }; 156 157 CK_BYTE inputKey[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 158 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; 159 160 CK_SP800_108_COUNTER_FORMAT iterator = {CK_FALSE, 8}; 161 CK_BYTE fixedData[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 162 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; 163 164 CK_PRF_DATA_PARAM dataParams[] = { 165 {CK_SP800_108_BYTE_ARRAY, fixedData, 166 sizeof(fixedData) / sizeof(*fixedData)}, 167 {CK_SP800_108_ITERATION_VARIABLE, &iterator, sizeof(iterator)}}; 168 169 CK_KEY_TYPE ckGeneric = CKK_GENERIC_SECRET; 170 CK_OBJECT_CLASS ckClass = CKO_SECRET_KEY; 171 CK_ULONG derivedLength = 16; 172 173 CK_ATTRIBUTE derivedTemplate[] = { 174 {CKA_CLASS, &ckClass, sizeof(ckClass)}, 175 {CKA_KEY_TYPE, &ckGeneric, sizeof(ckGeneric)}, 176 {CKA_VALUE_LEN, &derivedLength, sizeof(derivedLength)}}; 177 178 CK_OBJECT_HANDLE keyHandle; 179 CK_DERIVED_KEY derivedKey = { 180 derivedTemplate, sizeof(derivedTemplate) / sizeof(*derivedTemplate), 181 &keyHandle}; 182 183 SECItem keyItem = {siBuffer, inputKey, sizeof(inputKey) / sizeof(*inputKey)}; 184 185 for (CK_SP800_108_PRF_TYPE prfType : allowedPRFs) { 186 ScopedPK11SymKey p11Key = ImportKey(prfType, &keyItem); 187 188 CK_SP800_108_KDF_PARAMS kdfParams = { 189 prfType, sizeof(dataParams) / sizeof(*dataParams), dataParams, 1, 190 &derivedKey}; 191 SECItem paramsItem = {siBuffer, (unsigned char *)&kdfParams, 192 sizeof(kdfParams)}; 193 194 ScopedPK11SymKey result(PK11_Derive(p11Key.get(), CKM_SP800_108_COUNTER_KDF, 195 ¶msItem, CKM_SHA512_HMAC, CKA_SIGN, 196 derivedLength)); 197 ASSERT_NE(result, nullptr); 198 199 ASSERT_EQ(PK11_ExtractKeyValue(result.get()), SECSuccess); 200 } 201 202 for (CK_SP800_108_PRF_TYPE prfType : disallowedPRFs) { 203 ScopedPK11SymKey p11Key = ImportKey(prfType, &keyItem); 204 205 CK_SP800_108_KDF_PARAMS kdfParams = { 206 prfType, sizeof(dataParams) / sizeof(*dataParams), dataParams, 1, 207 &derivedKey}; 208 SECItem paramsItem = {siBuffer, (unsigned char *)&kdfParams, 209 sizeof(kdfParams)}; 210 211 ScopedPK11SymKey result(PK11_Derive(p11Key.get(), CKM_SP800_108_COUNTER_KDF, 212 ¶msItem, CKM_SHA512_HMAC, CKA_SIGN, 213 derivedLength)); 214 ASSERT_EQ(result, nullptr); 215 } 216 } 217 218 // Close the namespace 219 } // namespace nss_test