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
11 #include "testvectors/kw-vectors.h"
12 #include "gtest/gtest.h"
13 #include "nss_scoped_ptrs.h"
14
15 namespace nss_test {
16
17 class Pkcs11AESKeyWrapTest : public ::testing::TestWithParam<keywrap_vector> {
18 protected:
19 CK_MECHANISM_TYPE mechanism = CKM_NSS_AES_KEY_WRAP;
20
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)21 void WrapUnwrap(unsigned char* kek_data, unsigned int kek_len,
22 unsigned char* key_data, unsigned int key_data_len,
23 unsigned char* expected_ciphertext,
24 unsigned int expected_ciphertext_len,
25 std::map<Action, Result> tests, uint32_t test_id) {
26 std::vector<unsigned char> wrapped_key(PR_MAX(1U, expected_ciphertext_len));
27 std::vector<unsigned char> unwrapped_key(PR_MAX(1U, key_data_len));
28 std::vector<unsigned char> zeros(PR_MAX(1U, expected_ciphertext_len));
29 std::fill(zeros.begin(), zeros.end(), 0);
30 unsigned int wrapped_key_len = 0;
31 unsigned int unwrapped_key_len = 0;
32 SECStatus rv;
33
34 std::stringstream s;
35 s << "Test with original ID #" << test_id << " failed." << std::endl;
36 std::string msg = s.str();
37
38 ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
39 ASSERT_NE(nullptr, slot) << msg;
40
41 // Import encryption key.
42 SECItem kek_item = {siBuffer, kek_data, kek_len};
43 ScopedPK11SymKey kek(PK11_ImportSymKey(slot.get(), CKM_NSS_AES_KEY_WRAP,
44 PK11_OriginUnwrap, CKA_ENCRYPT,
45 &kek_item, nullptr));
46 EXPECT_TRUE(!!kek) << msg;
47
48 // Wrap key
49 Action test = WRAP;
50 if (tests.count(test)) {
51 rv = PK11_Encrypt(kek.get(), mechanism, nullptr /* param */,
52 wrapped_key.data(), &wrapped_key_len,
53 wrapped_key.size(), key_data, key_data_len);
54 ASSERT_EQ(rv, tests[test].expect_rv) << msg;
55
56 // If we failed, check that output was not produced.
57 if (rv == SECFailure) {
58 EXPECT_TRUE(wrapped_key_len == 0);
59 EXPECT_TRUE(!memcmp(wrapped_key.data(), zeros.data(), wrapped_key_len));
60 }
61
62 if (tests[test].output_match) {
63 EXPECT_EQ(expected_ciphertext_len, wrapped_key_len) << msg;
64 EXPECT_TRUE(!memcmp(expected_ciphertext, wrapped_key.data(),
65 expected_ciphertext_len))
66 << msg;
67 } else {
68 // If we produced output, verify that it doesn't match the vector
69 if (wrapped_key_len) {
70 EXPECT_FALSE(wrapped_key_len == expected_ciphertext_len &&
71 !memcmp(wrapped_key.data(), expected_ciphertext,
72 expected_ciphertext_len))
73 << msg;
74 }
75 }
76 }
77
78 // Unwrap key
79 test = UNWRAP;
80 if (tests.count(test)) {
81 rv = PK11_Decrypt(kek.get(), mechanism, nullptr /* param */,
82 unwrapped_key.data(), &unwrapped_key_len,
83 unwrapped_key.size(), expected_ciphertext,
84 expected_ciphertext_len);
85 ASSERT_EQ(rv, tests[test].expect_rv) << msg;
86
87 // If we failed, check that output was not produced.
88 if (rv == SECFailure) {
89 EXPECT_TRUE(unwrapped_key_len == 0);
90 EXPECT_TRUE(
91 !memcmp(unwrapped_key.data(), zeros.data(), unwrapped_key_len));
92 }
93
94 if (tests[test].output_match) {
95 EXPECT_EQ(unwrapped_key_len, key_data_len) << msg;
96 EXPECT_TRUE(!memcmp(key_data, unwrapped_key.data(), key_data_len))
97 << msg;
98 } else {
99 // If we produced output, verify that it doesn't match the vector
100 if (unwrapped_key_len) {
101 EXPECT_FALSE(
102 unwrapped_key_len == expected_ciphertext_len &&
103 !memcmp(unwrapped_key.data(), key_data, unwrapped_key_len))
104 << msg;
105 }
106 }
107 }
108 }
109
WrapUnwrap(keywrap_vector testvector)110 void WrapUnwrap(keywrap_vector testvector) {
111 WrapUnwrap(testvector.key.data(), testvector.key.size(),
112 testvector.msg.data(), testvector.msg.size(),
113 testvector.ct.data(), testvector.ct.size(), testvector.tests,
114 testvector.test_id);
115 }
116 };
117
TEST_P(Pkcs11AESKeyWrapTest,TestVectors)118 TEST_P(Pkcs11AESKeyWrapTest, TestVectors) { WrapUnwrap(GetParam()); }
119
120 INSTANTIATE_TEST_CASE_P(Pkcs11WycheproofAESKWTest, Pkcs11AESKeyWrapTest,
121 ::testing::ValuesIn(kWycheproofAesKWVectors));
122 } /* nss_test */
123