Source release v3.0.0-0-g8d3792b-ce + third_party

Change-Id: I399e71ddfffcd436171d1c60283c63ab4658e0b1
This commit is contained in:
Joey Parrish
2015-06-19 15:13:34 -07:00
parent 58aba6b2ec
commit 0546ee6732
965 changed files with 426663 additions and 12897 deletions

View File

@@ -2,15 +2,7 @@
#include "device_files.h"
#if defined(__APPLE__)
#include <CommonCrypto/CommonDigest.h>
#define SHA256 CC_SHA256
#define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
#else
#include <openssl/sha.h>
#endif
#include <cstring>
#include <string.h>
#include <string>
#include "device_files.pb.h"
@@ -18,6 +10,16 @@
#include "log.h"
#include "properties.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
#if defined(__APPLE__)
#include <CommonCrypto/CommonDigest.h>
#define SHA256 CC_SHA256
#define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
#else
#include <openssl/sha.h>
#include <openssl/md5.h>
#endif
// Protobuf generated classes.
using video_widevine_client::sdk::DeviceCertificate;
@@ -25,22 +27,25 @@ using video_widevine_client::sdk::HashedFile;
using video_widevine_client::sdk::License;
using video_widevine_client::sdk::License_LicenseState_ACTIVE;
using video_widevine_client::sdk::License_LicenseState_RELEASING;
using video_widevine_client::sdk::NameValue;
using video_widevine_client::sdk::UsageInfo;
using video_widevine_client::sdk::UsageInfo_ProviderSession;
namespace {
const char kCertificateFileName[] = "cert.bin";
const char kUsageInfoFileName[] = "usage.bin";
const char kCertificateFileNamePrefix[] = "cert";
const char kCertificateFileNameExt[] = ".bin";
const char kUsageInfoFileNamePrefix[] = "usage";
const char kUsageInfoFileNameExt[] = ".bin";
const char kLicenseFileNameExt[] = ".lic";
const char kEmptyFileName[] = "";
const char kWildcard[] = "*";
const char kDirectoryDelimiter = '/';
const char* kSecurityLevelPathCompatibilityExclusionList[] = {"ay64.dat"};
const char* kSecurityLevelPathCompatibilityExclusionList[] = {
"ay64.dat", "ay64.dat2", "ay64.dat3"};
size_t kSecurityLevelPathCompatibilityExclusionListSize =
sizeof(kSecurityLevelPathCompatibilityExclusionList) /
sizeof(*kSecurityLevelPathCompatibilityExclusionList);
// Some platforms cannot store a truly blank file, so we use a W for Widevine.
const char kBlankFileData[] = "W";
bool Hash(const std::string& data, std::string* hash) {
if (!hash) return false;
@@ -53,10 +58,13 @@ bool Hash(const std::string& data, std::string* hash) {
return true;
}
} // unnamed namespace
} // namespace
namespace wvcdm {
// static
std::set<std::string> DeviceFiles::reserved_license_ids_;
DeviceFiles::DeviceFiles()
: file_(NULL),
security_level_(kSecurityLevelUninitialized),
@@ -68,14 +76,10 @@ DeviceFiles::~DeviceFiles() {
}
bool DeviceFiles::Init(CdmSecurityLevel security_level) {
switch (security_level) {
case kSecurityLevelL1:
case kSecurityLevelL2:
case kSecurityLevelL3:
break;
default:
LOGW("DeviceFiles::Init: Unsupported security level %d", security_level);
return false;
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level, &path)) {
LOGW("DeviceFiles::Init: Unsupported security level %d", security_level);
return false;
}
if (!test_file_) file_.reset(new File());
security_level_ = security_level;
@@ -83,7 +87,8 @@ bool DeviceFiles::Init(CdmSecurityLevel security_level) {
return true;
}
bool DeviceFiles::StoreCertificate(const std::string& certificate,
bool DeviceFiles::StoreCertificate(const std::string& origin,
const std::string& certificate,
const std::string& wrapped_private_key) {
if (!initialized_) {
LOGW("DeviceFiles::StoreCertificate: not initialized");
@@ -103,10 +108,11 @@ bool DeviceFiles::StoreCertificate(const std::string& certificate,
std::string serialized_file;
file.SerializeToString(&serialized_file);
return StoreFileWithHash(kCertificateFileName, serialized_file);
return StoreFileWithHash(GetCertificateFileName(origin), serialized_file);
}
bool DeviceFiles::RetrieveCertificate(std::string* certificate,
bool DeviceFiles::RetrieveCertificate(const std::string& origin,
std::string* certificate,
std::string* wrapped_private_key) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveCertificate: not initialized");
@@ -118,7 +124,9 @@ bool DeviceFiles::RetrieveCertificate(std::string* certificate,
}
std::string serialized_file;
if (!RetrieveHashedFile(kCertificateFileName, &serialized_file)) return false;
if (!RetrieveHashedFile(GetCertificateFileName(origin), &serialized_file)) {
return false;
}
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
@@ -148,14 +156,32 @@ bool DeviceFiles::RetrieveCertificate(std::string* certificate,
return true;
}
bool DeviceFiles::StoreLicense(const std::string& key_set_id,
const LicenseState state,
const CdmInitData& pssh_data,
const CdmKeyMessage& license_request,
const CdmKeyResponse& license_message,
const CdmKeyMessage& license_renewal_request,
const CdmKeyResponse& license_renewal,
const std::string& release_server_url) {
bool DeviceFiles::HasCertificate(const std::string& origin) {
if (!initialized_) {
LOGW("DeviceFiles::HasCertificate: not initialized");
return false;
}
return FileExists(GetCertificateFileName(origin));
}
bool DeviceFiles::RemoveCertificate(const std::string& origin) {
if (!initialized_) {
LOGW("DeviceFiles::RemoveCertificate: not initialized");
return false;
}
return RemoveFile(GetCertificateFileName(origin));
}
bool DeviceFiles::StoreLicense(
const std::string& key_set_id, const LicenseState state,
const CdmInitData& pssh_data, const CdmKeyMessage& license_request,
const CdmKeyResponse& license_message,
const CdmKeyMessage& license_renewal_request,
const CdmKeyResponse& license_renewal,
const std::string& release_server_url, int64_t playback_start_time,
int64_t last_playback_time, const CdmAppParameterMap& app_parameters) {
if (!initialized_) {
LOGW("DeviceFiles::StoreLicense: not initialized");
return false;
@@ -186,29 +212,38 @@ bool DeviceFiles::StoreLicense(const std::string& key_set_id,
license->set_renewal_request(license_renewal_request);
license->set_renewal(license_renewal);
license->set_release_server_url(release_server_url);
license->set_playback_start_time(playback_start_time);
license->set_last_playback_time(last_playback_time);
NameValue* app_params;
for (CdmAppParameterMap::const_iterator iter = app_parameters.begin();
iter != app_parameters.end(); ++iter) {
app_params = license->add_app_parameters();
app_params->set_name(iter->first);
app_params->set_value(iter->second);
}
std::string serialized_file;
file.SerializeToString(&serialized_file);
std::string file_name = key_set_id + kLicenseFileNameExt;
return StoreFileWithHash(file_name.c_str(), serialized_file);
reserved_license_ids_.erase(key_set_id);
return StoreFileWithHash(key_set_id + kLicenseFileNameExt, serialized_file);
}
bool DeviceFiles::RetrieveLicense(const std::string& key_set_id,
LicenseState* state, CdmInitData* pssh_data,
CdmKeyMessage* license_request,
CdmKeyResponse* license_message,
CdmKeyMessage* license_renewal_request,
CdmKeyResponse* license_renewal,
std::string* release_server_url) {
bool DeviceFiles::RetrieveLicense(
const std::string& key_set_id, LicenseState* state, CdmInitData* pssh_data,
CdmKeyMessage* license_request, CdmKeyResponse* license_message,
CdmKeyMessage* license_renewal_request, CdmKeyResponse* license_renewal,
std::string* release_server_url, int64_t* playback_start_time,
int64_t* last_playback_time, CdmAppParameterMap* app_parameters) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveLicense: not initialized");
return false;
}
std::string serialized_file;
std::string file_name = key_set_id + kLicenseFileNameExt;
if (!RetrieveHashedFile(file_name.c_str(), &serialized_file)) return false;
if (!RetrieveHashedFile(key_set_id + kLicenseFileNameExt, &serialized_file)) {
return false;
}
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
@@ -252,6 +287,12 @@ bool DeviceFiles::RetrieveLicense(const std::string& key_set_id,
*license_renewal_request = license.renewal_request();
*license_renewal = license.renewal();
*release_server_url = license.release_server_url();
*playback_start_time = license.playback_start_time();
*last_playback_time = license.last_playback_time();
for (int i = 0; i < license.app_parameters_size(); ++i) {
(*app_parameters)[license.app_parameters(i).name()] =
license.app_parameters(i).value();
}
return true;
}
@@ -260,16 +301,7 @@ bool DeviceFiles::DeleteLicense(const std::string& key_set_id) {
LOGW("DeviceFiles::DeleteLicense: not initialized");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::DeleteLicense: Unable to get base path");
return false;
}
path.append(key_set_id);
path.append(kLicenseFileNameExt);
return file_->Remove(path);
return RemoveFile(key_set_id + kLicenseFileNameExt);
}
bool DeviceFiles::DeleteAllLicenses() {
@@ -277,16 +309,7 @@ bool DeviceFiles::DeleteAllLicenses() {
LOGW("DeviceFiles::DeleteAllLicenses: not initialized");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::DeleteAllLicenses: Unable to get base path");
return false;
}
path.append(kWildcard);
path.append(kLicenseFileNameExt);
return file_->Remove(path);
return RemoveFile(std::string(kWildcard) + kLicenseFileNameExt);
}
bool DeviceFiles::DeleteAllFiles() {
@@ -295,13 +318,9 @@ bool DeviceFiles::DeleteAllFiles() {
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::DeleteAllFiles: Unable to get base path");
return false;
}
return file_->Remove(path);
// We pass an empty string to RemoveFile to delete the device files base
// directory itself.
return RemoveFile(kEmptyFileName);
}
bool DeviceFiles::LicenseExists(const std::string& key_set_id) {
@@ -309,16 +328,8 @@ bool DeviceFiles::LicenseExists(const std::string& key_set_id) {
LOGW("DeviceFiles::LicenseExists: not initialized");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::LicenseExists: Unable to get base path");
return false;
}
path.append(key_set_id);
path.append(kLicenseFileNameExt);
return file_->Exists(path);
return reserved_license_ids_.count(key_set_id) ||
FileExists(key_set_id + kLicenseFileNameExt);
}
bool DeviceFiles::ReserveLicenseId(const std::string& key_set_id) {
@@ -326,14 +337,14 @@ bool DeviceFiles::ReserveLicenseId(const std::string& key_set_id) {
LOGW("DeviceFiles::ReserveLicenseId: not initialized");
return false;
}
std::string file_name = key_set_id + kLicenseFileNameExt;
return StoreFileRaw(file_name.c_str(), kBlankFileData);
reserved_license_ids_.insert(key_set_id);
return true;
}
bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
const CdmKeyMessage& key_request,
const CdmKeyResponse& key_response) {
const CdmKeyResponse& key_response,
const std::string& app_id) {
if (!initialized_) {
LOGW("DeviceFiles::StoreUsageInfo: not initialized");
return false;
@@ -341,7 +352,8 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
std::string serialized_file;
video_widevine_client::sdk::File file;
if (!RetrieveHashedFile(kUsageInfoFileName, &serialized_file)) {
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveHashedFile(file_name, &serialized_file)) {
file.set_type(video_widevine_client::sdk::File::USAGE_INFO);
file.set_version(video_widevine_client::sdk::File::VERSION_1);
} else {
@@ -360,17 +372,18 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
provider_session->set_license(key_response.data(), key_response.size());
file.SerializeToString(&serialized_file);
return StoreFileWithHash(kUsageInfoFileName, serialized_file);
return StoreFileWithHash(file_name, serialized_file);
}
bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
const std::string& provider_session_token) {
if (!initialized_) {
LOGW("DeviceFiles::DeleteUsageInfo: not initialized");
return false;
}
std::string serialized_file;
if (!RetrieveHashedFile(kUsageInfoFileName, &serialized_file)) return false;
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveHashedFile(file_name, &serialized_file)) return false;
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
@@ -382,8 +395,7 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
int index = 0;
bool found = false;
for (; index < usage_info->sessions_size(); ++index) {
if (usage_info->sessions(index).token().compare(provider_session_token) ==
0) {
if (usage_info->sessions(index).token() == provider_session_token) {
found = true;
break;
}
@@ -405,26 +417,43 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
sessions->RemoveLast();
file.SerializeToString(&serialized_file);
return StoreFileWithHash(kUsageInfoFileName, serialized_file);
return StoreFileWithHash(file_name, serialized_file);
}
bool DeviceFiles::DeleteUsageInfo() {
bool DeviceFiles::DeleteAllUsageInfoForApp(
const std::string& app_id,
std::vector<std::string>* provider_session_tokens) {
if (!initialized_) {
LOGW("DeviceFiles::DeleteUsageInfo: not initialized");
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: not initialized");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::DeleteUsageInfo: Unable to get base path");
if (NULL == provider_session_tokens) {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: pst destination not provided");
return false;
}
path.append(kUsageInfoFileName);
provider_session_tokens->clear();
return file_->Remove(path);
std::string file_name = GetUsageInfoFileName(app_id);
if (!FileExists(file_name)) return true;
std::string serialized_file;
if (RetrieveHashedFile(file_name, &serialized_file)) {
video_widevine_client::sdk::File file_proto;
if (!file_proto.ParseFromString(serialized_file)) {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: Unable to parse file");
} else {
for (int i = 0; i < file_proto.usage_info().sessions_size(); ++i) {
provider_session_tokens->push_back(
file_proto.usage_info().sessions(i).token());
}
}
} else {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: Unable to retrieve file");
}
return RemoveFile(file_name);
}
bool DeviceFiles::RetrieveUsageInfo(
const std::string& app_id,
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> >* usage_info) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
@@ -439,15 +468,9 @@ bool DeviceFiles::RetrieveUsageInfo(
}
std::string serialized_file;
if (!RetrieveHashedFile(kUsageInfoFileName, &serialized_file)) {
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
return false;
}
path += kUsageInfoFileName;
if (!file_->Exists(path) || 0 == file_->FileSize(path)) {
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveHashedFile(file_name, &serialized_file)) {
if (!FileExists(file_name) || GetFileSize(file_name) == 0) {
usage_info->resize(0);
return true;
}
@@ -471,15 +494,45 @@ bool DeviceFiles::RetrieveUsageInfo(
return true;
}
bool DeviceFiles::StoreFileWithHash(const char* name,
const std::string& serialized_file) {
if (!file_.get()) {
LOGW("DeviceFiles::StoreFileWithHash: Invalid file handle");
bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
const std::string& provider_session_token,
CdmKeyMessage* license_request,
CdmKeyResponse* license_response) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
return false;
}
std::string serialized_file;
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveHashedFile(file_name, &serialized_file)) return false;
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
LOGW("DeviceFiles::RetrieveUsageInfo: Unable to parse file");
return false;
}
int index = 0;
bool found = false;
for (; index < file.usage_info().sessions_size(); ++index) {
if (file.usage_info().sessions(index).token() == provider_session_token) {
found = true;
break;
}
}
if (!found) {
return false;
}
if (!name) {
LOGW("DeviceFiles::StoreFileWithHash: Unspecified file name parameter");
*license_request = file.usage_info().sessions(index).license_request();
*license_response = file.usage_info().sessions(index).license();
return true;
}
bool DeviceFiles::StoreFileWithHash(const std::string& name,
const std::string& serialized_file) {
if (!file_.get()) {
LOGW("DeviceFiles::StoreFileWithHash: Invalid file handle");
return false;
}
@@ -501,18 +554,13 @@ bool DeviceFiles::StoreFileWithHash(const char* name,
return StoreFileRaw(name, serialized_hash_file);
}
bool DeviceFiles::StoreFileRaw(const char* name,
bool DeviceFiles::StoreFileRaw(const std::string& name,
const std::string& serialized_file) {
if (!file_.get()) {
LOGW("DeviceFiles::StoreFileRaw: Invalid file handle");
return false;
}
if (!name) {
LOGW("DeviceFiles::StoreFileRaw: Unspecified file name parameter");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::StoreFileRaw: Unable to get base path");
@@ -546,18 +594,13 @@ bool DeviceFiles::StoreFileRaw(const char* name,
return true;
}
bool DeviceFiles::RetrieveHashedFile(const char* name,
bool DeviceFiles::RetrieveHashedFile(const std::string& name,
std::string* serialized_file) {
if (!file_.get()) {
LOGW("DeviceFiles::RetrieveHashedFile: Invalid file handle");
return false;
}
if (!name) {
LOGW("DeviceFiles::RetrieveHashedFile: Unspecified file name parameter");
return false;
}
if (!serialized_file) {
LOGW(
"DeviceFiles::RetrieveHashedFile: Unspecified serialized_file "
@@ -582,6 +625,9 @@ bool DeviceFiles::RetrieveHashedFile(const char* name,
if (bytes <= 0) {
LOGW("DeviceFiles::RetrieveHashedFile: File size invalid: %s",
path.c_str());
// Remove the corrupted file so the caller will not get the same error
// when trying to access the file repeatedly, causing the system to stall.
file_->Remove(path);
return false;
}
@@ -614,8 +660,11 @@ bool DeviceFiles::RetrieveHashedFile(const char* name,
return false;
}
if (hash.compare(hash_file.hash())) {
if (hash != hash_file.hash()) {
LOGW("DeviceFiles::RetrieveHashedFile: Hash mismatch");
// Remove the corrupted file so the caller will not get the same error
// when trying to access the file repeatedly, causing the system to stall.
file_->Remove(path);
return false;
}
@@ -623,6 +672,54 @@ bool DeviceFiles::RetrieveHashedFile(const char* name,
return true;
}
bool DeviceFiles::FileExists(const std::string& name) {
if (!file_.get()) {
LOGW("DeviceFiles::FileExists: Invalid file handle");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::FileExists: Unable to get base path");
return false;
}
path += name;
return file_->Exists(path);
}
bool DeviceFiles::RemoveFile(const std::string& name) {
if (!file_.get()) {
LOGW("DeviceFiles::RemoveFile: Invalid file handle");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::RemoveFile: Unable to get base path");
return false;
}
path += name;
return file_->Remove(path);
}
ssize_t DeviceFiles::GetFileSize(const std::string& name) {
if (!file_.get()) {
LOGW("DeviceFiles::GetFileSize: Invalid file handle");
return -1;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::GetFileSize: Unable to get base path");
return -1;
}
path += name;
return file_->FileSize(path);
}
void DeviceFiles::SecurityLevelPathBackwardCompatibility() {
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
@@ -687,17 +784,33 @@ void DeviceFiles::SecurityLevelPathBackwardCompatibility() {
}
}
std::string DeviceFiles::GetCertificateFileName() {
return kCertificateFileName;
std::string DeviceFiles::GetCertificateFileName(const std::string& origin) {
std::string hash;
if (origin != EMPTY_ORIGIN) {
hash = GetFileNameSafeHash(origin);
}
return kCertificateFileNamePrefix + hash + kCertificateFileNameExt;
}
std::string DeviceFiles::GetLicenseFileNameExtension() {
return kLicenseFileNameExt;
}
std::string DeviceFiles::GetUsageInfoFileName() { return kUsageInfoFileName; }
std::string DeviceFiles::GetUsageInfoFileName(const std::string& app_id) {
std::string hash;
if (app_id != "") {
hash = GetFileNameSafeHash(app_id);
}
return kUsageInfoFileNamePrefix + hash + kUsageInfoFileNameExt;
}
std::string DeviceFiles::GetBlankFileData() { return kBlankFileData; }
std::string DeviceFiles::GetFileNameSafeHash(const std::string& input) {
std::vector<uint8_t> hash(MD5_DIGEST_LENGTH);
const unsigned char* input_ptr =
reinterpret_cast<const unsigned char*>(input.data());
MD5(input_ptr, input.size(), &hash[0]);
return wvcdm::Base64SafeEncode(hash);
}
void DeviceFiles::SetTestFile(File* file) {
file_.reset(file);