File util, generic crypto, and key query
This CL merges several CLs from the widevine repo: http://go/wvgerrit/18012 Add support for querying allowed usage for key. http://go/wvgerrit/17971 Add per-origin storage. http://go/wvgerrit/18152 Add OEMCrypto's generic crypto operations to CDM. http://go/wvgerrit/17911 QueryKeyControlInfo => QueryOemCryptoSessionId Note: numbering in wv_cdm_types.h was added in this CL and will be back ported to wvgerrit in a future CL. Change-Id: Idb9e9a67e94f62f25dc16c5307f75a08b3430b64
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "config_test_env.h"
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "file_utils.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "license_request.h"
|
||||
#include "log.h"
|
||||
@@ -47,6 +48,8 @@ const int kHttpOk = 200;
|
||||
const int kHttpBadRequest = 400;
|
||||
const int kHttpInternalServerError = 500;
|
||||
|
||||
const char kOrigin[] = "com.example";
|
||||
|
||||
// Protobuf generated classes
|
||||
using video_widevine_server::sdk::LicenseIdentification;
|
||||
using video_widevine_server::sdk::LicenseRequest_ContentIdentification;
|
||||
@@ -1136,6 +1139,10 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
||||
}
|
||||
|
||||
void Provision(SecurityLevel level) {
|
||||
Provision(EMPTY_ORIGIN, level);
|
||||
}
|
||||
|
||||
void Provision(const std::string& origin, SecurityLevel level) {
|
||||
TestWvCdmClientPropertySet property_set_L3;
|
||||
TestWvCdmClientPropertySet* property_set = NULL;
|
||||
|
||||
@@ -1145,7 +1152,7 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
||||
}
|
||||
|
||||
CdmResponseType status = decryptor_.OpenSession(
|
||||
g_key_system, property_set, EMPTY_ORIGIN, NULL, &session_id_);
|
||||
g_key_system, property_set, origin, NULL, &session_id_);
|
||||
switch (status) {
|
||||
case NO_ERROR:
|
||||
decryptor_.CloseSession(session_id_);
|
||||
@@ -1162,7 +1169,7 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
|
||||
status = decryptor_.GetProvisioningRequest(cert_type, cert_authority,
|
||||
EMPTY_ORIGIN, &key_msg_,
|
||||
origin, &key_msg_,
|
||||
&provisioning_server_url);
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, status);
|
||||
if (NO_ERROR != status) return;
|
||||
@@ -1172,7 +1179,7 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response,
|
||||
decryptor_.HandleProvisioningResponse(origin, response,
|
||||
&cert, &wrapped_key));
|
||||
EXPECT_EQ(0, static_cast<int>(cert.size()));
|
||||
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
||||
@@ -1238,20 +1245,57 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningTest) {
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL3, kOrigin));
|
||||
|
||||
// Verify the empty origin is provisioned.
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL,
|
||||
&session_id_));
|
||||
decryptor_.CloseSession(session_id_);
|
||||
|
||||
// The other origin should not be provisioned.
|
||||
EXPECT_EQ(
|
||||
wvcdm::NEED_PROVISIONING,
|
||||
decryptor_.OpenSession(g_key_system, NULL, kOrigin, NULL, &session_id_));
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningSupportsOldPaths) {
|
||||
// This is the current file name scheme. This test exists to ensure we do
|
||||
// not break existing clients if we decide to change the naming/paths of
|
||||
// certificates.
|
||||
const char kOldFileName[] = "cert0LF0GfM75iqlNA_sByaQMA==.bin";
|
||||
ASSERT_EQ("com.example", kOrigin);
|
||||
|
||||
// Unprovision the device and delete all files.
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL3, kOrigin));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL3, EMPTY_ORIGIN));
|
||||
Provision(kOrigin, kLevel3);
|
||||
|
||||
std::string base_path;
|
||||
ASSERT_TRUE(Properties::GetDeviceFilesBasePath(kSecurityLevelL3, &base_path));
|
||||
|
||||
// Make sure that the cert exists.
|
||||
std::vector<std::string> files;
|
||||
ASSERT_TRUE(FileUtils::List(base_path, &files));
|
||||
ASSERT_EQ(1u, files.size());
|
||||
EXPECT_EQ(kOldFileName, files[0]);
|
||||
|
||||
// Reprovision the empty origin.
|
||||
Provision(EMPTY_ORIGIN, kLevel3);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, UnprovisionTest) {
|
||||
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
||||
DeviceFiles handle;
|
||||
FileSystem file_system;
|
||||
DeviceFiles handle(&file_system);
|
||||
EXPECT_TRUE(handle.Init(security_level));
|
||||
File file;
|
||||
handle.SetTestFile(&file);
|
||||
std::string certificate;
|
||||
std::string wrapped_private_key;
|
||||
EXPECT_TRUE(handle.RetrieveCertificate(EMPTY_ORIGIN, &certificate,
|
||||
&wrapped_private_key));
|
||||
EXPECT_TRUE(handle.RetrieveCertificate(&certificate, &wrapped_private_key));
|
||||
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(security_level, EMPTY_ORIGIN));
|
||||
EXPECT_FALSE(handle.RetrieveCertificate(EMPTY_ORIGIN, &certificate,
|
||||
&wrapped_private_key));
|
||||
EXPECT_FALSE(handle.RetrieveCertificate(&certificate, &wrapped_private_key));
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningInterposedRetryTest) {
|
||||
@@ -1437,10 +1481,9 @@ TEST_F(WvCdmRequestLicenseTest, ForceL3Test) {
|
||||
TestWvCdmClientPropertySet property_set;
|
||||
property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
|
||||
|
||||
File file;
|
||||
DeviceFiles handle;
|
||||
FileSystem file_system;
|
||||
DeviceFiles handle(&file_system);
|
||||
EXPECT_TRUE(handle.Init(kSecurityLevelL3));
|
||||
handle.SetTestFile(&file);
|
||||
EXPECT_TRUE(handle.DeleteAllFiles());
|
||||
|
||||
EXPECT_EQ(NEED_PROVISIONING,
|
||||
@@ -2151,10 +2194,9 @@ TEST_P(WvCdmUsageTest, WithClientId) {
|
||||
|
||||
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
||||
std::string app_id = "";
|
||||
DeviceFiles handle;
|
||||
FileSystem file_system;
|
||||
DeviceFiles handle(&file_system);
|
||||
EXPECT_TRUE(handle.Init(security_level));
|
||||
File file;
|
||||
handle.SetTestFile(&file);
|
||||
std::vector<std::string> psts;
|
||||
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(app_id, &psts));
|
||||
|
||||
@@ -2269,10 +2311,9 @@ TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) {
|
||||
|
||||
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
||||
std::string app_id = "";
|
||||
DeviceFiles handle;
|
||||
FileSystem file_system;
|
||||
DeviceFiles handle(&file_system);
|
||||
EXPECT_TRUE(handle.Init(security_level));
|
||||
File file;
|
||||
handle.SetTestFile(&file);
|
||||
std::vector<std::string> psts;
|
||||
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(app_id, &psts));
|
||||
|
||||
@@ -2351,10 +2392,9 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
|
||||
}
|
||||
|
||||
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
||||
DeviceFiles handle;
|
||||
FileSystem file_system;
|
||||
DeviceFiles handle(&file_system);
|
||||
EXPECT_TRUE(handle.Init(security_level));
|
||||
File file;
|
||||
handle.SetTestFile(&file);
|
||||
std::vector<std::string> psts;
|
||||
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(usage_info_data->app_id, &psts));
|
||||
|
||||
@@ -2425,10 +2465,9 @@ TEST_F(WvCdmRequestLicenseTest, UsageReleaseAllTest) {
|
||||
Provision(kLevelDefault);
|
||||
|
||||
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
||||
DeviceFiles handle;
|
||||
FileSystem file_system;
|
||||
DeviceFiles handle(&file_system);
|
||||
EXPECT_TRUE(handle.Init(security_level));
|
||||
File file;
|
||||
handle.SetTestFile(&file);
|
||||
std::vector<std::string> psts;
|
||||
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp("", &psts));
|
||||
|
||||
@@ -2739,7 +2778,7 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) {
|
||||
EXPECT_LE(10u, api_version);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
|
||||
TEST_F(WvCdmRequestLicenseTest, QueryOemCryptoSessionId) {
|
||||
Unprovision();
|
||||
Provision(kLevelDefault);
|
||||
|
||||
@@ -2750,7 +2789,7 @@ TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
|
||||
CdmQueryMap query_info;
|
||||
CdmQueryMap::iterator itr;
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.QueryKeyControlInfo(session_id_, &query_info));
|
||||
decryptor_.QueryOemCryptoSessionId(session_id_, &query_info));
|
||||
|
||||
uint32_t oem_crypto_session_id;
|
||||
itr = query_info.find(wvcdm::QUERY_KEY_OEMCRYPTO_SESSION_ID);
|
||||
@@ -2797,14 +2836,16 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
|
||||
if (std::string::npos != pos) break;
|
||||
}
|
||||
|
||||
// Delete any old files.
|
||||
EXPECT_NE(std::string::npos, pos);
|
||||
std::string old_base_path(base_path, 0, pos);
|
||||
File file;
|
||||
FileSystem file_system;
|
||||
for (size_t i = 0; i < security_dirs.size(); i++) {
|
||||
std::string path = old_base_path + kPathDelimiter + security_dirs[i];
|
||||
file.Remove(path);
|
||||
file_system.Remove(path);
|
||||
}
|
||||
|
||||
// Provision the device to create any required files.
|
||||
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
|
||||
std::string provisioning_server_url;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
@@ -2821,9 +2862,10 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
|
||||
decryptor_.CloseSession(session_id_);
|
||||
|
||||
std::vector<std::string> files;
|
||||
EXPECT_TRUE(file.List(base_path, &files));
|
||||
EXPECT_TRUE(FileUtils::List(base_path, &files));
|
||||
size_t number_of_files = files.size();
|
||||
|
||||
// Create an offline license to create license files.
|
||||
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
|
||||
GenerateKeyRequest(key_id, kLicenseTypeOffline);
|
||||
VerifyKeyRequestResponse(g_license_server, client_auth, false);
|
||||
@@ -2831,23 +2873,30 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
|
||||
EXPECT_FALSE(key_set_id_.empty());
|
||||
decryptor_.CloseSession(session_id_);
|
||||
|
||||
EXPECT_TRUE(file.List(base_path, &files));
|
||||
EXPECT_TRUE(FileUtils::List(base_path, &files));
|
||||
int number_of_new_files = files.size() - number_of_files;
|
||||
// There should be a new license file, and maybe a new usage table
|
||||
// file.
|
||||
EXPECT_LE(1, number_of_new_files);
|
||||
EXPECT_GE(2, number_of_new_files);
|
||||
|
||||
// Move files to the old location.
|
||||
for (size_t i = 0; i < files.size(); ++i) {
|
||||
std::string from = base_path + files[i];
|
||||
if (file.IsRegularFile(from)) {
|
||||
if (FileUtils::IsRegularFile(from)) {
|
||||
std::string to = old_base_path + files[i];
|
||||
EXPECT_TRUE(file.Copy(from, to));
|
||||
EXPECT_TRUE(FileUtils::Copy(from, to));
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(file.Remove(base_path));
|
||||
EXPECT_TRUE(file_system.Remove(base_path));
|
||||
|
||||
//// Setup complete to earlier version (non-security level based) path.
|
||||
|
||||
// Create a new file system. This will cause the files to be moved over.
|
||||
// Normally this will happen when the plugin is created, but since we are
|
||||
// reusing the same decryptor, we need it to update here.
|
||||
FileSystem dummy_file_system;
|
||||
|
||||
// Setup complete to earlier version (non-security level based) path.
|
||||
// Restore persistent license, retrieve L1, L3 streaming licenses to verify
|
||||
session_id_.clear();
|
||||
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
|
||||
|
||||
Reference in New Issue
Block a user