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:
ImportKey(CK_MECHANISM_TYPE mech,SECItem * key_item)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 
RunKDF(CK_MECHANISM_TYPE kdfMech,CK_SP800_108_KDF_PARAMS_PTR kdfParams,CK_BYTE_PTR inputKey,unsigned int inputKeyLen,CK_BYTE_PTR expectedKey,unsigned int expectedKeyLen,CK_BYTE_PTR expectedAdditional,unsigned int expectedAdditionalLen)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, &paramsItem,
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 
TEST_F(Pkcs11KbkdfTest,TestAdditionalKey)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 // Close the namespace
136 }
137