Source release v2.1.2-0-773 + third_party libs

Change-Id: Ia07608577b65b301c22a8ff4bf7f743c2d3f9274
This commit is contained in:
Joey Parrish
2014-06-10 13:36:59 -07:00
parent 557c42130a
commit aaa3c6192a
42 changed files with 2425 additions and 918 deletions

View File

@@ -2,14 +2,22 @@
#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>
#include "device_files.pb.h"
#include "file_store.h"
#include "log.h"
#include "openssl/sha.h"
#include "properties.h"
#include "string_conversions.h"
// Protobuf generated classes.
using video_widevine_client::sdk::DeviceCertificate;
@@ -17,9 +25,13 @@ 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::UsageInfo;
using video_widevine_client::sdk::UsageInfo_ProviderSession;
namespace {
const char kCertificateFileName[] = "cert.bin";
const char kUsageInfoFileName[] = "usage.bin";
const char kLicenseFileNameExt[] = ".lic";
const char kWildcard[] = "*";
const char kDirectoryDelimiter = '/';
@@ -27,15 +39,27 @@ const char* kSecurityLevelPathCompatibilityExclusionList[] = {"ay64.dat"};
size_t kSecurityLevelPathCompatibilityExclusionListSize =
sizeof(kSecurityLevelPathCompatibilityExclusionList) /
sizeof(*kSecurityLevelPathCompatibilityExclusionList);
} // namespace
bool Hash(const std::string& data, std::string* hash) {
if (!hash) return false;
hash->resize(SHA256_DIGEST_LENGTH);
const unsigned char* input =
reinterpret_cast<const unsigned char*>(data.data());
unsigned char* output = reinterpret_cast<unsigned char*>(&(*hash)[0]);
SHA256(input, data.size(), output);
return true;
}
} // unnamed namespace
namespace wvcdm {
bool DeviceFiles::Init(const File* handle, CdmSecurityLevel security_level) {
if (handle == NULL) {
LOGW("DeviceFiles::Init: Invalid file handle parameter");
return false;
}
DeviceFiles::~DeviceFiles() {
if (!file_ && !test_file_) delete file_;
}
bool DeviceFiles::Init(CdmSecurityLevel security_level) {
switch (security_level) {
case kSecurityLevelL1:
case kSecurityLevelL2:
@@ -45,7 +69,7 @@ bool DeviceFiles::Init(const File* handle, CdmSecurityLevel security_level) {
LOGW("DeviceFiles::Init: Unsupported security level %d", security_level);
return false;
}
file_ = const_cast<File*>(handle);
file_ = new File();
security_level_ = security_level;
initialized_ = true;
return true;
@@ -68,24 +92,10 @@ bool DeviceFiles::StoreCertificate(const std::string& certificate,
device_certificate->set_certificate(certificate);
device_certificate->set_wrapped_private_key(wrapped_private_key);
std::string serialized_string;
file.SerializeToString(&serialized_string);
std::string serialized_file;
file.SerializeToString(&serialized_file);
// calculate SHA hash
std::string hash;
if (!Hash(serialized_string, &hash)) {
LOGW("DeviceFiles::StoreCertificate: Hash computation failed");
return false;
}
// Fill in hashed file data
HashedFile hashed_file;
hashed_file.set_file(serialized_string);
hashed_file.set_hash(hash);
hashed_file.SerializeToString(&serialized_string);
return StoreFile(kCertificateFileName, serialized_string);
return StoreFile(kCertificateFileName, serialized_file);
}
bool DeviceFiles::RetrieveCertificate(std::string* certificate,
@@ -99,29 +109,12 @@ bool DeviceFiles::RetrieveCertificate(std::string* certificate,
SecurityLevelPathBackwardCompatibility();
}
std::string serialized_hashed_file;
if (!RetrieveFile(kCertificateFileName, &serialized_hashed_file))
std::string serialized_file;
if (!RetrieveFile(kCertificateFileName, &serialized_file))
return false;
HashedFile hashed_file;
if (!hashed_file.ParseFromString(serialized_hashed_file)) {
LOGW("DeviceFiles::RetrieveCertificate: Unable to parse hash file");
return false;
}
std::string hash;
if (!Hash(hashed_file.file(), &hash)) {
LOGW("DeviceFiles::RetrieveCertificate: Hash computation failed");
return false;
}
if (hash.compare(hashed_file.hash())) {
LOGW("DeviceFiles::RetrieveCertificate: Hash mismatch");
return false;
}
video_widevine_client::sdk::File file;
if (!file.ParseFromString(hashed_file.file())) {
if (!file.ParseFromString(serialized_file)) {
LOGW("DeviceFiles::RetrieveCertificate: Unable to parse file");
return false;
}
@@ -187,25 +180,11 @@ bool DeviceFiles::StoreLicense(const std::string& key_set_id,
license->set_renewal(license_renewal);
license->set_release_server_url(release_server_url);
std::string serialized_string;
file.SerializeToString(&serialized_string);
// calculate SHA hash
std::string hash;
if (!Hash(serialized_string, &hash)) {
LOGW("DeviceFiles::StoreLicense: Hash computation failed");
return false;
}
// File in hashed file data
HashedFile hashed_file;
hashed_file.set_file(serialized_string);
hashed_file.set_hash(hash);
hashed_file.SerializeToString(&serialized_string);
std::string serialized_file;
file.SerializeToString(&serialized_file);
std::string file_name = key_set_id + kLicenseFileNameExt;
return StoreFile(file_name.c_str(), serialized_string);
return StoreFile(file_name.c_str(), serialized_file);
}
bool DeviceFiles::RetrieveLicense(const std::string& key_set_id,
@@ -220,29 +199,12 @@ bool DeviceFiles::RetrieveLicense(const std::string& key_set_id,
return false;
}
std::string serialized_hashed_file;
std::string serialized_file;
std::string file_name = key_set_id + kLicenseFileNameExt;
if (!RetrieveFile(file_name.c_str(), &serialized_hashed_file)) return false;
HashedFile hashed_file;
if (!hashed_file.ParseFromString(serialized_hashed_file)) {
LOGW("DeviceFiles::RetrieveLicense: Unable to parse hash file");
return false;
}
std::string hash;
if (!Hash(hashed_file.file(), &hash)) {
LOGW("DeviceFiles::RetrieveLicense: Hash computation failed");
return false;
}
if (hash.compare(hashed_file.hash())) {
LOGW("DeviceFiles::RetrieveLicense: Hash mismatch");
return false;
}
if (!RetrieveFile(file_name.c_str(), &serialized_file)) return false;
video_widevine_client::sdk::File file;
if (!file.ParseFromString(hashed_file.file())) {
if (!file.ParseFromString(serialized_file)) {
LOGW("DeviceFiles::RetrieveLicense: Unable to parse file");
return false;
}
@@ -352,18 +314,144 @@ bool DeviceFiles::LicenseExists(const std::string& key_set_id) {
return file_->Exists(path);
}
bool DeviceFiles::Hash(const std::string& data, std::string* hash) {
if (!hash) return false;
bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
const CdmKeyMessage& key_request,
const CdmKeyResponse& key_response) {
if (!initialized_) {
LOGW("DeviceFiles::StoreUsageInfo: not initialized");
return false;
}
std::string serialized_file;
video_widevine_client::sdk::File file;
if (!RetrieveFile(kUsageInfoFileName, &serialized_file)) {
file.set_type(video_widevine_client::sdk::File::USAGE_INFO);
file.set_version(video_widevine_client::sdk::File::VERSION_1);
} else {
if (!file.ParseFromString(serialized_file)) {
LOGW("DeviceFiles::StoreUsageInfo: Unable to parse file");
return false;
}
}
UsageInfo* usage_info = file.mutable_usage_info();
UsageInfo_ProviderSession* provider_session = usage_info->add_sessions();
provider_session->set_token(provider_session_token.data(),
provider_session_token.size());
provider_session->set_license_request(key_request.data(),
key_request.size());
provider_session->set_license(key_response.data(),
key_response.size());
file.SerializeToString(&serialized_file);
return StoreFile(kUsageInfoFileName, serialized_file);
}
bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
if (!initialized_) {
LOGW("DeviceFiles::DeleteUsageInfo: not initialized");
return false;
}
std::string serialized_file;
if (!RetrieveFile(kUsageInfoFileName, &serialized_file)) return false;
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
LOGW("DeviceFiles::DeleteUsageInfo: Unable to parse file");
return false;
}
UsageInfo* updated_info = file.mutable_usage_info();
UsageInfo info(*(const_cast<const UsageInfo*>(updated_info)));
updated_info->clear_sessions();
bool found = false;
for (int i = 0; i < info.sessions_size(); ++i) {
if (info.sessions(i).token().compare(provider_session_token) == 0) {
found = true;
} else {
updated_info->add_sessions()->set_token(info.sessions(i).token());
updated_info->add_sessions()->set_license_request(
info.sessions(i).license_request());
updated_info->add_sessions()->set_license(info.sessions(i).license());
}
}
if (!found) {
LOGW("DeviceFiles::DeleteUsageInfo: Unable to find provider session "
"token: %s", b2a_hex(provider_session_token).c_str());
return false;
}
file.SerializeToString(&serialized_file);
return StoreFile(kUsageInfoFileName, serialized_file);
}
bool DeviceFiles::DeleteUsageInfo() {
if (!initialized_) {
LOGW("DeviceFiles::DeleteUsageInfo: not initialized");
return false;
}
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::DeleteUsageInfo: Unable to get base path");
return false;
}
path.append(kUsageInfoFileName);
return file_->Remove(path);
}
bool DeviceFiles::RetrieveUsageInfo(std::vector<
std::pair<CdmKeyMessage, CdmKeyResponse> >* usage_info) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
return false;
}
if (NULL == usage_info) {
LOGW("DeviceFiles::RetrieveUsageInfo: license destination not "
"provided");
return false;
}
std::string serialized_file;
if (!RetrieveFile(kUsageInfoFileName, &serialized_file)) {
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
return false;
}
path += kUsageInfoFileName;
if (!file_->Exists(path) || 0 == file_->FileSize(path)) {
usage_info->resize(0);
return true;
}
return false;
}
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
LOGW("DeviceFiles::RetrieveUsageInfo: Unable to parse file");
return false;
}
usage_info->resize(file.usage_info().sessions_size());
for (int i = 0; i < file.usage_info().sessions_size(); ++i) {
(*usage_info)[i] =
std::make_pair(file.usage_info().sessions(i).license_request(),
file.usage_info().sessions(i).license());
}
hash->resize(SHA256_DIGEST_LENGTH);
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, data.data(), data.size());
SHA256_Final(reinterpret_cast<unsigned char*>(&(*hash)[0]), &sha256);
return true;
}
bool DeviceFiles::StoreFile(const char* name, const std::string& data) {
bool DeviceFiles::StoreFile(const char* name,
const std::string& serialized_file) {
if (!file_) {
LOGW("DeviceFiles::StoreFile: Invalid file handle");
return false;
@@ -374,6 +462,21 @@ bool DeviceFiles::StoreFile(const char* name, const std::string& data) {
return false;
}
// calculate SHA hash
std::string hash;
if (!Hash(serialized_file, &hash)) {
LOGW("DeviceFiles::StoreFile: Hash computation failed");
return false;
}
// Fill in hashed file data
HashedFile hash_file;
hash_file.set_file(serialized_file);
hash_file.set_hash(hash);
std::string serialized_hash_file;
hash_file.SerializeToString(&serialized_hash_file);
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::StoreFile: Unable to get base path");
@@ -391,19 +494,24 @@ bool DeviceFiles::StoreFile(const char* name, const std::string& data) {
return false;
}
ssize_t bytes = file_->Write(data.data(), data.size());
ssize_t bytes = file_->Write(serialized_hash_file.data(),
serialized_hash_file.size());
file_->Close();
if (bytes != static_cast<ssize_t>(data.size())) {
LOGW("DeviceFiles::StoreFile: write failed: %d %d", data.size(), bytes);
if (bytes != static_cast<ssize_t>(serialized_hash_file.size())) {
LOGW("DeviceFiles::StoreFile: write failed: (actual: %d, expected: %d)",
bytes,
serialized_hash_file.size());
return false;
}
LOGV("DeviceFiles::StoreFile: success: %s (%db)", path.c_str(), data.size());
LOGV("DeviceFiles::StoreFile: success: %s (%db)",
path.c_str(),
serialized_hash_file.size());
return true;
}
bool DeviceFiles::RetrieveFile(const char* name, std::string* data) {
bool DeviceFiles::RetrieveFile(const char* name, std::string* serialized_file) {
if (!file_) {
LOGW("DeviceFiles::RetrieveFile: Invalid file handle");
return false;
@@ -414,8 +522,8 @@ bool DeviceFiles::RetrieveFile(const char* name, std::string* data) {
return false;
}
if (!data) {
LOGW("DeviceFiles::RetrieveFile: Unspecified data parameter");
if (!serialized_file) {
LOGW("DeviceFiles::RetrieveFile: Unspecified serialized_file parameter");
return false;
}
@@ -434,7 +542,7 @@ bool DeviceFiles::RetrieveFile(const char* name, std::string* data) {
ssize_t bytes = file_->FileSize(path);
if (bytes <= 0) {
LOGW("DeviceFiles::RetrieveFile: File size invalid: %d", path.c_str());
LOGW("DeviceFiles::RetrieveFile: File size invalid: %s", path.c_str());
return false;
}
@@ -442,17 +550,37 @@ bool DeviceFiles::RetrieveFile(const char* name, std::string* data) {
return false;
}
data->resize(bytes);
bytes = file_->Read(&(*data)[0], data->size());
std::string serialized_hash_file;
serialized_hash_file.resize(bytes);
bytes = file_->Read(&serialized_hash_file[0], serialized_hash_file.size());
file_->Close();
if (bytes != static_cast<ssize_t>(data->size())) {
if (bytes != static_cast<ssize_t>(serialized_hash_file.size())) {
LOGW("DeviceFiles::RetrieveFile: read failed");
return false;
}
LOGV("DeviceFiles::RetrieveFile: success: %s (%db)", path.c_str(),
data->size());
serialized_hash_file.size());
HashedFile hash_file;
if (!hash_file.ParseFromString(serialized_hash_file)) {
LOGW("DeviceFiles::RetrieveFile: Unable to parse hash file");
return false;
}
std::string hash;
if (!Hash(hash_file.file(), &hash)) {
LOGW("DeviceFiles::RetrieveFile: Hash computation failed");
return false;
}
if (hash.compare(hash_file.hash())) {
LOGW("DeviceFiles::RetrieveFile: Hash mismatch");
return false;
}
*serialized_file = hash_file.file();
return true;
}
@@ -528,4 +656,14 @@ std::string DeviceFiles::GetLicenseFileNameExtension() {
return kLicenseFileNameExt;
}
std::string DeviceFiles::GetUsageInfoFileName() {
return kUsageInfoFileName;
}
void DeviceFiles::SetTestFile(File* file) {
if (file_) delete file_;
file_ = file;
test_file_ = true;
}
} // namespace wvcdm