------------- Moves ecm_generator to media_cas_packager_sdk/internal. ------------- Add a simple TCP server listening on a port. My intention is to use this server to support the Simulcrypt APIs (TODO). Also add a simple TCP client binary for testing the server and also demo how to call the Simulcrypt APIs (TODO). ------------- If only a single key is in the ECM, it is the EVEN key. To make the code matches this understanding, change a parameter from 'false' to 'true'. But this change has NO impact on the produced ECM, regardless this parameter is 'false' or 'true' (i.e., whether using push_front or push_back), only a single key is in the ECM. ------------- Add classes that process Simulcrypt ECMG messages 1) Stream_set-up 2) CW_provision ------------- Renames server and client binaries. ------------- Make ecmg call ecm_generator to generate ecm. The return of the ecm to Simulcrypt caller will be implemented in the next CL. For now, using the 'key' (control word) in CW_provision message also as the 'key_id'. ------------- Move common folder ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=217358698
354 lines
14 KiB
C++
354 lines
14 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// 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 <stddef.h>
|
|
#include <memory>
|
|
|
|
#include <cstdint>
|
|
#include "glog/logging.h"
|
|
#include "testing/gmock.h"
|
|
#include "testing/gunit.h"
|
|
#include "openssl/bn.h"
|
|
#include "common/rsa_test_keys.h"
|
|
#include "common/rsa_util.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<RSA> 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<RSA> 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> rsa;
|
|
bssl::UniquePtr<RSA> private_key;
|
|
bssl::UniquePtr<BIGNUM> 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
|