From 3db1df97ea9e0a12a904f675037dc88c2b057adc Mon Sep 17 00:00:00 2001 From: tholenst <tholenst@google.com> Date: Wed, 4 Sep 2019 07:48:31 -0700 Subject: [PATCH] Migrate the tests for the RsaSsaPkcs1{Sign,Verify}KeyManager to directly operate on the KeyTypeManager interface. PiperOrigin-RevId: 267151372 --- cc/signature/BUILD.bazel | 22 +- cc/signature/CMakeLists.txt | 22 +- .../rsa_ssa_pkcs1_sign_key_manager_test.cc | 457 +++++++----------- .../rsa_ssa_pkcs1_verify_key_manager_test.cc | 303 ++++++------ 4 files changed, 333 insertions(+), 471 deletions(-) diff --git a/cc/signature/BUILD.bazel b/cc/signature/BUILD.bazel index 5f8d288be..9de97d38c 100644 --- a/cc/signature/BUILD.bazel +++ b/cc/signature/BUILD.bazel @@ -473,17 +473,19 @@ cc_test( srcs = ["rsa_ssa_pkcs1_verify_key_manager_test.cc"], copts = ["-Iexternal/gtest/include"], deps = [ + ":rsa_ssa_pkcs1_sign_key_manager", ":rsa_ssa_pkcs1_verify_key_manager", - "//cc:config", "//cc:public_key_sign", "//cc:public_key_verify", - "//cc:registry", + "//cc/subtle:rsa_ssa_pkcs1_sign_boringssl", + "//cc/subtle:subtle_util_boringssl", "//cc/util:status", + "//cc/util:statusor", + "//cc/util:test_matchers", "//cc/util:test_util", - "//proto:aes_eax_cc_proto", - "//proto:common_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", + "@boringssl//:crypto", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], @@ -563,20 +565,18 @@ cc_test( deps = [ ":rsa_ssa_pkcs1_sign_key_manager", ":rsa_ssa_pkcs1_verify_key_manager", - ":signature_key_templates", - "//cc:config", "//cc:public_key_sign", - "//cc:registry", - "//cc/aead:aead_key_templates", - "//cc/aead:aes_gcm_key_manager", + "//cc:public_key_verify", + "//cc/subtle:rsa_ssa_pkcs1_verify_boringssl", "//cc/subtle:subtle_util_boringssl", "//cc/util:status", + "//cc/util:statusor", + "//cc/util:test_matchers", "//cc/util:test_util", - "//proto:aes_eax_cc_proto", - "//proto:common_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "@boringssl//:crypto", + "@com_google_absl//absl/container:flat_hash_set", "@com_google_googletest//:gtest_main", ], ) diff --git a/cc/signature/CMakeLists.txt b/cc/signature/CMakeLists.txt index c07985fe6..87b499b97 100644 --- a/cc/signature/CMakeLists.txt +++ b/cc/signature/CMakeLists.txt @@ -411,18 +411,19 @@ tink_cc_test( NAME rsa_ssa_pkcs1_verify_key_manager_test SRCS rsa_ssa_pkcs1_verify_key_manager_test.cc DEPS + tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager - tink::core::config tink::core::public_key_sign tink::core::public_key_verify - tink::core::registry tink::util::status + tink::util::statusor tink::util::test_util - tink::proto::aes_eax_cc_proto - tink::proto::common_cc_proto + tink::util::test_matchers tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto absl::strings + crypto + gmock ) tink_cc_test( @@ -489,20 +490,19 @@ tink_cc_test( DEPS tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager - tink::signature::signature_key_templates - tink::core::config tink::core::public_key_sign - tink::core::registry - tink::aead::aead_key_templates - tink::aead::aes_gcm_key_manager + tink::core::public_key_verify + tink::subtle::rsa_ssa_pkcs1_verify_boringssl tink::subtle::subtle_util_boringssl tink::util::status + tink::util::statusor + tink::util::test_matchers tink::util::test_util - tink::proto::aes_eax_cc_proto - tink::proto::common_cc_proto tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto crypto + gmock + absl::flat_hash_set ) tink_cc_test( diff --git a/cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc b/cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc index e5d5d4151..e7e53fb12 100644 --- a/cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc +++ b/cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc @@ -17,49 +17,109 @@ #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "gtest/gtest.h" -#include "tink/aead/aead_key_templates.h" -#include "tink/aead/aes_gcm_key_manager.h" -#include "tink/core/key_manager_impl.h" +#include "gmock/gmock.h" +#include "absl/container/flat_hash_set.h" +#include "openssl/rsa.h" #include "tink/public_key_sign.h" -#include "tink/registry.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" -#include "tink/signature/signature_key_templates.h" +#include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_util.h" -#include "proto/aes_eax.pb.h" -#include "proto/common.pb.h" +#include "tink/util/test_matchers.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" -namespace pb = google::crypto::tink; - namespace crypto { namespace tink { +namespace { -using google::crypto::tink::AesEaxKeyFormat; -using google::crypto::tink::KeyData; -using google::crypto::tink::RsaSsaPkcs1KeyFormat; -using google::crypto::tink::RsaSsaPkcs1PrivateKey; -using google::crypto::tink::RsaSsaPkcs1PublicKey; -using subtle::SubtleUtilBoringSSL; +using ::crypto::tink::subtle::SubtleUtilBoringSSL; +using ::crypto::tink::test::IsOk; +using ::crypto::tink::util::StatusOr; +using ::google::crypto::tink::HashType; +using ::google::crypto::tink::KeyData; +using ::google::crypto::tink::RsaSsaPkcs1KeyFormat; +using ::google::crypto::tink::RsaSsaPkcs1PrivateKey; +using ::google::crypto::tink::RsaSsaPkcs1PublicKey; +using ::testing::Eq; +using ::testing::Not; +using ::testing::SizeIs; + +TEST(RsaSsaPkcsSignKeyManagerTest, Basic) { + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().get_version(), Eq(0)); + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().key_material_type(), + Eq(KeyData::ASYMMETRIC_PRIVATE)); + EXPECT_THAT( + RsaSsaPkcs1SignKeyManager().get_key_type(), + Eq("type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey")); +} -namespace { +RsaSsaPkcs1KeyFormat CreateKeyFormat(HashType hash_type, + int modulus_size_in_bits, + int public_exponent) { + RsaSsaPkcs1KeyFormat key_format; + auto params = key_format.mutable_params(); + params->set_hash_type(hash_type); + key_format.set_modulus_size_in_bits(modulus_size_in_bits); + bssl::UniquePtr<BIGNUM> e(BN_new()); + BN_set_word(e.get(), public_exponent); + key_format.set_public_exponent( + subtle::SubtleUtilBoringSSL::bn2str(e.get(), BN_num_bytes(e.get())) + .ValueOrDie()); + return key_format; +} + +RsaSsaPkcs1KeyFormat ValidKeyFormat() { + return CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); +} + +TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormat) { + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(ValidKeyFormat()), + IsOk()); +} + +TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatSha384Disallowed) { + RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); + key_format.mutable_params()->set_hash_type(HashType::SHA384); + // TODO(b/140410067): Check if SHA384 should be allowed. + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), + Not(IsOk())); +} + +TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatSha512Allowed) { + RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); + key_format.mutable_params()->set_hash_type(HashType::SHA512); + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), + IsOk()); +} -class RsaSsaPkcs1SignKeyManagerTest : public ::testing::Test { - protected: - std::string key_type_prefix_ = "type.googleapis.com/"; - std::string rsa_ssa_pkcs1_sign_key_type_ = - "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey"; -}; +TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatSha1Disallowed) { + RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); + key_format.mutable_params()->set_hash_type(HashType::SHA1); + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), + Not(IsOk())); +} + +TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatUnkownHashDisallowed) { + RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); + key_format.mutable_params()->set_hash_type(HashType::UNKNOWN_HASH); + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), + Not(IsOk())); +} + +TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatSmallModulusDisallowed) { + RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); + key_format.set_modulus_size_in_bits(2047); + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), + Not(IsOk())); +} // Checks whether given key is compatible with the given format. void CheckNewKey(const RsaSsaPkcs1PrivateKey& private_key, const RsaSsaPkcs1KeyFormat& key_format) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); + RsaSsaPkcs1SignKeyManager key_manager; RsaSsaPkcs1PublicKey public_key = private_key.public_key(); EXPECT_EQ(0, private_key.version()); EXPECT_TRUE(private_key.has_public_key()); @@ -69,8 +129,6 @@ void CheckNewKey(const RsaSsaPkcs1PrivateKey& private_key, EXPECT_EQ(public_key.params().SerializeAsString(), key_format.params().SerializeAsString()); EXPECT_EQ(key_format.public_exponent(), public_key.e()); - auto primitive_result = key_manager->GetPrimitive(private_key); - EXPECT_TRUE(primitive_result.ok()) << primitive_result.status(); auto n = std::move(SubtleUtilBoringSSL::str2bn(public_key.n()).ValueOrDie()); auto d = std::move(SubtleUtilBoringSSL::str2bn(private_key.d()).ValueOrDie()); auto p = std::move(SubtleUtilBoringSSL::str2bn(private_key.p()).ValueOrDie()); @@ -83,300 +141,119 @@ void CheckNewKey(const RsaSsaPkcs1PrivateKey& private_key, // Check n = p * q. auto n_calc = bssl::UniquePtr<BIGNUM>(BN_new()); - ASSERT_TRUE(BN_mul(n_calc.get(), p.get(), q.get(), ctx.get())); - ASSERT_TRUE(BN_equal_consttime(n_calc.get(), n.get())); + EXPECT_TRUE(BN_mul(n_calc.get(), p.get(), q.get(), ctx.get())); + EXPECT_TRUE(BN_equal_consttime(n_calc.get(), n.get())); // Check n size >= modulus_size_in_bits bit. EXPECT_GE(BN_num_bits(n.get()), key_format.modulus_size_in_bits()); // dp = d mod (p - 1) auto pm1 = bssl::UniquePtr<BIGNUM>(BN_dup(p.get())); - ASSERT_TRUE(BN_sub_word(pm1.get(), 1)); + EXPECT_TRUE(BN_sub_word(pm1.get(), 1)); auto dp_calc = bssl::UniquePtr<BIGNUM>(BN_new()); - ASSERT_TRUE(BN_mod(dp_calc.get(), d.get(), pm1.get(), ctx.get())); - ASSERT_TRUE(BN_equal_consttime(dp_calc.get(), dp.get())); + EXPECT_TRUE(BN_mod(dp_calc.get(), d.get(), pm1.get(), ctx.get())); + EXPECT_TRUE(BN_equal_consttime(dp_calc.get(), dp.get())); // dq = d mod (q - 1) auto qm1 = bssl::UniquePtr<BIGNUM>(BN_dup(q.get())); - ASSERT_TRUE(BN_sub_word(qm1.get(), 1)); + EXPECT_TRUE(BN_sub_word(qm1.get(), 1)); auto dq_calc = bssl::UniquePtr<BIGNUM>(BN_new()); - ASSERT_TRUE(BN_mod(dq_calc.get(), d.get(), qm1.get(), ctx.get())); - - ASSERT_TRUE(BN_equal_consttime(dq_calc.get(), dq.get())); -} - -TEST_F(RsaSsaPkcs1SignKeyManagerTest, Basic) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); - EXPECT_EQ(0, key_manager->get_version()); - EXPECT_EQ("type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey", - key_manager->get_key_type()); - EXPECT_TRUE(key_manager->DoesSupport(key_manager->get_key_type())); -} + EXPECT_TRUE(BN_mod(dq_calc.get(), d.get(), qm1.get(), ctx.get())); -TEST_F(RsaSsaPkcs1SignKeyManagerTest, NewKeyFromKeyFormat) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); - const KeyFactory& key_factory = key_manager->get_key_factory(); - RsaSsaPkcs1KeyFormat key_format; - ASSERT_TRUE(key_format.ParseFromString( - SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4().value())); - auto result = key_factory.NewKey(key_format); - EXPECT_TRUE(result.ok()) << result.status(); - auto key = std::move(result.ValueOrDie()); - ASSERT_EQ(rsa_ssa_pkcs1_sign_key_type_, - key_type_prefix_ + key->GetTypeName()); - std::unique_ptr<RsaSsaPkcs1PrivateKey> rsa_key( - static_cast<RsaSsaPkcs1PrivateKey*>(key.release())); - CheckNewKey(*rsa_key, key_format); + EXPECT_TRUE(BN_equal_consttime(dq_calc.get(), dq.get())); } -TEST_F(RsaSsaPkcs1SignKeyManagerTest, NewKeyFromSerializedKeyFormat) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); - const KeyFactory& key_factory = key_manager->get_key_factory(); - RsaSsaPkcs1KeyFormat key_format; - ASSERT_TRUE(key_format.ParseFromString( - SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4().value())); - auto result = key_factory.NewKey(key_format.SerializeAsString()); - EXPECT_TRUE(result.ok()) << result.status(); - auto key = std::move(result.ValueOrDie()); - ASSERT_EQ(rsa_ssa_pkcs1_sign_key_type_, - key_type_prefix_ + key->GetTypeName()); - std::unique_ptr<RsaSsaPkcs1PrivateKey> rsa_key( - static_cast<RsaSsaPkcs1PrivateKey*>(key.release())); - CheckNewKey(*rsa_key, key_format); +TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKey) { + RsaSsaPkcs1KeyFormat key_format = + CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); + StatusOr<RsaSsaPkcs1PrivateKey> private_key_or = + RsaSsaPkcs1SignKeyManager().CreateKey(key_format); + ASSERT_THAT(private_key_or.status(), IsOk()); + CheckNewKey(private_key_or.ValueOrDie(), key_format); } -TEST_F(RsaSsaPkcs1SignKeyManagerTest, NewKeyDataFromSerializedKeyFormat) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); - const KeyFactory& key_factory = key_manager->get_key_factory(); - RsaSsaPkcs1KeyFormat key_format; - ASSERT_TRUE(key_format.ParseFromString( - SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4().value())); - auto result = key_factory.NewKeyData(key_format.SerializeAsString()); - EXPECT_TRUE(result.ok()) << result.status(); - auto key_data = std::move(result.ValueOrDie()); - ASSERT_EQ(rsa_ssa_pkcs1_sign_key_type_, key_data->type_url()); - RsaSsaPkcs1PrivateKey rsa_key; - ASSERT_TRUE(rsa_key.ParseFromString(key_data->value())); - CheckNewKey(rsa_key, key_format); -} +TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKeySmallKey) { + RsaSsaPkcs1KeyFormat key_format = + CreateKeyFormat(HashType::SHA256, 2048, RSA_F4); -TEST_F(RsaSsaPkcs1SignKeyManagerTest, PublicKeyExtraction) { - RsaSsaPkcs1SignKeyManager sign_key_type_manager; - RsaSsaPkcs1VerifyKeyManager verify_key_type_manager; - auto verify_key_manager = - internal::MakeKeyManager<PublicKeyVerify>(&verify_key_type_manager); - auto sign_key_manager = internal::MakePrivateKeyManager<PublicKeySign>( - &sign_key_type_manager, &verify_key_type_manager); - auto private_key_factory = dynamic_cast<const PrivateKeyFactory*>( - &(sign_key_manager->get_key_factory())); - ASSERT_NE(private_key_factory, nullptr); - auto new_key_result = private_key_factory->NewKey( - SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4().value()); - std::unique_ptr<RsaSsaPkcs1PrivateKey> private_key( - static_cast<RsaSsaPkcs1PrivateKey*>( - new_key_result.ValueOrDie().release())); - auto public_key_data_result = - private_key_factory->GetPublicKeyData(private_key->SerializeAsString()); - EXPECT_TRUE(public_key_data_result.ok()) << public_key_data_result.status(); - auto public_key_data = std::move(public_key_data_result.ValueOrDie()); - EXPECT_EQ(RsaSsaPkcs1VerifyKeyManager().get_key_type(), - public_key_data->type_url()); - EXPECT_EQ(KeyData::ASYMMETRIC_PUBLIC, public_key_data->key_material_type()); - EXPECT_EQ(private_key->public_key().SerializeAsString(), - public_key_data->value()); - // Sign with private key and verify with public key. - auto signer = sign_key_manager->GetPrimitive(*private_key); - auto verifier = verify_key_manager->GetPrimitive(*public_key_data); - std::string message = "Wycheproof"; - EXPECT_TRUE( - verifier.ValueOrDie() - ->Verify(signer.ValueOrDie()->Sign(message).ValueOrDie(), message) - .ok()); + StatusOr<RsaSsaPkcs1PrivateKey> private_key_or = + RsaSsaPkcs1SignKeyManager().CreateKey(key_format); + ASSERT_THAT(private_key_or.status(), IsOk()); + CheckNewKey(private_key_or.ValueOrDie(), key_format); } -TEST_F(RsaSsaPkcs1SignKeyManagerTest, NewKeyWithWeakSignatureHash) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); - const KeyFactory& key_factory = key_manager->get_key_factory(); - RsaSsaPkcs1KeyFormat key_format; - ASSERT_TRUE(key_format.ParseFromString( - SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4().value())); - key_format.mutable_params()->set_hash_type(pb::HashType::SHA1); - auto result = key_factory.NewKey(key_format.SerializeAsString()); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, - "SHA1 is not safe for digital signature", - result.status().error_message()); -} +TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKeyLargeKey) { + RsaSsaPkcs1KeyFormat key_format = + CreateKeyFormat(HashType::SHA512, 4096, RSA_F4); -TEST_F(RsaSsaPkcs1SignKeyManagerTest, NewKeyWithSmallModulus) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); - const KeyFactory& key_factory = key_manager->get_key_factory(); - RsaSsaPkcs1KeyFormat key_format; - ASSERT_TRUE(key_format.ParseFromString( - SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4().value())); - key_format.set_modulus_size_in_bits(512); - auto result = key_factory.NewKey(key_format.SerializeAsString()); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, - "only modulus size >= 2048-bit is supported", - result.status().error_message()); + StatusOr<RsaSsaPkcs1PrivateKey> private_key_or = + RsaSsaPkcs1SignKeyManager().CreateKey(key_format); + ASSERT_THAT(private_key_or.status(), IsOk()); + CheckNewKey(private_key_or.ValueOrDie(), key_format); } -TEST_F(RsaSsaPkcs1SignKeyManagerTest, GetPrimitiveWithWeakSignatureHash) { - RsaSsaPkcs1SignKeyManager sign_key_type_manager; - RsaSsaPkcs1VerifyKeyManager verify_key_type_manager; - auto verify_key_manager = - internal::MakeKeyManager<PublicKeyVerify>(&verify_key_type_manager); - auto sign_key_manager = internal::MakePrivateKeyManager<PublicKeySign>( - &sign_key_type_manager, &verify_key_type_manager); - auto private_key_factory = dynamic_cast<const PrivateKeyFactory*>( - &(sign_key_manager->get_key_factory())); - ASSERT_NE(private_key_factory, nullptr); - auto new_key_result = private_key_factory->NewKey( - SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4().value()); - std::unique_ptr<RsaSsaPkcs1PrivateKey> private_key( - static_cast<RsaSsaPkcs1PrivateKey*>( - new_key_result.ValueOrDie().release())); - private_key->mutable_public_key()->mutable_params()->set_hash_type( - pb::HashType::SHA1); - auto result = sign_key_manager->GetPrimitive(*private_key); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, - "SHA1 is not safe for digital signature", - result.status().error_message()); +TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKeyValid) { + StatusOr<RsaSsaPkcs1PrivateKey> key_or = + RsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()); + ASSERT_THAT(key_or.status(), IsOk()); + EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKey(key_or.ValueOrDie()), + IsOk()); } -TEST_F(RsaSsaPkcs1SignKeyManagerTest, GetPrimitiveWithSmallModulus) { - RsaSsaPkcs1SignKeyManager sign_key_type_manager; - RsaSsaPkcs1VerifyKeyManager verify_key_type_manager; - auto verify_key_manager = - internal::MakeKeyManager<PublicKeyVerify>(&verify_key_type_manager); - auto sign_key_manager = internal::MakePrivateKeyManager<PublicKeySign>( - &sign_key_type_manager, &verify_key_type_manager); - auto private_key_factory = dynamic_cast<const PrivateKeyFactory*>( - &(sign_key_manager->get_key_factory())); - ASSERT_NE(private_key_factory, nullptr); - auto new_key_result = private_key_factory->NewKey( - SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4().value()); - std::unique_ptr<RsaSsaPkcs1PrivateKey> private_key( - static_cast<RsaSsaPkcs1PrivateKey*>( - new_key_result.ValueOrDie().release())); - private_key->mutable_public_key()->set_n("\x23"); - private_key->mutable_public_key()->set_e("\x3"); - auto result = sign_key_manager->GetPrimitive(*private_key); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, - "only modulus size >= 2048-bit is supported", - result.status().error_message()); -} - -TEST_F(RsaSsaPkcs1SignKeyManagerTest, KeyDataErrors) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); - - { // Bad key type. - KeyData key_data; - std::string bad_key_type = "type.googleapis.com/google.crypto.tink.SomeOtherKey"; - key_data.set_type_url(bad_key_type); - auto result = key_manager->GetPrimitive(key_data); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported", - result.status().error_message()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, bad_key_type, - result.status().error_message()); - } - - { // Bad key value. - KeyData key_data; - key_data.set_type_url(rsa_ssa_pkcs1_sign_key_type_); - key_data.set_value("some bad serialized proto"); - auto result = key_manager->GetPrimitive(key_data); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "not parse", - result.status().error_message()); - } - - { // Bad version. - KeyData key_data; - RsaSsaPkcs1PrivateKey key; - key.set_version(1); - key_data.set_type_url(rsa_ssa_pkcs1_sign_key_type_); - key_data.set_value(key.SerializeAsString()); - auto result = key_manager->GetPrimitive(key_data); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "version", - result.status().error_message()); +// Check that in a bunch of CreateKey calls all generated primes are distinct. +TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKeyAlwaysNewRsaPair) { + absl::flat_hash_set<std::string> keys; + // This test takes about a second per key. + int num_generated_keys = 5; + for (int i = 0; i < num_generated_keys; ++i) { + StatusOr<RsaSsaPkcs1PrivateKey> key_or = + RsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()); + ASSERT_THAT(key_or.status(), IsOk()); + keys.insert(key_or.ValueOrDie().p()); + keys.insert(key_or.ValueOrDie().q()); } + EXPECT_THAT(keys, SizeIs(2 * num_generated_keys)); } -TEST_F(RsaSsaPkcs1SignKeyManagerTest, NewKeyErrors) { - RsaSsaPkcs1SignKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeySign>(&key_type_manager); - const KeyFactory& key_factory = key_manager->get_key_factory(); - - // Empty key format. - RsaSsaPkcs1KeyFormat key_format; - { - auto result = key_factory.NewKey(key_format); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - } - - // Bad serialized format. - { - auto result = key_factory.NewKey("some bad serialization"); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - } - - // Wrong format proto. - { - AesEaxKeyFormat wrong_key_format; - auto result = key_factory.NewKey(wrong_key_format); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - } +TEST(RsaSsaPkcs1SignKeyManagerTest, GetPublicKey) { + StatusOr<RsaSsaPkcs1PrivateKey> key_or = + RsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()); + ASSERT_THAT(key_or.status(), IsOk()); + StatusOr<RsaSsaPkcs1PublicKey> public_key_or = + RsaSsaPkcs1SignKeyManager().GetPublicKey(key_or.ValueOrDie()); + ASSERT_THAT(public_key_or.status(), IsOk()); + EXPECT_THAT(public_key_or.ValueOrDie().version(), + Eq(key_or.ValueOrDie().public_key().version())); + EXPECT_THAT(public_key_or.ValueOrDie().params().hash_type(), + Eq(key_or.ValueOrDie().public_key().params().hash_type())); + EXPECT_THAT(public_key_or.ValueOrDie().n(), + Eq(key_or.ValueOrDie().public_key().n())); + EXPECT_THAT(public_key_or.ValueOrDie().e(), + Eq(key_or.ValueOrDie().public_key().e())); } -TEST_F(RsaSsaPkcs1SignKeyManagerTest, PublicKeyExtractionErrors) { - RsaSsaPkcs1SignKeyManager sign_key_type_manager; - RsaSsaPkcs1VerifyKeyManager verify_key_type_manager; - auto verify_key_manager = - internal::MakeKeyManager<PublicKeyVerify>(&verify_key_type_manager); - auto sign_key_manager = internal::MakePrivateKeyManager<PublicKeySign>( - &sign_key_type_manager, &verify_key_type_manager); - auto private_key_factory = dynamic_cast<const PrivateKeyFactory*>( - &(sign_key_manager->get_key_factory())); - ASSERT_NE(private_key_factory, nullptr); - - auto public_key_data_result = private_key_factory->GetPublicKeyData( - google::crypto::tink::AesGcmKey().SerializeAsString()); - EXPECT_FALSE(public_key_data_result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, - public_key_data_result.status().error_code()); +TEST(EcdsaSignKeyManagerTest, Create) { + RsaSsaPkcs1KeyFormat key_format = + CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); + StatusOr<RsaSsaPkcs1PrivateKey> key_or = + RsaSsaPkcs1SignKeyManager().CreateKey(key_format); + ASSERT_THAT(key_or.status(), IsOk()); + RsaSsaPkcs1PrivateKey key = key_or.ValueOrDie(); + + auto signer_or = RsaSsaPkcs1SignKeyManager().GetPrimitive<PublicKeySign>(key); + ASSERT_THAT(signer_or.status(), IsOk()); + + auto direct_verifier_or = subtle::RsaSsaPkcs1VerifyBoringSsl::New( + {key.public_key().n(), key.public_key().e()}, {subtle::HashType::SHA256}); + ASSERT_THAT(direct_verifier_or.status(), IsOk()); + + std::string message = "Some message"; + EXPECT_THAT(direct_verifier_or.ValueOrDie()->Verify( + signer_or.ValueOrDie()->Sign(message).ValueOrDie(), message), + IsOk()); } } // namespace } // namespace tink } // namespace crypto + diff --git a/cc/signature/rsa_ssa_pkcs1_verify_key_manager_test.cc b/cc/signature/rsa_ssa_pkcs1_verify_key_manager_test.cc index a6621e61d..93e54fd7e 100644 --- a/cc/signature/rsa_ssa_pkcs1_verify_key_manager_test.cc +++ b/cc/signature/rsa_ssa_pkcs1_verify_key_manager_test.cc @@ -16,45 +16,156 @@ #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" -#include "tink/core/key_manager_impl.h" +#include "openssl/bn.h" +#include "openssl/rsa.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" - -#include "tink/registry.h" +#include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" +#include "tink/subtle/rsa_ssa_pkcs1_sign_boringssl.h" +#include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" +#include "tink/util/test_matchers.h" #include "tink/util/test_util.h" -#include "proto/common.pb.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" -namespace pb = google::crypto::tink; - -// TODO(quannguyen): add more tests once RsaSsaPkcs1SignKeyManager is available. namespace crypto { namespace tink { -using google::crypto::tink::KeyData; -using google::crypto::tink::RsaSsaPkcs1KeyFormat; -using google::crypto::tink::RsaSsaPkcs1PublicKey; +using ::crypto::tink::test::IsOk; +using ::crypto::tink::test::StatusIs; +using ::crypto::tink::util::StatusOr; +using ::google::crypto::tink::HashType; +using ::google::crypto::tink::KeyData; +using ::google::crypto::tink::RsaSsaPkcs1KeyFormat; +using ::google::crypto::tink::RsaSsaPkcs1PrivateKey; +using ::google::crypto::tink::RsaSsaPkcs1PublicKey; +using ::testing::Eq; +using ::testing::HasSubstr; +using ::testing::Not; namespace { -// Test vector from -// https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures -struct NistTestVector { - std::string n; - std::string e; - std::string message; - std::string signature; - pb::HashType hash_type; -}; - -class RsaSsaPkcs1VerifyKeyManagerTest : public ::testing::Test { - protected: - const NistTestVector nist_test_vector_{ +TEST(RsaSsaPkcs1VerifyKeyManagerTest, Basics) { + EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().get_version(), Eq(0)); + EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().key_material_type(), + Eq(KeyData::ASYMMETRIC_PUBLIC)); + EXPECT_THAT( + RsaSsaPkcs1VerifyKeyManager().get_key_type(), + Eq("type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey")); +} + +TEST(RsaSsaPkcs1VerifyKeyManagerTest, ValidateEmptyKey) { + EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(RsaSsaPkcs1PublicKey()), + Not(IsOk())); +} + +RsaSsaPkcs1KeyFormat CreateKeyFormat(HashType hash_type, + int modulus_size_in_bits, + int public_exponent) { + RsaSsaPkcs1KeyFormat key_format; + auto params = key_format.mutable_params(); + params->set_hash_type(hash_type); + key_format.set_modulus_size_in_bits(modulus_size_in_bits); + bssl::UniquePtr<BIGNUM> e(BN_new()); + BN_set_word(e.get(), public_exponent); + key_format.set_public_exponent( + subtle::SubtleUtilBoringSSL::bn2str(e.get(), BN_num_bytes(e.get())) + .ValueOrDie()); + return key_format; +} + +RsaSsaPkcs1KeyFormat ValidKeyFormat() { + return CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); +} + +RsaSsaPkcs1PrivateKey CreateValidPrivateKey() { + return RsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()).ValueOrDie(); +} + +RsaSsaPkcs1PublicKey CreateValidPublicKey() { + return RsaSsaPkcs1SignKeyManager() + .GetPublicKey(CreateValidPrivateKey()) + .ValueOrDie(); +} + +// Checks that a public key generaed by the SignKeyManager is considered valid. +TEST(RsaSsaPkcs1VerifyKeyManagerTest, PublicKeyValid) { + RsaSsaPkcs1PublicKey key = CreateValidPublicKey(); + EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(key), IsOk()); +} + +TEST(RsaSsaPkcs1VerifyKeyManagerTest, PublicKeyWrongVersion) { + RsaSsaPkcs1PublicKey key = CreateValidPublicKey(); + key.set_version(1); + EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(key), Not(IsOk())); +} + +TEST(RsaSsaPkcs1VerifyKeyManagerTest, PublicKeyUnkownHashDisallowed) { + RsaSsaPkcs1PublicKey key = CreateValidPublicKey(); + key.mutable_params()->set_hash_type(HashType::UNKNOWN_HASH); + EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(key), Not(IsOk())); +} + +TEST(RsaSsaPkcs1VerifyKeyManagerTest, ValidateKeyFormatSmallModulusDisallowed) { + RsaSsaPkcs1PublicKey key = CreateValidPublicKey(); + key.set_n("\x23"); + key.set_e("\x3"); + EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(key), + StatusIs(util::error::INVALID_ARGUMENT, + HasSubstr("only modulus size >= 2048"))); +} + +TEST(RsaSsaPkcs1SignKeyManagerTest, Create) { + RsaSsaPkcs1KeyFormat key_format = + CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); + StatusOr<RsaSsaPkcs1PrivateKey> private_key_or = + RsaSsaPkcs1SignKeyManager().CreateKey(key_format); + ASSERT_THAT(private_key_or.status(), IsOk()); + RsaSsaPkcs1PrivateKey private_key = private_key_or.ValueOrDie(); + RsaSsaPkcs1PublicKey public_key = + RsaSsaPkcs1SignKeyManager().GetPublicKey(private_key).ValueOrDie(); + + subtle::SubtleUtilBoringSSL::RsaPrivateKey private_key_subtle; + private_key_subtle.n = private_key.public_key().n(); + private_key_subtle.e = private_key.public_key().e(); + private_key_subtle.d = private_key.d(); + private_key_subtle.p = private_key.p(); + private_key_subtle.q = private_key.q(); + private_key_subtle.dp = private_key.dp(); + private_key_subtle.dq = private_key.dq(); + private_key_subtle.crt = private_key.crt(); + + auto direct_signer_or = subtle::RsaSsaPkcs1SignBoringSsl::New( + private_key_subtle, {crypto::tink::subtle::HashType::SHA256}); + + auto verifier_or = + RsaSsaPkcs1VerifyKeyManager().GetPrimitive<PublicKeyVerify>(public_key); + ASSERT_THAT(verifier_or.status(), IsOk()); + + std::string message = "Some message"; + EXPECT_THAT( + verifier_or.ValueOrDie()->Verify( + direct_signer_or.ValueOrDie()->Sign(message).ValueOrDie(), message), + IsOk()); +} + +TEST(RsaSsaPkcs1VerifyKeyManagerTest, NistTestVector) { + // Test vector from + // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures + struct NistTestVector { + std::string n; + std::string e; + std::string message; + std::string signature; + HashType hash_type; + }; + + const NistTestVector nist_test_vector{ absl::HexStringToBytes( "c9548608087bed6be0a4623b9d849aa0b4b4b6114ad0a7d82578076ceefe26ce48d1" "448e16d69963510e1e5fc658f3cf8f32a489b62d93fec1cdea6e1dde3feba04bb6a0" @@ -79,145 +190,19 @@ class RsaSsaPkcs1VerifyKeyManagerTest : public ::testing::Test { "34b76711e76813ad5f5c3a5c95399e907650534dbfafec900c21be1308ddff6eda52" "5f35e4fb3d275de46250ea1e4b96b60bd125b85f6c52b5419a725cd69b10cefd0901" "abe7f9e15940594cf811e34c60f38768244c"), - pb::HashType::SHA256}; - - std::string rsa_ssa_pkcs1_verify_key_type_ = - "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey"; -}; + HashType::SHA256}; -TEST_F(RsaSsaPkcs1VerifyKeyManagerTest, NistTestVector) { - RsaSsaPkcs1VerifyKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeyVerify>(&key_type_manager); - - EXPECT_EQ(0, key_manager->get_version()); - EXPECT_EQ("type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey", - key_manager->get_key_type()); - EXPECT_TRUE(key_manager->DoesSupport(key_manager->get_key_type())); - - // NIST test vector should work. RsaSsaPkcs1PublicKey key; - key.mutable_params()->set_hash_type(nist_test_vector_.hash_type); + key.mutable_params()->set_hash_type(nist_test_vector.hash_type); key.set_version(0); - key.set_n(nist_test_vector_.n); - key.set_e(nist_test_vector_.e); - auto result = key_manager->GetPrimitive(key); - EXPECT_TRUE(result.ok()); - EXPECT_TRUE( - result.ValueOrDie() - ->Verify(nist_test_vector_.signature, nist_test_vector_.message) - .ok()); -} - -TEST_F(RsaSsaPkcs1VerifyKeyManagerTest, KeyDataErrors) { - RsaSsaPkcs1VerifyKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeyVerify>(&key_type_manager); - - { // Bad key type. - KeyData key_data; - std::string bad_key_type = "type.googleapis.com/google.crypto.tink.SomeOtherKey"; - key_data.set_type_url(bad_key_type); - auto result = key_manager->GetPrimitive(key_data); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported", - result.status().error_message()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, bad_key_type, - result.status().error_message()); - } - - { // Bad key value. - KeyData key_data; - key_data.set_type_url(rsa_ssa_pkcs1_verify_key_type_); - key_data.set_value("some bad serialized proto"); - auto result = key_manager->GetPrimitive(key_data); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "not parse", - result.status().error_message()); - } - - { // Bad version. - KeyData key_data; - RsaSsaPkcs1PublicKey key; - key.set_version(1); - key_data.set_type_url(rsa_ssa_pkcs1_verify_key_type_); - key_data.set_value(key.SerializeAsString()); - auto result = key_manager->GetPrimitive(key_data); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "version", - result.status().error_message()); - } -} - -TEST_F(RsaSsaPkcs1VerifyKeyManagerTest, KeyMessageErrors) { - RsaSsaPkcs1VerifyKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeyVerify>(&key_type_manager); - - { // Use SHA1 as signature hash. - RsaSsaPkcs1PublicKey key; - key.mutable_params()->set_hash_type(pb::HashType::SHA1); - key.set_version(0); - key.set_n(nist_test_vector_.n); - key.set_e(nist_test_vector_.e); - auto result = key_manager->GetPrimitive(key); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, - "SHA1 is not safe for digital signature", - result.status().error_message()); - } - - { // Small modulus. - RsaSsaPkcs1PublicKey key; - key.mutable_params()->set_hash_type(pb::HashType::SHA256); - key.set_version(0); - key.set_n("\x23"); - key.set_e("\x3"); - auto result = key_manager->GetPrimitive(key); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, - "only modulus size >= 2048-bit is supported", - result.status().error_message()); - } -} - -TEST_F(RsaSsaPkcs1VerifyKeyManagerTest, NewKeyError) { - RsaSsaPkcs1VerifyKeyManager key_type_manager; - auto key_manager = - internal::MakeKeyManager<PublicKeyVerify>(&key_type_manager); - const KeyFactory& key_factory = key_manager->get_key_factory(); - - { // Via NewKey(format_proto). - RsaSsaPkcs1KeyFormat key_format; - auto result = key_factory.NewKey(key_format); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::UNIMPLEMENTED, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported", - result.status().error_message()); - } - - { // Via NewKey(serialized_format_proto). - RsaSsaPkcs1KeyFormat key_format; - auto result = key_factory.NewKey(key_format.SerializeAsString()); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::UNIMPLEMENTED, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported", - result.status().error_message()); - } - - { // Via NewKeyData(serialized_format_proto). - RsaSsaPkcs1KeyFormat key_format; - auto result = key_factory.NewKeyData(key_format.SerializeAsString()); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(util::error::UNIMPLEMENTED, result.status().error_code()); - EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported", - result.status().error_message()); - } + key.set_n(nist_test_vector.n); + key.set_e(nist_test_vector.e); + auto result = + RsaSsaPkcs1VerifyKeyManager().GetPrimitive<PublicKeyVerify>(key); + EXPECT_THAT(result.status(), IsOk()); + EXPECT_THAT(result.ValueOrDie()->Verify(nist_test_vector.signature, + nist_test_vector.message), + IsOk()); } } // namespace -- GitLab