Source release v3.1.0

This commit is contained in:
Gene Morgan
2016-07-19 18:43:15 -07:00
parent 7a7f78d654
commit 643b91b616
108 changed files with 16537 additions and 7174 deletions

View File

@@ -18,13 +18,16 @@
#define MD5 CC_MD5
#define MD5_DIGEST_LENGTH CC_MD5_DIGEST_LENGTH
#else
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#endif
// Protobuf generated classes.
using video_widevine_client::sdk::DeviceCertificate;
using video_widevine_client::sdk::HashedFile;
using video_widevine_client::sdk::HlsAttributes;
using video_widevine_client::sdk::HlsAttributes_Method_AES_128;
using video_widevine_client::sdk::HlsAttributes_Method_SAMPLE_AES;
using video_widevine_client::sdk::License;
using video_widevine_client::sdk::License_LicenseState_ACTIVE;
using video_widevine_client::sdk::License_LicenseState_RELEASING;
@@ -34,19 +37,13 @@ using video_widevine_client::sdk::UsageInfo_ProviderSession;
namespace {
const char kCertificateFileNamePrefix[] = "cert";
const char kCertificateFileNameExt[] = ".bin";
const char kCertificateFileName[] = "cert.bin";
const char kHlsAttributesFileNameExt[] = ".hal";
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", "ay64.dat2", "ay64.dat3"};
size_t kSecurityLevelPathCompatibilityExclusionListSize =
sizeof(kSecurityLevelPathCompatibilityExclusionList) /
sizeof(*kSecurityLevelPathCompatibilityExclusionList);
bool Hash(const std::string& data, std::string* hash) {
if (!hash) return false;
@@ -66,30 +63,30 @@ namespace wvcdm {
// static
std::set<std::string> DeviceFiles::reserved_license_ids_;
DeviceFiles::DeviceFiles()
: file_(NULL),
DeviceFiles::DeviceFiles(FileSystem* file_system)
: file_system_(file_system),
security_level_(kSecurityLevelUninitialized),
initialized_(false),
test_file_(false) {}
initialized_(false) {}
DeviceFiles::~DeviceFiles() {
if (test_file_) file_.release();
}
DeviceFiles::~DeviceFiles() {}
bool DeviceFiles::Init(CdmSecurityLevel security_level) {
if (!file_system_) {
LOGD("DeviceFiles::Init: Invalid FileSystem given.");
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;
initialized_ = true;
return true;
}
bool DeviceFiles::StoreCertificate(const std::string& origin,
const std::string& certificate,
bool DeviceFiles::StoreCertificate(const std::string& certificate,
const std::string& wrapped_private_key) {
if (!initialized_) {
LOGW("DeviceFiles::StoreCertificate: not initialized");
@@ -109,23 +106,18 @@ bool DeviceFiles::StoreCertificate(const std::string& origin,
std::string serialized_file;
file.SerializeToString(&serialized_file);
return StoreFileWithHash(GetCertificateFileName(origin), serialized_file);
return StoreFileWithHash(GetCertificateFileName(), serialized_file);
}
bool DeviceFiles::RetrieveCertificate(const std::string& origin,
std::string* certificate,
bool DeviceFiles::RetrieveCertificate(std::string* certificate,
std::string* wrapped_private_key) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveCertificate: not initialized");
return false;
}
if (Properties::security_level_path_backward_compatibility_support()) {
SecurityLevelPathBackwardCompatibility();
}
video_widevine_client::sdk::File file;
if (!RetrieveHashedFile(GetCertificateFileName(origin), &file)) {
if (!RetrieveHashedFile(GetCertificateFileName(), &file)) {
return false;
}
@@ -151,22 +143,22 @@ bool DeviceFiles::RetrieveCertificate(const std::string& origin,
return true;
}
bool DeviceFiles::HasCertificate(const std::string& origin) {
bool DeviceFiles::HasCertificate() {
if (!initialized_) {
LOGW("DeviceFiles::HasCertificate: not initialized");
return false;
}
return FileExists(GetCertificateFileName(origin));
return FileExists(GetCertificateFileName());
}
bool DeviceFiles::RemoveCertificate(const std::string& origin) {
bool DeviceFiles::RemoveCertificate() {
if (!initialized_) {
LOGW("DeviceFiles::RemoveCertificate: not initialized");
return false;
}
return RemoveFile(GetCertificateFileName(origin));
return RemoveFile(GetCertificateFileName());
}
bool DeviceFiles::StoreLicense(
@@ -534,13 +526,105 @@ bool DeviceFiles::RetrieveUsageInfoByKeySetId(
return false;
}
bool DeviceFiles::StoreFileWithHash(const std::string& name,
const std::string& serialized_file) {
if (!file_.get()) {
LOGW("DeviceFiles::StoreFileWithHash: Invalid file handle");
bool DeviceFiles::StoreHlsAttributes(
const std::string& key_set_id, const CdmHlsMethod method,
const std::vector<uint8_t>& media_segment_iv) {
if (!initialized_) {
LOGW("DeviceFiles::StoreHlsAttributes: not initialized");
return false;
}
// Fill in file information
video_widevine_client::sdk::File file;
file.set_type(video_widevine_client::sdk::File::HLS_ATTRIBUTES);
file.set_version(video_widevine_client::sdk::File::VERSION_1);
HlsAttributes* hls_attributes = file.mutable_hls_attributes();
switch (method) {
case kHlsMethodAes128:
hls_attributes->set_method(HlsAttributes_Method_AES_128);
break;
case kHlsMethodSampleAes:
hls_attributes->set_method(HlsAttributes_Method_SAMPLE_AES);
break;
case kHlsMethodNone:
default:
LOGW("DeviceFiles::StoreHlsAttributeInfo: Unknown HLS method: %u",
method);
return false;
break;
}
hls_attributes->set_media_segment_iv(&media_segment_iv[0],
media_segment_iv.size());
std::string serialized_file;
file.SerializeToString(&serialized_file);
return StoreFileWithHash(key_set_id + kHlsAttributesFileNameExt,
serialized_file);
}
bool DeviceFiles::RetrieveHlsAttributes(
const std::string& key_set_id, CdmHlsMethod* method,
std::vector<uint8_t>* media_segment_iv) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveHlsAttributes: not initialized");
return false;
}
video_widevine_client::sdk::File file;
if (!RetrieveHashedFile(key_set_id + kHlsAttributesFileNameExt, &file)) {
return false;
}
if (file.type() != video_widevine_client::sdk::File::HLS_ATTRIBUTES) {
LOGW("DeviceFiles::RetrieveHlsAttributes: Incorrect file type: %u",
file.type());
return false;
}
if (file.version() != video_widevine_client::sdk::File::VERSION_1) {
LOGW("DeviceFiles::RetrieveHlsAttributes: Incorrect file version: %u",
file.version());
return false;
}
if (!file.has_hls_attributes()) {
LOGW("DeviceFiles::RetrieveHlsAttributes: HLS attributes not present");
return false;
}
HlsAttributes attributes = file.hls_attributes();
switch (attributes.method()) {
case HlsAttributes_Method_AES_128:
*method = kHlsMethodAes128;
break;
case HlsAttributes_Method_SAMPLE_AES:
*method = kHlsMethodSampleAes;
break;
default:
LOGW("DeviceFiles::RetrieveHlsAttributes: Unrecognized HLS method: %u",
attributes.method());
*method = kHlsMethodNone;
break;
}
media_segment_iv->assign(attributes.media_segment_iv().begin(),
attributes.media_segment_iv().end());
return true;
}
bool DeviceFiles::DeleteHlsAttributes(const std::string& key_set_id) {
if (!initialized_) {
LOGW("DeviceFiles::DeleteHlsAttributes: not initialized");
return false;
}
return RemoveFile(key_set_id + kHlsAttributesFileNameExt);
}
bool DeviceFiles::StoreFileWithHash(const std::string& name,
const std::string& serialized_file) {
// calculate SHA hash
std::string hash;
if (!Hash(serialized_file, &hash)) {
@@ -561,30 +645,23 @@ bool DeviceFiles::StoreFileWithHash(const std::string& name,
bool DeviceFiles::StoreFileRaw(const std::string& name,
const std::string& serialized_file) {
if (!file_.get()) {
LOGW("DeviceFiles::StoreFileRaw: Invalid file handle");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::StoreFileRaw: Unable to get base path");
return false;
}
if (!file_->IsDirectory(path)) {
if (!file_->CreateDirectory(path)) return false;
}
path += name;
if (!file_->Open(path, File::kCreate | File::kTruncate | File::kBinary)) {
File* file =
file_system_->Open(path, FileSystem::kCreate | FileSystem::kTruncate);
if (!file) {
LOGW("DeviceFiles::StoreFileRaw: File open failed: %s", path.c_str());
return false;
}
ssize_t bytes = file_->Write(serialized_file.data(), serialized_file.size());
file_->Close();
ssize_t bytes = file->Write(serialized_file.data(), serialized_file.size());
file->Close();
if (bytes != static_cast<ssize_t>(serialized_file.size())) {
LOGW(
@@ -599,16 +676,12 @@ bool DeviceFiles::StoreFileRaw(const std::string& name,
return true;
}
bool DeviceFiles::RetrieveHashedFile(const std::string& name,
video_widevine_client::sdk::File* file) {
bool DeviceFiles::RetrieveHashedFile(
const std::string& name,
video_widevine_client::sdk::File* deserialized_file) {
std::string serialized_file;
if (!file_.get()) {
LOGW("DeviceFiles::RetrieveHashedFile: Invalid file handle");
return false;
}
if (!file) {
if (!deserialized_file) {
LOGW("DeviceFiles::RetrieveHashedFile: Unspecified file parameter");
return false;
}
@@ -621,29 +694,30 @@ bool DeviceFiles::RetrieveHashedFile(const std::string& name,
path += name;
if (!file_->Exists(path)) {
if (!file_system_->Exists(path)) {
LOGW("DeviceFiles::RetrieveHashedFile: %s does not exist", path.c_str());
return false;
}
ssize_t bytes = file_->FileSize(path);
ssize_t bytes = file_system_->FileSize(path);
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);
file_system_->Remove(path);
return false;
}
if (!file_->Open(path, File::kReadOnly | File::kBinary)) {
File* file = file_system_->Open(path, FileSystem::kReadOnly);
if (!file) {
return false;
}
std::string serialized_hash_file;
serialized_hash_file.resize(bytes);
bytes = file_->Read(&serialized_hash_file[0], serialized_hash_file.size());
file_->Close();
bytes = file->Read(&serialized_hash_file[0], serialized_hash_file.size());
file->Close();
if (bytes != static_cast<ssize_t>(serialized_hash_file.size())) {
LOGW("DeviceFiles::RetrieveHashedFile: read failed");
@@ -669,11 +743,11 @@ bool DeviceFiles::RetrieveHashedFile(const std::string& name,
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);
file_system_->Remove(path);
return false;
}
if (!file->ParseFromString(hash_file.file())) {
if (!deserialized_file->ParseFromString(hash_file.file())) {
LOGW("DeviceFiles::RetrieveHashedFile: Unable to parse file");
return false;
}
@@ -681,11 +755,6 @@ bool DeviceFiles::RetrieveHashedFile(const std::string& name,
}
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");
@@ -693,15 +762,10 @@ bool DeviceFiles::FileExists(const std::string& name) {
}
path += name;
return file_->Exists(path);
return file_system_->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");
@@ -709,15 +773,10 @@ bool DeviceFiles::RemoveFile(const std::string& name) {
}
path += name;
return file_->Remove(path);
return file_system_->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");
@@ -725,79 +784,15 @@ ssize_t DeviceFiles::GetFileSize(const std::string& name) {
}
path += name;
return file_->FileSize(path);
return file_system_->FileSize(path);
}
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.find(security_dirs[i]);
if (pos != std::string::npos && pos > 0 &&
pos == path.size() - security_dirs[i].size() &&
path[pos - 1] == kDirectoryDelimiter) {
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;
if (!file_->List(from_dir, &files)) {
return;
}
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 < kSecurityLevelPathCompatibilityExclusionListSize;
++j) {
if (files[i] == kSecurityLevelPathCompatibilityExclusionList[j]) {
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;
}
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::GetHlsAttributesFileNameExtension() {
return kHlsAttributesFileNameExt;
}
std::string DeviceFiles::GetLicenseFileNameExtension() {
@@ -820,9 +815,4 @@ std::string DeviceFiles::GetFileNameSafeHash(const std::string& input) {
return wvcdm::Base64SafeEncode(hash);
}
void DeviceFiles::SetTestFile(File* file) {
file_.reset(file);
test_file_ = true;
}
} // namespace wvcdm