summaryrefslogtreecommitdiff
path: root/gtests/pk11_gtest
diff options
context:
space:
mode:
Diffstat (limited to 'gtests/pk11_gtest')
-rw-r--r--gtests/pk11_gtest/pk11_import_unittest.cc97
1 files changed, 80 insertions, 17 deletions
diff --git a/gtests/pk11_gtest/pk11_import_unittest.cc b/gtests/pk11_gtest/pk11_import_unittest.cc
index a155bbd73..5ffa92e64 100644
--- a/gtests/pk11_gtest/pk11_import_unittest.cc
+++ b/gtests/pk11_gtest/pk11_import_unittest.cc
@@ -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> {