Generate Key Set IDs at Key Request Generation Time

(This is a merge of http://go/wvgerrit/11285 from the Widevine CDM
repository.)

The key set ID is now available earlier, in order to support the CE
CDM 4.5 interface, which needs it at key request generation time, not
later at key response receipt time. It is still possible to receive
the key set ID at key response time, for Android's purposes. Either
API may now be passed a pointer to store the ID in, which may also be
left NULL if this is not needed.

Change-Id: I47e80ea4005c80282e36cfae92cb91142208f624
This commit is contained in:
John "Juce" Bruce
2015-03-04 13:22:18 -08:00
parent 4252a4b790
commit 620b05dba0
9 changed files with 143 additions and 49 deletions

View File

@@ -41,6 +41,8 @@ const char* kSecurityLevelPathCompatibilityExclusionList[] = {"ay64.dat"};
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;
@@ -102,7 +104,7 @@ bool DeviceFiles::StoreCertificate(const std::string& certificate,
std::string serialized_file;
file.SerializeToString(&serialized_file);
return StoreFile(kCertificateFileName, serialized_file);
return StoreFileWithHash(kCertificateFileName, serialized_file);
}
bool DeviceFiles::RetrieveCertificate(std::string* certificate,
@@ -117,7 +119,7 @@ bool DeviceFiles::RetrieveCertificate(std::string* certificate,
}
std::string serialized_file;
if (!RetrieveFile(kCertificateFileName, &serialized_file))
if (!RetrieveHashedFile(kCertificateFileName, &serialized_file))
return false;
video_widevine_client::sdk::File file;
@@ -195,7 +197,7 @@ bool DeviceFiles::StoreLicense(const std::string& key_set_id,
file.SerializeToString(&serialized_file);
std::string file_name = key_set_id + kLicenseFileNameExt;
return StoreFile(file_name.c_str(), serialized_file);
return StoreFileWithHash(file_name.c_str(), serialized_file);
}
bool DeviceFiles::RetrieveLicense(const std::string& key_set_id,
@@ -214,7 +216,7 @@ bool DeviceFiles::RetrieveLicense(const std::string& key_set_id,
std::string serialized_file;
std::string file_name = key_set_id + kLicenseFileNameExt;
if (!RetrieveFile(file_name.c_str(), &serialized_file)) return false;
if (!RetrieveHashedFile(file_name.c_str(), &serialized_file)) return false;
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
@@ -320,7 +322,7 @@ bool DeviceFiles::LicenseExists(const std::string& key_set_id) {
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::StoreFile: Unable to get base path");
LOGW("DeviceFiles::LicenseExists: Unable to get base path");
return false;
}
path.append(key_set_id);
@@ -329,6 +331,16 @@ bool DeviceFiles::LicenseExists(const std::string& key_set_id) {
return file_->Exists(path);
}
bool DeviceFiles::ReserveLicenseId(const std::string& key_set_id) {
if (!initialized_) {
LOGW("DeviceFiles::ReserveLicenseId: not initialized");
return false;
}
std::string file_name = key_set_id + kLicenseFileNameExt;
return StoreFileRaw(file_name.c_str(), kBlankFileData);
}
bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
const CdmKeyMessage& key_request,
const CdmKeyResponse& key_response,
@@ -341,7 +353,7 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
std::string serialized_file;
video_widevine_client::sdk::File file;
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveFile(file_name.c_str(), &serialized_file)) {
if (!RetrieveHashedFile(file_name.c_str(), &serialized_file)) {
file.set_type(video_widevine_client::sdk::File::USAGE_INFO);
file.set_version(video_widevine_client::sdk::File::VERSION_1);
} else {
@@ -362,7 +374,7 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
key_response.size());
file.SerializeToString(&serialized_file);
return StoreFile(file_name.c_str(), serialized_file);
return StoreFileWithHash(file_name.c_str(), serialized_file);
}
bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
@@ -374,7 +386,7 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
std::string serialized_file;
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveFile(file_name.c_str(), &serialized_file)) return false;
if (!RetrieveHashedFile(file_name.c_str(), &serialized_file)) return false;
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
@@ -406,7 +418,7 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
sessions->RemoveLast();
file.SerializeToString(&serialized_file);
return StoreFile(file_name.c_str(), serialized_file);
return StoreFileWithHash(file_name.c_str(), serialized_file);
}
bool DeviceFiles::DeleteAllUsageInfoForApp(const std::string& app_id) {
@@ -442,7 +454,7 @@ bool DeviceFiles::RetrieveUsageInfo(
std::string serialized_file;
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveFile(file_name.c_str(), &serialized_file)) {
if (!RetrieveHashedFile(file_name.c_str(), &serialized_file)) {
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
return false;
@@ -484,7 +496,7 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
}
std::string serialized_file;
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveFile(file_name.c_str(), &serialized_file)) return false;
if (!RetrieveHashedFile(file_name.c_str(), &serialized_file)) return false;
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
@@ -510,22 +522,22 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
return true;
}
bool DeviceFiles::StoreFile(const char* name,
const std::string& serialized_file) {
bool DeviceFiles::StoreFileWithHash(const char* name,
const std::string& serialized_file) {
if (!file_.get()) {
LOGW("DeviceFiles::StoreFile: Invalid file handle");
LOGW("DeviceFiles::StoreFileWithHash: Invalid file handle");
return false;
}
if (!name) {
LOGW("DeviceFiles::StoreFile: Unspecified file name parameter");
LOGW("DeviceFiles::StoreFileWithHash: Unspecified file name parameter");
return false;
}
// calculate SHA hash
std::string hash;
if (!Hash(serialized_file, &hash)) {
LOGW("DeviceFiles::StoreFile: Hash computation failed");
LOGW("DeviceFiles::StoreFileWithHash: Hash computation failed");
return false;
}
@@ -537,9 +549,24 @@ bool DeviceFiles::StoreFile(const char* name,
std::string serialized_hash_file;
hash_file.SerializeToString(&serialized_hash_file);
return StoreFileRaw(name, serialized_hash_file);
}
bool DeviceFiles::StoreFileRaw(const char* 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::StoreFile: Unable to get base path");
LOGW("DeviceFiles::StoreFileRaw: Unable to get base path");
return false;
}
@@ -550,40 +577,40 @@ bool DeviceFiles::StoreFile(const char* name,
path += name;
if (!file_->Open(path, File::kCreate | File::kTruncate | File::kBinary)) {
LOGW("DeviceFiles::StoreFile: File open failed: %s", path.c_str());
LOGW("DeviceFiles::StoreFileRaw: File open failed: %s", path.c_str());
return false;
}
ssize_t bytes = file_->Write(serialized_hash_file.data(),
serialized_hash_file.size());
ssize_t bytes = file_->Write(serialized_file.data(),
serialized_file.size());
file_->Close();
if (bytes != static_cast<ssize_t>(serialized_hash_file.size())) {
LOGW("DeviceFiles::StoreFile: write failed: (actual: %d, expected: %d)",
if (bytes != static_cast<ssize_t>(serialized_file.size())) {
LOGW("DeviceFiles::StoreFileRaw: write failed: (actual: %d, expected: %d)",
bytes,
serialized_hash_file.size());
serialized_file.size());
return false;
}
LOGV("DeviceFiles::StoreFile: success: %s (%db)",
LOGV("DeviceFiles::StoreFileRaw: success: %s (%db)",
path.c_str(),
serialized_hash_file.size());
serialized_file.size());
return true;
}
bool DeviceFiles::RetrieveFile(const char* name, std::string* serialized_file) {
bool DeviceFiles::RetrieveHashedFile(const char* name, std::string* serialized_file) {
if (!file_.get()) {
LOGW("DeviceFiles::RetrieveFile: Invalid file handle");
LOGW("DeviceFiles::RetrieveHashedFile: Invalid file handle");
return false;
}
if (!name) {
LOGW("DeviceFiles::RetrieveFile: Unspecified file name parameter");
LOGW("DeviceFiles::RetrieveHashedFile: Unspecified file name parameter");
return false;
}
if (!serialized_file) {
LOGW("DeviceFiles::RetrieveFile: Unspecified serialized_file parameter");
LOGW("DeviceFiles::RetrieveHashedFile: Unspecified serialized_file parameter");
return false;
}
@@ -596,13 +623,13 @@ bool DeviceFiles::RetrieveFile(const char* name, std::string* serialized_file) {
path += name;
if (!file_->Exists(path)) {
LOGW("DeviceFiles::RetrieveFile: %s does not exist", path.c_str());
LOGW("DeviceFiles::RetrieveHashedFile: %s does not exist", path.c_str());
return false;
}
ssize_t bytes = file_->FileSize(path);
if (bytes <= 0) {
LOGW("DeviceFiles::RetrieveFile: File size invalid: %s", path.c_str());
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);
@@ -619,27 +646,27 @@ bool DeviceFiles::RetrieveFile(const char* name, std::string* serialized_file) {
file_->Close();
if (bytes != static_cast<ssize_t>(serialized_hash_file.size())) {
LOGW("DeviceFiles::RetrieveFile: read failed");
LOGW("DeviceFiles::RetrieveHashedFile: read failed");
return false;
}
LOGV("DeviceFiles::RetrieveFile: success: %s (%db)", path.c_str(),
LOGV("DeviceFiles::RetrieveHashedFile: success: %s (%db)", path.c_str(),
serialized_hash_file.size());
HashedFile hash_file;
if (!hash_file.ParseFromString(serialized_hash_file)) {
LOGW("DeviceFiles::RetrieveFile: Unable to parse hash file");
LOGW("DeviceFiles::RetrieveHashedFile: Unable to parse hash file");
return false;
}
std::string hash;
if (!Hash(hash_file.file(), &hash)) {
LOGW("DeviceFiles::RetrieveFile: Hash computation failed");
LOGW("DeviceFiles::RetrieveHashedFile: Hash computation failed");
return false;
}
if (hash.compare(hash_file.hash())) {
LOGW("DeviceFiles::RetrieveFile: Hash mismatch");
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);
@@ -733,6 +760,8 @@ std::string DeviceFiles::GetUsageInfoFileName(const std::string& app_id) {
std::string(kUsageInfoFileNameExt);
}
std::string DeviceFiles::GetBlankFileData() { return kBlankFileData; }
void DeviceFiles::SetTestFile(File* file) {
file_.reset(file);
test_file_ = true;