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:
@@ -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_ +
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user