Merges to android Pi release (part 3)

These are a set of CLs merged from the wv cdm repo to the android repo.

* Add CDM status return for decrypt blocked by HDCP.

  Author: Gene Morgan <gmorgan@google.com>

  [ Merge of http://go/wvgerrit/28062 ]

  New status code is kKeyUsageBlockedByPolicy. It is returned by the decrypt()
  call instead of kDecryptError or kNoKey.

  Also shuffled the CDM status returns to define the EME-aligned codes
  first, and added comments to highlight the differences in handling.

  BUG: 37540672

* Change division and mod ops to relocatables

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/28600 ]

  This is similar to I2dad1028acf295288cd10817a2bcff2513c053c9.
  We should be using the relocatable functions instead of the
  native division and mod operations.

* Cleanup Encrypted ClientID in provisioning request

  Author: Gene Morgan <gmorgan@google.com>

  [ Merge of http://go/wvgerrit/28083 ]

  b/36897239

  Staging server does not support it (or the client is not constructing
  it properly).  Leave it disabled pending investigation.

* Certificate Provisioning fixes.

  Author: Gene Morgan <gmorgan@google.com>

  [ Merge of http://go/wvgerrit/28066 ]

  Partial fix for BUG: 37482676
  Partial fix for BUG: 37481392

  Update service certificates, get rid of DEV/QA root certificate.
  Provisioning request and response are base64 (web-safe) encoded.
  Response is optionally JSON-wrapped.

  Change ConfigTestEnv; clearer comments and a closer match to reality.

BUG: 71650075
Test: Not currently passing. Will be addressed in a subsequent
      commit in the chain.

Change-Id: I79d3c4bf1124e5e0d3e4d40baead65a8266ea874
This commit is contained in:
Rahul Frias
2018-01-09 15:43:41 -08:00
parent 387147dffe
commit 11068accd2
30 changed files with 902 additions and 920 deletions

View File

@@ -38,24 +38,26 @@ KeyId g_key_id_unwrapped;
CdmKeySystem g_key_system;
std::string g_license_server;
std::string g_provisioning_server;
std::string g_service_certificate;
std::string g_provisioning_service_certificate;
std::string g_license_service_certificate;
KeyId g_wrong_key_id;
const std::string kCencMimeType = "video/mp4";
const std::string kWebmMimeType = "video/webm";
static void CommonSetup(bool use_qa) {
static void CommonSetup(ServerConfigurationId which) {
// NOTE: Select QA/Test server config vs. UAT server config
ConfigTestEnv config((use_qa) ? kContentProtectionTestQAServer :
kContentProtectionUatServer);
// NOTE: Select configuration
ConfigTestEnv config(which);
g_client_auth.assign(config.client_auth());
g_key_system.assign(config.key_system());
g_wrong_key_id.assign(config.wrong_key_id());
g_license_server.assign(config.license_server());
g_key_id_pssh.assign(a2bs_hex(config.key_id()));
g_service_certificate.assign(config.service_certificate());
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());
// Extract the key ID from the PSSH box.
@@ -63,6 +65,45 @@ static void CommonSetup(bool use_qa) {
g_key_id_unwrapped = extractor.data();
}
/*
* Locate the portion of the server's response message that is between
* the strings jason_start_substr and json_end_substr. Returns the string
* through *result. If the start substring match fails, assume the entire
* string represents a serialized protobuf mesaage and return true with
* the entire string. If the end_substring match fails, return false with
* an empty *result.
*/
bool ExtractSignedMessage(const std::string& response,
const std::string& json_start_substr,
const std::string& json_end_substr,
std::string* result) {
std::string response_string;
size_t start = response.find(json_start_substr);
if (start == response.npos) {
// Assume serialized protobuf message.
result->assign(response);
} else {
// Assume JSON-wrapped protobuf.
size_t end = response.find(json_end_substr,
start + json_start_substr.length());
if (end == response.npos) {
LOGE("ExtractSignedMessage cannot locate end substring");
result->clear();
return false;
}
size_t result_string_size = end - start - json_start_substr.length();
result->assign(response, start + json_start_substr.length(),
result_string_size);
}
if (result->empty()) {
LOGE("ExtractSignedMessage: Response message is empty");
return false;
}
return true;
}
} // namespace
class WvCdmEnginePreProvTest : public testing::Test {
@@ -72,15 +113,6 @@ class WvCdmEnginePreProvTest : public testing::Test {
virtual ~WvCdmEnginePreProvTest() {}
static void SetUpTestCase() {
// NOTE: Select QA/Test server config vs. UAT server config
#if defined(QA_TEST_SERVER)
CommonSetup(true);
#else
CommonSetup(false);
#endif // !defined(QA_TEST_SERVER)
}
virtual void SetUp() {
CdmResponseType status =
cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
@@ -97,24 +129,11 @@ class WvCdmEnginePreProvTest : public testing::Test {
protected:
bool IsBase64Encoded(const std::string& message) {
for (size_t i = 0; i < message.size(); ++i) {
uint8_t ch = message[i];
if (ch >= 'a' && ch <= 'z') continue;
if (ch >= 'A' && ch <= 'Z') continue;
if (ch >= '0' && ch <= '9') continue;
if (ch == '-' || ch == '_' || ch == '=' || ch == '.' || ch == '/') {
continue;
}
return false;
}
return true;
}
// Trade request for response via the license server.
bool LicenseServerRequestResponse(const std::string& request,
std::string* response) {
LOGV("server url: %s", g_license_server.c_str());
LOGV("LicenseServerRequestResponse: server url: %s",
g_license_server.c_str());
UrlRequest url_request(g_license_server + g_client_auth);
url_request.PostRequest(request);
@@ -123,29 +142,67 @@ class WvCdmEnginePreProvTest : public testing::Test {
return false;
}
LOGV("http_resp:\n%s\n", http_response.c_str());
LOGV("http_response:\n%s\n", http_response.c_str());
// Separate message from HTTP headers.
LicenseRequest license_request;
std::string response_message;
license_request.GetDrmMessage(http_response, response_message);
license_request.GetDrmMessage(http_response, *response);
LOGV("resp: size=%u, string:\n%s\n", response_message.size(),
Base64SafeEncode(
std::vector<uint8_t>(response_message.begin(),
response_message.end())).c_str());
// Response should be base64 encoded. If it is not,
// fix it now.
if (!IsBase64Encoded(response_message)) {
std::vector<uint8_t> response_vector(response_message.begin(),
response_message.end());
response_message = Base64SafeEncode(response_vector);
}
response->swap(response_message);
LOGV("response: size=%u, string:\n%s\n", response->size(),
Base64SafeEncode(std::vector<uint8_t>(response->begin(),
response->end())).c_str());
return true;
}
virtual void Provision() {
LOGV("WvCdmEnginePreProvTest::Provision: url=%s",
g_provisioning_server.c_str());
CdmProvisioningRequest prov_request;
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority;
std::string cert, wrapped_key;
ASSERT_EQ(NO_ERROR, cdm_engine_.SetServiceCertificate(
g_provisioning_service_certificate));
ASSERT_EQ(NO_ERROR, cdm_engine_.GetProvisioningRequest(
cert_type, cert_authority, &prov_request,
&provisioning_server_url));
LOGV("WvCdmEnginePreProvTest::Provision: req=%s", prov_request.c_str());
// Ignore URL provided by CdmEngine. Use ours, as configured
// for test vs. production server.
provisioning_server_url.assign(g_provisioning_server);
UrlRequest url_request(provisioning_server_url);
EXPECT_TRUE(url_request.is_connected());
url_request.PostCertRequestInQueryString(prov_request);
std::string http_message;
bool ok = url_request.GetResponse(&http_message);
EXPECT_TRUE(ok);
LOGV("WvCdmEnginePreProvTest::Provision: http_message: \n%s\n",
http_message.c_str());
// extract provisioning response from received message
// Extracts signed response from JSON string, result is serialized protobuf.
const std::string kMessageStart = "\"signedResponse\": \"";
const std::string kMessageEnd = "\"";
std::string protobuf_response;
EXPECT_TRUE (ExtractSignedMessage(http_message, kMessageStart, kMessageEnd,
&protobuf_response)) <<
"Failed to extract signed serialized response from JSON response";
LOGV("WvCdmEnginePreProvTest::Provision: extracted response "
"message: \n%s\n", protobuf_response.c_str());
ASSERT_EQ(NO_ERROR,
cdm_engine_.HandleProvisioningResponse(protobuf_response,
&cert, &wrapped_key));
ASSERT_EQ(NO_ERROR,
cdm_engine_.SetServiceCertificate(g_license_service_certificate));
}
FileSystem file_system_;
CdmEngine cdm_engine_;
bool session_opened_;
@@ -153,10 +210,75 @@ class WvCdmEnginePreProvTest : public testing::Test {
std::string session_id_;
};
class WvCdmEnginePreProvTestStaging : public WvCdmEnginePreProvTest {
public:
WvCdmEnginePreProvTestStaging() {}
virtual ~WvCdmEnginePreProvTestStaging() {}
static void SetUpTestCase() {
// NOTE: Select server configuration
CommonSetup(kContentProtectionStagingLicense);
}
};
class WvCdmEnginePreProvTestProd : public WvCdmEnginePreProvTest {
public:
WvCdmEnginePreProvTestProd() {}
virtual ~WvCdmEnginePreProvTestProd() {}
static void SetUpTestCase() {
// NOTE: Select server configuration
CommonSetup(kContentProtectionProdLicense);
}
};
class WvCdmEnginePreProvTestUat : public WvCdmEnginePreProvTest {
public:
WvCdmEnginePreProvTestUat() {}
virtual ~WvCdmEnginePreProvTestUat() {}
static void SetUpTestCase() {
// NOTE: Select server configuration
CommonSetup(kContentProtectionUatLicense);
}
};
class WvCdmEnginePreProvTestStagingProv30 : public WvCdmEnginePreProvTest {
public:
WvCdmEnginePreProvTestStagingProv30() {}
virtual ~WvCdmEnginePreProvTestStagingProv30() {}
static void SetUpTestCase() {
// NOTE: Select server configuration
CommonSetup(kContentProtectionStagingPlusProv30);
}
};
class WvCdmEnginePreProvTestUatProv30 : public WvCdmEnginePreProvTest {
public:
WvCdmEnginePreProvTestUatProv30() {}
virtual ~WvCdmEnginePreProvTestUatProv30() {}
static void SetUpTestCase() {
// NOTE: Select server configuration
CommonSetup(kContentProtectionUatPlusProv30);
}
};
class WvCdmEngineTest : public WvCdmEnginePreProvTest {
public:
WvCdmEngineTest() {}
static void SetUpTestCase() {
// NOTE: Select server configuration
CommonSetup(kContentProtectionStagingLicense);
}
virtual void SetUp() {
CdmResponseType status =
cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
@@ -170,43 +292,6 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest {
}
protected:
void Provision() {
CdmProvisioningRequest prov_request;
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority;
std::string cert, wrapped_key;
ASSERT_EQ(NO_ERROR, cdm_engine_.SetServiceCertificate(
g_service_certificate));
CdmResponseType result = NO_ERROR;
for (int i = 0; i < 2; i++) { // Retry once if there is a nonce problem.
result = cdm_engine_.GetProvisioningRequest(
cert_type, cert_authority, &prov_request, &provisioning_server_url);
if (result == CERT_PROVISIONING_NONCE_GENERATION_ERROR) {
LOGW("Woops. Nonce problem. Try again?");
sleep(1);
} else {
break;
}
}
ASSERT_EQ(NO_ERROR, result);
// Ignore URL provided by CdmEngine. Use ours, as configured
// for test vs. production server.
provisioning_server_url.assign(g_provisioning_server);
UrlRequest url_request(provisioning_server_url);
EXPECT_TRUE(url_request.is_connected());
url_request.PostCertRequestInQueryString(prov_request);
std::string message;
bool ok = url_request.GetResponse(&message);
EXPECT_TRUE(ok);
// One of many reasons a device might fail to provision is that the server
// rejects its keybox. In that case, we usually see an error of
// CERT_PROVISIONING_RESPONSE_ERROR_1. The error response may help
// somebody look through the server logs for more clues.
ASSERT_EQ(NO_ERROR, cdm_engine_.HandleProvisioningResponse(message, &cert,
&wrapped_key))
<< "Error response: " << message;
}
void GenerateKeyRequest(const std::string& key_id,
const std::string& init_data_type_string) {
@@ -269,6 +354,9 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest {
const std::string& client_auth,
bool expect_success) {
// Use secure connection and chunk transfer coding.
LOGV("GetKeyRequestResponse: server_url: %s", server_url.c_str());
UrlRequest url_request(server_url + client_auth);
if (!url_request.is_connected()) {
return "";
@@ -315,19 +403,19 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest {
};
// Test that service certificate is initially absent.
TEST_F(WvCdmEnginePreProvTest, ServiceCertificateInitialNoneTest) {
TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateInitialNoneTest) {
ASSERT_FALSE(cdm_engine_.HasServiceCertificate());
};
// Test that service certificate can be properly installed.
TEST_F(WvCdmEnginePreProvTest, ServiceCertificateGoodTest) {
ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_service_certificate),
TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateGoodTest) {
ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_license_service_certificate),
NO_ERROR);
ASSERT_TRUE(cdm_engine_.HasServiceCertificate());
};
// Test that service certificate can be retrieved from the license server.
TEST_F(WvCdmEnginePreProvTest, ServiceCertificateRequestResponse) {
TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateRequestResponse) {
CdmKeyMessage request;
std::string certificate;
@@ -335,65 +423,110 @@ TEST_F(WvCdmEnginePreProvTest, ServiceCertificateRequestResponse) {
ASSERT_FALSE(cdm_engine_.HasServiceCertificate());
// Generate request.
// The request will be a base64 encode of a serialized protobuf message.
// The request will be a serialized protobuf message.
ASSERT_TRUE(cdm_engine_.GetServiceCertificateRequest(&request));
LOGV("ret'd request message:\"%s\"", request.c_str());
std::string response;
ASSERT_TRUE(LicenseServerRequestResponse(request, &response));
// Extract the service certificate
if (cdm_engine_.ParseServiceCertificateResponse(response, &certificate) ==
NO_ERROR) {
ASSERT_TRUE(cdm_engine_.HasServiceCertificate());
LOGV("ret'd cert:\"%s\"", b2a_hex(certificate).c_str());
return;
}
// Message did not parse. Possibly it is because of base64 encoding
// of the request. Try again with binary (base64 decoded) message.
LOGE("Base64 encoded request failed - RETRY with binary request");
while (request.size() % 4 != 0) {
request = request + "="; // add padding if necessary
}
std::vector<uint8_t> binary_vector = Base64SafeDecode(request);
std::string binary_request(binary_vector.begin(), binary_vector.end());
LOGV("raw_string=%s", b2a_hex(binary_request).c_str());
ASSERT_TRUE(LicenseServerRequestResponse(binary_request, &response));
ASSERT_EQ(cdm_engine_.ParseServiceCertificateResponse(response, &certificate),
NO_ERROR);
LOGV("ret'd cert:\"%s\"", b2a_hex(certificate).c_str());
ASSERT_TRUE(cdm_engine_.HasServiceCertificate());
LOGV("ret'd service certificate:\n%s\n", b2a_hex(certificate).c_str());
};
// Test that service certificate can be retrieved from the license server.
TEST_F(WvCdmEnginePreProvTestUat, ServiceCertificateRequestResponse) {
CdmKeyMessage request;
std::string certificate;
// Initial condition - no service certificate.
ASSERT_FALSE(cdm_engine_.HasServiceCertificate());
// Generate request.
// The request will be a serialized protobuf message.
ASSERT_TRUE(cdm_engine_.GetServiceCertificateRequest(&request));
std::string response;
ASSERT_TRUE(LicenseServerRequestResponse(request, &response));
// Extract the service certificate
ASSERT_EQ(cdm_engine_.ParseServiceCertificateResponse(response, &certificate),
NO_ERROR);
ASSERT_TRUE(cdm_engine_.HasServiceCertificate());
LOGV("ret'd service certificate:\n%s\n", b2a_hex(certificate).c_str());
};
// Test that service certificate can be retrieved from the license server.
TEST_F(WvCdmEnginePreProvTestProd, ServiceCertificateRequestResponse) {
CdmKeyMessage request;
std::string certificate;
// Initial condition - no service certificate.
ASSERT_FALSE(cdm_engine_.HasServiceCertificate());
// Generate request.
// The request will be a serialized protobuf message.
ASSERT_TRUE(cdm_engine_.GetServiceCertificateRequest(&request));
std::string response;
ASSERT_TRUE(LicenseServerRequestResponse(request, &response));
// Extract the service certificate
ASSERT_EQ(cdm_engine_.ParseServiceCertificateResponse(response, &certificate),
NO_ERROR);
ASSERT_TRUE(cdm_engine_.HasServiceCertificate());
LOGV("ret'd service certificate:\n%s\n", b2a_hex(certificate).c_str());
};
// Test that empty service certificate fails.
TEST_F(WvCdmEnginePreProvTest, ServiceCertificateEmptyFailTest) {
TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateEmptyFailTest) {
std::string empty_cert;
ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_service_certificate),
ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_license_service_certificate),
NO_ERROR);
ASSERT_TRUE(cdm_engine_.HasServiceCertificate());
};
// Test that provisioning works, even if device is already provisioned.
TEST_F(WvCdmEngineTest, DISABLED_Provisioning30Test) {
TEST_F(WvCdmEnginePreProvTestStaging, DISABLED_ProvisioningTest) {
uint32_t nonce = 0;
uint8_t buffer[1];
size_t size = 0;
int result = OEMCrypto_RewrapDeviceRSAKey(
0, buffer, 0, buffer, 0, &nonce, buffer, 0, buffer, buffer, &size);
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
int result30 = OEMCrypto_RewrapDeviceRSAKey30(
0, &nonce, buffer, 0, buffer, 0, buffer, buffer, &size);
int method = OEMCrypto_GetProvisioningMethod(kLevelDefault);
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED &&
result30 == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
LOGW("WARNING: Skipping ProvisioningTest because the device does not "
"support provisioning. If you are using a baked-in certificate, this "
"is expected. Otherwise, something is wrong.");
return;
"support provisioning. If you are using a baked-in certificate, "
"this is expected. Otherwise, something is wrong.");
ASSERT_EQ(method, OEMCrypto_DrmCertificate);
} else {
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
ASSERT_EQ(method, OEMCrypto_OEMCertificate);
} else {
ASSERT_EQ(method, OEMCrypto_Keybox);
}
}
Provision();
}
TEST_F(WvCdmEnginePreProvTestStagingProv30, ProvisioningTest) {
Provision();
}
// Test that provisioning works, even if device is already provisioned.
TEST_F(WvCdmEngineTest, DISABLED_ProvisioningTest) {
Provision();
}
@@ -403,7 +536,7 @@ TEST_F(WvCdmEngineTest, BaseIsoBmffMessageTest) {
}
// TODO(juce): Set up with correct test data.
TEST_F(WvCdmEngineTest, BaseWebmMessageTest) {
TEST_F(WvCdmEngineTest, DISABLED_BaseWebmMessageTest) {
GenerateKeyRequest(g_key_id_unwrapped, kWebmMimeType);
GetKeyRequestResponse(g_license_server, g_client_auth);
}
@@ -423,7 +556,7 @@ TEST_F(WvCdmEngineTest, NormalDecryptionIsoBmff) {
}
// TODO(juce): Set up with correct test data.
TEST_F(WvCdmEngineTest, NormalDecryptionWebm) {
TEST_F(WvCdmEngineTest, DISABLED_NormalDecryptionWebm) {
GenerateKeyRequest(g_key_id_unwrapped, kWebmMimeType);
VerifyNewKeyResponse(g_license_server, g_client_auth);
}

View File

@@ -3,6 +3,12 @@
#include "config_test_env.h"
#include "string_conversions.h"
// Holds the data needed to talk to the various provisioning and
// license servers.
//
// Define a series of configurations, and specify the specific
// data items needed for that configuration.
namespace wvcdm {
namespace {
@@ -95,18 +101,14 @@ const std::string kUatServiceCertificate =
"38540F8A0C227C0011E0F5B38E4E298ED2CB301EB4564965F55C5D79757A"
"250A4EB9C84AB3E6539F6B6FDF56899EA29914";
// QA/Test server (kContentProtectionTestQAServer)
//
const std::string kQALicenseServerUrl =
"https://widevine-proxy-qa.corp.google.com/proxy";
const std::string kQAProvisioningServerUrl =
"http://www-googleapis-test.sandbox.google.com/"
"certificateprovisioning/v1/devicecertificates/create";
// Content Protection license server (Production) data
const std::string kCpProdLicenseServer =
"https://widevine-proxy.appspot.com/proxy";
// Content Protection license server (UAT) data
const std::string kCpUatLicenseServer =
"http://widevine-proxy.appspot.com/proxy";
"https://proxy.uat.widevine.com/proxy";
const std::string kCpClientAuth = "";
const std::string kCpKeyId =
"00000042" // blob size
@@ -130,7 +132,7 @@ const std::string kCpOfflineKeyId =
// Content Protection license server (staging) data
const std::string kCpStagingLicenseServer =
"http://wv-staging-proxy.appspot.com/proxy";
"https://proxy.staging.widevine.com/proxy";
// Google Play license server data
const std::string kGpLicenseServer =
@@ -181,28 +183,47 @@ const std::string kStagingProvisioningServerUrl =
"certificateprovisioning/v1/devicecertificates/create"
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
const ConfigTestEnv::LicenseServerConfiguration license_servers[] = {
{kGooglePlayServer, kGpLicenseServer, kGpClientAuth, kGpKeyId,
kGpOfflineKeyId, "", kStagingProvisioningServerUrl},
{kContentProtectionUatServer, kCpUatLicenseServer, kCpClientAuth,
kCpKeyId, kCpOfflineKeyId, kProdServiceCertificate,
kStagingProvisioningServerUrl},
{kContentProtectionStagingServer, kCpStagingLicenseServer,
kCpClientAuth, kCpKeyId, kCpOfflineKeyId, kProdServiceCertificate,
kStagingProvisioningServerUrl},
{kGooglePlayServer, kGpLicenseServer, "", kGpClientAuth, kGpKeyId,
kGpOfflineKeyId, kStagingProvisioningServerUrl, ""},
{kContentProtectionProdLicense, kCpProdLicenseServer,
kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId,
kProductionProvisioningServerUrl, kProdServiceCertificate},
{kContentProtectionUatLicense, kCpUatLicenseServer,
kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId,
kProductionProvisioningServerUrl, kProdServiceCertificate},
{kContentProtectionStagingLicense, kCpStagingLicenseServer,
kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId,
kStagingProvisioningServerUrl, kStagingServiceCertificate},
{kContentProtectionProdPlusProv30, kCpProdLicenseServer,
kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId,
kStagingProvisioningServerUrl, kStagingServiceCertificate},
{kContentProtectionUatPlusProv30, kCpUatLicenseServer,
kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId,
kStagingProvisioningServerUrl, kStagingServiceCertificate},
{kContentProtectionStagingPlusProv30, kCpStagingLicenseServer,
kStagingServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId,
kStagingProvisioningServerUrl, kStagingServiceCertificate},
};
} // namespace
ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id) { Init(server_id); }
ConfigTestEnv::ConfigTestEnv(ServerConfigurationId server_id) {
Init(server_id);
}
ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id, bool streaming) {
ConfigTestEnv::ConfigTestEnv(ServerConfigurationId server_id, bool streaming) {
Init(server_id);
if (!streaming) key_id_ = license_servers[server_id].offline_key_id;
}
ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id, bool streaming,
ConfigTestEnv::ConfigTestEnv(ServerConfigurationId server_id, bool streaming,
bool renew, bool release) {
Init(server_id);
if (!streaming) {
@@ -220,13 +241,16 @@ ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id, bool streaming,
}
}
void ConfigTestEnv::Init(LicenseServerId server_id) {
void ConfigTestEnv::Init(ServerConfigurationId server_id) {
client_auth_ = license_servers[server_id].client_tag;
key_id_ = license_servers[server_id].key_id;
key_system_ = kWidevineKeySystem;
license_server_ = license_servers[server_id].url;
provisioning_server_ = license_servers[server_id].provisioning_server;
service_certificate_ = a2bs_hex(license_servers[server_id].service_certificate);
license_server_ = license_servers[server_id].license_server_url;
provisioning_server_ = license_servers[server_id].provisioning_server_url;
license_service_certificate_ =
a2bs_hex(license_servers[server_id].license_service_certificate);
provisioning_service_certificate_ =
a2bs_hex(license_servers[server_id].provisioning_service_certificate);
wrong_key_id_ = kWrongKeyId;
}

View File

@@ -6,30 +6,50 @@
#include <string>
#include "wv_cdm_types.h"
// Declare class ConfigTestEnv - holds the configuration settings needed
// to talk to the various provisioning and license servers.
//
// License Servers
// QA - early test server (corporate access only, not generally usable).
// UAT - test server with non-production data.
// Staging - test server with access to production data.
// Production - live, production server.
// Google Play - Allows testing on Google Play servers (very stale).
//
// Provisioning Servers
// UAT - early access provisioning server.
// Staging - early access to features.
// Production - live production server.
// Useful configurations
namespace wvcdm {
typedef enum {
kGooglePlayServer,
kContentProtectionUatServer,
kContentProtectionStagingServer,
kContentProtectionTestQAServer,
} LicenseServerId;
kGooglePlayServer, // not tested recently
kContentProtectionProdLicense,
kContentProtectionUatLicense,
kContentProtectionStagingLicense,
kContentProtectionProdPlusProv30,
kContentProtectionUatPlusProv30,
kContentProtectionStagingPlusProv30,
} ServerConfigurationId;
// Configures default test environment.
class ConfigTestEnv {
public:
typedef struct {
LicenseServerId id;
std::string url;
ServerConfigurationId id;
std::string license_server_url;
std::string license_service_certificate;
std::string client_tag;
std::string key_id;
std::string offline_key_id;
std::string service_certificate;
std::string provisioning_server;
std::string provisioning_server_url;
std::string provisioning_service_certificate;
} LicenseServerConfiguration;
explicit ConfigTestEnv(LicenseServerId server_id);
ConfigTestEnv(LicenseServerId server_id, bool streaming);
ConfigTestEnv(LicenseServerId server_id, bool streaming, bool renew,
explicit ConfigTestEnv(ServerConfigurationId server_id);
ConfigTestEnv(ServerConfigurationId server_id, bool streaming);
ConfigTestEnv(ServerConfigurationId server_id, bool streaming, bool renew,
bool release);
~ConfigTestEnv() {};
@@ -40,8 +60,11 @@ class ConfigTestEnv {
const std::string& provisioning_server() const {
return provisioning_server_;
}
const std::string& service_certificate() const {
return service_certificate_;
const std::string& license_service_certificate() const {
return license_service_certificate_;
}
const std::string& provisioning_service_certificate() const {
return provisioning_service_certificate_;
}
const KeyId& wrong_key_id() const { return wrong_key_id_; }
@@ -54,14 +77,15 @@ class ConfigTestEnv {
}
private:
void Init(LicenseServerId server_id);
void Init(ServerConfigurationId server_id);
std::string client_auth_;
KeyId key_id_;
CdmKeySystem key_system_;
std::string license_server_;
std::string provisioning_server_;
std::string service_certificate_;
std::string license_service_certificate_;
std::string provisioning_service_certificate_;
KeyId wrong_key_id_;
CORE_DISALLOW_COPY_AND_ASSIGN(ConfigTestEnv);

View File

@@ -124,6 +124,7 @@ struct LicenseInfo {
int64_t grace_period_end_time;
std::string app_parameters;
std::string usage_entry;
uint32_t usage_entry_number;
std::string file_data;
};
@@ -230,9 +231,9 @@ LicenseInfo license_test_data[] = {
"0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF"
"A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0"
"BEA6CABACA1C2C"),
"https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "", "",
"https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "", "", 0,
a2bs_hex(
"0AAC150802100122A5150801121408011210303132333435363738394142434445461"
"0AAE150802100122A7150801121408011210303132333435363738394142434445461"
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
"7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302"
"5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B"
@@ -311,8 +312,9 @@ LicenseInfo license_test_data[] = {
"106B63746C0000000000ECDCBE0000000020DBDFA68F051A20182F029E35047A3841F"
"A176C74E5B387350E8D58DEA6878FF0BEA6CABACA1C2C3A2E68747470733A2F2F7465"
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
"3654000480058006200122039CB77169260F923E5D4BA5BBF6A7611117483253F2869"
"9DF3D9D14C3718E309")},
"365400048005800620068001220785CE1756656A049E77F28C8449AB2DD115B6C43B2"
"FF232D23F98B72F1DCE96A"
)},
// license 1
{"ksidC8EAA2579A282EB0", DeviceFiles::kLicenseStateReleasing,
@@ -415,8 +417,9 @@ LicenseInfo license_test_data[] = {
a2bs_hex(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
"22232425262728292a2b2c2d2e2f"),
5,
a2bs_hex(
"0AF5150802100122EE150802121408011210303132333435363738394142434445461"
"0AF7150802100122F0150802121408011210303132333435363738394142434445461"
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
"7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302"
"5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B"
@@ -497,8 +500,8 @@ LicenseInfo license_test_data[] = {
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
"36540F8ACD1910148E58ED29101520F0A054E616D6531120656616C75653158006230"
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212"
"2232425262728292A2B2C2D2E2F1220312487214ACA5A9AF5ED9D45F209DC77E03CA1"
"DBFFDF86C44A35A1351CE968B9")},
"2232425262728292A2B2C2D2E2F6805122010DB816A045F2AA5865B17FE2F20DA2114"
"17B2F8B2D7511C9DE89A87CB5208AB")},
// license 2
{"ksidE8C37662C88DC673", DeviceFiles::kLicenseStateReleasing,
@@ -601,8 +604,9 @@ LicenseInfo license_test_data[] = {
a2bs_hex(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
"22232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"),
12,
a2bs_hex(
"0AAB160802100122A4160802121408011210303132333435363738394142434445461"
"0AAD160802100122A6160802121408011210303132333435363738394142434445461"
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
"7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302"
"5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B"
@@ -684,8 +688,9 @@ LicenseInfo license_test_data[] = {
"36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910152150A054E616D6531120C5661"
"6C756531204E616D653252160A0C4E616D653220506172616D321206506172616D325"
"8006240000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E"
"1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F122"
"07CEAAE401B81E635808AC830A0F3F43308A38FAB16069E542F994B6EC1325280")}};
"1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F680"
"C12206AA0237760D1F06E5CB78F5AFC3D124BBF7C26921CB3CC2EA44766801E25D34"
"F")}};
// Sample license data and related data for storage and use for offline
// playback. The license data and URLs in this test are not real.
@@ -792,8 +797,9 @@ LicenseInfo license_update_test_data[] = {
a2bs_hex(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
"22232425262728292a2b2c2d2e2f"),
15,
a2bs_hex(
"0AEC150802100122E5150801121408011210303132333435363738394142434445461"
"0AEE150802100122E7150801121408011210303132333435363738394142434445461"
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
"7A7D5076189EDFB68F05228E023082010A0282010100CC1715C81AD3F6F279C686F82"
"6E6D7C8961EB13318367D06B4061BBC57E3C616A226A10F042CAD54D44C6484C725CD"
@@ -874,14 +880,14 @@ LicenseInfo license_update_test_data[] = {
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
"36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910158006230000102030405060708"
"090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2"
"B2C2D2E2F1220A33C179B7718632337DFDC32D3711FD543336EBE838979DFDEB3A168"
"BC9AFB27")},
"B2C2D2E2F680F122009B8588A8E9926339289BA373DB8479A71F7AA1164083D90613F"
"766D60B07CBC")},
// license being released. all fields are identical except for license
// state and hashed file data
{"", DeviceFiles::kLicenseStateReleasing, "", "", "", "", "", "", 0, 0, 0,
"", "",
"", "", 15,
a2bs_hex(
"0AEC150802100122E5150802121408011210303132333435363738394142434445461"
"0AEE150802100122E7150802121408011210303132333435363738394142434445461"
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
"7A7D5076189EDFB68F05228E023082010A0282010100CC1715C81AD3F6F279C686F82"
"6E6D7C8961EB13318367D06B4061BBC57E3C616A226A10F042CAD54D44C6484C725CD"
@@ -962,8 +968,8 @@ LicenseInfo license_update_test_data[] = {
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
"36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910158006230000102030405060708"
"090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2"
"B2C2D2E2F1220394BA01DFB519C1A7311115F8B2A0AC3141F981FFEA09FCD48A8EFA3"
"A045AAE6")}};
"B2C2D2E2F680F12202F5B77A3168AC2A81832231A435D0587F6D1DF3B905A7058C5E8"
"565C81B96CA6")}};
// Application parameters were added to the License message. This data
// is used to verify that a License saved without application parameters can
@@ -1065,7 +1071,7 @@ LicenseInfo license_app_parameters_backwards_compatibility_test_data = {
"0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF"
"A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0"
"BEA6CABACA1C2C"),
"https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "", "",
"https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "", "", 0,
a2bs_hex(
"0AA8150802100122A1150801121408011210303132333435363738394142434445461"
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
@@ -1154,11 +1160,12 @@ struct UsageInfo {
std::string license_request;
std::string license;
std::string usage_entry;
uint32_t usage_entry_number;
std::string file_data;
};
UsageInfo kUsageInfoTestData[] = {
{"", "", "", "", // 0 usage info records
{"", "", "", "", 0, // 0 usage info records
a2bs_hex("0A06080210012A00122095053501C5FA405B7EF01DA94685C6B20CB36493"
"A9CF1653B720E2BEA3B77929")},
{// 1 usage info record
@@ -1196,6 +1203,7 @@ UsageInfo kUsageInfoTestData[] = {
a2bs_hex(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
"22232425262728292a2b2c2d2e2f"),
6,
a2bs_hex(
"0AB307080210012AAC070AA9070A8001924B035FBDA56AE5EF0ED05A08DE7AECC8ABE"
"1835E0C4A548F7803937F4C3B4520EB7F3334FFCDFA00DE56408F09D5019FCE87072D"
@@ -1261,6 +1269,7 @@ UsageInfo kUsageInfoTestData[] = {
a2bs_hex(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
"22232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"),
14,
a2bs_hex(
"0ADF0E080210012AD80E0AA9070A8001924B035FBDA56AE5EF0ED05A08DE7AECC8ABE"
"1835E0C4A548F7803937F4C3B4520EB7F3334FFCDFA00DE56408F09D5019FCE87072D"
@@ -1353,6 +1362,7 @@ UsageInfo kUsageInfoTestData[] = {
a2bs_hex(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
"22232425262728292a2b2c2d2e2f"),
19,
a2bs_hex(
"0A8B16080210012A84160AA9070A8001924B035FBDA56AE5EF0ED05A08DE7AECC8ABE"
"1835E0C4A548F7803937F4C3B4520EB7F3334FFCDFA00DE56408F09D5019FCE87072D"
@@ -1465,88 +1475,82 @@ HlsAttributesInfo kHlsAttributesTestData[] = {
// Usage Table and Entry Test Data
// Note: Make sure the number of entries in kUsageEntriesTestData and
// kUsageTableInfoTestData are equal.
DeviceFiles::UsageEntryInfo kUsageEntriesTestData[] = {
CdmUsageEntryInfo kUsageEntriesTestData[] = {
// usage entry 0
{
DeviceFiles::kStorageLicense, "ksid0", "", "",
kStorageLicense, "ksid0", "",
},
// usage entry 1
{
DeviceFiles::kStorageLicense, "ksid1", "", "",
kStorageLicense, "ksid1", "",
},
// usage entry 2
{
DeviceFiles::kStorageUsageInfo, "", "provider_session_token_2",
"app_id_2",
kStorageUsageInfo, "", "app_id_2",
},
// usage entry 3
{
DeviceFiles::kStorageUsageInfo, "", "provider_session_token_3",
"app_id_3",
kStorageUsageInfo, "", "app_id_3",
},
// usage entry 4
{
DeviceFiles::kStorageLicense, "ksid4", "", "",
kStorageLicense, "ksid4", "",
},
// usage entry 5
{
DeviceFiles::kStorageUsageInfo, "", "provider_session_token_5",
"app_id_5",
kStorageUsageInfo, "", "app_id_5",
},
};
struct UsageTableTestInfo {
std::string usage_table_header;
CdmUsageTableHeader usage_table_header;
std::string file_data;
};
UsageTableTestInfo kUsageTableInfoTestData[] = {
// usage table 0
{a2bs_hex("5574517CCC"),
a2bs_hex("0A18080510013A120A055574517CCC1209080112056B73696430122018268E3F"
"384F28D04BEE00304089C000463C22E987532855390915FD02C36B5C")},
// usage table 1
{a2bs_hex("CA870203010001288001"),
a2bs_hex("0A28080510013A220A0ACA8702030100012880011209080112056B7369643012"
"09080112056B7369643112202D3638164ADC3B4276734A8EDE96C40BFE14DDB2"
"8013337A3A1A9DFC09F34923")},
a2bs_hex("0A2C080510013A260A0ACA870203010001288001120B080112056B736964301A"
"00120B080112056B736964311A00122049A8F3481444A5B64B6C4F05FBCC2EF8"
"CB67444A08654763F2F5B80F658D7B38")},
// usage table 2
{a2bs_hex("7A7D507618A5D3A68F05228E023082010A028201"),
a2bs_hex("0A5A080510013A540A147A7D507618A5D3A68F05228E023082010A0282011209"
"080112056B736964301209080112056B73696431122608021A1870726F766964"
"65725F73657373696F6E5F746F6B656E5F3222086170705F69645F321220CB07"
"CA08A1E76C61A5F45067176B960A9DB40D169025AF245CF1AFC66C979F47")},
a2bs_hex("0A46080510013A400A147A7D507618A5D3A68F05228E023082010A028201120B"
"080112056B736964301A00120B080112056B736964311A00120E080212001A08"
"6170705F69645F321220783E93A02223BDB94E743856C0F69C35B213ACCDDE91"
"93E48E9186AA83B80584")},
// usage table 3
{a2bs_hex("E83A4902772DAFD2740B7748E9C3B1752D6F12859CED07E82969B4EC"),
a2bs_hex("0A8B01080510013A84010A1CE83A4902772DAFD2740B7748E9C3B1752D6F1285"
"9CED07E82969B4EC1209080112056B736964301209080112056B736964311226"
"08021A1870726F76696465725F73657373696F6E5F746F6B656E5F3222086170"
"705F69645F32122608021A1870726F76696465725F73657373696F6E5F746F6B"
"656E5F3322086170705F69645F331220C4157F80E81C923A9F0885CE6B928D15"
"7E1648384C3E44F04A966815EB09B260")},
a2bs_hex("0A5E080510013A580A1CE83A4902772DAFD2740B7748E9C3B1752D6F12859CED"
"07E82969B4EC120B080112056B736964301A00120B080112056B736964311A00"
"120E080212001A086170705F69645F32120E080212001A086170705F69645F33"
"122084E67F1338727291BC3D92E28442DC8B0F44CB5AF7B98A799313B7EB7F55"
"ED18")},
// usage table 4
{a2bs_hex("CA870203010001288001300112800250D1F8B1ECF849B60FF93E37C4DEEF"
"52F1CCFC047EF42300131F9C4758F4"),
a2bs_hex("0AA701080510013AA0010A2DCA870203010001288001300112800250D1F8B1EC"
"F849B60FF93E37C4DEEF52F1CCFC047EF42300131F9C4758F41209080112056B"
"736964301209080112056B73696431122608021A1870726F76696465725F7365"
"7373696F6E5F746F6B656E5F3222086170705F69645F32122608021A1870726F"
"76696465725F73657373696F6E5F746F6B656E5F3322086170705F69645F3312"
"09080112056B7369643412203F75C53693E7A3DC9BA5BF3E23D7EFCF3C05687A"
"A6082E3AB78F563525981999")},
a2bs_hex("0A7C080510013A760A2DCA870203010001288001300112800250D1F8B1ECF849"
"B60FF93E37C4DEEF52F1CCFC047EF42300131F9C4758F4120B080112056B7369"
"64301A00120B080112056B736964311A00120E080212001A086170705F69645F"
"32120E080212001A086170705F69645F33120B080112056B736964341A001220"
"1CDFCFED5E58A1DF77E1B335305424E1F0260340F9CC15985684C43A4207652"
"1")},
// usage table 5
{a2bs_hex("EC83A4902772DAFD2740B7748E9C3B1752D6F12859CED07E8882969B433E"
"C29AC6FDBE79230B0FAED5D94CF6B829A420BBE3270323941776EE60DD6B"),
a2bs_hex("0ADE01080510013AD7010A3CEC83A4902772DAFD2740B7748E9C3B1752D6F128"
a2bs_hex("0A9C01080510013A95010A3CEC83A4902772DAFD2740B7748E9C3B1752D6F128"
"59CED07E8882969B433EC29AC6FDBE79230B0FAED5D94CF6B829A420BBE32703"
"23941776EE60DD6B1209080112056B736964301209080112056B736964311226"
"08021A1870726F76696465725F73657373696F6E5F746F6B656E5F3222086170"
"705F69645F32122608021A1870726F76696465725F73657373696F6E5F746F6B"
"656E5F3322086170705F69645F331209080112056B73696434122608021A1870"
"726F76696465725F73657373696F6E5F746F6B656E5F3522086170705F69645F"
"3512203B35BD5C615BBA79008A7A1DA29AFA69F5CD529DFDE794A0544E423B72"
"1CB8E8")},
"23941776EE60DD6B120B080112056B736964301A00120B080112056B73696431"
"1A00120E080212001A086170705F69645F32120E080212001A086170705F6964"
"5F33120B080112056B736964341A00120E080212001A086170705F69645F3512"
"20305C7A27A918268119E1996FC182C153DF805034A387F90C3585749E764731"
"32")},
};
class MockFile : public File {
@@ -1889,7 +1893,8 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) {
license_test_data[license_num].playback_start_time,
license_test_data[license_num].last_playback_time,
license_test_data[license_num].grace_period_end_time, app_parameters,
license_test_data[license_num].usage_entry));
license_test_data[license_num].usage_entry,
license_test_data[license_num].usage_entry_number));
}
INSTANTIATE_TEST_CASE_P(StoreLicense, DeviceFilesStoreTest, ::testing::Bool());
@@ -1939,7 +1944,8 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
license_test_data[i].playback_start_time,
license_test_data[i].last_playback_time,
license_test_data[i].grace_period_end_time, app_parameters,
license_test_data[i].usage_entry));
license_test_data[i].usage_entry,
license_test_data[i].usage_entry_number));
}
}
@@ -1981,6 +1987,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
std::string release_server_url;
CdmAppParameterMap app_parameters;
std::string usage_entry;
uint32_t usage_entry_number;
for (size_t i = 0; i < kNumberOfLicenses; i++) {
DeviceFiles::LicenseState license_state;
@@ -1989,7 +1996,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
&key_request, &key_response, &key_renewal_request,
&key_renewal_response, &release_server_url, &playback_start_time,
&last_playback_time, &grace_period_end_time, &app_parameters,
&usage_entry));
&usage_entry, &usage_entry_number));
EXPECT_EQ(license_test_data[i].license_state, license_state);
EXPECT_EQ(license_test_data[i].pssh_data, pssh_data);
EXPECT_EQ(license_test_data[i].key_request, key_request);
@@ -2001,6 +2008,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
EXPECT_EQ(license_test_data[i].grace_period_end_time,
grace_period_end_time);
EXPECT_EQ(license_test_data[i].usage_entry, usage_entry);
EXPECT_EQ(license_test_data[i].usage_entry_number, usage_entry_number);
std::map<std::string, std::string>::iterator itr;
for (itr = app_parameters.begin(); itr != app_parameters.end(); ++itr) {
@@ -2049,12 +2057,14 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
std::string release_server_url;
CdmAppParameterMap app_parameters;
std::string usage_entry;
uint32_t usage_entry_number;
EXPECT_TRUE(device_files.RetrieveLicense(
test_data->key_set_id, &license_state, &pssh_data, &key_request,
&key_response, &key_renewal_request, &key_renewal_response,
&release_server_url, &playback_start_time, &last_playback_time,
&grace_period_end_time, &app_parameters, &usage_entry));
&grace_period_end_time, &app_parameters, &usage_entry,
&usage_entry_number));
EXPECT_EQ(test_data->license_state, license_state);
EXPECT_EQ(test_data->pssh_data, pssh_data);
EXPECT_EQ(test_data->key_request, key_request);
@@ -2066,6 +2076,7 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
EXPECT_EQ(test_data->grace_period_end_time, grace_period_end_time);
EXPECT_EQ(0u, app_parameters.size());
EXPECT_EQ(test_data->usage_entry, usage_entry);
EXPECT_EQ(test_data->usage_entry_number, usage_entry_number);
}
TEST_F(DeviceFilesTest, UpdateLicenseState) {
@@ -2102,7 +2113,8 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) {
license_update_test_data[0].last_playback_time,
license_update_test_data[0].grace_period_end_time,
GetAppParameters(license_test_data[0].app_parameters),
license_update_test_data[0].usage_entry));
license_update_test_data[0].usage_entry,
license_update_test_data[0].usage_entry_number));
EXPECT_TRUE(device_files.StoreLicense(
license_update_test_data[0].key_set_id,
@@ -2117,7 +2129,8 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) {
license_update_test_data[0].last_playback_time,
license_update_test_data[0].grace_period_end_time,
GetAppParameters(license_test_data[0].app_parameters),
license_update_test_data[0].usage_entry));
license_update_test_data[0].usage_entry,
license_update_test_data[0].usage_entry_number));
}
TEST_F(DeviceFilesTest, DeleteLicense) {
@@ -2158,12 +2171,14 @@ TEST_F(DeviceFilesTest, DeleteLicense) {
int64_t playback_start_time, last_playback_time, grace_period_end_time;
CdmAppParameterMap app_parameters;
std::string usage_entry;
uint32_t usage_entry_number;
EXPECT_TRUE(device_files.RetrieveLicense(
license_test_data[0].key_set_id, &license_state, &pssh_data, &key_request,
&key_response, &key_renewal_request, &key_renewal_response,
&release_server_url, &playback_start_time, &last_playback_time,
&grace_period_end_time, &app_parameters, &usage_entry));
&grace_period_end_time, &app_parameters, &usage_entry,
&usage_entry_number));
EXPECT_EQ(license_test_data[0].license_state, license_state);
EXPECT_EQ(license_test_data[0].pssh_data, pssh_data);
EXPECT_EQ(license_test_data[0].key_request, key_request);
@@ -2181,6 +2196,7 @@ TEST_F(DeviceFilesTest, DeleteLicense) {
std::string::npos);
}
EXPECT_EQ(license_test_data[0].usage_entry, usage_entry);
EXPECT_EQ(license_test_data[0].usage_entry_number, usage_entry_number);
EXPECT_TRUE(device_files.DeleteLicense(license_test_data[0].key_set_id));
EXPECT_FALSE(device_files.LicenseExists(license_test_data[0].key_set_id));
@@ -2235,7 +2251,9 @@ TEST_P(DeviceFilesUsageInfoTest, Read) {
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> > license_info;
ASSERT_TRUE(device_files.RetrieveUsageInfo(app_id, &license_info));
ASSERT_TRUE(device_files.RetrieveUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
&license_info));
if (index >= 0) {
EXPECT_EQ(static_cast<size_t>(index), license_info.size());
for (size_t i = 0; i < license_info.size(); ++i) {
@@ -2263,6 +2281,7 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
std::string license(GenerateRandomData(kLicenseLen));
std::string key_set_id(GenerateRandomData(kKeySetIdLen));
std::string usage_entry(GenerateRandomData(kUsageEntryLen));
uint32_t usage_entry_number = 16;
std::string path =
device_base_path_ + DeviceFiles::GetUsageInfoFileName(app_id);
@@ -2300,8 +2319,10 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
ASSERT_TRUE(device_files.StoreUsageInfo(pst, license_request, license, app_id,
key_set_id, usage_entry));
ASSERT_TRUE(device_files.StoreUsageInfo(
pst, license_request, license,
DeviceFiles::GetUsageInfoFileName(app_id),
key_set_id, usage_entry, usage_entry_number));
}
TEST_P(DeviceFilesUsageInfoTest, Delete) {
@@ -2349,9 +2370,13 @@ TEST_P(DeviceFilesUsageInfoTest, Delete) {
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
if (index >= 1) {
ASSERT_TRUE(device_files.DeleteUsageInfo(app_id, pst));
ASSERT_TRUE(device_files.DeleteUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
pst));
} else {
ASSERT_FALSE(device_files.DeleteUsageInfo(app_id, pst));
ASSERT_FALSE(device_files.DeleteUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
pst));
}
}
@@ -2385,7 +2410,9 @@ TEST_P(DeviceFilesUsageInfoTest, DeleteAll) {
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
std::vector<std::string> psts;
ASSERT_TRUE(device_files.DeleteAllUsageInfoForApp(app_id, &psts));
ASSERT_TRUE(device_files.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&psts));
if (index < 0) {
EXPECT_EQ(0u, psts.size());
} else {
@@ -2479,20 +2506,14 @@ TEST_P(DeviceFilesUsageTableTest, Store) {
size_t entry_data_length = 0;
std::vector<std::string> entry_data;
std::vector<DeviceFiles::UsageEntryInfo> usage_entry_info;
std::vector<CdmUsageEntryInfo> usage_entry_info;
usage_entry_info.resize(index + 1);
for (int i = 0; i <= index; ++i) {
usage_entry_info[i] = kUsageEntriesTestData[i];
if (kUsageEntriesTestData[i].storage_type == DeviceFiles::kStorageLicense) {
entry_data.push_back(kUsageEntriesTestData[i].key_set_id);
entry_data_length += kUsageEntriesTestData[i].key_set_id.size();
} else {
entry_data.push_back(kUsageEntriesTestData[i].provider_session_token);
entry_data.push_back(kUsageEntriesTestData[i].app_id);
entry_data_length +=
kUsageEntriesTestData[i].provider_session_token.size() +
kUsageEntriesTestData[i].app_id.size();
}
entry_data.push_back(kUsageEntriesTestData[i].key_set_id);
entry_data.push_back(kUsageEntriesTestData[i].usage_info_file_name);
entry_data_length += kUsageEntriesTestData[i].key_set_id.size() +
kUsageEntriesTestData[i].usage_info_file_name.size();
}
entry_data.push_back(kUsageTableInfoTestData[index].usage_table_header);
entry_data_length += kUsageTableInfoTestData[index].usage_table_header.size();
@@ -2516,7 +2537,7 @@ TEST_P(DeviceFilesUsageTableTest, Store) {
TEST_P(DeviceFilesUsageTableTest, Read) {
MockFileSystem file_system;
MockFile file;
int index = GetParam();
size_t index = GetParam();
std::string path = device_base_path_ + DeviceFiles::GetUsageTableFileName();
@@ -2535,28 +2556,22 @@ TEST_P(DeviceFilesUsageTableTest, Read) {
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
std::vector<DeviceFiles::UsageEntryInfo> usage_entry_info;
std::string usage_table_header;
std::vector<CdmUsageEntryInfo> usage_entry_info;
CdmUsageTableHeader usage_table_header;
ASSERT_TRUE(device_files.RetrieveUsageTableInfo(&usage_table_header,
&usage_entry_info));
EXPECT_EQ(kUsageTableInfoTestData[index].usage_table_header,
usage_table_header);
EXPECT_EQ(index + 1u, usage_entry_info.size());
for (int i = 0; i <= index; ++i) {
for (size_t i = 0; i <= index; ++i) {
EXPECT_EQ(kUsageEntriesTestData[i].storage_type,
usage_entry_info[i].storage_type);
if (usage_entry_info[i].storage_type == DeviceFiles::kStorageLicense) {
EXPECT_EQ(kUsageEntriesTestData[i].key_set_id,
usage_entry_info[i].key_set_id);
EXPECT_EQ(kEmptyString, usage_entry_info[i].provider_session_token);
EXPECT_EQ(kEmptyString, usage_entry_info[i].app_id);
} else {
EXPECT_EQ(kEmptyString, usage_entry_info[i].key_set_id);
EXPECT_EQ(kUsageEntriesTestData[i].provider_session_token,
usage_entry_info[i].provider_session_token);
EXPECT_EQ(kUsageEntriesTestData[i].app_id, usage_entry_info[i].app_id);
}
EXPECT_EQ(kUsageEntriesTestData[i].key_set_id,
usage_entry_info[i].key_set_id);
EXPECT_EQ(
kUsageEntriesTestData[i].usage_info_file_name,
usage_entry_info[i].usage_info_file_name);
}
}

View File

@@ -25,7 +25,50 @@ namespace {
const std::string kKeySystem = "com.widevine.alpha";
std::string g_provisioning_server;
std::string g_service_certificate;
std::string g_license_service_certificate;
std::string g_provisioning_service_certificate;
/*
* Locate the portion of the server's response message that is between
* the strings jason_start_substr and json_end_substr. Returns the string
* through *result. If the start substring match fails, assume the entire
* string represents a serialized protobuf mesaage and return true with
* the entire string. If the end_substring match fails, return false with
* an empty *result.
*/
bool ExtractSignedMessage(const std::string& response,
const std::string& json_start_substr,
const std::string& json_end_substr,
std::string* result) {
std::string b64_string;
size_t start = response.find(json_start_substr);
if (start == response.npos) {
// Assume web safe protobuf
b64_string.assign(response);
} else {
// Assume JSON-wrapped protobuf
size_t end = response.find(json_end_substr,
start + json_start_substr.length());
if (end == response.npos) {
LOGE("ExtractSignedMessage cannot locate end substring");
result->clear();
return false;
}
size_t b64_string_size = end - start - json_start_substr.length();
b64_string.assign(response, start + json_start_substr.length(),
b64_string_size);
}
if (b64_string.empty()) {
LOGE("Response message is empty");
result->clear();
return false;
}
result->swap(b64_string);
return true;
}
} // namespace
@@ -38,13 +81,11 @@ class WvGenericOperationsTest : public testing::Test {
virtual void SetUp() {
::testing::Test::SetUp();
#if defined(QA_TEST_SERVER)
ConfigTestEnv config(kContentProtectionTestQAServer);
#else
ConfigTestEnv config(kContentProtectionUatServer);
#endif // !defined(QA_TEST_SERVER)
ConfigTestEnv config(kContentProtectionStagingPlusProv30);
g_service_certificate.assign(config.service_certificate());
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());
cdm_engine_ = NULL;
@@ -52,15 +93,13 @@ class WvGenericOperationsTest : public testing::Test {
// TODO(fredgc or gmorgan): This should be updated for provisioning 3.0
// Load test keybox. This keybox will be used by any CryptoSession
// created by the CDM under test.
#if defined(PROVISIONING_30)
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
#else
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox());
#endif // !defined(PROVISIONING_30)
// Perform CdmEngine setup
cdm_engine_ = new CdmEngine(&file_system_);
Provision();
CdmResponseType status =
cdm_engine_->OpenSession(kKeySystem, NULL, NULL, &session_id_);
if (status == NEED_PROVISIONING) {
@@ -177,29 +216,55 @@ class WvGenericOperationsTest : public testing::Test {
}
protected:
void Provision() {
virtual void Provision() {
LOGE("WvCdmEnginePreProvTest::Provision: url=%s",
g_provisioning_server.c_str());
CdmProvisioningRequest prov_request;
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority;
std::string cert, wrapped_key;
cdm_engine_->SetServiceCertificate(g_service_certificate);
ASSERT_EQ(NO_ERROR,
cdm_engine_->GetProvisioningRequest(
cert_type, cert_authority, &prov_request,
&provisioning_server_url));
ASSERT_EQ(NO_ERROR, cdm_engine_->SetServiceCertificate(
g_provisioning_service_certificate));
ASSERT_EQ(NO_ERROR, cdm_engine_->GetProvisioningRequest(
cert_type, cert_authority, &prov_request,
&provisioning_server_url));
LOGV("WvCdmEnginePreProvTest::Provision: req=%s", prov_request.c_str());
// Ignore URL provided by CdmEngine. Use ours, as configured
// for test vs. production server.
provisioning_server_url.assign(g_provisioning_server);
UrlRequest url_request(provisioning_server_url);
EXPECT_TRUE(url_request.is_connected());
url_request.PostCertRequestInQueryString(prov_request);
std::string message;
bool ok = url_request.GetResponse(&message);
std::string http_message;
bool ok = url_request.GetResponse(&http_message);
EXPECT_TRUE(ok);
LOGV("WvCdmEnginePreProvTest::Provision: http_message: \n%s\n",
http_message.c_str());
// extract provisioning response from received message
// Extracts signed response from JSON string, decodes base64 signed response
const std::string kMessageStart = "\"signedResponse\": \"";
const std::string kMessageEnd = "\"";
std::string base64_response;
EXPECT_TRUE (ExtractSignedMessage(http_message, kMessageStart, kMessageEnd,
&base64_response)) <<
"Failed to extract signed serialized response from JSON response";
LOGV("WvCdmEnginePreProvTest::Provision: extracted response "
"message: \n%s\n", base64_response.c_str());
ASSERT_EQ(NO_ERROR,
cdm_engine_->HandleProvisioningResponse(message, &cert,
&wrapped_key));
cdm_engine_->HandleProvisioningResponse(base64_response,
&cert, &wrapped_key));
ASSERT_EQ(NO_ERROR,
cdm_engine_->SetServiceCertificate(
g_license_service_certificate));
}
// This CryptoSession object handles Initialization and Termination