723 lines
29 KiB
C++
723 lines
29 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.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "provisioning_sdk/internal/provisioning_engine_impl.h"
|
|
|
|
#include <ctime>
|
|
#include <memory>
|
|
|
|
#include "glog/logging.h"
|
|
#include "testing/gmock.h"
|
|
#include "testing/gunit.h"
|
|
#include "common/certificate_type.h"
|
|
#include "common/mock_rsa_key.h"
|
|
#include "common/rsa_test_keys.h"
|
|
#include "common/rsa_util.h"
|
|
#include "common/test_drm_certificates.h"
|
|
|
|
using ::testing::_;
|
|
using ::testing::ByMove;
|
|
using ::testing::DoAll;
|
|
using ::testing::Invoke;
|
|
using ::testing::Return;
|
|
using ::testing::SaveArg;
|
|
using ::testing::SetArgPointee;
|
|
using ::testing::StrEq;
|
|
|
|
namespace {
|
|
const int kSystemId = 100;
|
|
const int kExpirationPeriodSeconds = 3600;
|
|
const int kInfiniteExpirationPeriodSeconds = 0;
|
|
const char kEmptyOemSerialNumber[] = "";
|
|
const char kSecretSauce[] = "Twas bryllyg, and ye slythy toves";
|
|
const char RootCertificateSerialNumber[] = "certificate_serial_number";
|
|
const char kDrmRootPublicKey[] = "drm_root_public_key";
|
|
const char kOemSerialNumber0[] = "oem_serial_number_0";
|
|
const char kOemSerialNumber1[] = "oem_serial_number_1";
|
|
const char kDevicePublicKey[] = "device_public_key";
|
|
const char kSignature[] = "mock_signature";
|
|
const char kIntermediatePrivateKey[] = "intermediate_private_key";
|
|
const char kIntermediatePrivateKeyPassphrase[] =
|
|
"intermediate_private_key_passphrase";
|
|
const char kIntermediatePublicKey[] = "intermediate_public_key";
|
|
const char kServicePrivateKeyPassphrase[] = "service_private_key_passphrase";
|
|
const char kProvisioningDrmCertificate[] = "provisioning_drm_certificate";
|
|
const char kProvisioningPrivateKey[] = "provisioning_private_key";
|
|
const char kProvisioningPrivateKeyPassphrase[] =
|
|
"provisioning_private_key_passphrase";
|
|
const char kProvisioningPublicKey[] = "provisioning_public_key";
|
|
const char kProvisioningSignature[] = "provisioning_signature";
|
|
|
|
// A simple std::string concatenation function. This assumes i within [0, 9].
|
|
std::string StrCat(const std::string& in, int i) {
|
|
DCHECK_LE(i, 9);
|
|
DCHECK_GE(i, 0);
|
|
std::string out = in + "0";
|
|
out[out.size() - 1] += i;
|
|
return out;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace widevine {
|
|
|
|
class MockDrmRootCertificate : public DrmRootCertificate {
|
|
public:
|
|
MockDrmRootCertificate()
|
|
: DrmRootCertificate(kCertificateTypeTesting, std::string(),
|
|
std::string(), kDrmRootPublicKey,
|
|
std::unique_ptr<RsaKeyFactory>()) {}
|
|
|
|
MOCK_METHOD(Status, VerifyCertificate,
|
|
(const std::string& serialized_cert,
|
|
SignedDrmCertificate* signed_drm_cert, DrmCertificate* drm_cert),
|
|
(const, override));
|
|
};
|
|
|
|
class ProvisioningEngineImplTest : public ::testing::Test {
|
|
protected:
|
|
ProvisioningEngineImplTest() {
|
|
RsaTestKeys test_keys;
|
|
rsa_util::RsaPrivateKeyToEncryptedPrivateKeyInfo(
|
|
test_keys.private_test_key_2_2048_bits(), kServicePrivateKeyPassphrase,
|
|
&service_private_key_);
|
|
TestDrmCertificates test_certificates;
|
|
service_certificate_ = test_certificates.test_service_certificate_no_type();
|
|
}
|
|
|
|
ProvisioningStatus CheckDeviceStatus(
|
|
uint32_t system_id, const std::string& oem_ca_serial_number) {
|
|
return engine_impl_.CheckDeviceStatus(system_id, oem_ca_serial_number);
|
|
}
|
|
|
|
ProvisioningEngineImpl engine_impl_;
|
|
std::string service_certificate_;
|
|
std::string service_private_key_;
|
|
};
|
|
|
|
TEST_F(ProvisioningEngineImplTest, InvalidDrmServiceCertificate) {
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE,
|
|
engine_impl_.Initialize(
|
|
kCertificateTypeTesting, "bad-certificate",
|
|
service_private_key_, kServicePrivateKeyPassphrase,
|
|
kProvisioningDrmCertificate, kProvisioningPrivateKey,
|
|
kProvisioningPrivateKeyPassphrase, kSecretSauce));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplTest, InvalidServiceKey) {
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE,
|
|
engine_impl_.Initialize(
|
|
kCertificateTypeTesting, service_certificate_, "bad_key",
|
|
kServicePrivateKeyPassphrase, kProvisioningDrmCertificate,
|
|
kProvisioningPrivateKey, kProvisioningPrivateKeyPassphrase,
|
|
kSecretSauce));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplTest, InvalidServiceKeyPassprase) {
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE,
|
|
engine_impl_.Initialize(
|
|
kCertificateTypeTesting, service_certificate_,
|
|
service_private_key_, "bad-passphrase",
|
|
kProvisioningDrmCertificate, kProvisioningPrivateKey,
|
|
kProvisioningPrivateKeyPassphrase, kSecretSauce));
|
|
}
|
|
|
|
class ProvisioningEngineImplProvTest : public ProvisioningEngineImplTest {
|
|
protected:
|
|
void SetUp() override {
|
|
prov_cert_.set_public_key(kProvisioningPublicKey);
|
|
prov_cert_.set_type(DrmCertificate::PROVISIONER);
|
|
signed_prov_cert_.set_drm_certificate(prov_cert_.SerializeAsString());
|
|
signed_prov_cert_.set_signature(kProvisioningSignature);
|
|
|
|
SetUpMockDrmRootCertificateWithExpectations();
|
|
SetUpMockRsa();
|
|
SetUpMockRootPublicKey();
|
|
}
|
|
|
|
void SetUpMockDrmRootCertificateWithExpectations() {
|
|
mock_drm_root_certificate_ = new MockDrmRootCertificate;
|
|
engine_impl_.set_drm_root_certificate(
|
|
std::unique_ptr<DrmRootCertificate>(mock_drm_root_certificate_));
|
|
|
|
EXPECT_CALL(*mock_drm_root_certificate_, VerifyCertificate(_, _, _))
|
|
.WillRepeatedly(Invoke([](const std::string& serialized_cert,
|
|
SignedDrmCertificate* signed_drm_cert,
|
|
DrmCertificate* drm_cert) {
|
|
SignedDrmCertificate signed_cert;
|
|
if (!signed_cert.ParseFromString(serialized_cert)) {
|
|
return Status(error::INVALID_ARGUMENT,
|
|
"Invalid SignedDrmCertificate proto");
|
|
}
|
|
if (signed_drm_cert) *signed_drm_cert = signed_cert;
|
|
if (drm_cert) {
|
|
EXPECT_TRUE(
|
|
drm_cert->ParseFromString(signed_cert.drm_certificate()));
|
|
}
|
|
return OkStatus();
|
|
}));
|
|
}
|
|
|
|
void SetUpMockRsa() {
|
|
mock_rsa_key_factory_ = new MockRsaKeyFactory;
|
|
engine_impl_.set_rsa_key_factory(
|
|
std::unique_ptr<RsaKeyFactory>(mock_rsa_key_factory_));
|
|
}
|
|
|
|
void SetUpMockRootPublicKey() {
|
|
mock_root_public_key_ = new MockRsaPublicKey();
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kDrmRootPublicKey))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPublicKey>(mock_root_public_key_))));
|
|
}
|
|
|
|
ProvisioningStatus Initialize(
|
|
const std::string& provisioning_drm_certificate) {
|
|
return engine_impl_.Initialize(
|
|
kCertificateTypeTesting, service_certificate_, service_private_key_,
|
|
kServicePrivateKeyPassphrase, provisioning_drm_certificate,
|
|
kProvisioningPrivateKey, kProvisioningPrivateKeyPassphrase,
|
|
kSecretSauce);
|
|
}
|
|
|
|
RsaTestKeys test_keys_;
|
|
MockRsaKeyFactory* mock_rsa_key_factory_ = nullptr;
|
|
MockDrmRootCertificate* mock_drm_root_certificate_ = nullptr;
|
|
MockRsaPublicKey* mock_root_public_key_ = nullptr;
|
|
DrmCertificate prov_cert_;
|
|
SignedDrmCertificate signed_prov_cert_;
|
|
};
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, InvalidDeviceCertType) {
|
|
prov_cert_.set_type(DrmCertificate::SERVICE);
|
|
signed_prov_cert_.set_drm_certificate(prov_cert_.SerializeAsString());
|
|
EXPECT_EQ(INVALID_PROVISIONER_DRM_CERTIFICATE,
|
|
Initialize(signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, InvalidPublicKey) {
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kProvisioningPublicKey))
|
|
.WillOnce(Return(ByMove(nullptr)));
|
|
EXPECT_EQ(INVALID_PROVISIONER_DRM_CERTIFICATE,
|
|
Initialize(signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, InvalidPrivateKey) {
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kProvisioningPublicKey))
|
|
.WillOnce(
|
|
Return(ByMove(std::unique_ptr<RsaPublicKey>(new MockRsaPublicKey))));
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kProvisioningPrivateKey,
|
|
kProvisioningPrivateKeyPassphrase))
|
|
.WillOnce(Return(ByMove(nullptr)));
|
|
EXPECT_EQ(INVALID_PROVISIONER_PRIVATE_KEY,
|
|
Initialize(signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, MismatchPublicKeyPrivateKey) {
|
|
MockRsaPublicKey* mock_rsa_public_key = new MockRsaPublicKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kProvisioningPublicKey))
|
|
.WillOnce(
|
|
Return(ByMove(std::unique_ptr<RsaPublicKey>(mock_rsa_public_key))));
|
|
MockRsaPrivateKey* mock_rsa_private_key = new MockRsaPrivateKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kProvisioningPrivateKey,
|
|
kProvisioningPrivateKeyPassphrase))
|
|
.WillOnce(
|
|
Return(ByMove(std::unique_ptr<RsaPrivateKey>(mock_rsa_private_key))));
|
|
EXPECT_CALL(*mock_rsa_public_key, MatchesPrivateKey(_))
|
|
.WillOnce(Return(false));
|
|
EXPECT_EQ(INVALID_PROVISIONER_PRIVATE_KEY,
|
|
Initialize(signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
class ProvisioningEngineImplContextTest
|
|
: public ProvisioningEngineImplProvTest {
|
|
protected:
|
|
void SetUp() override {
|
|
ProvisioningEngineImplProvTest::SetUp();
|
|
|
|
SetUpMockRsaExpectations();
|
|
ASSERT_EQ(OK, ProvisioningEngineImplProvTest::Initialize(
|
|
signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
void SetUpMockRsaExpectations() {
|
|
MockRsaPublicKey* mock_prov_public_key(new MockRsaPublicKey);
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kProvisioningPublicKey))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPublicKey>(mock_prov_public_key))));
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kProvisioningPrivateKey,
|
|
kProvisioningPrivateKeyPassphrase))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPrivateKey>(new MockRsaPrivateKey))));
|
|
EXPECT_CALL(*mock_prov_public_key, MatchesPrivateKey(_))
|
|
.WillOnce(Return(true));
|
|
}
|
|
};
|
|
|
|
TEST_F(ProvisioningEngineImplContextTest, ContextStoreAndRetrieveSuccess) {
|
|
const char kContextData[] = "I dislike tacky orange things";
|
|
SignedProvisioningContext signed_context;
|
|
ASSERT_EQ(OK, engine_impl_.StoreContext(kContextData, &signed_context));
|
|
EXPECT_FALSE(signed_context.signature().empty());
|
|
std::string context_data;
|
|
ASSERT_EQ(OK, engine_impl_.RetrieveContext(signed_context, &context_data));
|
|
EXPECT_EQ(kContextData, context_data);
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplContextTest, ContextStoreAndRetrieveFailBadData) {
|
|
const char kContextData[] = "Climate change is not a hoax";
|
|
SignedProvisioningContext signed_context;
|
|
ASSERT_EQ(OK, engine_impl_.StoreContext(kContextData, &signed_context));
|
|
++(*signed_context.mutable_provisioning_context())[5];
|
|
std::string context_data;
|
|
ASSERT_EQ(INVALID_CONTEXT,
|
|
engine_impl_.RetrieveContext(signed_context, &context_data));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplContextTest,
|
|
ContextStoreAndRetrieveFailBadSignature) {
|
|
const char kContextData[] = "No one wants coal anymore";
|
|
SignedProvisioningContext signed_context;
|
|
ASSERT_EQ(OK, engine_impl_.StoreContext(kContextData, &signed_context));
|
|
++(*signed_context.mutable_signature())[5];
|
|
std::string context_data;
|
|
ASSERT_EQ(INVALID_CONTEXT,
|
|
engine_impl_.RetrieveContext(signed_context, &context_data));
|
|
}
|
|
|
|
class ProvisioningEngineImplGeneralTest
|
|
: public ProvisioningEngineImplProvTest {
|
|
protected:
|
|
void SetUp() override {
|
|
ProvisioningEngineImplProvTest::SetUp();
|
|
SetUpMockProvisionerKey();
|
|
|
|
// Set up a DrmCertificate to be used later.
|
|
intermediate_cert_.set_type(DrmCertificate::DEVICE_MODEL);
|
|
intermediate_cert_.set_system_id(kSystemId);
|
|
intermediate_cert_.set_public_key(kIntermediatePublicKey);
|
|
signed_intermediate_cert_.set_drm_certificate(
|
|
intermediate_cert_.SerializeAsString());
|
|
signed_intermediate_cert_.set_signature(kSignature);
|
|
|
|
ASSERT_EQ(OK, ProvisioningEngineImplProvTest::Initialize(
|
|
signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
void SetUpMockProvisionerKey() {
|
|
mock_prov_public_key_ = new MockRsaPublicKey();
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kProvisioningPublicKey))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPublicKey>(mock_prov_public_key_))));
|
|
|
|
mock_prov_private_key_ = new MockRsaPrivateKey();
|
|
ON_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kProvisioningPrivateKey,
|
|
kProvisioningPrivateKeyPassphrase))
|
|
.WillByDefault(Return(
|
|
ByMove(std::unique_ptr<RsaPrivateKey>(mock_prov_private_key_))));
|
|
EXPECT_CALL(*mock_prov_public_key_, MatchesPrivateKey(_))
|
|
.WillOnce(Return(true));
|
|
}
|
|
|
|
void SetUpDcsl() {
|
|
// SetUp certificate status list.
|
|
cert_status_list_.set_creation_time_seconds(time(nullptr));
|
|
for (int i = 0; i < 2; ++i) {
|
|
DeviceCertificateStatus* cert_status =
|
|
cert_status_list_.add_certificate_status();
|
|
cert_status->set_oem_serial_number(StrCat("oem_serial_number_", i));
|
|
ProvisionedDeviceInfo* device_info = cert_status->mutable_device_info();
|
|
device_info->set_system_id(kSystemId + i);
|
|
device_info->set_model(StrCat("model_", i));
|
|
}
|
|
cert_status_list_.mutable_certificate_status(0)->set_status(
|
|
DeviceCertificateStatus::STATUS_RELEASED);
|
|
cert_status_list_.mutable_certificate_status(1)->set_status(
|
|
DeviceCertificateStatus::STATUS_REVOKED);
|
|
|
|
SignedDeviceCertificateStatusList signed_cert_status_list;
|
|
signed_cert_status_list.set_certificate_status_list(
|
|
cert_status_list_.SerializeAsString());
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(
|
|
StrEq(signed_cert_status_list.certificate_status_list()), _,
|
|
"cert_status_list_signature"))
|
|
.WillOnce(Return(true));
|
|
signed_cert_status_list.set_signature("cert_status_list_signature");
|
|
ASSERT_EQ(OK, engine_impl_.SetCertificateStatusList(
|
|
signed_cert_status_list.SerializeAsString(),
|
|
kInfiniteExpirationPeriodSeconds));
|
|
}
|
|
|
|
MockRsaPublicKey* mock_prov_public_key_ = nullptr;
|
|
MockRsaPrivateKey* mock_prov_private_key_ = nullptr;
|
|
DeviceCertificateStatusList cert_status_list_;
|
|
DrmCertificate intermediate_cert_;
|
|
SignedDrmCertificate signed_intermediate_cert_;
|
|
};
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest, InvalidCertificateStatusList) {
|
|
EXPECT_EQ(INVALID_STATUS_LIST, engine_impl_.SetCertificateStatusList(
|
|
"", kExpirationPeriodSeconds));
|
|
EXPECT_EQ(INVALID_STATUS_LIST,
|
|
engine_impl_.SetCertificateStatusList(
|
|
"invalid_certificate_status_list", kExpirationPeriodSeconds));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
CertificateStatusListIncorrectSignature) {
|
|
SignedDeviceCertificateStatusList signed_cert_status_list;
|
|
signed_cert_status_list.set_certificate_status_list(
|
|
cert_status_list_.SerializeAsString());
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(_, _, "cert_status_list_signature"))
|
|
.WillOnce(Return(false));
|
|
signed_cert_status_list.set_signature("cert_status_list_signature");
|
|
ASSERT_EQ(INVALID_STATUS_LIST,
|
|
engine_impl_.SetCertificateStatusList(
|
|
signed_cert_status_list.SerializeAsString(),
|
|
kExpirationPeriodSeconds));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest, GetDeviceInfoAndCheckDeviceStatus) {
|
|
SetUpDcsl();
|
|
|
|
EXPECT_EQ(OK, CheckDeviceStatus(kSystemId, kEmptyOemSerialNumber));
|
|
auto device_info = engine_impl_.GetDeviceInfo(kSystemId);
|
|
ASSERT_NE(nullptr, device_info);
|
|
EXPECT_EQ("model_0", device_info->model());
|
|
|
|
EXPECT_EQ(DEVICE_REVOKED,
|
|
CheckDeviceStatus(kSystemId + 1, kEmptyOemSerialNumber));
|
|
// We can still query device info for revoked device.
|
|
device_info = engine_impl_.GetDeviceInfo(kSystemId + 1);
|
|
ASSERT_NE(nullptr, device_info);
|
|
EXPECT_EQ("model_1", device_info->model());
|
|
|
|
EXPECT_EQ(UNKNOWN_SYSTEM_ID,
|
|
CheckDeviceStatus(kSystemId + 2, kEmptyOemSerialNumber));
|
|
EXPECT_EQ(nullptr, engine_impl_.GetDeviceInfo(kSystemId + 2));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest, UpdateCertificateStatusList) {
|
|
SetUpDcsl();
|
|
|
|
cert_status_list_.mutable_certificate_status(0)->set_status(
|
|
DeviceCertificateStatus::STATUS_REVOKED);
|
|
|
|
DeviceCertificateStatus* cert_status =
|
|
cert_status_list_.add_certificate_status();
|
|
ProvisionedDeviceInfo* device_info = cert_status->mutable_device_info();
|
|
device_info->set_system_id(kSystemId + 2);
|
|
device_info->set_model("model_2");
|
|
|
|
SignedDeviceCertificateStatusList signed_cert_status_list;
|
|
signed_cert_status_list.set_certificate_status_list(
|
|
cert_status_list_.SerializeAsString());
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(_, _, "cert_status_list_signature"))
|
|
.WillOnce(Return(true));
|
|
signed_cert_status_list.set_signature("cert_status_list_signature");
|
|
ASSERT_EQ(OK, engine_impl_.SetCertificateStatusList(
|
|
signed_cert_status_list.SerializeAsString(),
|
|
kInfiniteExpirationPeriodSeconds));
|
|
|
|
// Now device with system id = kSystemId is revoked.
|
|
EXPECT_EQ(DEVICE_REVOKED,
|
|
CheckDeviceStatus(kSystemId, kEmptyOemSerialNumber));
|
|
EXPECT_EQ("model_0", engine_impl_.GetDeviceInfo(kSystemId)->model());
|
|
EXPECT_EQ(DEVICE_REVOKED,
|
|
CheckDeviceStatus(kSystemId + 1, kEmptyOemSerialNumber));
|
|
EXPECT_EQ("model_1", engine_impl_.GetDeviceInfo(kSystemId + 1)->model());
|
|
EXPECT_EQ(OK, CheckDeviceStatus(kSystemId + 2, kEmptyOemSerialNumber));
|
|
EXPECT_EQ("model_2", engine_impl_.GetDeviceInfo(kSystemId + 2)->model());
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
GenerateDrmIntermediateCertificateInvalidPublicKey) {
|
|
std::string drm_certificate;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kIntermediatePublicKey))
|
|
.WillOnce(Return(ByMove(nullptr)));
|
|
std::string certificate;
|
|
ASSERT_EQ(INVALID_INTERMEDIATE_PUBLIC_KEY,
|
|
engine_impl_.GenerateDrmIntermediateCertificate(
|
|
kSystemId, kIntermediatePublicKey, &certificate));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest, GenerateDrmIntermediateCertificate) {
|
|
std::string drm_certificate;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kIntermediatePublicKey))
|
|
.WillOnce(
|
|
Return(ByMove(std::unique_ptr<RsaPublicKey>(new MockRsaPublicKey))));
|
|
EXPECT_CALL(*mock_prov_private_key_, GenerateSignature(_, _, _))
|
|
.WillOnce(DoAll(SaveArg<0>(&drm_certificate),
|
|
SetArgPointee<2>(kSignature), Return(true)));
|
|
std::string certificate;
|
|
ASSERT_EQ(OK, engine_impl_.GenerateDrmIntermediateCertificate(
|
|
kSystemId, kIntermediatePublicKey, &certificate));
|
|
|
|
SignedDrmCertificate signed_drm_cert_proto;
|
|
ASSERT_TRUE(signed_drm_cert_proto.ParseFromString(certificate));
|
|
EXPECT_EQ(drm_certificate, signed_drm_cert_proto.drm_certificate());
|
|
EXPECT_EQ(kSignature, signed_drm_cert_proto.signature());
|
|
EXPECT_EQ(signed_prov_cert_.SerializeAsString(),
|
|
signed_drm_cert_proto.signer().SerializeAsString());
|
|
|
|
DrmCertificate drm_cert_proto;
|
|
ASSERT_TRUE(drm_cert_proto.ParseFromString(drm_certificate));
|
|
EXPECT_EQ(DrmCertificate::DEVICE_MODEL, drm_cert_proto.type());
|
|
EXPECT_NE("", drm_cert_proto.serial_number());
|
|
EXPECT_EQ(kSystemId, drm_cert_proto.system_id());
|
|
EXPECT_EQ(kIntermediatePublicKey, drm_cert_proto.public_key());
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateInvalidCert) {
|
|
EXPECT_EQ(
|
|
INVALID_INTERMEDIATE_DRM_CERTIFICATE,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
"", kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
EXPECT_EQ(INVALID_INTERMEDIATE_DRM_CERTIFICATE,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
"invalid_intermediate_cert", kIntermediatePrivateKey,
|
|
kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateIncorrectCertType) {
|
|
intermediate_cert_.set_type(DrmCertificate::DEVICE);
|
|
signed_intermediate_cert_.set_drm_certificate(
|
|
intermediate_cert_.SerializeAsString());
|
|
|
|
EXPECT_EQ(INVALID_INTERMEDIATE_DRM_CERTIFICATE,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateMissingSystemId) {
|
|
intermediate_cert_.clear_system_id();
|
|
signed_intermediate_cert_.set_drm_certificate(
|
|
intermediate_cert_.SerializeAsString());
|
|
|
|
EXPECT_EQ(UNKNOWN_SYSTEM_ID,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateRevokedCert) {
|
|
SetUpDcsl();
|
|
|
|
intermediate_cert_.set_system_id(kSystemId + 1);
|
|
signed_intermediate_cert_.set_drm_certificate(
|
|
intermediate_cert_.SerializeAsString());
|
|
|
|
EXPECT_EQ(DEVICE_REVOKED,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateInvalidPublicKey) {
|
|
SetUpDcsl();
|
|
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kIntermediatePublicKey))
|
|
.WillOnce(Return(ByMove(nullptr)));
|
|
EXPECT_EQ(INVALID_INTERMEDIATE_DRM_CERTIFICATE,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateInvalidPrivateKey) {
|
|
SetUpDcsl();
|
|
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kIntermediatePublicKey))
|
|
.WillOnce(
|
|
Return(ByMove(std::unique_ptr<RsaPublicKey>(new MockRsaPublicKey))));
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kIntermediatePrivateKey,
|
|
kIntermediatePrivateKeyPassphrase))
|
|
.WillOnce(Return(ByMove(nullptr)));
|
|
|
|
EXPECT_EQ(INVALID_INTERMEDIATE_PRIVATE_KEY,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateMismatchPublicPrivateKey) {
|
|
SetUpDcsl();
|
|
|
|
MockRsaPublicKey* mock_intermediate_public_key = new MockRsaPublicKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kIntermediatePublicKey))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPublicKey>(mock_intermediate_public_key))));
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kIntermediatePrivateKey,
|
|
kIntermediatePrivateKeyPassphrase))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPrivateKey>(new MockRsaPrivateKey))));
|
|
EXPECT_CALL(*mock_intermediate_public_key, MatchesPrivateKey(_))
|
|
.WillOnce(Return(false));
|
|
|
|
EXPECT_EQ(INVALID_INTERMEDIATE_PRIVATE_KEY,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateSuccess) {
|
|
SetUpDcsl();
|
|
|
|
MockRsaPublicKey* mock_intermediate_public_key = new MockRsaPublicKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kIntermediatePublicKey))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPublicKey>(mock_intermediate_public_key))));
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kIntermediatePrivateKey,
|
|
kIntermediatePrivateKeyPassphrase))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPrivateKey>(new MockRsaPrivateKey))));
|
|
EXPECT_CALL(*mock_intermediate_public_key, MatchesPrivateKey(_))
|
|
.WillOnce(Return(true));
|
|
|
|
EXPECT_EQ(OK,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest, ExpiredCertificateStatusList) {
|
|
cert_status_list_.set_creation_time_seconds(time(nullptr) -
|
|
kExpirationPeriodSeconds - 1);
|
|
|
|
SignedDeviceCertificateStatusList signed_cert_status_list;
|
|
signed_cert_status_list.set_certificate_status_list(
|
|
cert_status_list_.SerializeAsString());
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(_, _, "cert_status_list_signature"))
|
|
.WillOnce(Return(true));
|
|
signed_cert_status_list.set_signature("cert_status_list_signature");
|
|
ASSERT_EQ(OK, engine_impl_.SetCertificateStatusList(
|
|
signed_cert_status_list.SerializeAsString(),
|
|
kExpirationPeriodSeconds));
|
|
|
|
EXPECT_EQ(STATUS_LIST_EXPIRED,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
GenerateDeviceDrmCertificateRevokedDevice) {
|
|
SetUpDcsl();
|
|
|
|
std::string certificate;
|
|
EXPECT_EQ(DEVICE_REVOKED,
|
|
engine_impl_.GenerateDeviceDrmCertificate(
|
|
kSystemId + 1, kOemSerialNumber1, kDevicePublicKey,
|
|
RootCertificateSerialNumber, &certificate));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
GenerateDeviceDrmCertificateWithMismatchingOemSerialNumber) {
|
|
SetUpDcsl();
|
|
|
|
std::string certificate;
|
|
// If oem serial number does not match, consider as revoked.
|
|
EXPECT_EQ(DEVICE_REVOKED, engine_impl_.GenerateDeviceDrmCertificate(
|
|
kSystemId, kOemSerialNumber1, kDevicePublicKey,
|
|
RootCertificateSerialNumber, &certificate));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
GenerateDeviceDrmCertificateWithoutIntermediateCert) {
|
|
SetUpDcsl();
|
|
|
|
std::string certificate;
|
|
EXPECT_EQ(MISSING_DEVICE_MODEL_CERT,
|
|
engine_impl_.GenerateDeviceDrmCertificate(
|
|
kSystemId, kOemSerialNumber0, kDevicePublicKey,
|
|
RootCertificateSerialNumber, &certificate));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest, GenerateDeviceDrmCertificate) {
|
|
SetUpDcsl();
|
|
|
|
// Add Intermediate certificate.
|
|
|
|
MockRsaPublicKey* mock_intermediate_public_key = new MockRsaPublicKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey(kIntermediatePublicKey))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPublicKey>(mock_intermediate_public_key))));
|
|
MockRsaPrivateKey* mock_intermediate_private_key = new MockRsaPrivateKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kIntermediatePrivateKey,
|
|
kIntermediatePrivateKeyPassphrase))
|
|
.WillOnce(Return(ByMove(
|
|
std::unique_ptr<RsaPrivateKey>(mock_intermediate_private_key))));
|
|
EXPECT_CALL(*mock_intermediate_public_key, MatchesPrivateKey(_))
|
|
.WillOnce(Return(true));
|
|
|
|
EXPECT_EQ(OK,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
|
|
// Intermediate private key expectation.
|
|
std::string drm_certificate;
|
|
EXPECT_CALL(*mock_intermediate_private_key, GenerateSignature(_, _, _))
|
|
.WillOnce(DoAll(SaveArg<0>(&drm_certificate),
|
|
SetArgPointee<2>(kSignature), Return(true)));
|
|
std::string certificate;
|
|
EXPECT_EQ(OK, engine_impl_.GenerateDeviceDrmCertificate(
|
|
kSystemId, kOemSerialNumber0, kDevicePublicKey,
|
|
RootCertificateSerialNumber, &certificate));
|
|
|
|
SignedDrmCertificate signed_drm_cert_proto;
|
|
ASSERT_TRUE(signed_drm_cert_proto.ParseFromString(certificate));
|
|
EXPECT_EQ(drm_certificate, signed_drm_cert_proto.drm_certificate());
|
|
EXPECT_EQ(kSignature, signed_drm_cert_proto.signature());
|
|
EXPECT_THAT(signed_intermediate_cert_.SerializeAsString(),
|
|
signed_drm_cert_proto.signer().SerializeAsString());
|
|
|
|
DrmCertificate drm_cert_proto;
|
|
ASSERT_TRUE(drm_cert_proto.ParseFromString(drm_certificate));
|
|
EXPECT_EQ(DrmCertificate::DEVICE, drm_cert_proto.type());
|
|
EXPECT_EQ(RootCertificateSerialNumber, drm_cert_proto.serial_number());
|
|
EXPECT_EQ(kSystemId, drm_cert_proto.system_id());
|
|
EXPECT_EQ(kDevicePublicKey, drm_cert_proto.public_key());
|
|
}
|
|
|
|
} // namespace widevine
|