summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Jacobs <kjacobs@mozilla.com>2019-10-17 21:52:26 +0000
committerKevin Jacobs <kjacobs@mozilla.com>2019-10-17 21:52:26 +0000
commit4dbf47be67cb8123ce72a0da5c78995a78b833ad (patch)
tree6aa555b174951d83682421b0245d455db99cf1e6
parent12f24624250b1dff9c0225b3d9f57ad72ca2f9ca (diff)
downloadnss-hg-4dbf47be67cb8123ce72a0da5c78995a78b833ad.tar.gz
Bug 1589120 - Tests for padded AES key wrap r=jcj
This patch adds test vectors for padded AES Key Wrap. AES-CBC and 3DES-CBC ports of the same vectors will be included in a separate revision. Differential Revision: https://phabricator.services.mozilla.com/D49503
-rw-r--r--gtests/pk11_gtest/manifest.mn1
-rw-r--r--gtests/pk11_gtest/pk11_aeskeywrappad_unittest.cc415
-rw-r--r--gtests/pk11_gtest/pk11_gtest.gyp1
3 files changed, 417 insertions, 0 deletions
diff --git a/gtests/pk11_gtest/manifest.mn b/gtests/pk11_gtest/manifest.mn
index 52b4c06aa..861f45fec 100644
--- a/gtests/pk11_gtest/manifest.mn
+++ b/gtests/pk11_gtest/manifest.mn
@@ -9,6 +9,7 @@ MODULE = nss
CPPSRCS = \
pk11_aes_gcm_unittest.cc \
pk11_aeskeywrap_unittest.cc \
+ pk11_aeskeywrappad_unittest.cc \
pk11_cbc_unittest.cc \
pk11_chacha20poly1305_unittest.cc \
pk11_curve25519_unittest.cc \
diff --git a/gtests/pk11_gtest/pk11_aeskeywrappad_unittest.cc b/gtests/pk11_gtest/pk11_aeskeywrappad_unittest.cc
new file mode 100644
index 000000000..0f79abed5
--- /dev/null
+++ b/gtests/pk11_gtest/pk11_aeskeywrappad_unittest.cc
@@ -0,0 +1,415 @@
+/* -*- 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 "gtest/gtest.h"
+#include "nss.h"
+#include "nss_scoped_ptrs.h"
+#include "pk11pub.h"
+
+namespace nss_test {
+
+class Pkcs11AESKeyWrapPadTest : public ::testing::Test {};
+
+// Encrypt an ephemeral EC key (U2F use case)
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapECKey) {
+ const uint32_t kwrappedBufLen = 256;
+ const uint32_t kPublicKeyLen = 65;
+ const uint32_t kOidLen = 65;
+ unsigned char param_buf[kOidLen];
+ unsigned char unwrap_buf[kPublicKeyLen];
+
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+
+ SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)};
+ SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
+ ASSERT_NE(oid_data, nullptr);
+ ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID;
+ ecdsa_params.data[1] = oid_data->oid.len;
+ memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len);
+ ecdsa_params.len = oid_data->oid.len + 2;
+
+ SECKEYPublicKey* pub_tmp;
+ ScopedSECKEYPublicKey pub_key;
+ ScopedSECKEYPrivateKey priv_key(
+ PK11_GenerateKeyPair(slot.get(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params,
+ &pub_tmp, PR_FALSE, PR_TRUE, nullptr));
+ ASSERT_NE(nullptr, priv_key);
+ ASSERT_NE(nullptr, pub_tmp);
+ pub_key.reset(pub_tmp);
+
+ // Generate a KEK.
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ ScopedSECItem wrapped(::SECITEM_AllocItem(nullptr, nullptr, kwrappedBufLen));
+ ScopedSECItem param(PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP_PAD, nullptr));
+
+ SECStatus rv = PK11_WrapPrivKey(slot.get(), kek.get(), priv_key.get(),
+ CKM_NSS_AES_KEY_WRAP_PAD, param.get(),
+ wrapped.get(), nullptr);
+ ASSERT_EQ(rv, SECSuccess);
+
+ SECItem pubKey = {siBuffer, unwrap_buf, kPublicKeyLen};
+ CK_ATTRIBUTE_TYPE usages[] = {CKA_SIGN};
+ int usageCount = 1;
+
+ ScopedSECKEYPrivateKey unwrapped(
+ PK11_UnwrapPrivKey(slot.get(), kek.get(), CKM_NSS_AES_KEY_WRAP_PAD,
+ param.get(), wrapped.get(), nullptr, &pubKey, false,
+ true, CKK_EC, usages, usageCount, nullptr));
+ ASSERT_EQ(0, PORT_GetError());
+ ASSERT_TRUE(!!unwrapped);
+}
+
+// Encrypt an ephemeral RSA key
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRsaKey) {
+ const uint32_t kwrappedBufLen = 648;
+ unsigned char unwrap_buf[kwrappedBufLen];
+
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+
+ PK11RSAGenParams rsa_param;
+ rsa_param.keySizeInBits = 1024;
+ rsa_param.pe = 65537L;
+
+ SECKEYPublicKey* pub_tmp;
+ ScopedSECKEYPublicKey pub_key;
+ ScopedSECKEYPrivateKey priv_key(
+ PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsa_param,
+ &pub_tmp, PR_FALSE, PR_FALSE, nullptr));
+ ASSERT_NE(nullptr, priv_key);
+ ASSERT_NE(nullptr, pub_tmp);
+ pub_key.reset(pub_tmp);
+
+ // Generate a KEK.
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ ScopedSECItem wrapped(::SECITEM_AllocItem(nullptr, nullptr, kwrappedBufLen));
+ ScopedSECItem param(PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP_PAD, nullptr));
+
+ SECStatus rv = PK11_WrapPrivKey(slot.get(), kek.get(), priv_key.get(),
+ CKM_NSS_AES_KEY_WRAP_PAD, param.get(),
+ wrapped.get(), nullptr);
+ ASSERT_EQ(rv, SECSuccess);
+
+ SECItem pubKey = {siBuffer, unwrap_buf, kwrappedBufLen};
+ CK_ATTRIBUTE_TYPE usages[] = {CKA_SIGN};
+ int usageCount = 1;
+
+ ScopedSECKEYPrivateKey unwrapped(
+ PK11_UnwrapPrivKey(slot.get(), kek.get(), CKM_NSS_AES_KEY_WRAP_PAD,
+ param.get(), wrapped.get(), nullptr, &pubKey, false,
+ false, CKK_EC, usages, usageCount, nullptr));
+ ASSERT_EQ(0, PORT_GetError());
+ ASSERT_TRUE(!!unwrapped);
+
+ ScopedSECItem priv_key_data(
+ PK11_ExportDERPrivateKeyInfo(priv_key.get(), nullptr));
+ ScopedSECItem unwrapped_data(
+ PK11_ExportDERPrivateKeyInfo(unwrapped.get(), nullptr));
+ EXPECT_TRUE(!!priv_key_data);
+ EXPECT_TRUE(!!unwrapped_data);
+ ASSERT_EQ(priv_key_data->len, unwrapped_data->len);
+ ASSERT_EQ(
+ 0, memcmp(priv_key_data->data, unwrapped_data->data, priv_key_data->len));
+}
+
+// Wrap a random that's a multiple of the block size, and compare the unwrap
+// result.
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_EvenBlock) {
+ const uint32_t kInputKeyLen = 128;
+ uint32_t out_len = 0;
+ std::vector<unsigned char> input_key(kInputKeyLen);
+ std::vector<unsigned char> wrapped_key(
+ kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
+ std::vector<unsigned char> unwrapped_key(
+ kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
+
+ // Generate input key material
+ SECStatus rv = PK11_GenerateRandom(input_key.data(), input_key.size());
+ EXPECT_EQ(SECSuccess, rv);
+
+ // Generate a KEK.
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ rv = PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ wrapped_key.data(), &out_len,
+ static_cast<unsigned int>(wrapped_key.size()),
+ input_key.data(),
+ static_cast<unsigned int>(input_key.size()));
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ unwrapped_key.data(), &out_len,
+ static_cast<unsigned int>(unwrapped_key.size()),
+ wrapped_key.data(), out_len);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(input_key.size(), out_len);
+ ASSERT_EQ(0, memcmp(input_key.data(), unwrapped_key.data(), out_len));
+}
+
+// Wrap a random that's NOT a multiple of the block size, and compare the unwrap
+// result.
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_OddBlock1) {
+ const uint32_t kInputKeyLen = 65;
+ uint32_t out_len = 0;
+ std::vector<unsigned char> input_key(kInputKeyLen);
+ std::vector<unsigned char> wrapped_key(
+ kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
+ std::vector<unsigned char> unwrapped_key(
+ kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
+
+ // Generate input key material
+ SECStatus rv = PK11_GenerateRandom(input_key.data(), input_key.size());
+ EXPECT_EQ(SECSuccess, rv);
+
+ // Generate a KEK.
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ rv = PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ wrapped_key.data(), &out_len,
+ static_cast<unsigned int>(wrapped_key.size()),
+ input_key.data(),
+ static_cast<unsigned int>(input_key.size()));
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ unwrapped_key.data(), &out_len,
+ static_cast<unsigned int>(unwrapped_key.size()),
+ wrapped_key.data(), out_len);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(input_key.size(), out_len);
+ ASSERT_EQ(0, memcmp(input_key.data(), unwrapped_key.data(), out_len));
+}
+
+// Wrap a random that's NOT a multiple of the block size, and compare the unwrap
+// result.
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_OddBlock2) {
+ const uint32_t kInputKeyLen = 63;
+ uint32_t out_len = 0;
+ std::vector<unsigned char> input_key(kInputKeyLen);
+ std::vector<unsigned char> wrapped_key(
+ kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
+ std::vector<unsigned char> unwrapped_key(
+ kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
+
+ // Generate input key material
+ SECStatus rv = PK11_GenerateRandom(input_key.data(), input_key.size());
+ EXPECT_EQ(SECSuccess, rv);
+
+ // Generate a KEK.
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ rv = PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ wrapped_key.data(), &out_len, wrapped_key.size(),
+ input_key.data(), input_key.size());
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ unwrapped_key.data(), &out_len,
+ static_cast<unsigned int>(unwrapped_key.size()),
+ wrapped_key.data(), out_len);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(input_key.size(), out_len);
+ ASSERT_EQ(0, memcmp(input_key.data(), unwrapped_key.data(), out_len));
+}
+
+// Invalid long padding (over the block size, but otherwise valid)
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_PaddingTooLong) {
+ const uint32_t kInputKeyLen = 32;
+ uint32_t out_len = 0;
+
+ // Apply our own padding
+ const unsigned char buf[32] = {
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
+ std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+ std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+
+ // Generate a KEK.
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ SECStatus rv =
+ PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
+ /* param */ nullptr, wrapped_key.data(), &out_len,
+ wrapped_key.size(), buf, sizeof(buf));
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ unwrapped_key.data(), &out_len,
+ static_cast<unsigned int>(unwrapped_key.size()),
+ wrapped_key.data(), out_len);
+ ASSERT_EQ(SECFailure, rv);
+}
+
+// Invalid 0-length padding (there should be a full block if the message doesn't
+// need to be padded)
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_NoPadding) {
+ const uint32_t kInputKeyLen = 32;
+ uint32_t out_len = 0;
+
+ // Apply our own padding
+ const unsigned char buf[32] = {0};
+ std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+ std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+
+ // Generate a KEK.
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ SECStatus rv =
+ PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
+ /* param */ nullptr, wrapped_key.data(), &out_len,
+ wrapped_key.size(), buf, sizeof(buf));
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ unwrapped_key.data(), &out_len,
+ static_cast<unsigned int>(unwrapped_key.size()),
+ wrapped_key.data(), out_len);
+ ASSERT_EQ(SECFailure, rv);
+}
+
+// Invalid padding
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_BadPadding1) {
+ const uint32_t kInputKeyLen = 32;
+ uint32_t out_len = 0;
+
+ // Apply our own padding
+ const unsigned char buf[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08}; // Check all 8 bytes
+ std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+ std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+
+ // Generate a KEK.
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ SECStatus rv =
+ PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
+ /* param */ nullptr, wrapped_key.data(), &out_len,
+ wrapped_key.size(), buf, sizeof(buf));
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ unwrapped_key.data(), &out_len,
+ static_cast<unsigned int>(unwrapped_key.size()),
+ wrapped_key.data(), out_len);
+ ASSERT_EQ(SECFailure, rv);
+}
+
+// Invalid padding
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_BadPadding2) {
+ const uint32_t kInputKeyLen = 32;
+ uint32_t out_len = 0;
+
+ // Apply our own padding
+ const unsigned char
+ buf[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x02}; // Check first loop repeat
+ std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+ std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+
+ // Generate a KEK.
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ SECStatus rv =
+ PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
+ /* param */ nullptr, wrapped_key.data(), &out_len,
+ wrapped_key.size(), buf, sizeof(buf));
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ unwrapped_key.data(), &out_len,
+ static_cast<unsigned int>(unwrapped_key.size()),
+ wrapped_key.data(), out_len);
+ ASSERT_EQ(SECFailure, rv);
+}
+
+// Minimum valid padding
+TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_ShortValidPadding) {
+ const uint32_t kInputKeyLen = 32;
+ uint32_t out_len = 0;
+
+ // Apply our own padding
+ const unsigned char buf[kInputKeyLen] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; // Minimum
+ std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+ std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
+
+ // Generate a KEK.
+ ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+ ASSERT_NE(nullptr, slot);
+ ScopedPK11SymKey kek(
+ PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
+ ASSERT_NE(nullptr, kek);
+
+ // Wrap the key
+ SECStatus rv =
+ PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
+ /* param */ nullptr, wrapped_key.data(), &out_len,
+ wrapped_key.size(), buf, sizeof(buf));
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
+ unwrapped_key.data(), &out_len,
+ static_cast<unsigned int>(unwrapped_key.size()),
+ wrapped_key.data(), out_len);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(kInputKeyLen - 1, out_len);
+ ASSERT_EQ(0, memcmp(buf, unwrapped_key.data(), out_len));
+}
+
+} /* nss_test */
diff --git a/gtests/pk11_gtest/pk11_gtest.gyp b/gtests/pk11_gtest/pk11_gtest.gyp
index 29c1a4a52..f2a81d6df 100644
--- a/gtests/pk11_gtest/pk11_gtest.gyp
+++ b/gtests/pk11_gtest/pk11_gtest.gyp
@@ -14,6 +14,7 @@
'pk11_aes_cmac_unittest.cc',
'pk11_aes_gcm_unittest.cc',
'pk11_aeskeywrap_unittest.cc',
+ 'pk11_aeskeywrappad_unittest.cc',
'pk11_cbc_unittest.cc',
'pk11_chacha20poly1305_unittest.cc',
'pk11_cipherop_unittest.cc',