Merge "File util, generic crypto, and key query"

This commit is contained in:
Fred Gylys-Colwell
2016-10-25 17:40:54 +00:00
committed by Android (Google) Code Review
55 changed files with 4631 additions and 2082 deletions

View File

@@ -31,6 +31,10 @@ test_name := file_store_unittest
test_src_dir := ../core/test
include $(LOCAL_PATH)/unit-test.mk
test_name := file_utils_unittest
test_src_dir := .
include $(LOCAL_PATH)/unit-test.mk
test_name := http_socket_test
test_src_dir := ../core/test
include $(LOCAL_PATH)/unit-test.mk
@@ -43,7 +47,7 @@ test_name := license_unittest
test_src_dir := ../core/test
include $(LOCAL_PATH)/unit-test.mk
test_name := max_res_engine_unittest
test_name := license_keys_unittest
test_src_dir := ../core/test
include $(LOCAL_PATH)/unit-test.mk
@@ -51,6 +55,10 @@ test_name := policy_engine_unittest
test_src_dir := ../core/test
include $(LOCAL_PATH)/unit-test.mk
test_name := policy_engine_constraints_unittest
test_src_dir := ../core/test
include $(LOCAL_PATH)/unit-test.mk
test_name := request_license_test
test_src_dir := .
include $(LOCAL_PATH)/unit-test.mk

View File

@@ -795,10 +795,9 @@ TEST_F(WvCdmExtendedDurationTest, UsageOverflowTest) {
TestWvCdmClientPropertySet* property_set = NULL;
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> provider_session_tokens;
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp("", &provider_session_tokens));
@@ -831,8 +830,9 @@ TEST_F(WvCdmExtendedDurationTest, UsageOverflowTest) {
switch (status) {
case KEY_MESSAGE: EXPECT_FALSE(usage_info.empty()); break;
case NO_ERROR: EXPECT_TRUE(usage_info.empty()); break;
default: FAIL() << "GetUsageInfo failed with error "
<< static_cast<int>(status) ; break;
default:
FAIL() << "GetUsageInfo failed with error " << static_cast<int>(status);
break;
}
}
}

View File

@@ -0,0 +1,148 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#include <gtest/gtest.h>
#include "file_store.h"
#include "file_utils.h"
#include "test_vectors.h"
namespace wvcdm {
namespace {
const std::string kTestDirName = "test_dir";
const std::string kTestFileName = "test.txt";
const std::string kTestFileName2 = "test2.txt";
const std::string kTestFileNameExt = ".txt";
const std::string kWildcard = "*";
} // namespace
class FileUtilsTest : public testing::Test {
protected:
FileUtilsTest() {}
virtual ~FileUtilsTest() {}
virtual void SetUp() { CreateTestDir(); }
virtual void TearDown() { RemoveTestDir(); }
void CreateTestDir() {
if (!file_system.Exists(test_vectors::kTestDir)) {
EXPECT_TRUE(FileUtils::CreateDirectory(test_vectors::kTestDir));
}
EXPECT_TRUE(file_system.Exists(test_vectors::kTestDir));
}
void RemoveTestDir() {
EXPECT_TRUE(file_system.Remove(test_vectors::kTestDir));
}
std::string GenerateRandomData(uint32_t len) {
std::string data(len, 0);
for (size_t i = 0; i < len; i++) {
data[i] = rand() % 256;
}
return data;
}
FileSystem file_system;
};
TEST_F(FileUtilsTest, CreateDirectory) {
std::string dir_wo_delimiter =
test_vectors::kTestDir.substr(0, test_vectors::kTestDir.size() - 1);
if (file_system.Exists(dir_wo_delimiter))
EXPECT_TRUE(file_system.Remove(dir_wo_delimiter));
EXPECT_FALSE(file_system.Exists(dir_wo_delimiter));
EXPECT_TRUE(FileUtils::CreateDirectory(dir_wo_delimiter));
EXPECT_TRUE(file_system.Exists(dir_wo_delimiter));
EXPECT_TRUE(file_system.Remove(dir_wo_delimiter));
EXPECT_TRUE(FileUtils::CreateDirectory(test_vectors::kTestDir));
EXPECT_TRUE(file_system.Exists(test_vectors::kTestDir));
EXPECT_TRUE(file_system.Remove(test_vectors::kTestDir));
}
TEST_F(FileUtilsTest, IsDir) {
std::string path = test_vectors::kTestDir + kTestFileName;
File* file = file_system.Open(path, FileSystem::kCreate);
EXPECT_TRUE(file);
file->Close();
EXPECT_TRUE(file_system.Exists(path));
EXPECT_TRUE(file_system.Exists(test_vectors::kTestDir));
EXPECT_FALSE(FileUtils::IsDirectory(path));
EXPECT_TRUE(FileUtils::IsDirectory(test_vectors::kTestDir));
}
TEST_F(FileUtilsTest, IsRegularFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
File* file = file_system.Open(path, FileSystem::kCreate);
EXPECT_TRUE(file);
file->Close();
EXPECT_TRUE(file_system.Exists(path));
EXPECT_TRUE(file_system.Exists(test_vectors::kTestDir));
EXPECT_TRUE(FileUtils::IsRegularFile(path));
EXPECT_FALSE(FileUtils::IsRegularFile(test_vectors::kTestDir));
}
TEST_F(FileUtilsTest, CopyFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
file_system.Remove(path);
std::string write_data = GenerateRandomData(600);
File* wr_file = file_system.Open(path, FileSystem::kCreate);
EXPECT_TRUE(wr_file);
EXPECT_TRUE(wr_file->Write(write_data.data(), write_data.size()));
wr_file->Close();
ASSERT_TRUE(file_system.Exists(path));
std::string path_copy = test_vectors::kTestDir + kTestFileName2;
EXPECT_FALSE(file_system.Exists(path_copy));
EXPECT_TRUE(FileUtils::Copy(path, path_copy));
std::string read_data;
read_data.resize(file_system.FileSize(path_copy));
File* rd_file = file_system.Open(path_copy, FileSystem::kReadOnly);
EXPECT_TRUE(rd_file);
EXPECT_TRUE(rd_file->Read(&read_data[0], read_data.size()));
rd_file->Close();
EXPECT_EQ(write_data, read_data);
EXPECT_EQ(file_system.FileSize(path), file_system.FileSize(path_copy));
}
TEST_F(FileUtilsTest, ListEmptyDirectory) {
std::vector<std::string> files;
EXPECT_TRUE(FileUtils::List(test_vectors::kTestDir, &files));
EXPECT_EQ(0u, files.size());
}
TEST_F(FileUtilsTest, ListFiles) {
std::string path = test_vectors::kTestDir + kTestDirName;
EXPECT_TRUE(FileUtils::CreateDirectory(path));
path = test_vectors::kTestDir + kTestFileName;
std::string write_data = GenerateRandomData(600);
File* file = file_system.Open(path, FileSystem::kCreate);
EXPECT_TRUE(file);
EXPECT_TRUE(file->Write(write_data.data(), write_data.size()));
file->Close();
EXPECT_TRUE(file_system.Exists(path));
path = test_vectors::kTestDir + kTestFileName2;
write_data = GenerateRandomData(600);
file = file_system.Open(path, FileSystem::kCreate);
EXPECT_TRUE(file);
EXPECT_TRUE(file->Write(write_data.data(), write_data.size()));
file->Close();
EXPECT_TRUE(file_system.Exists(path));
std::vector<std::string> files;
EXPECT_TRUE(FileUtils::List(test_vectors::kTestDir, &files));
EXPECT_EQ(3u, files.size());
for (size_t i = 0; i < files.size(); ++i) {
EXPECT_TRUE(files[i] == kTestDirName || files[i] == kTestFileName ||
files[i] == kTestFileName2);
}
}
} // namespace wvcdm

View File

@@ -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_);

View File

@@ -18,7 +18,6 @@ LOCAL_SRC_FILES := \
../core/test/url_request.cpp
LOCAL_C_INCLUDES := \
external/openssl/include \
vendor/widevine/libwvdrmengine/android/cdm/test \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/core/test \