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_SUITE_P(Pkcs11WycheproofAESKWTest, Pkcs11AESKeyWrapTest,
121                          ::testing::ValuesIn(kWycheproofAesKWVectors));
122 } /* nss_test */
123