Minimal implementation of Widevine MediaCAS ECMG.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=226515998
This commit is contained in:
Fang Yu
2018-12-21 11:17:37 -08:00
parent 7487ce5aa8
commit bc68878bdf
88 changed files with 2456 additions and 2774 deletions

View File

@@ -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