diff options
author | Kevin Jacobs <kjacobs@mozilla.com> | 2020-01-16 21:42:56 +0000 |
---|---|---|
committer | Kevin Jacobs <kjacobs@mozilla.com> | 2020-01-16 21:42:56 +0000 |
commit | 1d9fba9af57f097e333fcda14b0f207030972609 (patch) | |
tree | bbdf5736d5c293f71c9143b529eadee65b9b957a /gtests/pk11_gtest | |
parent | ec4c67acc49349c622d09d05c36c7ecda4c85e3c (diff) | |
download | nss-hg-1d9fba9af57f097e333fcda14b0f207030972609.tar.gz |
Bug 1604596 - Update Wycheproof vectors and add support for CBC, P256-ECDH, and CMAC tests r=franziskus
This patch updates to the latest Wycheproof vectors and adds Wycheproof support for CBC, CMAC, and P256-ECDH:
ChaCha20: +141 tests
Curve25519: +431 tests
GCM: +39 tests
CBC (new): +183 tests
CMAC (new): +308 tests
P256 ECDH (new): +460 tests
Differential Revision: https://phabricator.services.mozilla.com/D57477
Diffstat (limited to 'gtests/pk11_gtest')
-rw-r--r-- | gtests/pk11_gtest/manifest.mn | 1 | ||||
-rw-r--r-- | gtests/pk11_gtest/pk11_aes_cmac_unittest.cc | 43 | ||||
-rw-r--r-- | gtests/pk11_gtest/pk11_aes_gcm_unittest.cc | 22 | ||||
-rw-r--r-- | gtests/pk11_gtest/pk11_cbc_unittest.cc | 52 | ||||
-rw-r--r-- | gtests/pk11_gtest/pk11_chacha20poly1305_unittest.cc | 18 | ||||
-rw-r--r-- | gtests/pk11_gtest/pk11_curve25519_unittest.cc | 4 | ||||
-rw-r--r-- | gtests/pk11_gtest/pk11_ecdh_unittest.cc | 80 | ||||
-rw-r--r-- | gtests/pk11_gtest/pk11_gtest.gyp | 1 |
8 files changed, 195 insertions, 26 deletions
diff --git a/gtests/pk11_gtest/manifest.mn b/gtests/pk11_gtest/manifest.mn index 4bf73a699..d655bb4bf 100644 --- a/gtests/pk11_gtest/manifest.mn +++ b/gtests/pk11_gtest/manifest.mn @@ -16,6 +16,7 @@ CPPSRCS = \ pk11_der_private_key_import_unittest.cc \ pk11_des_unittest.cc \ pk11_ecdsa_unittest.cc \ + pk11_ecdh_unittest.cc \ pk11_encrypt_derive_unittest.cc \ pk11_export_unittest.cc \ pk11_find_certs_unittest.cc \ diff --git a/gtests/pk11_gtest/pk11_aes_cmac_unittest.cc b/gtests/pk11_gtest/pk11_aes_cmac_unittest.cc index c520fffd1..45e4cac1a 100644 --- a/gtests/pk11_gtest/pk11_aes_cmac_unittest.cc +++ b/gtests/pk11_gtest/pk11_aes_cmac_unittest.cc @@ -14,11 +14,12 @@ #include "gtest/gtest.h" #include "nss_scoped_ptrs.h" +#include "testvectors/cmac-vectors.h" #include "util.h" namespace nss_test { -class Pkcs11AesCmacTest : public ::testing::Test { +class Pkcs11AesCmacTest : public ::testing::TestWithParam<AesCmacTestVector> { protected: ScopedPK11SymKey ImportKey(CK_MECHANISM_TYPE mech, SECItem *key_item) { ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); @@ -54,8 +55,46 @@ class Pkcs11AesCmacTest : public ::testing::Test { ASSERT_EQ(SECSuccess, ret); ASSERT_EQ(0, SECITEM_CompareItem(&output_item, &expected_item)); } + + void RunTestVector(const AesCmacTestVector vec) { + bool valid = !vec.invalid; + std::string err = "Test #" + std::to_string(vec.id) + " failed"; + std::vector<uint8_t> key = hex_string_to_bytes(vec.key); + std::vector<uint8_t> tag = hex_string_to_bytes(vec.tag); + std::vector<uint8_t> msg = hex_string_to_bytes(vec.msg); + + std::vector<uint8_t> output(AES_BLOCK_SIZE); + // Don't provide a null pointer, even if the input is empty. + uint8_t tmp; + SECItem key_item = {siBuffer, key.data() ? key.data() : &tmp, + static_cast<unsigned int>(key.size())}; + SECItem tag_item = {siBuffer, tag.data() ? tag.data() : &tmp, + static_cast<unsigned int>(tag.size())}; + SECItem msg_item = {siBuffer, msg.data() ? msg.data() : &tmp, + static_cast<unsigned int>(msg.size())}; + SECItem out_item = {siBuffer, output.data() ? output.data() : &tmp, + static_cast<unsigned int>(output.size())}; + + ScopedPK11SymKey p11_key = ImportKey(CKM_AES_CMAC_GENERAL, &key_item); + if (vec.comment == "invalid key size") { + ASSERT_EQ(nullptr, p11_key.get()) << err; + return; + } + + ASSERT_NE(nullptr, p11_key.get()) << err; + SECStatus rv = PK11_SignWithSymKey(p11_key.get(), CKM_AES_CMAC, NULL, + &out_item, &msg_item); + + EXPECT_EQ(SECSuccess, rv) << err; + EXPECT_EQ(valid, 0 == SECITEM_CompareItem(&out_item, &tag_item)) << err; + } }; +TEST_P(Pkcs11AesCmacTest, TestVectors) { RunTestVector(GetParam()); } + +INSTANTIATE_TEST_CASE_P(WycheproofTestVector, Pkcs11AesCmacTest, + ::testing::ValuesIn(kCmacWycheproofVectors)); + // Sanity check of the PKCS #11 API only. Extensive tests for correctness of // underling CMAC implementation conducted in the following file: // gtests/freebl_gtest/cmac_unittests.cc @@ -88,4 +127,4 @@ TEST_F(Pkcs11AesCmacTest, InvalidKeySize) { ScopedPK11SymKey result = ImportKey(CKM_AES_CMAC, &key_item); ASSERT_EQ(nullptr, result.get()); } -} +} // namespace nss_test diff --git a/gtests/pk11_gtest/pk11_aes_gcm_unittest.cc b/gtests/pk11_gtest/pk11_aes_gcm_unittest.cc index 2c58063d4..94736c695 100644 --- a/gtests/pk11_gtest/pk11_aes_gcm_unittest.cc +++ b/gtests/pk11_gtest/pk11_aes_gcm_unittest.cc @@ -18,19 +18,17 @@ namespace nss_test { -class Pkcs11AesGcmTest : public ::testing::TestWithParam<gcm_kat_value> { +class Pkcs11AesGcmTest : public ::testing::TestWithParam<AesGcmKatValue> { protected: - void RunTest(const gcm_kat_value val) { - std::vector<uint8_t> key = hex_string_to_bytes(val.key); - std::vector<uint8_t> iv = hex_string_to_bytes(val.iv); - std::vector<uint8_t> plaintext = hex_string_to_bytes(val.plaintext); - std::vector<uint8_t> aad = hex_string_to_bytes(val.additional_data); - std::vector<uint8_t> result = hex_string_to_bytes(val.result); - bool invalid_ct = val.invalid_ct; - bool invalid_iv = val.invalid_iv; - std::stringstream s; - s << "Test #" << val.test_id << " failed."; - std::string msg = s.str(); + void RunTest(const AesGcmKatValue vec) { + std::vector<uint8_t> key = hex_string_to_bytes(vec.key); + std::vector<uint8_t> iv = hex_string_to_bytes(vec.iv); + std::vector<uint8_t> plaintext = hex_string_to_bytes(vec.plaintext); + std::vector<uint8_t> aad = hex_string_to_bytes(vec.additional_data); + std::vector<uint8_t> result = hex_string_to_bytes(vec.result); + bool invalid_ct = vec.invalid_ct; + bool invalid_iv = vec.invalid_iv; + std::string msg = "Test #" + std::to_string(vec.id) + " failed"; // Ignore GHASH-only vectors. if (key.empty()) { return; diff --git a/gtests/pk11_gtest/pk11_cbc_unittest.cc b/gtests/pk11_gtest/pk11_cbc_unittest.cc index ecc705ad4..43b267cea 100644 --- a/gtests/pk11_gtest/pk11_cbc_unittest.cc +++ b/gtests/pk11_gtest/pk11_cbc_unittest.cc @@ -9,8 +9,10 @@ #include "pk11pub.h" #include "secerr.h" -#include "nss_scoped_ptrs.h" #include "gtest/gtest.h" +#include "nss_scoped_ptrs.h" +#include "testvectors/cbc-vectors.h" +#include "util.h" namespace nss_test { @@ -555,4 +557,52 @@ INSTANTIATE_TEST_CASE_P(EncryptDecrypt, Pkcs11CbcPadTest, ::testing::Values(CKM_AES_CBC_PAD, CKM_AES_CBC, CKM_DES3_CBC_PAD, CKM_DES3_CBC)); +class Pkcs11AesCbcWycheproofTest + : public ::testing::TestWithParam<AesCbcTestVector> { + protected: + void RunTest(const AesCbcTestVector vec) { + bool valid = vec.valid; + std::string err = "Test #" + std::to_string(vec.id) + " failed"; + std::vector<uint8_t> key = hex_string_to_bytes(vec.key); + std::vector<uint8_t> iv = hex_string_to_bytes(vec.iv); + std::vector<uint8_t> ciphertext = hex_string_to_bytes(vec.ciphertext); + std::vector<uint8_t> msg = hex_string_to_bytes(vec.msg); + std::vector<uint8_t> decrypted(vec.ciphertext.size()); + unsigned int decrypted_len = 0; + + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + ASSERT_NE(nullptr, slot); + + // Don't provide a null pointer, even if the length is 0. We don't want to + // fail on trivial checks. + uint8_t tmp; + SECItem iv_item = {siBuffer, iv.data() ? iv.data() : &tmp, + static_cast<unsigned int>(iv.size())}; + SECItem key_item = {siBuffer, key.data() ? key.data() : &tmp, + static_cast<unsigned int>(key.size())}; + + PK11SymKey* pKey = PK11_ImportSymKey(slot.get(), kMech, PK11_OriginUnwrap, + CKA_ENCRYPT, &key_item, nullptr); + ASSERT_NE(nullptr, pKey); + ScopedPK11SymKey spKey = ScopedPK11SymKey(pKey); + + SECStatus rv = PK11_Decrypt(spKey.get(), kMech, &iv_item, decrypted.data(), + &decrypted_len, decrypted.size(), + ciphertext.data(), ciphertext.size()); + + ASSERT_EQ(valid ? SECSuccess : SECFailure, rv) << err; + if (valid) { + EXPECT_EQ(msg.size(), static_cast<size_t>(decrypted_len)) << err; + EXPECT_EQ(0, memcmp(msg.data(), decrypted.data(), decrypted_len)) << err; + } + } + + const CK_MECHANISM_TYPE kMech = CKM_AES_CBC_PAD; +}; + +TEST_P(Pkcs11AesCbcWycheproofTest, TestVectors) { RunTest(GetParam()); } + +INSTANTIATE_TEST_CASE_P(WycheproofTestVector, Pkcs11AesCbcWycheproofTest, + ::testing::ValuesIn(kCbcWycheproofVectors)); + } // namespace nss_test diff --git a/gtests/pk11_gtest/pk11_chacha20poly1305_unittest.cc b/gtests/pk11_gtest/pk11_chacha20poly1305_unittest.cc index 10cc2a8c6..26634411c 100644 --- a/gtests/pk11_gtest/pk11_chacha20poly1305_unittest.cc +++ b/gtests/pk11_gtest/pk11_chacha20poly1305_unittest.cc @@ -26,7 +26,7 @@ static const uint8_t kCtrNonce[16] = {'c', 0, 0, 0, 'n'}; static const uint8_t kData[16] = {'d'}; class Pkcs11ChaCha20Poly1305Test - : public ::testing::TestWithParam<chaChaTestVector> { + : public ::testing::TestWithParam<ChaChaTestVector> { public: void EncryptDecrypt(const ScopedPK11SymKey& key, const bool invalid_iv, const bool invalid_tag, const uint8_t* data, @@ -168,10 +168,10 @@ class Pkcs11ChaCha20Poly1305Test } } - void EncryptDecrypt(const chaChaTestVector testvector) { + void EncryptDecrypt(const ChaChaTestVector testvector) { ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); - SECItem keyItem = {siBuffer, toUcharPtr(testvector.Key.data()), - static_cast<unsigned int>(testvector.Key.size())}; + SECItem keyItem = {siBuffer, toUcharPtr(testvector.key.data()), + static_cast<unsigned int>(testvector.key.size())}; // Import key. ScopedPK11SymKey key(PK11_ImportSymKey(slot.get(), kMech, PK11_OriginUnwrap, @@ -179,11 +179,11 @@ class Pkcs11ChaCha20Poly1305Test EXPECT_TRUE(!!key); // Check. - EncryptDecrypt(key, testvector.invalidIV, testvector.invalidTag, - testvector.Data.data(), testvector.Data.size(), - testvector.AAD.data(), testvector.AAD.size(), - testvector.IV.data(), testvector.IV.size(), - testvector.CT.data(), testvector.CT.size()); + EncryptDecrypt(key, testvector.invalid_iv, testvector.invalid_tag, + testvector.plaintext.data(), testvector.plaintext.size(), + testvector.aad.data(), testvector.aad.size(), + testvector.iv.data(), testvector.iv.size(), + testvector.ciphertext.data(), testvector.ciphertext.size()); } protected: diff --git a/gtests/pk11_gtest/pk11_curve25519_unittest.cc b/gtests/pk11_gtest/pk11_curve25519_unittest.cc index 647e3a706..b26e5d41e 100644 --- a/gtests/pk11_gtest/pk11_curve25519_unittest.cc +++ b/gtests/pk11_gtest/pk11_curve25519_unittest.cc @@ -15,7 +15,7 @@ namespace nss_test { class Pkcs11Curve25519Test - : public ::testing::TestWithParam<curve25519_testvector> { + : public ::testing::TestWithParam<EcdhTestVectorStr> { protected: void Derive(const uint8_t* pkcs8, size_t pkcs8_len, const uint8_t* spki, size_t spki_len, const uint8_t* secret, size_t secret_len, @@ -107,7 +107,7 @@ class Pkcs11Curve25519Test } }; - void Derive(const curve25519_testvector testvector) { + void Derive(const EcdhTestVectorStr testvector) { Derive(testvector.private_key.data(), testvector.private_key.size(), testvector.public_key.data(), testvector.public_key.size(), testvector.secret.data(), testvector.secret.size(), diff --git a/gtests/pk11_gtest/pk11_ecdh_unittest.cc b/gtests/pk11_gtest/pk11_ecdh_unittest.cc new file mode 100644 index 000000000..b6be1972f --- /dev/null +++ b/gtests/pk11_gtest/pk11_ecdh_unittest.cc @@ -0,0 +1,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 "cpputil.h" +#include "nss_scoped_ptrs.h" + +#include "testvectors/p256ecdh-vectors.h" +#include "gtest/gtest.h" + +namespace nss_test { + +class Pkcs11P256EcdhTest : public ::testing::TestWithParam<EcdhTestVector> { + protected: + void Derive(const EcdhTestVector vec) { + std::string err = "Test #" + std::to_string(vec.id) + " failed"; + + SECItem expect_item = {siBuffer, toUcharPtr(vec.secret.data()), + static_cast<unsigned int>(vec.secret.size())}; + + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + ASSERT_TRUE(slot); + + SECItem priv_item = {siBuffer, toUcharPtr(vec.private_key.data()), + static_cast<unsigned int>(vec.private_key.size())}; + SECKEYPrivateKey* key = nullptr; + SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( + slot.get(), &priv_item, nullptr, nullptr, false, false, KU_ALL, &key, + nullptr); + EXPECT_EQ(SECSuccess, rv) << err; + + ScopedSECKEYPrivateKey priv_key(key); + ASSERT_TRUE(priv_key) << err; + + SECItem spki_item = {siBuffer, toUcharPtr(vec.public_key.data()), + static_cast<unsigned int>(vec.public_key.size())}; + + ScopedCERTSubjectPublicKeyInfo cert_spki( + SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); + if (vec.valid) { + ASSERT_TRUE(!!cert_spki) << err; + } else if (!cert_spki) { + ASSERT_TRUE(vec.invalid_asn) << err; + return; + } + + ScopedSECKEYPublicKey pub_key(SECKEY_ExtractPublicKey(cert_spki.get())); + if (vec.valid) { + ASSERT_TRUE(!!pub_key) << err; + } else if (!pub_key) { + ASSERT_FALSE(vec.valid) << err; + return; + } + + ScopedPK11SymKey sym_key( + PK11_PubDeriveWithKDF(priv_key.get(), pub_key.get(), false, nullptr, + nullptr, CKM_ECDH1_DERIVE, CKM_SHA512_HMAC, + CKA_DERIVE, 0, CKD_NULL, nullptr, nullptr)); + ASSERT_EQ(vec.valid, !!sym_key) << err; + + if (vec.valid) { + rv = PK11_ExtractKeyValue(sym_key.get()); + EXPECT_EQ(SECSuccess, rv) << err; + + SECItem* derived_key = PK11_GetKeyData(sym_key.get()); + EXPECT_EQ(0, SECITEM_CompareItem(derived_key, &expect_item)) << err; + } + }; +}; + +TEST_P(Pkcs11P256EcdhTest, TestVectors) { Derive(GetParam()); } + +INSTANTIATE_TEST_CASE_P(WycheproofP256EcdhTest, Pkcs11P256EcdhTest, + ::testing::ValuesIn(kP256EcdhWycheproofVectors)); + +} // namespace nss_test diff --git a/gtests/pk11_gtest/pk11_gtest.gyp b/gtests/pk11_gtest/pk11_gtest.gyp index 58ea31cf6..c746ac650 100644 --- a/gtests/pk11_gtest/pk11_gtest.gyp +++ b/gtests/pk11_gtest/pk11_gtest.gyp @@ -22,6 +22,7 @@ 'pk11_der_private_key_import_unittest.cc', 'pk11_des_unittest.cc', 'pk11_ecdsa_unittest.cc', + 'pk11_ecdh_unittest.cc', 'pk11_encrypt_derive_unittest.cc', 'pk11_find_certs_unittest.cc', 'pk11_hkdf_unittest.cc', |