//////////////////////////////////////////////////////////////////////////////// // Copyright 2016 Google LLC. // // This software is licensed under the terms defined in the Widevine Master // License Agreement. For a copy of this agreement, please contact // widevine-licensing@google.com. //////////////////////////////////////////////////////////////////////////////// // // Description: // Unit test for rsa_util RSA utilties library. #include "common/rsa_util.h" #include #include #include #include "glog/logging.h" #include "testing/gmock.h" #include "testing/gunit.h" #include "openssl/bn.h" #include "common/rsa_test_keys.h" using ::testing::NotNull; namespace { const uint32_t kRsaPublicExponent = 65537; const int kTestRsaBits = 2048; } // anonymous namespace namespace widevine { namespace rsa_util { class RsaUtilTest : public ::testing::Test { protected: RsaTestKeys test_keys_; }; TEST_F(RsaUtilTest, SerializeDeserializePrivateKey) { RSA* private_key; std::string serialized_private_key; // Key 1 EXPECT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_1_3072_bits(), &private_key)); ASSERT_TRUE(private_key != NULL); EXPECT_TRUE(SerializeRsaPrivateKey(private_key, &serialized_private_key)); EXPECT_EQ(serialized_private_key, test_keys_.private_test_key_1_3072_bits()); EXPECT_EQ(RSA_check_key(private_key), 1); RSA_free(private_key); // Key 2 EXPECT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_2_2048_bits(), &private_key)); ASSERT_TRUE(private_key != NULL); EXPECT_TRUE(SerializeRsaPrivateKey(private_key, &serialized_private_key)); EXPECT_EQ(serialized_private_key, test_keys_.private_test_key_2_2048_bits()); EXPECT_EQ(RSA_check_key(private_key), 1); RSA_free(private_key); // Key 3 EXPECT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_3_2048_bits(), &private_key)); ASSERT_TRUE(private_key != NULL); EXPECT_TRUE(SerializeRsaPrivateKey(private_key, &serialized_private_key)); EXPECT_EQ(serialized_private_key, test_keys_.private_test_key_3_2048_bits()); EXPECT_EQ(RSA_check_key(private_key), 1); RSA_free(private_key); // Invalid key EXPECT_FALSE(DeserializeRsaPrivateKey("this is a bad key", &private_key)); } TEST_F(RsaUtilTest, SerializeDeserializePublicKey) { RSA* public_key; std::string serialized_public_key; // Key 1 EXPECT_TRUE(DeserializeRsaPublicKey( test_keys_.public_test_key_1_3072_bits(), &public_key)); ASSERT_TRUE(public_key != NULL); EXPECT_TRUE(SerializeRsaPublicKey(public_key, &serialized_public_key)); EXPECT_EQ(serialized_public_key, test_keys_.public_test_key_1_3072_bits()); RSA_free(public_key); // Key 2 EXPECT_TRUE(DeserializeRsaPublicKey( test_keys_.public_test_key_2_2048_bits(), &public_key)); ASSERT_TRUE(public_key != NULL); EXPECT_TRUE(SerializeRsaPublicKey(public_key, &serialized_public_key)); EXPECT_EQ(serialized_public_key, test_keys_.public_test_key_2_2048_bits()); RSA_free(public_key); // Key 3 EXPECT_TRUE(DeserializeRsaPublicKey( test_keys_.public_test_key_3_2048_bits(), &public_key)); ASSERT_TRUE(public_key != NULL); EXPECT_TRUE(SerializeRsaPublicKey(public_key, &serialized_public_key)); EXPECT_EQ(serialized_public_key, test_keys_.public_test_key_3_2048_bits()); RSA_free(public_key); // Invalid key EXPECT_FALSE(DeserializeRsaPublicKey("this is a bad key", &public_key)); } TEST_F(RsaUtilTest, PublicKeyExtraction) { RSA* private_key; std::string serialized_public_key; // Key 1 EXPECT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_1_3072_bits(), &private_key)); ASSERT_TRUE(private_key != NULL); EXPECT_TRUE(SerializeRsaPublicKey(private_key, &serialized_public_key)); EXPECT_EQ(serialized_public_key, test_keys_.public_test_key_1_3072_bits()); RSA_free(private_key); // Key 2 EXPECT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_2_2048_bits(), &private_key)); ASSERT_TRUE(private_key != NULL); EXPECT_TRUE(SerializeRsaPublicKey(private_key, &serialized_public_key)); EXPECT_EQ(serialized_public_key, test_keys_.public_test_key_2_2048_bits()); RSA_free(private_key); // Key 3 EXPECT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_3_2048_bits(), &private_key)); ASSERT_TRUE(private_key != NULL); EXPECT_TRUE(SerializeRsaPublicKey(private_key, &serialized_public_key)); EXPECT_EQ(serialized_public_key, test_keys_.public_test_key_3_2048_bits()); RSA_free(private_key); } TEST_F(RsaUtilTest, Pkcs8PrivateKeyInfo) { // The PKCS#1 <-> PKCS#8 conversion routines exercise all the PKCS#8 // serialization/deserialization functionality , so we test those. std::string serialized_pkcs8; std::string serialized_pkcs1; // Key 1 EXPECT_TRUE(RsaPrivateKeyToPrivateKeyInfo( test_keys_.private_test_key_1_3072_bits(), &serialized_pkcs8)); EXPECT_TRUE(PrivateKeyInfoToRsaPrivateKey(serialized_pkcs8, &serialized_pkcs1)); EXPECT_NE(serialized_pkcs1, serialized_pkcs8); EXPECT_EQ(test_keys_.private_test_key_1_3072_bits(), serialized_pkcs1); // Key 2 EXPECT_TRUE(RsaPrivateKeyToPrivateKeyInfo( test_keys_.private_test_key_2_2048_bits(), &serialized_pkcs8)); EXPECT_TRUE(PrivateKeyInfoToRsaPrivateKey(serialized_pkcs8, &serialized_pkcs1)); EXPECT_NE(serialized_pkcs1, serialized_pkcs8); EXPECT_EQ(test_keys_.private_test_key_2_2048_bits(), serialized_pkcs1); // Key 3 EXPECT_TRUE(RsaPrivateKeyToPrivateKeyInfo( test_keys_.private_test_key_3_2048_bits(), &serialized_pkcs8)); EXPECT_TRUE(PrivateKeyInfoToRsaPrivateKey(serialized_pkcs8, &serialized_pkcs1)); EXPECT_NE(serialized_pkcs1, serialized_pkcs8); EXPECT_EQ(test_keys_.private_test_key_3_2048_bits(), serialized_pkcs1); } TEST_F(RsaUtilTest, Pkcs8EncryptedPrivateKeyInfo) { // The PKCS#1 <-> PKCS#8 conversion routines exercise all the PKCS#8 // serialization/deserialization functionality , so we test those. std::string serialized_pkcs8; std::string serialized_pkcs1; std::string passphrase("passphrase"); // Key 1 EXPECT_TRUE(RsaPrivateKeyToEncryptedPrivateKeyInfo( test_keys_.private_test_key_1_3072_bits(), passphrase, &serialized_pkcs8)); EXPECT_TRUE(EncryptedPrivateKeyInfoToRsaPrivateKey(serialized_pkcs8, passphrase, &serialized_pkcs1)); EXPECT_NE(serialized_pkcs1, serialized_pkcs8); EXPECT_EQ(test_keys_.private_test_key_1_3072_bits(), serialized_pkcs1); // Key 2 EXPECT_TRUE(RsaPrivateKeyToEncryptedPrivateKeyInfo( test_keys_.private_test_key_2_2048_bits(), passphrase, &serialized_pkcs8)); EXPECT_TRUE(EncryptedPrivateKeyInfoToRsaPrivateKey(serialized_pkcs8, passphrase, &serialized_pkcs1)); EXPECT_NE(serialized_pkcs1, serialized_pkcs8); EXPECT_EQ(test_keys_.private_test_key_2_2048_bits(), serialized_pkcs1); // Key 3 EXPECT_TRUE(RsaPrivateKeyToEncryptedPrivateKeyInfo( test_keys_.private_test_key_3_2048_bits(), passphrase, &serialized_pkcs8)); EXPECT_TRUE(EncryptedPrivateKeyInfoToRsaPrivateKey(serialized_pkcs8, passphrase, &serialized_pkcs1)); EXPECT_NE(serialized_pkcs1, serialized_pkcs8); EXPECT_EQ(test_keys_.private_test_key_3_2048_bits(), serialized_pkcs1); } TEST_F(RsaUtilTest, FailOnInvalidParams) { RSA* test_input_key = NULL; RSA* test_output_key = NULL; std::string test_string; std::string pass("password"); ASSERT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_2_2048_bits(), &test_input_key)); ASSERT_TRUE(test_input_key != NULL); EXPECT_FALSE(SerializeRsaPrivateKey(NULL, &test_string)); EXPECT_FALSE(SerializeRsaPrivateKey(test_input_key, NULL)); EXPECT_FALSE(SerializeRsaPublicKey(NULL, &test_string)); EXPECT_FALSE(SerializeRsaPublicKey(test_input_key, NULL)); EXPECT_FALSE(SerializePrivateKeyInfo(NULL, &test_string)); EXPECT_FALSE(SerializePrivateKeyInfo(test_input_key, NULL)); EXPECT_FALSE(SerializeEncryptedPrivateKeyInfo(NULL, pass, &test_string)); EXPECT_FALSE(SerializeEncryptedPrivateKeyInfo(test_input_key, pass, NULL)); EXPECT_FALSE(DeserializeRsaPrivateKey("", &test_output_key)); EXPECT_FALSE(DeserializeRsaPrivateKey( test_keys_.private_test_key_2_2048_bits(), NULL)); EXPECT_FALSE(DeserializeRsaPublicKey("", &test_output_key)); EXPECT_FALSE(DeserializeRsaPublicKey( test_keys_.public_test_key_2_2048_bits(), NULL)); EXPECT_FALSE(DeserializePrivateKeyInfo("", &test_output_key)); EXPECT_FALSE(DeserializePrivateKeyInfo( test_keys_.private_test_key_2_2048_bits(), NULL)); EXPECT_FALSE(DeserializeEncryptedPrivateKeyInfo("", pass, &test_output_key)); EXPECT_FALSE(DeserializeEncryptedPrivateKeyInfo( test_keys_.private_test_key_2_2048_bits(), pass, NULL)); RSA_free(test_input_key); } TEST_F(RsaUtilTest, Pkcs8FailOnInvalidPassword) { RSA* test_input_key = NULL; RSA* test_output_key = NULL; std::string serialized_pkcs8; std::string pass("password"); ASSERT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_2_2048_bits(), &test_input_key)); EXPECT_FALSE(SerializeEncryptedPrivateKeyInfo(test_input_key, "", &serialized_pkcs8)); ASSERT_TRUE(SerializeEncryptedPrivateKeyInfo(test_input_key, pass, &serialized_pkcs8)); EXPECT_FALSE(DeserializeEncryptedPrivateKeyInfo(serialized_pkcs8, pass + "a", &test_output_key)); EXPECT_TRUE(DeserializeEncryptedPrivateKeyInfo(serialized_pkcs8, pass, &test_output_key)); RSA_free(test_input_key); RSA_free(test_output_key); } TEST_F(RsaUtilTest, ConvertToCarmichaelTotient_ExistingKey_Success) { bssl::UniquePtr original_private_key; RSA* original_key_ptr = nullptr; EXPECT_TRUE(DeserializeRsaPrivateKey( test_keys_.private_test_key_2_2048_bits(), &original_key_ptr)); original_private_key.reset(original_key_ptr); ASSERT_THAT(original_private_key, NotNull()); bssl::UniquePtr private_key( RSAPrivateKey_dup(original_private_key.get())); ASSERT_THAT(private_key, NotNull()); EXPECT_TRUE(ConvertToCarmichaelTotient(private_key.get())); // Confirm that the key is valid and has changed from the original. EXPECT_EQ(1, RSA_check_key(private_key.get())); std::string serialized_carmichael_private_key; EXPECT_TRUE(SerializeRsaPrivateKey(private_key.get(), &serialized_carmichael_private_key)); EXPECT_NE(serialized_carmichael_private_key, test_keys_.private_test_key_2_2048_bits()); // Convert back and make sure the serialized key matches the original. EXPECT_TRUE(ConvertToEulerTotient(private_key.get())); EXPECT_EQ(1, RSA_check_key(private_key.get())); std::string serialized_euler_private_key; EXPECT_TRUE(SerializeRsaPrivateKey(private_key.get(), &serialized_euler_private_key)); EXPECT_EQ(serialized_euler_private_key, test_keys_.private_test_key_2_2048_bits()); } TEST_F(RsaUtilTest, ConvertToEulerTotient_NewKey_Success) { bssl::UniquePtr rsa; bssl::UniquePtr private_key; bssl::UniquePtr exponent(BN_new()); ASSERT_TRUE(BN_set_word(exponent.get(), kRsaPublicExponent)); // It is possible that sometimes, the d value generated using carmichael // and euler is the same. For this test, find a key where they are not the // same (max 100 tries). bool found_distinct_keys = false; for (int i = 0; i < 100; i++) { rsa.reset(RSA_new()); ASSERT_TRUE(RSA_generate_key_ex(rsa.get(), kTestRsaBits, exponent.get(), nullptr)); private_key.reset(RSAPrivateKey_dup(rsa.get())); EXPECT_TRUE(ConvertToEulerTotient(private_key.get())); EXPECT_EQ(1, RSA_check_key(private_key.get())); // If the values are different, break. if (BN_cmp(private_key->d, rsa->d) != 0) { found_distinct_keys = true; break; } LOG(INFO) << "Euler and Carmichael d values are the same. Count: " << i; } ASSERT_TRUE(found_distinct_keys) << "Reached maximum attempts, but did not generate distinct keys"; EXPECT_EQ(1, RSA_check_key(private_key.get())); // Sanity check that the serialized keys are distinct. std::string serialized_carmichael_private_key; std::string serialized_private_key; EXPECT_TRUE(SerializeRsaPrivateKey(rsa.get(), &serialized_carmichael_private_key)); EXPECT_TRUE(SerializeRsaPrivateKey(private_key.get(), &serialized_private_key)); EXPECT_NE(serialized_carmichael_private_key, serialized_private_key); // Convert back to Carmichael, validate, and confirm that the keys are the // same. EXPECT_TRUE(ConvertToCarmichaelTotient(private_key.get())); EXPECT_EQ(1, RSA_check_key(private_key.get())); EXPECT_TRUE(SerializeRsaPrivateKey(private_key.get(), &serialized_private_key)); EXPECT_EQ(serialized_carmichael_private_key, serialized_private_key); } TEST_F(RsaUtilTest, ConvertToSerializedCarmichaelTotient_Success) { std::string private_key; EXPECT_TRUE(ConvertToCarmichaelTotient( test_keys_.private_test_key_2_2048_bits(), &private_key)); EXPECT_EQ(test_keys_.private_test_key_2_carmichael_totient_2048_bits(), private_key); } TEST_F(RsaUtilTest, ConvertToSerializedEulerTotient_Success) { std::string private_key; EXPECT_TRUE(ConvertToEulerTotient( test_keys_.private_test_key_2_carmichael_totient_2048_bits(), &private_key)); EXPECT_EQ(test_keys_.private_test_key_2_2048_bits(), private_key); } TEST_F(RsaUtilTest, ConvertToEulerTotient_Idempotent_Success) { std::string private_key; EXPECT_TRUE(ConvertToEulerTotient(test_keys_.private_test_key_2_2048_bits(), &private_key)); EXPECT_EQ(test_keys_.private_test_key_2_2048_bits(), private_key); } TEST_F(RsaUtilTest, ConvertToCarmichaelTotient_Idempotent_Success) { std::string private_key; EXPECT_TRUE(ConvertToCarmichaelTotient( test_keys_.private_test_key_2_carmichael_totient_2048_bits(), &private_key)); EXPECT_EQ(test_keys_.private_test_key_2_carmichael_totient_2048_bits(), private_key); } } // namespace rsa_util } // namespace widevine