Backward compatibility for licenses and certificates

Certificates and offline licenses are stored in security level
specific directories in klp. When devices transition from jb-mr2,
their persistent information has to be ported to these directories.

bug:10366036

Merge of https://widevine-internal-review.googlesource.com/#/c/7310/
from the widevine CDM repo

Change-Id: I70b4a79dc5b69bda7fc3a4b92fdcde7ef8b41836
This commit is contained in:
Jeff Tinker
2013-08-22 09:37:18 -07:00
parent 2fa6b63292
commit db41502f86
10 changed files with 455 additions and 12 deletions

View File

@@ -59,6 +59,8 @@ class DeviceFiles {
bool RetrieveFile(const char* name, std::string* data);
private:
virtual void SecurityLevelPathBackwardCompatibility();
File* file_;
CdmSecurityLevel security_level_;
bool initialized_;

View File

@@ -31,6 +31,8 @@ class File {
virtual bool Exists(const std::string& file_path);
virtual bool Remove(const std::string& file_path);
virtual bool Copy(const std::string& old_path, const std::string& new_path);
virtual bool List(const std::string& path, std::vector<std::string>* files);
virtual bool CreateDirectory(const std::string dir_path);
virtual bool IsDirectory(const std::string& dir_path);
virtual bool IsRegularFile(const std::string& file_path);

View File

@@ -48,6 +48,9 @@ class Properties {
static inline bool decrypt_with_empty_session_support() {
return decrypt_with_empty_session_support_;
}
static inline bool security_level_path_backward_compatibility_support() {
return security_level_path_backward_compatibility_support_;
}
static bool GetCompanyName(std::string* company_name);
static bool GetModelName(std::string* model_name);
static bool GetArchitectureName(std::string* arch_name);
@@ -58,6 +61,7 @@ class Properties {
std::string* base_path);
static bool GetFactoryKeyboxPath(std::string* keybox);
static bool GetOEMCryptoPath(std::string* library_name);
static bool GetSecurityLevelDirectories(std::vector<std::string>* dirs);
static const std::string GetSecurityLevel(const CdmSessionId& session_id);
static const std::vector<uint8_t> GetServiceCertificate(
const CdmSessionId& session_id);
@@ -95,6 +99,9 @@ class Properties {
static void set_decrypt_with_empty_session_support(bool flag) {
decrypt_with_empty_session_support_ = flag;
}
static void set_security_level_path_backward_compatibility_support(bool flag) {
security_level_path_backward_compatibility_support_ = flag;
}
static bool begin_license_usage_when_received_;
static bool require_explicit_renew_request_;
@@ -104,6 +111,7 @@ class Properties {
static bool use_certificates_as_identification_;
static bool extract_pssh_data_;
static bool decrypt_with_empty_session_support_;
static bool security_level_path_backward_compatibility_support_;
static scoped_ptr<CdmClientPropertySetMap> session_property_set_;
CORE_DISALLOW_COPY_AND_ASSIGN(Properties);

View File

@@ -22,6 +22,8 @@ namespace {
const char kCertificateFileName[] = "cert.bin";
const char kLicenseFileNameExt[] = ".lic";
const char kWildcard[] = "*";
const char kPathDelimiter[] = "/";
const char *kSecurityLevelPathCompatibilityExclusionList[] = { "ay64.dat" };
} // namespace
namespace wvcdm {
@@ -90,6 +92,10 @@ bool DeviceFiles::RetrieveCertificate(std::string* certificate,
return false;
}
if (Properties::security_level_path_backward_compatibility_support()) {
SecurityLevelPathBackwardCompatibility();
}
std::string serialized_hashed_file;
if (!RetrieveFile(kCertificateFileName, &serialized_hashed_file))
return false;
@@ -448,6 +454,65 @@ bool DeviceFiles::RetrieveFile(const char* name, std::string* data) {
return true;
}
void DeviceFiles::SecurityLevelPathBackwardCompatibility() {
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::SecurityLevelPathBackwardCompatibility: Unable to "
"get base path");
return;
}
std::vector<std::string> security_dirs;
if (!Properties::GetSecurityLevelDirectories(&security_dirs)) {
LOGW("DeviceFiles::SecurityLevelPathBackwardCompatibility: Unable to "
"get security directories");
return;
}
size_t pos = std::string::npos;
for (size_t i = 0; i < security_dirs.size(); ++i) {
pos = path.rfind(security_dirs[i]);
if (std::string::npos != pos)
break;
}
if (pos == std::string::npos) {
LOGV("DeviceFiles::SecurityLevelPathBackwardCompatibility: Security level "
"specific path not found. Check properties?");
return;
}
std::string from_dir(path, 0, pos);
std::vector<std::string> files;
file_->List(from_dir, &files);
for (size_t i = 0; i < files.size(); ++i) {
std::string from = from_dir + files[i];
bool exclude = false;
for (size_t j = 0;
j < sizeof(kSecurityLevelPathCompatibilityExclusionList) /
sizeof(const char*);
j++) {
if (files[i].compare(kSecurityLevelPathCompatibilityExclusionList[j]) == 0) {
exclude = true;
break;
}
}
if (exclude) continue;
if (!file_->IsRegularFile(from)) continue;
for (size_t j = 0; j < security_dirs.size(); ++j) {
std::string to_dir = from_dir + security_dirs[j];
if (!file_->Exists(to_dir))
file_->CreateDirectory(to_dir);
std::string to = to_dir + files[i];
file_->Copy(from, to);
}
file_->Remove(from);
}
}
std::string DeviceFiles::GetCertificateFileName() {
return kCertificateFileName;
}

View File

@@ -4,6 +4,10 @@
#include "properties_configuration.h"
#include "wv_cdm_constants.h"
namespace {
const char *kSecurityLevelDirs[] = { "L1/", "L3/" };
} // namespace
namespace wvcdm {
bool Properties::begin_license_usage_when_received_;
bool Properties::require_explicit_renew_request_;
@@ -13,6 +17,7 @@ bool Properties::oem_crypto_use_userspace_buffers_;
bool Properties::use_certificates_as_identification_;
bool Properties::extract_pssh_data_;
bool Properties::decrypt_with_empty_session_support_;
bool Properties::security_level_path_backward_compatibility_support_;
scoped_ptr<CdmClientPropertySetMap> Properties::session_property_set_;
void Properties::Init() {
@@ -25,6 +30,7 @@ void Properties::Init() {
kPropertyUseCertificatesAsIdentification;
extract_pssh_data_ = kExtractPsshData;
decrypt_with_empty_session_support_ = kDecryptWithEmptySessionSupport;
security_level_path_backward_compatibility_support_ = kSecurityLevelPathBackwardCompatibilitySupport;
session_property_set_.reset(new CdmClientPropertySetMap());
}
@@ -93,4 +99,13 @@ bool Properties::UsePrivacyMode(const CdmSessionId& session_id) {
}
return property_set->use_privacy_mode();
}
bool Properties::GetSecurityLevelDirectories(std::vector<std::string>* dirs) {
dirs->resize(sizeof(kSecurityLevelDirs)/sizeof(const char*));
for (size_t i = 0; i < dirs->size(); ++i) {
(*dirs)[i] = kSecurityLevelDirs[i];
}
return true;
}
} // namespace wvcdm

View File

@@ -19,6 +19,7 @@ using ::testing::HasSubstr;
using ::testing::NotNull;
using ::testing::Return;
using ::testing::ReturnArg;
using ::testing::SetArgPointee;
using ::testing::SetArrayArgument;
using ::testing::StrEq;
@@ -987,6 +988,8 @@ class MockFile : public File {
MOCK_METHOD1(Exists, bool(const std::string&));
MOCK_METHOD1(Remove, bool(const std::string&));
MOCK_METHOD2(Copy, bool(const std::string&, const std::string&));
MOCK_METHOD2(List, bool(const std::string&, std::vector<std::string>*));
MOCK_METHOD1(CreateDirectory, bool(const std::string));
MOCK_METHOD1(IsDirectory, bool(const std::string&));
MOCK_METHOD1(IsRegularFile, bool(const std::string&));
@@ -1021,6 +1024,10 @@ class DeviceFilesTest : public ::testing::Test {
class DeviceFilesStoreTest : public DeviceFilesTest,
public ::testing::WithParamInterface<bool> {};
class DeviceFilesSecurityLevelTest
: public DeviceFilesTest,
public ::testing::WithParamInterface<CdmSecurityLevel> {};
MATCHER(IsCreateFileFlagSet, "") { return File::kCreate & arg; }
MATCHER(IsBinaryFileFlagSet, "") { return File::kBinary & arg; }
MATCHER_P(IsStrEq, str, "") {
@@ -1031,7 +1038,7 @@ MATCHER_P(IsStrEq, str, "") {
MATCHER_P2(Contains, str1, str2, "") {
// Estimating the length of data. We can have gmock provide length
// as well as pointer to data but that will introduce a dependency on tr1
std::string data(arg, str1.size() + str2.size() + 500);
std::string data(arg, str1.size() + str2.size() + 75);
return (data.find(str1) != std::string::npos &&
data.find(str2) != std::string::npos);
}
@@ -1039,12 +1046,12 @@ MATCHER_P6(Contains, str1, str2, str3, str4, str5, str6, "") {
// Estimating the length of data. We can have gmock provide length
// as well as pointer to data but that will introduce a dependency on tr1
std::string data(arg, str1.size() + str2.size() + str3.size() + str4.size() +
str5.size() + str6.size() + 500);
str5.size() + str6.size() + 75);
return (data.find(str1) != std::string::npos &&
data.find(str2) != std::string::npos,
data.find(str3) != std::string::npos,
data.find(str4) != std::string::npos,
data.find(str5) != std::string::npos,
data.find(str2) != std::string::npos &&
data.find(str3) != std::string::npos &&
data.find(str4) != std::string::npos &&
data.find(str5) != std::string::npos &&
data.find(str6) != std::string::npos);
}
@@ -1109,6 +1116,40 @@ TEST_F(DeviceFilesTest, ReadCertificate) {
EXPECT_EQ(kTestWrappedPrivateKey, b2a_hex(wrapped_private_key));
}
TEST_P(DeviceFilesSecurityLevelTest, SecurityLevel) {
MockFile file;
std::string certificate(GenerateRandomData(kCertificateLen));
std::string wrapped_private_key(GenerateRandomData(kWrappedKeyLen));
CdmSecurityLevel security_level = GetParam();
std::string device_base_path;
ASSERT_TRUE(
Properties::GetDeviceFilesBasePath(security_level, &device_base_path));
std::string device_certificate_path =
device_base_path + DeviceFiles::GetCertificateFileName();
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path)))
.WillOnce(Return(false));
EXPECT_CALL(file, CreateDirectory(StrEq(device_base_path)))
.WillOnce(Return(true));
EXPECT_CALL(file, Open(StrEq(device_certificate_path),
AllOf(IsCreateFileFlagSet(), IsBinaryFileFlagSet())))
.WillOnce(Return(true));
EXPECT_CALL(file, Write(Contains(certificate, wrapped_private_key),
Gt(certificate.size() + wrapped_private_key.size())))
.WillOnce(ReturnArg<1>());
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Read(_, _)).Times(0);
DeviceFiles device_files;
EXPECT_TRUE(device_files.Init(&file, security_level));
EXPECT_TRUE(device_files.StoreCertificate(certificate, wrapped_private_key));
}
INSTANTIATE_TEST_CASE_P(SecurityLevel, DeviceFilesSecurityLevelTest,
::testing::Values(kSecurityLevelL1, kSecurityLevelL3));
TEST_P(DeviceFilesStoreTest, StoreLicense) {
MockFile file;
size_t license_num = 0;
@@ -1244,6 +1285,81 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
}
}
TEST_F(DeviceFilesTest, SecurityLevelPathBackwardCompatibility) {
MockFile file;
std::vector<std::string> security_dirs;
EXPECT_TRUE(Properties::GetSecurityLevelDirectories(&security_dirs));
size_t pos = std::string::npos;
for (size_t i = 0; i < security_dirs.size(); ++i) {
pos = device_base_path_.rfind(security_dirs[i]);
if (std::string::npos != pos) break;
}
EXPECT_NE(std::string::npos, pos);
std::string base_path(device_base_path_, 0, pos);
std::vector<std::string> old_files;
std::string new_path;
for (size_t i = 0; i < security_dirs.size(); ++i) {
old_files.push_back(security_dirs[i]);
new_path = base_path + security_dirs[i];
EXPECT_CALL(file, IsRegularFile(StrEq(new_path))).WillOnce(Return(false));
EXPECT_CALL(file, Exists(StrEq(new_path)))
.WillOnce(Return(false))
.WillRepeatedly(Return(true));
EXPECT_CALL(file, CreateDirectory(StrEq(new_path))).WillOnce(Return(true));
}
std::string old_path = base_path + DeviceFiles::GetCertificateFileName();
old_files.push_back(DeviceFiles::GetCertificateFileName());
EXPECT_CALL(file, IsRegularFile(StrEq(old_path)))
.WillOnce(Return(true));
EXPECT_CALL(file, Remove(StrEq(old_path))).WillOnce(Return(true));
for (size_t i = 0; i < security_dirs.size(); ++i) {
new_path = base_path + security_dirs[i] +
DeviceFiles::GetCertificateFileName();
EXPECT_CALL(file, Copy(StrEq(old_path), StrEq(new_path)))
.WillOnce(Return(true));
}
for (size_t j = 0; j < kNumberOfLicenses; ++j) {
std::string file_name = license_test_data[j].key_set_id +
DeviceFiles::GetLicenseFileNameExtension();
old_path = base_path + file_name;
old_files.push_back(file_name);
EXPECT_CALL(file, IsRegularFile(StrEq(old_path))).WillOnce(Return(true));
EXPECT_CALL(file, Remove(StrEq(old_path))).WillOnce(Return(true));
for (size_t i = 0; i < security_dirs.size(); ++i) {
new_path = base_path + security_dirs[i] + file_name;
EXPECT_CALL(file, Copy(StrEq(old_path), StrEq(new_path)))
.WillOnce(Return(true));
}
}
EXPECT_CALL(file, List(StrEq(base_path), NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(old_files), Return(true)));
std::string data = a2bs_hex(kTestCertificateFileData);
new_path = device_base_path_ + DeviceFiles::GetCertificateFileName();
EXPECT_CALL(file, Exists(StrEq(new_path))).WillOnce(Return(true));
EXPECT_CALL(file, FileSize(_)).WillOnce(Return(data.size()));
EXPECT_CALL(file, Open(_, _)).WillOnce(Return(true));
EXPECT_CALL(file, Read(NotNull(), Eq(data.size()))).WillOnce(DoAll(
SetArrayArgument<0>(data.begin(), data.end()), Return(data.size())));
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Write(_, _)).Times(0);
DeviceFiles device_files;
EXPECT_TRUE(device_files.Init(&file, kSecurityLevelL1));
Properties::Init();
std::string certificate, wrapped_private_key;
ASSERT_TRUE(
device_files.RetrieveCertificate(&certificate, &wrapped_private_key));
}
TEST_F(DeviceFilesTest, UpdateLicenseState) {
MockFile file;
std::string license_path = device_base_path_ +

View File

@@ -7,6 +7,7 @@
#include "test_vectors.h"
namespace {
const std::string kTestDirName = "test";
const std::string kTestFileName = "test.txt";
const std::string kTestFileName2 = "test2.txt";
const std::string kTestFileNameExt = ".txt";
@@ -199,4 +200,67 @@ TEST_F(FileTest, WriteReadBinaryFile) {
EXPECT_EQ(write_data, read_data);
}
TEST_F(FileTest, CopyFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
File file;
file.Remove(path);
std::string write_data = GenerateRandomData(600);
File wr_file;
EXPECT_TRUE(wr_file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(wr_file.Write(write_data.data(), write_data.size()));
wr_file.Close();
EXPECT_TRUE(file.Exists(path));
std::string path_copy = test_vectors::kTestDir + kTestFileName2;
EXPECT_FALSE(file.Exists(path_copy));
EXPECT_TRUE(file.Copy(path, path_copy));
std::string read_data;
read_data.resize(file.FileSize(path_copy));
File rd_file;
EXPECT_TRUE(rd_file.Open(path_copy, File::kReadOnly));
EXPECT_TRUE(rd_file.Read(&read_data[0], read_data.size()));
rd_file.Close();
EXPECT_EQ(write_data, read_data);
EXPECT_EQ(file.FileSize(path), file.FileSize(path_copy));
}
TEST_F(FileTest, ListEmptyDirectory) {
std::vector<std::string> files;
File file;
EXPECT_TRUE(file.List(test_vectors::kTestDir, &files));
EXPECT_EQ(0u, files.size());
}
TEST_F(FileTest, ListFiles) {
File file;
std::string path = test_vectors::kTestDir + kTestDirName;
EXPECT_TRUE(file.CreateDirectory(path));
path = test_vectors::kTestDir + kTestFileName;
std::string write_data = GenerateRandomData(600);
EXPECT_TRUE(file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(file.Write(write_data.data(), write_data.size()));
file.Close();
EXPECT_TRUE(file.Exists(path));
path = test_vectors::kTestDir + kTestFileName2;
write_data = GenerateRandomData(600);
EXPECT_TRUE(file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(file.Write(write_data.data(), write_data.size()));
file.Close();
EXPECT_TRUE(file.Exists(path));
std::vector<std::string> files;
EXPECT_TRUE(file.List(test_vectors::kTestDir, &files));
EXPECT_EQ(3u, files.size());
for (size_t i = 0; i < files.size(); ++i) {
EXPECT_TRUE(files[i].compare(kTestDirName) == 0 ||
files[i].compare(kTestFileName) == 0 ||
files[i].compare(kTestFileName2) == 0);
}
}
} // namespace wvcdm

View File

@@ -35,6 +35,10 @@ const bool kExtractPsshData = true;
// function will try to find out the session_id from the key_id.
const bool kDecryptWithEmptySessionSupport = false;
// If true, device files will be moved to the directory specified by
// Properties::GetDeviceFilesBasePath
const bool kSecurityLevelPathBackwardCompatibilitySupport = true;
} // namespace wvcdm
#endif // CDM_BASE_WV_PROPERTIES_CONFIGURATION_H_

View File

@@ -6,8 +6,10 @@
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
@@ -175,18 +177,80 @@ bool File::Remove(const std::string& path) {
}
}
bool File::Copy(const std::string& src, const std::string& dest) {
struct stat stat_buf;
if (stat(src.c_str(), &stat_buf)) {
LOGV("File::Copy: file %s does not exist: %d", src.c_str(), errno);
return false;
}
int fd_src = open(src.c_str(), O_RDONLY);
if (fd_src < 0) {
LOGV("File::Copy: unable to open file %s: %d", src.c_str(), errno);
return false;
}
int fd_dest = open(dest.c_str(), O_WRONLY|O_CREAT, stat_buf.st_mode);
if (fd_dest < 0) {
LOGV("File::Copy: unable to open file %s: %d", dest.c_str(), errno);
close(fd_src);
return false;
}
off_t offset = 0;
bool sts = true;
if (sendfile(fd_dest, fd_src, &offset, stat_buf.st_size) < 0) {
LOGV("File::Copy: unable to copy %s to %s: %d", src.c_str(), dest.c_str(),
errno);
sts = false;
}
close(fd_src);
close(fd_dest);
return sts;
}
bool File::List(const std::string& path, std::vector<std::string>* files) {
if (NULL == files) {
LOGV("File::List: files destination not provided");
return false;
}
if (!Exists(path)) {
LOGV("File::List: path %s does not exist: %d", path.c_str(), errno);
return false;
}
DIR* dir;
if ((dir = opendir(path.c_str())) == NULL) {
LOGW("File::List: unable to open directory %s: %d", path.c_str(), errno);
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, kCurrentDirectory) &&
(strcmp(entry->d_name, kParentDirectory))) {
files->push_back(entry->d_name);
}
}
closedir(dir);
return true;
}
bool File::CreateDirectory(std::string path) {
size_t size = path.size();
if ((size == 1) && (path[0] == '/')) return true;
if ((size == 1) && (path[0] == kPathDelimiter[0])) return true;
if (size <= 1) return false;
if (path.at(size - 1) == '/') {
if (path.at(size - 1) == kPathDelimiter[0]) {
--size;
path.resize(size);
}
size_t pos = path.find('/', 1);
size_t pos = path.find(kPathDelimiter[0], 1);
while (pos < size) {
path.at(pos) = '\0';
if (mkdir(path.c_str(), 0775) != 0) {
@@ -195,8 +259,8 @@ bool File::CreateDirectory(std::string path) {
return false;
}
}
path.at(pos) = '/';
pos = path.find('/', pos + 1);
path.at(pos) = kPathDelimiter[0];
pos = path.find(kPathDelimiter[0], pos + 1);
}
if (mkdir(path.c_str(), 0775) != 0) {
if (errno != EEXIST) {

View File

@@ -730,6 +730,109 @@ TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
CdmQueryMap query_info;
CdmQueryMap::iterator itr;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(&query_info));
itr = query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
ASSERT_TRUE(itr != query_info.end());
EXPECT_EQ(2u, itr->second.size());
EXPECT_TRUE(itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3) == 0 ||
itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1) == 0);
CdmSecurityLevel security_level =
(itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1) == 0)
? kSecurityLevelL1
: kSecurityLevelL3;
std::string base_path;
EXPECT_TRUE(Properties::GetDeviceFilesBasePath(security_level, &base_path));
std::vector<std::string> security_dirs;
EXPECT_TRUE(Properties::GetSecurityLevelDirectories(&security_dirs));
size_t pos = std::string::npos;
for (size_t i = 0; i < security_dirs.size(); i++) {
pos = base_path.rfind(security_dirs[i]);
if (std::string::npos != pos)
break;
}
EXPECT_NE(std::string::npos, pos);
std::string old_base_path(base_path, 0, pos);
File file;
file.Remove(old_base_path);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
std::string provisioning_server_url;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(response));
decryptor_.CloseSession(session_id_);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_.CloseSession(session_id_);
std::vector<std::string> files;
EXPECT_TRUE(file.List(base_path, &files));
EXPECT_TRUE(2u == files.size() || 3u == files.size());
for (size_t i = 0; i < files.size(); ++i) {
std::string from = base_path + files[i];
if (file.IsRegularFile(from)) {
std::string to = old_base_path + files[i];
EXPECT_TRUE(file.Copy(from, to));
}
}
EXPECT_TRUE(file.Remove(base_path));
// 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, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
decryptor_.CloseSession(session_id_);
TestWvCdmClientPropertySet property_set;
property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
EXPECT_EQ(NO_ERROR,
decryptor_.OpenSession(g_key_system, &property_set, &session_id_));
wvcdm::CdmAppParameterMap app_parameters;
std::string server_url;
EXPECT_EQ(wvcdm::NEED_PROVISIONING,
decryptor_.GenerateKeyRequest(session_id_, key_set_id, g_key_id,
kLicenseTypeStreaming, app_parameters,
&key_msg_, &server_url));
EXPECT_EQ(NO_ERROR,
decryptor_.GetProvisioningRequest(&key_msg_,
&provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set,
&session_id_));
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
decryptor_.CloseSession(session_id_);
}
TEST_P(WvCdmDecryptionTest, DecryptionTest) {
SubSampleInfo* data = GetParam();
decryptor_.OpenSession(g_key_system, NULL, &session_id_);