tor-browser

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

pk11_aes_cmac_unittest.cc (5022B)


      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 #include "secerr.h"
     11 #include "sechash.h"
     12 
     13 #include "blapi.h"
     14 
     15 #include "gtest/gtest.h"
     16 #include "nss_scoped_ptrs.h"
     17 #include "testvectors/cmac-vectors.h"
     18 #include "util.h"
     19 
     20 namespace nss_test {
     21 
     22 class Pkcs11AesCmacTest : public ::testing::TestWithParam<AesCmacTestVector> {
     23 protected:
     24  ScopedPK11SymKey ImportKey(CK_MECHANISM_TYPE mech, SECItem *key_item) {
     25    ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
     26    if (!slot) {
     27      ADD_FAILURE() << "Can't get slot";
     28      return nullptr;
     29    }
     30 
     31    ScopedPK11SymKey result(PK11_ImportSymKey(
     32        slot.get(), mech, PK11_OriginUnwrap, CKA_SIGN, key_item, nullptr));
     33 
     34    return result;
     35  }
     36 
     37  void RunTest(uint8_t *key, unsigned int key_len, uint8_t *data,
     38               unsigned int data_len, uint8_t *expected,
     39               unsigned int expected_len, CK_ULONG mechanism) {
     40    // Create SECItems for everything...
     41    std::vector<uint8_t> output(expected_len);
     42    SECItem key_item = {siBuffer, key, key_len};
     43    SECItem output_item = {siBuffer, output.data(), expected_len};
     44    SECItem data_item = {siBuffer, data, data_len};
     45    SECItem expected_item = {siBuffer, expected, expected_len};
     46 
     47    // Do the PKCS #11 stuff...
     48    ScopedPK11SymKey p11_key = ImportKey(mechanism, &key_item);
     49    ASSERT_NE(nullptr, p11_key.get());
     50 
     51    SECStatus ret = PK11_SignWithSymKey(p11_key.get(), CKM_AES_CMAC, NULL,
     52                                        &output_item, &data_item);
     53 
     54    // Verify the result...
     55    ASSERT_EQ(SECSuccess, ret);
     56    ASSERT_EQ(0, SECITEM_CompareItem(&output_item, &expected_item));
     57  }
     58 
     59  void RunTestVector(const AesCmacTestVector vec) {
     60    bool valid = !vec.invalid;
     61    std::string err = "Test #" + std::to_string(vec.id) + " failed";
     62    std::vector<uint8_t> key = hex_string_to_bytes(vec.key);
     63    std::vector<uint8_t> tag = hex_string_to_bytes(vec.tag);
     64    std::vector<uint8_t> msg = hex_string_to_bytes(vec.msg);
     65 
     66    std::vector<uint8_t> output(AES_BLOCK_SIZE);
     67    // Don't provide a null pointer, even if the input is empty.
     68    uint8_t tmp;
     69    SECItem key_item = {siBuffer, key.data() ? key.data() : &tmp,
     70                        static_cast<unsigned int>(key.size())};
     71    SECItem tag_item = {siBuffer, tag.data() ? tag.data() : &tmp,
     72                        static_cast<unsigned int>(tag.size())};
     73    SECItem msg_item = {siBuffer, msg.data() ? msg.data() : &tmp,
     74                        static_cast<unsigned int>(msg.size())};
     75    SECItem out_item = {siBuffer, output.data() ? output.data() : &tmp,
     76                        static_cast<unsigned int>(output.size())};
     77 
     78    ScopedPK11SymKey p11_key = ImportKey(CKM_AES_CMAC_GENERAL, &key_item);
     79    if (vec.comment == "invalid key size") {
     80      ASSERT_EQ(nullptr, p11_key.get()) << err;
     81      return;
     82    }
     83 
     84    ASSERT_NE(nullptr, p11_key.get()) << err;
     85    SECStatus rv = PK11_SignWithSymKey(p11_key.get(), CKM_AES_CMAC, NULL,
     86                                       &out_item, &msg_item);
     87 
     88    EXPECT_EQ(SECSuccess, rv) << err;
     89    EXPECT_EQ(valid, 0 == SECITEM_CompareItem(&out_item, &tag_item)) << err;
     90  }
     91 };
     92 
     93 TEST_P(Pkcs11AesCmacTest, TestVectors) { RunTestVector(GetParam()); }
     94 
     95 INSTANTIATE_TEST_SUITE_P(WycheproofTestVector, Pkcs11AesCmacTest,
     96                         ::testing::ValuesIn(kCmacWycheproofVectors));
     97 
     98 // Sanity check of the PKCS #11 API only. Extensive tests for correctness of
     99 // underling CMAC implementation conducted in the following file:
    100 //      gtests/freebl_gtest/cmac_unittests.cc
    101 
    102 TEST_F(Pkcs11AesCmacTest, Aes128NistExample1) {
    103  uint8_t key[AES_128_KEY_LENGTH] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE,
    104                                     0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88,
    105                                     0x09, 0xCF, 0x4F, 0x3C};
    106  uint8_t known[AES_BLOCK_SIZE] = {0xBB, 0x1D, 0x69, 0x29, 0xE9, 0x59,
    107                                   0x37, 0x28, 0x7F, 0xA3, 0x7D, 0x12,
    108                                   0x9B, 0x75, 0x67, 0x46};
    109 
    110  RunTest(key, AES_128_KEY_LENGTH, NULL, 0, known, AES_BLOCK_SIZE,
    111          CKM_AES_CMAC);
    112 }
    113 
    114 TEST_F(Pkcs11AesCmacTest, General) {
    115  uint8_t key[AES_128_KEY_LENGTH] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE,
    116                                     0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88,
    117                                     0x09, 0xCF, 0x4F, 0x3C};
    118  uint8_t known[4] = {0xBB, 0x1D, 0x69, 0x29};
    119 
    120  RunTest(key, AES_128_KEY_LENGTH, NULL, 0, known, 4, CKM_AES_CMAC_GENERAL);
    121 }
    122 
    123 TEST_F(Pkcs11AesCmacTest, InvalidKeySize) {
    124  uint8_t key[4] = {0x00, 0x00, 0x00, 0x00};
    125  SECItem key_item = {siBuffer, key, 4};
    126 
    127  ScopedPK11SymKey result = ImportKey(CKM_AES_CMAC, &key_item);
    128  ASSERT_EQ(nullptr, result.get());
    129 }
    130 }  // namespace nss_test