nss: update to 3.44.1, with vc2013 fix and gyp fix

This commit is contained in:
Roy Tam 2019-06-24 21:44:17 +08:00
commit d4b834111b
553 changed files with 1515569 additions and 1130 deletions

View file

@ -8,6 +8,7 @@ MODULE = nss
CPPSRCS = \
pk11_aeskeywrap_unittest.cc \
pk11_aes_gcm_unittest.cc \
pk11_chacha20poly1305_unittest.cc \
pk11_curve25519_unittest.cc \
pk11_ecdsa_unittest.cc \

View file

@ -8,6 +8,7 @@
#include "nss.h"
#include "pk11pub.h"
#include "sechash.h"
#include "secerr.h"
#include "cpputil.h"
#include "nss_scoped_ptrs.h"
@ -17,10 +18,17 @@
namespace nss_test {
static const CK_MECHANISM_TYPE kMech = CKM_NSS_CHACHA20_POLY1305;
static const CK_MECHANISM_TYPE kMechXor = CKM_NSS_CHACHA20_CTR;
// Some test data for simple tests.
static const uint8_t kKeyData[32] = {'k'};
static const uint8_t kCtrNonce[16] = {'c', 0, 0, 0, 'n'};
static const uint8_t kData[16] = {'d'};
class Pkcs11ChaCha20Poly1305Test
: public ::testing::TestWithParam<chacha_testvector> {
public:
void EncryptDecrypt(PK11SymKey* symKey, const bool invalid_iv,
void EncryptDecrypt(const ScopedPK11SymKey& key, const bool invalid_iv,
const bool invalid_tag, const uint8_t* data,
size_t data_len, const uint8_t* aad, size_t aad_len,
const uint8_t* iv, size_t iv_len,
@ -39,7 +47,7 @@ class Pkcs11ChaCha20Poly1305Test
// Encrypt.
unsigned int outputLen = 0;
std::vector<uint8_t> output(data_len + aead_params.ulTagLen);
SECStatus rv = PK11_Encrypt(symKey, mech, &params, output.data(),
SECStatus rv = PK11_Encrypt(key.get(), kMech, &params, output.data(),
&outputLen, output.size(), data, data_len);
// Return if encryption failure was expected due to invalid IV.
@ -60,8 +68,9 @@ class Pkcs11ChaCha20Poly1305Test
// Decrypt.
unsigned int decryptedLen = 0;
std::vector<uint8_t> decrypted(data_len);
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), output.data(), outputLen);
rv =
PK11_Decrypt(key.get(), kMech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), output.data(), outputLen);
EXPECT_EQ(rv, SECSuccess);
// Check the plaintext.
@ -73,8 +82,9 @@ class Pkcs11ChaCha20Poly1305Test
if (outputLen != 0) {
std::vector<uint8_t> bogusCiphertext(output);
bogusCiphertext[0] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), bogusCiphertext.data(), outputLen);
rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
&decryptedLen, decrypted.size(), bogusCiphertext.data(),
outputLen);
EXPECT_NE(rv, SECSuccess);
}
@ -83,8 +93,9 @@ class Pkcs11ChaCha20Poly1305Test
if (outputLen != 0) {
std::vector<uint8_t> bogusTag(output);
bogusTag[outputLen - 1] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), bogusTag.data(), outputLen);
rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
&decryptedLen, decrypted.size(), bogusTag.data(),
outputLen);
EXPECT_NE(rv, SECSuccess);
}
@ -100,7 +111,7 @@ class Pkcs11ChaCha20Poly1305Test
bogusAeadParams.pNonce = toUcharPtr(bogusIV.data());
bogusIV[0] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &bogusParams, decrypted.data(),
rv = PK11_Decrypt(key.get(), kMech, &bogusParams, decrypted.data(),
&decryptedLen, data_len, output.data(), outputLen);
EXPECT_NE(rv, SECSuccess);
}
@ -117,7 +128,7 @@ class Pkcs11ChaCha20Poly1305Test
bogusAeadParams.pAAD = toUcharPtr(bogusAAD.data());
bogusAAD[0] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &bogusParams, decrypted.data(),
rv = PK11_Decrypt(key.get(), kMech, &bogusParams, decrypted.data(),
&decryptedLen, data_len, output.data(), outputLen);
EXPECT_NE(rv, SECSuccess);
}
@ -125,16 +136,16 @@ class Pkcs11ChaCha20Poly1305Test
void EncryptDecrypt(const chacha_testvector testvector) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
SECItem keyItem = {siBuffer, toUcharPtr(testvector.Key.data()),
static_cast<unsigned int>(testvector.Key.size())};
SECItem key_item = {siBuffer, toUcharPtr(testvector.Key.data()),
static_cast<unsigned int>(testvector.Key.size())};
// Import key.
ScopedPK11SymKey symKey(PK11_ImportSymKey(
slot.get(), mech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr));
EXPECT_TRUE(!!symKey);
ScopedPK11SymKey key(PK11_ImportSymKey(slot.get(), kMech, PK11_OriginUnwrap,
CKA_ENCRYPT, &key_item, nullptr));
EXPECT_TRUE(!!key);
// Check.
EncryptDecrypt(symKey.get(), testvector.invalid_iv, testvector.invalid_tag,
EncryptDecrypt(key, testvector.invalid_iv, testvector.invalid_tag,
testvector.Data.data(), testvector.Data.size(),
testvector.AAD.data(), testvector.AAD.size(),
testvector.IV.data(), testvector.IV.size(),
@ -142,14 +153,13 @@ class Pkcs11ChaCha20Poly1305Test
}
protected:
CK_MECHANISM_TYPE mech = CKM_NSS_CHACHA20_POLY1305;
};
TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateEncryptDecrypt) {
// Generate a random key.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ScopedPK11SymKey symKey(PK11_KeyGen(slot.get(), mech, nullptr, 32, nullptr));
EXPECT_TRUE(!!symKey);
ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
EXPECT_TRUE(!!key);
// Generate random data.
std::vector<uint8_t> data(512);
@ -168,8 +178,85 @@ TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateEncryptDecrypt) {
EXPECT_EQ(rv, SECSuccess);
// Check.
EncryptDecrypt(symKey.get(), false, false, data.data(), data.size(),
aad.data(), aad.size(), iv.data(), iv.size());
EncryptDecrypt(key, false, false, data.data(), data.size(), aad.data(),
aad.size(), iv.data(), iv.size());
}
TEST_F(Pkcs11ChaCha20Poly1305Test, Xor) {
static const uint8_t kExpected[sizeof(kData)] = {
0xd8, 0x15, 0xd3, 0xb3, 0xe9, 0x34, 0x3b, 0x7a,
0x24, 0xf6, 0x5f, 0xd7, 0x95, 0x3d, 0xd3, 0x51};
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
SECItem keyItem = {siBuffer, toUcharPtr(kKeyData),
static_cast<unsigned int>(sizeof(kKeyData))};
ScopedPK11SymKey key(PK11_ImportSymKey(
slot.get(), kMechXor, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr));
EXPECT_TRUE(!!key);
SECItem ctr_nonce_item = {siBuffer, toUcharPtr(kCtrNonce),
static_cast<unsigned int>(sizeof(kCtrNonce))};
uint8_t output[sizeof(kData)];
unsigned int output_len = 88; // This should be overwritten.
SECStatus rv =
PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(sizeof(kExpected), static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(kExpected, output, sizeof(kExpected)));
// Decrypting has the same effect.
rv = PK11_Decrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(sizeof(kData), static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(kExpected, output, sizeof(kExpected)));
// Operating in reverse too.
rv = PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kExpected, sizeof(kExpected));
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(sizeof(kExpected), static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(kData, output, sizeof(kData)));
}
// This test just ensures that a key can be generated for use with the XOR
// function. The result is random and therefore cannot be checked.
TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateXor) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
EXPECT_TRUE(!!key);
SECItem ctr_nonce_item = {siBuffer, toUcharPtr(kCtrNonce),
static_cast<unsigned int>(sizeof(kCtrNonce))};
uint8_t output[sizeof(kData)];
unsigned int output_len = 88; // This should be overwritten.
SECStatus rv =
PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(sizeof(kData), static_cast<size_t>(output_len));
}
TEST_F(Pkcs11ChaCha20Poly1305Test, XorInvalidParams) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
EXPECT_TRUE(!!key);
SECItem ctr_nonce_item = {siBuffer, toUcharPtr(kCtrNonce),
static_cast<unsigned int>(sizeof(kCtrNonce)) - 1};
uint8_t output[sizeof(kData)];
unsigned int output_len = 88;
SECStatus rv =
PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
EXPECT_EQ(SECFailure, rv);
ctr_nonce_item.data = nullptr;
rv = PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
EXPECT_EQ(SECFailure, rv);
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
}
TEST_P(Pkcs11ChaCha20Poly1305Test, TestVectors) { EncryptDecrypt(GetParam()); }

View file

@ -40,6 +40,9 @@ class Pkcs11Curve25519Test
ScopedCERTSubjectPublicKeyInfo certSpki(
SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem));
if (!expect_success && !certSpki) {
return;
}
ASSERT_TRUE(certSpki);
ScopedSECKEYPublicKey pubKey(SECKEY_ExtractPublicKey(certSpki.get()));

View file

@ -29,20 +29,20 @@
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
],
'conditions': [
[ 'test_build==1', {
[ 'static_libs==1', {
'dependencies': [
'<(DEPTH)/lib/base/base.gyp:nssb',
'<(DEPTH)/lib/certdb/certdb.gyp:certdb',
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
'<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
'<(DEPTH)/lib/nss/nss.gyp:nss_static',
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
'<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
'<(DEPTH)/lib/certdb/certdb.gyp:certdb',
'<(DEPTH)/lib/base/base.gyp:nssb',
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
'<(DEPTH)/lib/pki/pki.gyp:nsspki',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl',
],

View file

@ -48,8 +48,15 @@ class Pk11KeyImportTestBase : public ::testing::Test {
ScopedSECKEYEncryptedPrivateKeyInfo key_info;
ScopedSECItem public_value;
GenerateAndExport(&key_type, &key_info, &public_value);
ASSERT_NE(nullptr, key_info);
ASSERT_NE(nullptr, public_value);
// Note: NSS is currently unable export wrapped DH keys, so this doesn't
// test
// CKM_DH_PKCS_KEY_PAIR_GEN beyond generate and verify
if (key_type == dhKey) {
return;
}
ASSERT_NE(nullptr, key_info);
// Now import the encrypted key.
static const uint8_t nick[] = "nick";
@ -78,17 +85,41 @@ class Pk11KeyImportTestBase : public ::testing::Test {
CK_MECHANISM_TYPE mech_;
private:
SECItem GetPublicComponent(ScopedSECKEYPublicKey& pub_key) {
SECItem null = {siBuffer, NULL, 0};
switch (SECKEY_GetPublicKeyType(pub_key.get())) {
case rsaKey:
case rsaPssKey:
case rsaOaepKey:
return pub_key->u.rsa.modulus;
case keaKey:
return pub_key->u.kea.publicValue;
case dsaKey:
return pub_key->u.dsa.publicValue;
case dhKey:
return pub_key->u.dh.publicValue;
case ecKey:
return pub_key->u.ec.publicValue;
case fortezzaKey: /* depricated */
case nullKey:
/* didn't use default here so we can catch new key types at compile time
*/
break;
}
return null;
}
void CheckForPublicKey(const ScopedSECKEYPrivateKey& priv_key,
const SECItem* expected_public) {
// Verify the public key exists.
StackSECItem priv_id;
KeyType type = SECKEY_GetPrivateKeyType(priv_key.get());
SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, priv_key.get(),
CKA_ID, &priv_id);
ASSERT_EQ(SECSuccess, rv) << "Couldn't read CKA_ID from private key: "
<< PORT_ErrorToName(PORT_GetError());
CK_ATTRIBUTE_TYPE value_type = CKA_VALUE;
switch (SECKEY_GetPrivateKeyType(priv_key.get())) {
switch (type) {
case rsaKey:
value_type = CKA_MODULUS;
break;
@ -106,6 +137,8 @@ class Pk11KeyImportTestBase : public ::testing::Test {
FAIL() << "unknown key type";
}
// Scan public key objects until we find one with the same CKA_ID as
// priv_key
std::unique_ptr<PK11GenericObject, PK11GenericObjectsDeleter> objs(
PK11_FindGenericObjects(slot_.get(), CKO_PUBLIC_KEY));
ASSERT_NE(nullptr, objs);
@ -128,20 +161,44 @@ class Pk11KeyImportTestBase : public ::testing::Test {
ASSERT_EQ(1U, token.len);
ASSERT_NE(0, token.data[0]);
StackSECItem value;
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &value);
StackSECItem raw_value;
SECItem decoded_value;
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &raw_value);
ASSERT_EQ(SECSuccess, rv);
SECItem value = raw_value;
// Decode the EC_POINT and check the output against expected.
// CKA_EC_POINT isn't stable, see Bug 1520649.
ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
ASSERT_TRUE(arena);
if (value_type == CKA_EC_POINT) {
continue;
// If this fails due to the noted inconsistency, we may need to
// check the whole raw_value, or remove a leading UNCOMPRESSED_POINT tag
rv = SEC_QuickDERDecodeItem(arena.get(), &decoded_value,
SEC_ASN1_GET(SEC_OctetStringTemplate),
&raw_value);
ASSERT_EQ(SECSuccess, rv);
value = decoded_value;
}
ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &value))
<< "expected: "
<< DataBuffer(expected_public->data, expected_public->len)
<< std::endl
<< "actual: " << DataBuffer(value.data, value.len) << std::endl;
// Finally, convert the private to public and ensure it matches.
ScopedSECKEYPublicKey pub_key(SECKEY_ConvertToPublicKey(priv_key.get()));
ASSERT_TRUE(pub_key);
SECItem converted_public = GetPublicComponent(pub_key);
ASSERT_TRUE(converted_public.len != 0);
ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &converted_public))
<< "expected: "
<< DataBuffer(expected_public->data, expected_public->len)
<< std::endl
<< "actual: "
<< DataBuffer(converted_public.data, converted_public.len)
<< std::endl;
}
}
@ -160,13 +217,6 @@ class Pk11KeyImportTestBase : public ::testing::Test {
ScopedSECKEYPublicKey pub_key(pub_tmp);
ASSERT_NE(nullptr, pub_key);
// Wrap and export the key.
ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
slot_.get(), SEC_OID_AES_256_CBC, password_.get(), priv_key.get(), 1,
nullptr));
ASSERT_NE(nullptr, epki) << "PK11_ExportEncryptedPrivKeyInfo failed: "
<< PORT_ErrorToName(PORT_GetError());
// Save the public value, which we will need on import */
SECItem* pub_val;
KeyType t = SECKEY_GetPublicKeyType(pub_key.get());
@ -190,8 +240,22 @@ class Pk11KeyImportTestBase : public ::testing::Test {
CheckForPublicKey(priv_key, pub_val);
*key_type = t;
key_info->swap(epki);
public_value->reset(SECITEM_DupItem(pub_val));
// Note: NSS is currently unable export wrapped DH keys, so this doesn't
// test
// CKM_DH_PKCS_KEY_PAIR_GEN beyond generate and verify
if (mech_ == CKM_DH_PKCS_KEY_PAIR_GEN) {
return;
}
// Wrap and export the key.
ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
slot_.get(), SEC_OID_AES_256_CBC, password_.get(), priv_key.get(), 1,
nullptr));
ASSERT_NE(nullptr, epki) << "PK11_ExportEncryptedPrivKeyInfo failed: "
<< PORT_ErrorToName(PORT_GetError());
key_info->swap(epki);
}
ScopedPK11SlotInfo slot_;
@ -281,9 +345,8 @@ TEST_P(Pk11KeyImportTest, GenerateExportImport) { Test(); }
INSTANTIATE_TEST_CASE_P(Pk11KeyImportTest, Pk11KeyImportTest,
::testing::Values(CKM_RSA_PKCS_KEY_PAIR_GEN,
CKM_DSA_KEY_PAIR_GEN));
// Note: NSS is currently unable export wrapped DH keys, so this doesn't test
// CKM_DH_PKCS_KEY_PAIR_GEN.
CKM_DSA_KEY_PAIR_GEN,
CKM_DH_PKCS_KEY_PAIR_GEN));
class Pk11KeyImportTestEC : public Pk11KeyImportTestBase,
public ::testing::WithParamInterface<SECOidTag> {