Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
Showing
19 changed files
with
39,582 additions
and
116 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.