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