784 lines
33 KiB
C++
784 lines
33 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// Copyright 2016 Google Inc.
|
|
//
|
|
// 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 <time.h>
|
|
#include <memory>
|
|
|
|
#include "glog/logging.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
#include "common/mock_rsa_key.h"
|
|
#include "provisioning_sdk/public/certificate_type.h"
|
|
|
|
using ::testing::_;
|
|
using ::testing::ByMove;
|
|
using ::testing::DoAll;
|
|
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 kCertificateSerialNumber[] = "certificate_serial_number";
|
|
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 kServicePrivateKey[] = "service_private_key";
|
|
const char kServicePrivateKeyPassphrase[] = "service_private_key_phassphrase";
|
|
const char kServiceDrmCertificate[] = "service_drm_certificate";
|
|
const char kProvisioningDrmCertificate[] = "provisioning_drm_certificate";
|
|
const char kProvisioningPrivateKey[] = "provisioning_private_key";
|
|
const char kProvisioningPrivateKeyPassphrase[] =
|
|
"provisioning_private_key_phassphrase";
|
|
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 ProvisioningEngineImplTest : public ::testing::Test {
|
|
protected:
|
|
ProvisioningEngineImplTest() {
|
|
mock_rsa_key_factory_ = new MockRsaKeyFactory;
|
|
engine_impl_.set_rsa_key_factory(
|
|
std::unique_ptr<RsaKeyFactory>(mock_rsa_key_factory_));
|
|
}
|
|
|
|
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_;
|
|
MockRsaKeyFactory* mock_rsa_key_factory_ = nullptr;
|
|
};
|
|
|
|
TEST_F(ProvisioningEngineImplTest, InvalidCertType) {
|
|
CertificateType invalid_certificate = static_cast<CertificateType>(100);
|
|
EXPECT_EQ(
|
|
INVALID_CERTIFICATE_TYPE,
|
|
engine_impl_.Initialize(
|
|
invalid_certificate, kServiceDrmCertificate, kServicePrivateKey,
|
|
kServicePrivateKeyPassphrase, kProvisioningDrmCertificate,
|
|
kProvisioningPrivateKey, kProvisioningPrivateKeyPassphrase,
|
|
kSecretSauce));
|
|
}
|
|
|
|
class ProvisioningEngineImplServiceTest : public ProvisioningEngineImplTest {
|
|
protected:
|
|
void SetUp() override {
|
|
mock_root_public_key_ = new MockRsaPublicKey();
|
|
EXPECT_CALL(*mock_rsa_key_factory_, CreateFromPkcs1PublicKey(_))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPublicKey>(mock_root_public_key_))));
|
|
|
|
service_cert_.set_public_key("service_public_key");
|
|
service_cert_.set_type(DrmDeviceCertificate::SERVICE);
|
|
signed_service_cert_.set_drm_certificate(service_cert_.SerializeAsString());
|
|
signed_service_cert_.set_signature("service_signature");
|
|
}
|
|
|
|
ProvisioningStatus Initialize(const std::string& service_drm_certificate) {
|
|
return engine_impl_.Initialize(
|
|
kCertTesting, service_drm_certificate, kServicePrivateKey,
|
|
kServicePrivateKeyPassphrase, kProvisioningDrmCertificate,
|
|
kProvisioningPrivateKey, kProvisioningPrivateKeyPassphrase,
|
|
kSecretSauce);
|
|
}
|
|
|
|
DrmDeviceCertificate service_cert_;
|
|
SignedDrmDeviceCertificate signed_service_cert_;
|
|
MockRsaPublicKey* mock_root_public_key_;
|
|
};
|
|
|
|
TEST_F(ProvisioningEngineImplServiceTest, Empty) {
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE, Initialize(""));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplServiceTest, MissingDeviceCert) {
|
|
signed_service_cert_.clear_drm_certificate();
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE,
|
|
Initialize(signed_service_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplServiceTest, MissingSignature) {
|
|
signed_service_cert_.clear_signature();
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE,
|
|
Initialize(signed_service_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplServiceTest, SignatureVerificationFailure) {
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(StrEq(service_cert_.SerializeAsString()),
|
|
"service_signature"))
|
|
.WillOnce(Return(false));
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE,
|
|
Initialize(signed_service_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplServiceTest, InvalidDeviceCertType) {
|
|
service_cert_.set_type(DrmDeviceCertificate::PROVISIONER);
|
|
signed_service_cert_.set_drm_certificate(service_cert_.SerializeAsString());
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(StrEq(service_cert_.SerializeAsString()),
|
|
"service_signature"))
|
|
.WillOnce(Return(true));
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE,
|
|
Initialize(signed_service_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplServiceTest, InvaidPublicKey) {
|
|
EXPECT_CALL(*mock_root_public_key_, VerifySignature(_, "service_signature"))
|
|
.WillOnce(Return(true));
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey("service_public_key"))
|
|
.WillOnce(Return(ByMove(nullptr)));
|
|
EXPECT_EQ(INVALID_SERVICE_DRM_CERTIFICATE,
|
|
Initialize(signed_service_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplServiceTest, InvalidPrivateKey) {
|
|
EXPECT_CALL(*mock_root_public_key_, VerifySignature(_, "service_signature"))
|
|
.WillOnce(Return(true));
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey("service_public_key"))
|
|
.WillOnce(
|
|
Return(ByMove(std::unique_ptr<RsaPublicKey>(new MockRsaPublicKey))));
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kServicePrivateKey,
|
|
kServicePrivateKeyPassphrase))
|
|
.WillOnce(Return(ByMove(nullptr)));
|
|
EXPECT_EQ(INVALID_SERVICE_PRIVATE_KEY,
|
|
Initialize(signed_service_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplServiceTest, MismatchPublicKeyPrivateKey) {
|
|
EXPECT_CALL(*mock_root_public_key_, VerifySignature(_, "service_signature"))
|
|
.WillOnce(Return(true));
|
|
MockRsaPublicKey* mock_rsa_public_key = new MockRsaPublicKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey("service_public_key"))
|
|
.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(kServicePrivateKey,
|
|
kServicePrivateKeyPassphrase))
|
|
.WillOnce(
|
|
Return(ByMove(std::unique_ptr<RsaPrivateKey>(mock_rsa_private_key))));
|
|
EXPECT_CALL(*mock_rsa_public_key, MatchesPrivateKey(_))
|
|
.WillOnce(Return(false));
|
|
EXPECT_EQ(INVALID_SERVICE_PRIVATE_KEY,
|
|
Initialize(signed_service_cert_.SerializeAsString()));
|
|
}
|
|
|
|
class ProvisioningEngineImplProvTest
|
|
: public ProvisioningEngineImplServiceTest {
|
|
protected:
|
|
void SetUp() override {
|
|
ProvisioningEngineImplServiceTest::SetUp();
|
|
|
|
// Service certificate expectations.
|
|
EXPECT_CALL(*mock_root_public_key_, VerifySignature(_, "service_signature"))
|
|
.WillOnce(Return(true));
|
|
mock_service_public_key_ = new MockRsaPublicKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs1PublicKey("service_public_key"))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPublicKey>(mock_service_public_key_))));
|
|
mock_service_private_key_ = new MockRsaPrivateKey;
|
|
EXPECT_CALL(*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kServicePrivateKey,
|
|
kServicePrivateKeyPassphrase))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPrivateKey>(mock_service_private_key_))));
|
|
EXPECT_CALL(*mock_service_public_key_, MatchesPrivateKey(_))
|
|
.WillOnce(Return(true));
|
|
|
|
prov_cert_.set_public_key(kProvisioningPublicKey);
|
|
prov_cert_.set_type(DrmDeviceCertificate::PROVISIONER);
|
|
signed_prov_cert_.set_drm_certificate(prov_cert_.SerializeAsString());
|
|
signed_prov_cert_.set_signature(kProvisioningSignature);
|
|
}
|
|
|
|
ProvisioningStatus Initialize(const std::string& provisioning_drm_certificate) {
|
|
return engine_impl_.Initialize(
|
|
kCertTesting, signed_service_cert_.SerializeAsString(),
|
|
kServicePrivateKey, kServicePrivateKeyPassphrase,
|
|
provisioning_drm_certificate, kProvisioningPrivateKey,
|
|
kProvisioningPrivateKeyPassphrase, "spoid_secret_sauce");
|
|
}
|
|
|
|
DrmDeviceCertificate prov_cert_;
|
|
SignedDrmDeviceCertificate signed_prov_cert_;
|
|
MockRsaPublicKey* mock_service_public_key_ = nullptr;
|
|
MockRsaPrivateKey* mock_service_private_key_ = nullptr;
|
|
};
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, Empty) {
|
|
EXPECT_EQ(INVALID_PROVISIONER_DRM_CERTIFICATE, Initialize(""));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, MissingDeviceCert) {
|
|
signed_prov_cert_.clear_drm_certificate();
|
|
EXPECT_EQ(INVALID_PROVISIONER_DRM_CERTIFICATE,
|
|
Initialize(signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, MissingSignature) {
|
|
signed_prov_cert_.clear_signature();
|
|
EXPECT_EQ(INVALID_PROVISIONER_DRM_CERTIFICATE,
|
|
Initialize(signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, SignatureVerificationFailure) {
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(StrEq(prov_cert_.SerializeAsString()),
|
|
kProvisioningSignature))
|
|
.WillOnce(Return(false));
|
|
EXPECT_EQ(INVALID_PROVISIONER_DRM_CERTIFICATE,
|
|
Initialize(signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, InvalidDeviceCertType) {
|
|
prov_cert_.set_type(DrmDeviceCertificate::SERVICE);
|
|
signed_prov_cert_.set_drm_certificate(prov_cert_.SerializeAsString());
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(StrEq(prov_cert_.SerializeAsString()),
|
|
kProvisioningSignature))
|
|
.WillOnce(Return(true));
|
|
EXPECT_EQ(INVALID_PROVISIONER_DRM_CERTIFICATE,
|
|
Initialize(signed_prov_cert_.SerializeAsString()));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplProvTest, InvaidPublicKey) {
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(_, kProvisioningSignature))
|
|
.WillOnce(Return(true));
|
|
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_root_public_key_,
|
|
VerifySignature(_, kProvisioningSignature))
|
|
.WillOnce(Return(true));
|
|
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) {
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(_, kProvisioningSignature))
|
|
.WillOnce(Return(true));
|
|
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 ProvisioningEngineImplGeneralTest
|
|
: public ProvisioningEngineImplProvTest {
|
|
protected:
|
|
void SetUp() override {
|
|
ProvisioningEngineImplProvTest::SetUp();
|
|
|
|
// Provisioning certificate expectations.
|
|
EXPECT_CALL(*mock_root_public_key_,
|
|
VerifySignature(_, kProvisioningSignature))
|
|
.WillOnce(Return(true));
|
|
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;
|
|
EXPECT_CALL(
|
|
*mock_rsa_key_factory_,
|
|
CreateFromPkcs8PrivateKey(kProvisioningPrivateKey,
|
|
kProvisioningPrivateKeyPassphrase))
|
|
.WillOnce(Return(
|
|
ByMove(std::unique_ptr<RsaPrivateKey>(mock_prov_private_key_))));
|
|
EXPECT_CALL(*mock_prov_public_key_, MatchesPrivateKey(_))
|
|
.WillOnce(Return(true));
|
|
|
|
ASSERT_EQ(OK, ProvisioningEngineImplProvTest::Initialize(
|
|
signed_prov_cert_.SerializeAsString()));
|
|
|
|
// 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::VALID);
|
|
cert_status_list_.mutable_certificate_status(1)->set_status(
|
|
DeviceCertificateStatus::REVOKED);
|
|
|
|
SignedCertificateStatusList 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(),
|
|
kExpirationPeriodSeconds));
|
|
|
|
// Setup a DrmDeviceCertificate to be used later.
|
|
intermediate_cert_.set_type(DrmDeviceCertificate::DRM_INTERMEDIATE);
|
|
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);
|
|
}
|
|
|
|
MockRsaPublicKey* mock_prov_public_key_ = nullptr;
|
|
MockRsaPrivateKey* mock_prov_private_key_ = nullptr;
|
|
DeviceCertificateStatusList cert_status_list_;
|
|
DrmDeviceCertificate intermediate_cert_;
|
|
SignedDrmDeviceCertificate 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) {
|
|
SignedCertificateStatusList 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) {
|
|
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) {
|
|
cert_status_list_.mutable_certificate_status(0)->set_status(
|
|
DeviceCertificateStatus::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");
|
|
|
|
SignedCertificateStatusList 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<1>(kSignature), Return(true)));
|
|
std::string certificate;
|
|
ASSERT_EQ(OK, engine_impl_.GenerateDrmIntermediateCertificate(
|
|
kSystemId, kIntermediatePublicKey, &certificate));
|
|
|
|
SignedDrmDeviceCertificate 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());
|
|
|
|
DrmDeviceCertificate drm_cert_proto;
|
|
ASSERT_TRUE(drm_cert_proto.ParseFromString(drm_certificate));
|
|
EXPECT_EQ(DrmDeviceCertificate::DRM_INTERMEDIATE, 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(DrmDeviceCertificate::DRM_USER_DEVICE);
|
|
signed_intermediate_cert_.set_drm_certificate(
|
|
intermediate_cert_.SerializeAsString());
|
|
|
|
EXPECT_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
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_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
EXPECT_EQ(
|
|
UNKNOWN_SYSTEM_ID,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateRevokedCert) {
|
|
intermediate_cert_.set_system_id(kSystemId + 1);
|
|
signed_intermediate_cert_.set_drm_certificate(
|
|
intermediate_cert_.SerializeAsString());
|
|
|
|
EXPECT_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
EXPECT_EQ(DEVICE_REVOKED, engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey,
|
|
kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
AddDrmIntermediateCertificateInvalidPublicKey) {
|
|
EXPECT_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
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) {
|
|
EXPECT_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
|
|
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) {
|
|
EXPECT_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
|
|
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) {
|
|
EXPECT_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
|
|
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);
|
|
|
|
SignedCertificateStatusList 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_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
EXPECT_EQ(
|
|
STATUS_LIST_EXPIRED,
|
|
engine_impl_.AddDrmIntermediateCertificate(
|
|
signed_intermediate_cert_.SerializeAsString(),
|
|
kIntermediatePrivateKey, kIntermediatePrivateKeyPassphrase));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
GenerateDeviceDrmCertificateRevokedDevice) {
|
|
std::string certificate;
|
|
EXPECT_EQ(DEVICE_REVOKED,
|
|
engine_impl_.GenerateDeviceDrmCertificate(
|
|
kSystemId + 1, kOemSerialNumber1, kDevicePublicKey,
|
|
kCertificateSerialNumber, &certificate));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
GenerateDeviceDrmCertificateWithMismatchingOemSerialNumber) {
|
|
std::string certificate;
|
|
// If oem serial number does not match, consider as revoked.
|
|
EXPECT_EQ(DEVICE_REVOKED,
|
|
engine_impl_.GenerateDeviceDrmCertificate(
|
|
kSystemId, kOemSerialNumber1, kDevicePublicKey,
|
|
kCertificateSerialNumber, &certificate));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
GenerateDeviceDrmCertificateWithoutIntermediateCert) {
|
|
std::string certificate;
|
|
EXPECT_EQ(MISSING_DRM_INTERMEDIATE_CERT,
|
|
engine_impl_.GenerateDeviceDrmCertificate(
|
|
kSystemId, kOemSerialNumber0, kDevicePublicKey,
|
|
kCertificateSerialNumber, &certificate));
|
|
}
|
|
|
|
TEST_F(ProvisioningEngineImplGeneralTest,
|
|
GenerateDeviceDrmCertificate) {
|
|
// Add Intermediate certificate.
|
|
EXPECT_CALL(
|
|
*mock_prov_public_key_,
|
|
VerifySignature(StrEq(signed_intermediate_cert_.drm_certificate()),
|
|
StrEq(signed_intermediate_cert_.signature())))
|
|
.WillOnce(Return(true));
|
|
|
|
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<1>(kSignature), Return(true)));
|
|
std::string certificate;
|
|
EXPECT_EQ(OK, engine_impl_.GenerateDeviceDrmCertificate(
|
|
kSystemId, kOemSerialNumber0, kDevicePublicKey,
|
|
kCertificateSerialNumber, &certificate));
|
|
|
|
SignedDrmDeviceCertificate 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());
|
|
|
|
DrmDeviceCertificate drm_cert_proto;
|
|
ASSERT_TRUE(drm_cert_proto.ParseFromString(drm_certificate));
|
|
EXPECT_EQ(DrmDeviceCertificate::DRM_USER_DEVICE, drm_cert_proto.type());
|
|
EXPECT_EQ(kCertificateSerialNumber, drm_cert_proto.serial_number());
|
|
EXPECT_EQ(kSystemId, drm_cert_proto.system_id());
|
|
EXPECT_EQ(kDevicePublicKey, drm_cert_proto.public_key());
|
|
}
|
|
|
|
} // namespace widevine
|