Source release v3.3.0

This commit is contained in:
Gene Morgan
2017-05-04 14:01:27 -07:00
parent baa7b133d3
commit 8082775924
678 changed files with 51264 additions and 14200 deletions

View File

@@ -8,8 +8,8 @@
#include "cdm.h"
#include "cdm_test_printers.h"
#include "config_test_env.h"
#include "decryption_test_data.h"
#include "default_service_certificate.h"
#include "license_request.h"
#include "log.h"
#include "OEMCryptoCENC.h"
@@ -37,14 +37,10 @@ const Cdm::SessionType kBogusSessionType = static_cast<Cdm::SessionType>(-1);
const Cdm::InitDataType kBogusInitDataType = static_cast<Cdm::InitDataType>(-1);
const std::string kBogusSessionId = "asdf";
const std::string kProvisioningServerUrl =
"https://www.googleapis.com/"
"certificateprovisioning/v1/devicecertificates/create"
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
const std::string kLicenseServerAppspot =
"http://widevine-proxy.appspot.com/proxy";
const std::string kLicenseServerUat = "https://proxy.uat.widevine.com/proxy";
std::string g_provisioning_server;
std::string g_provisioning_service_certificate;
std::string g_license_server;
std::string g_license_service_certificate;
const std::string kCencInitData = a2bs_hex(
"00000042" // blob size
@@ -85,11 +81,11 @@ const std::string kHlsInitData =
"yI6IFsNCiAgICAgICI5Yjc1OTA0MDMyMWE0MDhhNWM3NzY4YjQ1MTEyODdhNiINCiAgIF0NCn0"
"=\",IV=0x75537a79fa41abc7b598ea72aba0c26f";
// This Key ID must match the key retrieved from kLicenseServerAppspot by
// This Key ID must match the key retrieved from the license server by
// kCencInitData.
const std::vector<uint8_t> kKeyIdCtr = a2b_hex(
"371ea35e1a985d75d198a7f41020dc23");
// This Key ID must match the key retrieved from kLicenseServerUat by
// This Key ID must match the key retrieved from the license server by
// kHlsInitData.
const std::vector<uint8_t> kKeyIdCbc = a2b_hex(
"9b759040321a408a5c7768b4511287a6");
@@ -133,6 +129,15 @@ class CdmTest : public Test, public Cdm::IEventListener {
protected:
virtual void SetUp() OVERRIDE {
ConfigTestEnv config(kContentProtectionStagingPlusProv30);
g_provisioning_service_certificate.assign(
config.provisioning_service_certificate());
g_license_service_certificate.assign(config.license_service_certificate());
g_provisioning_server.assign(config.provisioning_server());
g_license_server.assign(config.license_server());
// Clear anything stored, load default device cert.
g_host->Reset();
@@ -162,9 +167,14 @@ class CdmTest : public Test, public Cdm::IEventListener {
usleep(500 * 1000);
}
virtual void Provision() {
cdm_->removeProvisioning();
cdm_->setServiceCertificate(g_provisioning_service_certificate);
}
void RecreateCdm(bool privacy_mode) {
CreateAdditionalCdm(privacy_mode, &cdm_);
cdm_->setServiceCertificate(kDefaultServiceCertificate);
cdm_->setServiceCertificate(g_license_service_certificate);
}
void CreateAdditionalCdm(bool privacy_mode, scoped_ptr<Cdm>* cdm) {
@@ -203,7 +213,11 @@ class CdmTest : public Test, public Cdm::IEventListener {
} else {
*response = http_response;
}
LOGV("Reply body: %s", b2a_hex(*response).c_str());
LOGV("Reply body(hex): \n%s\n", b2a_hex(*response).c_str());
LOGV("Reply body(b64): \n%s\n",
Base64SafeEncode(
std::vector<uint8_t>(response->begin(),
response->end())).c_str());
}
return true;
}
@@ -228,7 +242,7 @@ class CdmTest : public Test, public Cdm::IEventListener {
void FetchLicenseFailure(const std::string& message,
int expected_status_code) {
int status_code;
bool ok = Fetch(kLicenseServerAppspot, message, NULL, &status_code);
bool ok = Fetch(g_license_server, message, NULL, &status_code);
ASSERT_TRUE(ok);
if (ok) ASSERT_EQ(expected_status_code, status_code);
}
@@ -238,7 +252,7 @@ class CdmTest : public Test, public Cdm::IEventListener {
std::string* session_id,
std::string* message) {
Cdm::Status status;
status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
status = cdm_->setServiceCertificate(g_license_service_certificate);
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->createSession(session_type, session_id);
@@ -276,9 +290,9 @@ class CdmTest : public Test, public Cdm::IEventListener {
std::string license_server;
if (init_data_type == Cdm::kCenc) {
license_server = kLicenseServerAppspot;
license_server = g_license_server;
} else if (init_data_type == Cdm::kHls) {
license_server = kLicenseServerUat;
license_server = g_license_server;
}
ASSERT_FALSE(license_server.empty());
FetchLicense(license_server, message, response);
@@ -301,7 +315,7 @@ class CdmTest : public Test, public Cdm::IEventListener {
// Acquire a license.
std::string response;
ASSERT_NO_FATAL_FAILURE(FetchLicense(
kLicenseServerAppspot, message, &response));
g_license_server, message, &response));
// This license should be accepted, but the keys are not expected to change.
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
@@ -465,19 +479,24 @@ TEST_F(CdmTest, Initialize) {
EXPECT_EQ(Cdm::kSuccess, status);
}
TEST_F(CdmTest, GetServiceCertificateRequest) {
// Set a server certificate with privacy mode disabled - should work.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(false /* privacy_mode */));
std::string message;
Cdm::Status status = cdm_->getServiceCertificateRequest(&message);
EXPECT_EQ(Cdm::kSuccess, status);
}
TEST_F(CdmTest, SetServiceCertificate) {
// Set a server certificate with privacy mode disabled - should work.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(false /* privacy_mode */));
Cdm::Status status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
Cdm::Status status =
cdm_->setServiceCertificate(g_license_service_certificate);
EXPECT_EQ(Cdm::kSuccess, status);
// Can set a server certificate if privacy mode is enabled.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
EXPECT_EQ(Cdm::kSuccess, status);
// Setting an empty cert is allowed.
status = cdm_->setServiceCertificate("");
status = cdm_->setServiceCertificate(g_license_service_certificate);
EXPECT_EQ(Cdm::kSuccess, status);
// It is invalid to set a malformed cert.
@@ -515,7 +534,7 @@ TEST_F(CdmTest, CreateSession) {
TEST_F(CdmTest, GenerateRequest) {
std::string session_id;
Cdm::Status status;
status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
status = cdm_->setServiceCertificate(g_license_service_certificate);
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->createSession(Cdm::kTemporary, &session_id);
@@ -608,7 +627,7 @@ TEST_F(CdmTest, Update) {
std::string session_id;
std::string message;
Cdm::Status status;
status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
status = cdm_->setServiceCertificate(g_license_service_certificate);
ASSERT_EQ(Cdm::kSuccess, status);
ASSERT_NO_FATAL_FAILURE(CreateSessionAndGenerateRequest(
@@ -617,7 +636,7 @@ TEST_F(CdmTest, Update) {
// Acquire a license.
std::string response;
ASSERT_NO_FATAL_FAILURE(FetchLicense(
kLicenseServerAppspot, message, &response));
g_license_server, message, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id));
@@ -669,7 +688,7 @@ TEST_F(CdmTest, LoadTemporary) {
std::string session_id;
std::string response;
Cdm::Status status;
status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
status = cdm_->setServiceCertificate(g_license_service_certificate);
ASSERT_EQ(Cdm::kSuccess, status);
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
@@ -772,7 +791,7 @@ TEST_F(CdmTest, PerOriginLoadPersistent) {
scoped_ptr<Cdm> other_cdm(
Cdm::create(this, &other_host, /* privacy_mode */ true));
ASSERT_TRUE(other_cdm.get());
status = other_cdm->setServiceCertificate(kDefaultServiceCertificate);
status = other_cdm->setServiceCertificate(g_license_service_certificate);
ASSERT_EQ(Cdm::kSuccess, status);
// Should not be able to load from another origin.
@@ -785,6 +804,7 @@ TEST_F(CdmTest, PerOriginLoadPersistent) {
TEST_F(CdmTest, LoadUsageRecord) {
std::string session_id;
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
Cdm::kPersistentUsageRecord, Cdm::kCenc, &session_id, &response));
@@ -824,6 +844,114 @@ TEST_F(CdmTest, LoadUsageRecord) {
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, DestroyUsageRecord) {
std::string session_id;
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
Cdm::kPersistentUsageRecord, Cdm::kCenc, &session_id, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id));
Cdm::Status status = cdm_->update(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after closing it.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
// There should be no usable keys after loading this session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after recreating the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->deleteUsageRecord(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSessionNotFound, status);
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, DestroyAllUsageRecords) {
std::string session_id;
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
Cdm::kPersistentUsageRecord, Cdm::kCenc, &session_id, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id));
Cdm::Status status = cdm_->update(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after closing it.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
// There should be no usable keys after loading this session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after recreating the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->deleteAllUsageRecords();
EXPECT_EQ(Cdm::kSuccess, status);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSessionNotFound, status);
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, ListUsageRecords) {
std::string session_id;
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
Cdm::kPersistentUsageRecord, Cdm::kCenc, &session_id, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id));
Cdm::Status status = cdm_->update(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after closing it.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
// There should be no usable keys after loading this session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after recreating the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
std::vector<std::string> ksids;
status = cdm_->listUsageRecords(&ksids);
EXPECT_EQ(Cdm::kSuccess, status);
EXPECT_EQ(ksids.size(), 1UL);
if (ksids.size() > 0UL) {
EXPECT_TRUE(ksids[0] == session_id);
}
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, LoadBogus) {
EXPECT_CALL(*this, onKeyStatusesChange(_)).Times(0);
Cdm::Status status = cdm_->load(kBogusSessionId);
@@ -921,7 +1049,7 @@ TEST_F(CdmTest, Remove) {
// Post the release message to the license server.
std::string response;
ASSERT_NO_FATAL_FAILURE(FetchLicense(
kLicenseServerAppspot, message, &response));
g_license_server, message, &response));
// Update the session.
EXPECT_CALL(*this, onRemoveComplete(session_id));
@@ -975,7 +1103,7 @@ TEST_F(CdmTest, RemoveUsageRecord) {
// Post the release message to the license server.
std::string response;
ASSERT_NO_FATAL_FAILURE(FetchLicense(
kLicenseServerAppspot, message, &response));
g_license_server, message, &response));
// Update the session.
EXPECT_CALL(*this, onRemoveComplete(session_id));
@@ -1037,7 +1165,7 @@ TEST_F(CdmTest, RemoveIncomplete) {
// Post the release message to the license server.
std::string response;
ASSERT_NO_FATAL_FAILURE(FetchLicense(
kLicenseServerAppspot, message, &response));
g_license_server, message, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
@@ -1108,7 +1236,7 @@ TEST_F(CdmTest, RemoveUsageRecordIncomplete) {
// Post the release message to the license server.
std::string response;
ASSERT_NO_FATAL_FAILURE(FetchLicense(
kLicenseServerAppspot, message, &response));
g_license_server, message, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id)).Times(0);
@@ -1141,7 +1269,7 @@ TEST_F(CdmTest, RequestPersistentLicenseWithWrongInitData) {
// persistent content init data.
std::string session_id;
Cdm::Status status;
status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
status = cdm_->setServiceCertificate(g_license_service_certificate);
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->createSession(Cdm::kPersistentLicense, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
@@ -1161,7 +1289,7 @@ TEST_F(CdmTest, RequestTemporaryLicenseWithWrongInitData) {
// Generate a request for a temporary license using persistent init data.
std::string session_id;
Cdm::Status status;
status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
status = cdm_->setServiceCertificate(g_license_service_certificate);
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
@@ -1177,7 +1305,7 @@ TEST_F(CdmTest, RequestTemporaryLicenseWithWrongInitData) {
// Acquire a license.
std::string response;
ASSERT_NO_FATAL_FAILURE(FetchLicense(
kLicenseServerAppspot, message, &response));
g_license_server, message, &response));
// This license should not be accepted.
EXPECT_CALL(*this, onKeyStatusesChange(session_id));
@@ -1408,11 +1536,19 @@ class CdmIndividualizationTest : public CdmTest {
std::string GetProvisioningResponse(const std::string& message) {
std::string reply;
std::string uri = kProvisioningServerUrl;
std::string uri = g_provisioning_server;
LOGV("GetProvisioningResponse: URI: %s", uri.c_str());
LOGV("GetProvisioningResponse: message:\n%s\n", message.c_str());
uri += "&signedRequest=" + message;
FetchCertificate(uri, &reply);
if (HasFatalFailure())
if (HasFatalFailure()) {
LOGE("GetProvisioningResponse: Failed.");
return "";
}
LOGV("GetProvisioningResponse: response:\n%s\n", reply.c_str());
return reply;
}
};
@@ -1426,7 +1562,7 @@ TEST_F(CdmIndividualizationTest, BasicFlow) {
// Creating a session should succeed.
std::string session_id;
Cdm::Status status;
status = cdm_->setServiceCertificate(kDefaultServiceCertificate);
status = cdm_->setServiceCertificate(g_license_service_certificate);
EXPECT_EQ(Cdm::kSuccess, status);
status = cdm_->createSession(Cdm::kTemporary, &session_id);
EXPECT_EQ(Cdm::kSuccess, status);
@@ -1454,7 +1590,7 @@ TEST_F(CdmIndividualizationTest, BasicFlow) {
// Acquire a license and update the session.
ASSERT_NO_FATAL_FAILURE(FetchLicense(
kLicenseServerAppspot, message, &reply));
g_license_server, message, &reply));
EXPECT_CALL(*this, onKeyStatusesChange(session_id));
status = cdm_->update(session_id, reply);
EXPECT_EQ(Cdm::kSuccess, status);

View File

@@ -36,8 +36,8 @@ class TestHost : public widevine::Cdm::IStorage,
private:
struct Timer {
Timer(int64_t expiry_time, IClient* client, void* context)
: expiry_time(expiry_time), client(client), context(context) {}
Timer(int64_t expiry_time_, IClient* client_, void* context_)
: expiry_time(expiry_time_), client(client_), context(context_) {}
bool operator<(const Timer& other) const {
// We want to reverse the order so that the smallest expiry times go to