Minimal implementation of Widevine MediaCAS ECMG.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=226515998
This commit is contained in:
@@ -24,6 +24,8 @@
|
||||
#include "common/drm_root_certificate.h"
|
||||
#include "common/error_space.h"
|
||||
#include "common/rsa_test_keys.h"
|
||||
#include "common/sha_util.h"
|
||||
#include "common/test_drm_certificates.h"
|
||||
#include "common/wvm_test_keys.h"
|
||||
#include "protos/public/drm_certificate.pb.h"
|
||||
#include "protos/public/errors.pb.h"
|
||||
@@ -31,7 +33,7 @@
|
||||
|
||||
// TODO(user): Change these tests to use on-the-fly generated intermediate
|
||||
// and device certificates based on RsaTestKeys.
|
||||
// TODO(user): Add testcase(s) VerifySignature, CreateSignature,
|
||||
// TODO(user): Add testcase(s) CreateSignature,
|
||||
// and GenerateSigningKey.
|
||||
|
||||
namespace widevine {
|
||||
@@ -73,11 +75,10 @@ class ClientCertTest : public ::testing::Test {
|
||||
const std::string certificate_;
|
||||
const std::string expected_serial_number_;
|
||||
uint32_t expected_system_id_;
|
||||
util::Status expected_status_;
|
||||
Status expected_status_;
|
||||
TestCertificateAndData(const std::string& certificate,
|
||||
const std::string& expected_serial_number,
|
||||
uint32_t expected_system_id,
|
||||
util::Status expected_status)
|
||||
uint32_t expected_system_id, Status expected_status)
|
||||
: certificate_(certificate),
|
||||
expected_serial_number_(expected_serial_number),
|
||||
expected_system_id_(expected_system_id),
|
||||
@@ -111,7 +112,8 @@ class ClientCertTest : public ::testing::Test {
|
||||
SignedDrmCertificate* signer, uint32_t system_id,
|
||||
const std::string& serial_number);
|
||||
|
||||
RsaTestKeys test_keys_;
|
||||
RsaTestKeys test_rsa_keys_;
|
||||
TestDrmCertificates test_drm_certs_;
|
||||
std::unique_ptr<DrmRootCertificate> root_cert_;
|
||||
static bool setup_preprov_keys_;
|
||||
};
|
||||
@@ -121,7 +123,7 @@ void ClientCertTest::TestBasicValidation(const TestTokenAndKeys& expectation,
|
||||
const bool expect_success,
|
||||
const bool compare_device_key) {
|
||||
// Test validation of a valid request.
|
||||
util::Status status;
|
||||
Status status;
|
||||
ClientCert* client_cert_ptr = nullptr;
|
||||
|
||||
// Two ways to create a client cert object, test both.
|
||||
@@ -136,7 +138,7 @@ void ClientCertTest::TestBasicValidation(const TestTokenAndKeys& expectation,
|
||||
}
|
||||
std::unique_ptr<ClientCert> keybox_cert(client_cert_ptr);
|
||||
if (expect_success) {
|
||||
ASSERT_EQ(util::OkStatus(), status);
|
||||
ASSERT_EQ(OkStatus(), status);
|
||||
ASSERT_TRUE(keybox_cert.get());
|
||||
EXPECT_EQ(expectation.expected_system_id_, keybox_cert->system_id());
|
||||
EXPECT_EQ(expectation.expected_serial_number_,
|
||||
@@ -145,7 +147,7 @@ void ClientCertTest::TestBasicValidation(const TestTokenAndKeys& expectation,
|
||||
EXPECT_EQ(expectation.expected_device_key_, keybox_cert->key());
|
||||
}
|
||||
} else {
|
||||
EXPECT_NE(util::OkStatus(), status);
|
||||
EXPECT_NE(OkStatus(), status);
|
||||
EXPECT_FALSE(keybox_cert);
|
||||
}
|
||||
}
|
||||
@@ -159,7 +161,7 @@ void ClientCertTest::TestBasicValidationDrmCertificate(
|
||||
DrmRootCertificate::CreateByType(kCertificateTypeTesting, &root_cert_));
|
||||
|
||||
// Test validation of a valid request.
|
||||
util::Status status;
|
||||
Status status;
|
||||
ClientCert* client_cert_ptr = nullptr;
|
||||
status = ClientCert::Create(root_cert_.get(),
|
||||
ClientIdentification::DRM_DEVICE_CERTIFICATE,
|
||||
@@ -209,7 +211,7 @@ DrmCertificate* ClientCertTest::GenerateIntermediateCertificate(
|
||||
intermediate_certificate->set_type(DrmCertificate::DEVICE_MODEL);
|
||||
intermediate_certificate->set_serial_number(serial_number);
|
||||
intermediate_certificate->set_public_key(
|
||||
test_keys_.public_test_key_2_2048_bits());
|
||||
test_rsa_keys_.public_test_key_2_2048_bits());
|
||||
intermediate_certificate->set_system_id(system_id);
|
||||
intermediate_certificate->set_creation_time_seconds(1234);
|
||||
return intermediate_certificate.release();
|
||||
@@ -221,7 +223,7 @@ SignedDrmCertificate* ClientCertTest::GenerateSignedIntermediateCertificate(
|
||||
std::unique_ptr<DrmCertificate> intermediate_certificate(
|
||||
GenerateIntermediateCertificate(system_id, serial_number));
|
||||
return SignCertificate(*intermediate_certificate, signer,
|
||||
test_keys_.private_test_key_1_3072_bits());
|
||||
test_rsa_keys_.private_test_key_1_3072_bits());
|
||||
}
|
||||
|
||||
DrmCertificate* ClientCertTest::GenerateDrmCertificate(
|
||||
@@ -230,7 +232,7 @@ DrmCertificate* ClientCertTest::GenerateDrmCertificate(
|
||||
drm_certificate->set_type(DrmCertificate::DEVICE);
|
||||
drm_certificate->set_serial_number(serial_number);
|
||||
drm_certificate->set_system_id(system_id);
|
||||
drm_certificate->set_public_key(test_keys_.public_test_key_3_2048_bits());
|
||||
drm_certificate->set_public_key(test_rsa_keys_.public_test_key_3_2048_bits());
|
||||
drm_certificate->set_creation_time_seconds(4321);
|
||||
return drm_certificate.release();
|
||||
}
|
||||
@@ -241,7 +243,7 @@ SignedDrmCertificate* ClientCertTest::GenerateSignedDrmCertificate(
|
||||
std::unique_ptr<DrmCertificate> drm_certificate(
|
||||
GenerateDrmCertificate(system_id, serial_number));
|
||||
std::unique_ptr<SignedDrmCertificate> signed_drm_certificate(SignCertificate(
|
||||
*drm_certificate, signer, test_keys_.private_test_key_2_2048_bits()));
|
||||
*drm_certificate, signer, test_rsa_keys_.private_test_key_2_2048_bits()));
|
||||
return signed_drm_certificate.release();
|
||||
}
|
||||
|
||||
@@ -252,7 +254,7 @@ DrmCertificate* ClientCertTest::GenerateProvisionerCertificate(
|
||||
provisioner_certificate->set_serial_number(serial_number);
|
||||
// TODO(user): Need to generate 3072 bit test for provisioner certificates.
|
||||
provisioner_certificate->set_public_key(
|
||||
test_keys_.public_test_key_1_3072_bits());
|
||||
test_rsa_keys_.public_test_key_1_3072_bits());
|
||||
provisioner_certificate->set_system_id(system_id);
|
||||
provisioner_certificate->set_provider_id(provider_id);
|
||||
provisioner_certificate->set_creation_time_seconds(1234);
|
||||
@@ -264,7 +266,7 @@ SignedDrmCertificate* ClientCertTest::GenerateSignedProvisionerCertificate(
|
||||
std::unique_ptr<DrmCertificate> provisioner_certificate(
|
||||
GenerateProvisionerCertificate(system_id, serial_number, service_id));
|
||||
return SignCertificate(*provisioner_certificate, nullptr,
|
||||
test_keys_.private_test_key_1_3072_bits());
|
||||
test_rsa_keys_.private_test_key_1_3072_bits());
|
||||
}
|
||||
|
||||
TEST_F(ClientCertTest, BasicValidation) {
|
||||
@@ -302,8 +304,7 @@ TEST_F(ClientCertTest, BasicCertValidation) {
|
||||
nullptr, system_id, serial_number),
|
||||
system_id, serial_number + "-device"));
|
||||
const TestCertificateAndData kValidCertificateAndExpectedData(
|
||||
signed_cert->SerializeAsString(), serial_number, system_id,
|
||||
util::OkStatus());
|
||||
signed_cert->SerializeAsString(), serial_number, system_id, OkStatus());
|
||||
const bool compare_data = true;
|
||||
TestBasicValidationDrmCertificate(kValidCertificateAndExpectedData,
|
||||
compare_data);
|
||||
@@ -347,7 +348,7 @@ TEST_F(ClientCertTest, InvalidCertificate) {
|
||||
new SignedDrmCertificate);
|
||||
invalid_drm_cert->set_drm_certificate("bad-serialized-cert");
|
||||
GenerateSignature(invalid_drm_cert->drm_certificate(),
|
||||
test_keys_.private_test_key_2_2048_bits(),
|
||||
test_rsa_keys_.private_test_key_2_2048_bits(),
|
||||
invalid_drm_cert->mutable_signature());
|
||||
invalid_drm_cert->set_allocated_signer(
|
||||
GenerateSignedIntermediateCertificate(nullptr, system_id, signer_sn));
|
||||
@@ -357,18 +358,18 @@ TEST_F(ClientCertTest, InvalidCertificate) {
|
||||
std::unique_ptr<SignedDrmCertificate> bad_device_public_key(SignCertificate(
|
||||
*dev_cert,
|
||||
GenerateSignedIntermediateCertificate(nullptr, system_id, signer_sn),
|
||||
test_keys_.private_test_key_2_2048_bits()));
|
||||
test_rsa_keys_.private_test_key_2_2048_bits()));
|
||||
// Invalid serialized intermediate certificate.
|
||||
signed_signer.reset(
|
||||
GenerateSignedIntermediateCertificate(nullptr, system_id, signer_sn));
|
||||
signed_signer->set_drm_certificate("bad-serialized-cert");
|
||||
GenerateSignature(signed_signer->drm_certificate(),
|
||||
test_keys_.private_test_key_1_3072_bits(),
|
||||
test_rsa_keys_.private_test_key_1_3072_bits(),
|
||||
signed_signer->mutable_signature());
|
||||
dev_cert.reset(GenerateDrmCertificate(system_id, device_sn));
|
||||
std::unique_ptr<SignedDrmCertificate> invalid_signer(
|
||||
SignCertificate(*dev_cert, signed_signer.release(),
|
||||
test_keys_.private_test_key_2_2048_bits()));
|
||||
test_rsa_keys_.private_test_key_2_2048_bits()));
|
||||
// Invalid signer public key.
|
||||
dev_cert.reset(GenerateDrmCertificate(system_id, device_sn));
|
||||
signer_cert.reset(GenerateIntermediateCertificate(system_id, signer_sn));
|
||||
@@ -376,8 +377,8 @@ TEST_F(ClientCertTest, InvalidCertificate) {
|
||||
std::unique_ptr<SignedDrmCertificate> bad_signer_public_key(SignCertificate(
|
||||
*dev_cert,
|
||||
SignCertificate(*signer_cert, nullptr,
|
||||
test_keys_.private_test_key_1_3072_bits()),
|
||||
test_keys_.private_test_key_2_2048_bits()));
|
||||
test_rsa_keys_.private_test_key_1_3072_bits()),
|
||||
test_rsa_keys_.private_test_key_2_2048_bits()));
|
||||
// Invalid device certificate signature.
|
||||
std::unique_ptr<SignedDrmCertificate> bad_device_signature(
|
||||
GenerateSignedDrmCertificate(
|
||||
@@ -391,8 +392,8 @@ TEST_F(ClientCertTest, InvalidCertificate) {
|
||||
std::unique_ptr<SignedDrmCertificate> missing_model_sn(SignCertificate(
|
||||
*dev_cert,
|
||||
SignCertificate(*signer_cert, nullptr,
|
||||
test_keys_.private_test_key_1_3072_bits()),
|
||||
test_keys_.private_test_key_2_2048_bits()));
|
||||
test_rsa_keys_.private_test_key_1_3072_bits()),
|
||||
test_rsa_keys_.private_test_key_2_2048_bits()));
|
||||
// Missing signer serial number.
|
||||
dev_cert.reset(GenerateDrmCertificate(system_id, device_sn));
|
||||
signer_cert.reset(GenerateIntermediateCertificate(system_id, signer_sn));
|
||||
@@ -400,8 +401,8 @@ TEST_F(ClientCertTest, InvalidCertificate) {
|
||||
std::unique_ptr<SignedDrmCertificate> missing_signer_sn(SignCertificate(
|
||||
*dev_cert,
|
||||
SignCertificate(*signer_cert, nullptr,
|
||||
test_keys_.private_test_key_1_3072_bits()),
|
||||
test_keys_.private_test_key_2_2048_bits()));
|
||||
test_rsa_keys_.private_test_key_1_3072_bits()),
|
||||
test_rsa_keys_.private_test_key_2_2048_bits()));
|
||||
// Invalid serialized intermediate certificate.
|
||||
dev_cert.reset(GenerateDrmCertificate(system_id, device_sn));
|
||||
signed_signer.reset(
|
||||
@@ -409,37 +410,36 @@ TEST_F(ClientCertTest, InvalidCertificate) {
|
||||
signed_signer->set_signature("bad-signature");
|
||||
std::unique_ptr<SignedDrmCertificate> bad_signer_signature(
|
||||
SignCertificate(*dev_cert, signed_signer.release(),
|
||||
test_keys_.private_test_key_2_2048_bits()));
|
||||
test_rsa_keys_.private_test_key_2_2048_bits()));
|
||||
|
||||
const TestCertificateAndData kInvalidCertificate[] = {
|
||||
TestCertificateAndData("f", "", 0,
|
||||
util::Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"invalid-signed-drm-certificate")),
|
||||
Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"invalid-signed-drm-certificate")),
|
||||
TestCertificateAndData(invalid_drm_cert->SerializeAsString(), "", 0,
|
||||
util::Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"invalid-drm-certificate")),
|
||||
Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"invalid-drm-certificate")),
|
||||
TestCertificateAndData(bad_device_public_key->SerializeAsString(), "", 0,
|
||||
util::Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"drm-certificate-public-key-failed")),
|
||||
Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"drm-certificate-public-key-failed")),
|
||||
TestCertificateAndData(invalid_signer->SerializeAsString(), "", 0,
|
||||
util::Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"invalid-signer-certificate")),
|
||||
Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"invalid-signer-certificate")),
|
||||
TestCertificateAndData(bad_signer_public_key->SerializeAsString(), "", 0,
|
||||
util::Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"invalid-leaf-signer-public-key")),
|
||||
Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"invalid-leaf-signer-public-key")),
|
||||
TestCertificateAndData(bad_device_signature->SerializeAsString(), "", 0,
|
||||
util::Status(error_space, INVALID_SIGNATURE,
|
||||
"cache-miss-invalid-signature")),
|
||||
TestCertificateAndData(
|
||||
missing_model_sn->SerializeAsString(), "", 0,
|
||||
util::Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"model-certificate-missing-system-id")),
|
||||
Status(error_space, INVALID_SIGNATURE,
|
||||
"cache-miss-invalid-signature")),
|
||||
TestCertificateAndData(missing_model_sn->SerializeAsString(), "", 0,
|
||||
Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"model-certificate-missing-system-id")),
|
||||
TestCertificateAndData(missing_signer_sn->SerializeAsString(), "", 0,
|
||||
util::Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"missing-signer-serial-number")),
|
||||
Status(error_space, INVALID_DRM_CERTIFICATE,
|
||||
"missing-signer-serial-number")),
|
||||
TestCertificateAndData(bad_signer_signature->SerializeAsString(), "", 0,
|
||||
util::Status(error_space, INVALID_SIGNATURE,
|
||||
"cache-miss-invalid-signature")),
|
||||
Status(error_space, INVALID_SIGNATURE,
|
||||
"cache-miss-invalid-signature")),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ABSL_ARRAYSIZE(kInvalidCertificate); ++i) {
|
||||
@@ -454,7 +454,7 @@ TEST_F(ClientCertTest, MissingPreProvKey) {
|
||||
"beaa24924907e128f9ff49b54a165cd9c33e6547537eb4d29fb7e8df3c2c1cd9"
|
||||
"2517a12f4922953e"));
|
||||
ClientCert* client_cert_ptr = nullptr;
|
||||
util::Status status = ClientCert::CreateWithKeybox(token, &client_cert_ptr);
|
||||
Status status = ClientCert::CreateWithKeybox(token, &client_cert_ptr);
|
||||
ASSERT_EQ(MISSING_PRE_PROV_KEY, status.error_code());
|
||||
}
|
||||
|
||||
@@ -563,4 +563,55 @@ TEST_F(ClientCertTest, InvalidProvisionerDeviceCertChain) {
|
||||
EXPECT_FALSE(client_cert_ptr);
|
||||
}
|
||||
|
||||
TEST_F(ClientCertTest, Protocol21WithDrmCert) {
|
||||
const char message[] = "A weekend wasted is a weekend well spent.";
|
||||
|
||||
ClientCert* client_cert_ptr = nullptr;
|
||||
ASSERT_OK(ClientCert::Create(
|
||||
root_cert_.get(), ClientIdentification::DRM_DEVICE_CERTIFICATE,
|
||||
test_drm_certs_.test_user_device_certificate(), &client_cert_ptr));
|
||||
std::unique_ptr<ClientCert> client_cert(client_cert_ptr);
|
||||
|
||||
std::unique_ptr<RsaPrivateKey> private_key(
|
||||
RsaPrivateKey::Create(test_rsa_keys_.private_test_key_3_2048_bits()));
|
||||
ASSERT_TRUE(private_key);
|
||||
|
||||
// Success
|
||||
std::string signature;
|
||||
ASSERT_TRUE(private_key->GenerateSignature(message, &signature));
|
||||
EXPECT_OK(client_cert->VerifySignature(message, signature, VERSION_2_1));
|
||||
|
||||
// Failure
|
||||
ASSERT_EQ(256, signature.size());
|
||||
++signature[127];
|
||||
EXPECT_FALSE(
|
||||
client_cert->VerifySignature(message, signature, VERSION_2_1).ok());
|
||||
}
|
||||
|
||||
TEST_F(ClientCertTest, Protocol22WithDrmCert) {
|
||||
const char message[] = "There is nothing permanent except change.";
|
||||
const std::string message_hash(Sha512_Hash(message));
|
||||
|
||||
ClientCert* client_cert_ptr = nullptr;
|
||||
ASSERT_OK(ClientCert::Create(
|
||||
root_cert_.get(), ClientIdentification::DRM_DEVICE_CERTIFICATE,
|
||||
test_drm_certs_.test_user_device_certificate(), &client_cert_ptr));
|
||||
std::unique_ptr<ClientCert> client_cert(client_cert_ptr);
|
||||
|
||||
std::unique_ptr<RsaPrivateKey> private_key(
|
||||
RsaPrivateKey::Create(test_rsa_keys_.private_test_key_3_2048_bits()));
|
||||
ASSERT_TRUE(private_key);
|
||||
|
||||
// Success
|
||||
std::string signature;
|
||||
ASSERT_TRUE(private_key->GenerateSignature(message_hash, &signature));
|
||||
EXPECT_OK(client_cert->VerifySignature(message, signature, VERSION_2_2));
|
||||
|
||||
// Failure
|
||||
ASSERT_EQ(256, signature.size());
|
||||
++signature[127];
|
||||
EXPECT_FALSE(
|
||||
client_cert->VerifySignature(message, signature, VERSION_2_2).ok());
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
Reference in New Issue
Block a user