tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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, &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 
     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                                        &paramsItem, 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                                        &paramsItem, CKM_SHA512_HMAC, CKA_SIGN,
    213                                        derivedLength));
    214    ASSERT_EQ(result, nullptr);
    215  }
    216 }
    217 
    218 // Close the namespace
    219 }  // namespace nss_test