Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bug 1630721 Softoken Functions for FIPS missing r=mt
For FIPS we need the following:

 1. NIST official Key padding for AES Key Wrap.
 2. Combined Hash/Sign mechanisms for DSA and ECDSA.

In the first case our AES_KEY_WRAP_PAD function addes pkcs8 padding to the
normal AES_KEY_WRAP, which is a different algorithm then the padded key wrap
specified by NIST. PKCS #11 recognized this and created a special mechanism to
handle NIST padding. That is why we don't have industry test vectors for
CKM_NSS_AES_KEY_WRAP_PAD. This patch implements that NIST version (while
maintaining our own). Also PKCS #11 v3.0 specified PKCS #11 mechanism for
AES_KEY_WRAP which are compatible (semantically) with the NSS vendor specific
versions, but with non-vendor specific numbers. Softoken now accepts both
numbers.

This patch also updates softoken to handle DSA and ECDSA combined hash
algorithms other than just SHA1 (which is no longer validated).

Finally this patch uses the NIST KWP test vectors in new gtests for the
AES_KEY_WRAP_KWP wrapping algorithm.

As part of the AES_KEY_WRAP_KWP code, the Constant time macros have been
generalized and moved to secport. Old macros scattered throughout the code
have been deleted and existing contant time code has been updated to use
the new macros.

Differential Revision: https://phabricator.services.mozilla.com/D71225
  • Loading branch information
rjrelyea committed Apr 16, 2020
1 parent 7d4b0ba commit 60de8da
Show file tree
Hide file tree
Showing 19 changed files with 39,582 additions and 116 deletions.
38,977 changes: 38,977 additions & 0 deletions gtests/common/testvectors/kwp-vectors.h

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions gtests/pk11_gtest/manifest.mn
Expand Up @@ -9,6 +9,7 @@ MODULE = nss
CPPSRCS = \
pk11_aes_gcm_unittest.cc \
pk11_aeskeywrap_unittest.cc \
pk11_aeskeywrapkwp_unittest.cc \
pk11_aeskeywrappad_unittest.cc \
pk11_cbc_unittest.cc \
pk11_chacha20poly1305_unittest.cc \
Expand Down
123 changes: 123 additions & 0 deletions gtests/pk11_gtest/pk11_aeskeywrapkwp_unittest.cc
@@ -0,0 +1,123 @@
/* -*- 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 "testvectors/kwp-vectors.h"
#include "gtest/gtest.h"
#include "nss_scoped_ptrs.h"

namespace nss_test {

class Pkcs11AESKeyWrapKwpTest
: public ::testing::TestWithParam<keywrap_vector> {
protected:
CK_MECHANISM_TYPE mechanism = CKM_AES_KEY_WRAP_KWP;

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), 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_ImportSymKeyWithFlags(
slot.get(), mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &kek_item,
CKF_DECRYPT, PR_FALSE, 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(Pkcs11AESKeyWrapKwpTest, TestVectors) { WrapUnwrap(GetParam()); }

INSTANTIATE_TEST_CASE_P(Pkcs11NistAESKWPTest, Pkcs11AESKeyWrapKwpTest,
::testing::ValuesIn(kNistAesKWPVectors));
} /* nss_test */
1 change: 1 addition & 0 deletions gtests/pk11_gtest/pk11_gtest.gyp
Expand Up @@ -14,6 +14,7 @@
'pk11_aes_cmac_unittest.cc',
'pk11_aes_gcm_unittest.cc',
'pk11_aeskeywrap_unittest.cc',
'pk11_aeskeywrapkwp_unittest.cc',
'pk11_aeskeywrappad_unittest.cc',
'pk11_cbc_unittest.cc',
'pk11_chacha20poly1305_unittest.cc',
Expand Down

0 comments on commit 60de8da

Please sign in to comment.