| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| /* vim: set ts=2 et sw=2 tw=80: */ |
| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| #include <memory> |
| #include "nss.h" |
| #include "pk11pub.h" |
| |
| #include "testvectors/kw-vectors.h" |
| #include "gtest/gtest.h" |
| #include "nss_scoped_ptrs.h" |
| |
| namespace nss_test { |
| |
| class Pkcs11AESKeyWrapTest : public ::testing::TestWithParam<keywrap_vector> { |
| protected: |
| CK_MECHANISM_TYPE mechanism = CKM_NSS_AES_KEY_WRAP; |
| |
| void WrapUnwrap(unsigned char* kek_data, unsigned int kek_len, |
| unsigned char* key_data, unsigned int key_data_len, |
| unsigned char* expected_ciphertext, |
| unsigned int expected_ciphertext_len, |
| std::map<Action, Result> tests, uint32_t test_id) { |
| std::vector<unsigned char> wrapped_key(PR_MAX(1U, expected_ciphertext_len)); |
| std::vector<unsigned char> unwrapped_key(PR_MAX(1U, key_data_len)); |
| std::vector<unsigned char> zeros(PR_MAX(1U, expected_ciphertext_len)); |
| std::fill(zeros.begin(), zeros.end(), 0); |
| unsigned int wrapped_key_len = 0; |
| unsigned int unwrapped_key_len = 0; |
| SECStatus rv; |
| |
| std::stringstream s; |
| s << "Test with original ID #" << test_id << " failed." << std::endl; |
| std::string msg = s.str(); |
| |
| ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); |
| ASSERT_NE(nullptr, slot) << msg; |
| |
| // Import encryption key. |
| SECItem kek_item = {siBuffer, kek_data, kek_len}; |
| ScopedPK11SymKey kek(PK11_ImportSymKey(slot.get(), CKM_NSS_AES_KEY_WRAP, |
| PK11_OriginUnwrap, CKA_ENCRYPT, |
| &kek_item, nullptr)); |
| EXPECT_TRUE(!!kek) << msg; |
| |
| // Wrap key |
| Action test = WRAP; |
| if (tests.count(test)) { |
| rv = PK11_Encrypt(kek.get(), mechanism, nullptr /* param */, |
| wrapped_key.data(), &wrapped_key_len, |
| wrapped_key.size(), key_data, key_data_len); |
| ASSERT_EQ(rv, tests[test].expect_rv) << msg; |
| |
| // If we failed, check that output was not produced. |
| if (rv == SECFailure) { |
| EXPECT_TRUE(wrapped_key_len == 0); |
| EXPECT_TRUE(!memcmp(wrapped_key.data(), zeros.data(), wrapped_key_len)); |
| } |
| |
| if (tests[test].output_match) { |
| EXPECT_EQ(expected_ciphertext_len, wrapped_key_len) << msg; |
| EXPECT_TRUE(!memcmp(expected_ciphertext, wrapped_key.data(), |
| expected_ciphertext_len)) |
| << msg; |
| } else { |
| // If we produced output, verify that it doesn't match the vector |
| if (wrapped_key_len) { |
| EXPECT_FALSE(wrapped_key_len == expected_ciphertext_len && |
| !memcmp(wrapped_key.data(), expected_ciphertext, |
| expected_ciphertext_len)) |
| << msg; |
| } |
| } |
| } |
| |
| // Unwrap key |
| test = UNWRAP; |
| if (tests.count(test)) { |
| rv = PK11_Decrypt(kek.get(), mechanism, nullptr /* param */, |
| unwrapped_key.data(), &unwrapped_key_len, |
| unwrapped_key.size(), expected_ciphertext, |
| expected_ciphertext_len); |
| ASSERT_EQ(rv, tests[test].expect_rv) << msg; |
| |
| // If we failed, check that output was not produced. |
| if (rv == SECFailure) { |
| EXPECT_TRUE(unwrapped_key_len == 0); |
| EXPECT_TRUE( |
| !memcmp(unwrapped_key.data(), zeros.data(), unwrapped_key_len)); |
| } |
| |
| if (tests[test].output_match) { |
| EXPECT_EQ(unwrapped_key_len, key_data_len) << msg; |
| EXPECT_TRUE(!memcmp(key_data, unwrapped_key.data(), key_data_len)) |
| << msg; |
| } else { |
| // If we produced output, verify that it doesn't match the vector |
| if (unwrapped_key_len) { |
| EXPECT_FALSE( |
| unwrapped_key_len == expected_ciphertext_len && |
| !memcmp(unwrapped_key.data(), key_data, unwrapped_key_len)) |
| << msg; |
| } |
| } |
| } |
| } |
| |
| void WrapUnwrap(keywrap_vector testvector) { |
| WrapUnwrap(testvector.key.data(), testvector.key.size(), |
| testvector.msg.data(), testvector.msg.size(), |
| testvector.ct.data(), testvector.ct.size(), testvector.tests, |
| testvector.test_id); |
| } |
| }; |
| |
| TEST_P(Pkcs11AESKeyWrapTest, TestVectors) { WrapUnwrap(GetParam()); } |
| |
| INSTANTIATE_TEST_SUITE_P(Pkcs11WycheproofAESKWTest, Pkcs11AESKeyWrapTest, |
| ::testing::ValuesIn(kWycheproofAesKWVectors)); |
| } /* nss_test */ |