Merge "Generate Key Set IDs at Key Request Generation Time"

This commit is contained in:
John "Juce" Bruce
2015-03-05 20:05:12 +00:00
committed by Android (Google) Code Review
9 changed files with 143 additions and 49 deletions

View File

@@ -174,7 +174,8 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
const CdmLicenseType license_type,
CdmAppParameterMap& app_parameters,
CdmKeyMessage* key_request,
std::string* server_url) {
std::string* server_url,
CdmKeySetId* key_set_id_out) {
LOGI("CdmEngine::GenerateKeyRequest");
CdmSessionId id = session_id;
@@ -227,7 +228,7 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
sts = iter->second->GenerateKeyRequest(init_data, license_type,
app_parameters, key_request,
server_url);
server_url, key_set_id_out);
if (KEY_MESSAGE != sts) {
if (sts == NEED_PROVISIONING) {

View File

@@ -194,7 +194,7 @@ CdmResponseType CdmSession::RestoreUsageSession(
CdmResponseType CdmSession::GenerateKeyRequest(
const InitializationData& init_data, const CdmLicenseType license_type,
const CdmAppParameterMap& app_parameters, CdmKeyMessage* key_request,
std::string* server_url) {
std::string* server_url, CdmKeySetId* key_set_id) {
if (crypto_session_.get() == NULL) {
LOGW("CdmSession::GenerateKeyRequest: Invalid crypto session");
return UNKNOWN_ERROR;
@@ -229,6 +229,10 @@ CdmResponseType CdmSession::GenerateKeyRequest(
LOGW("CdmSession::GenerateKeyRequest: init data absent");
return KEY_ERROR;
}
if (is_offline_ && !GenerateKeySetId(&key_set_id_)) {
LOGE("CdmSession::GenerateKeyRequest: Unable to generate key set ID");
return UNKNOWN_ERROR;
}
if (!license_parser_->PrepareKeyRequest(init_data, license_type,
app_parameters, session_id_,
@@ -242,6 +246,7 @@ CdmResponseType CdmSession::GenerateKeyRequest(
offline_release_server_url_ = *server_url;
}
if (key_set_id) *key_set_id = key_set_id_;
return KEY_MESSAGE;
}
}
@@ -277,7 +282,7 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response,
if (sts != NO_ERROR) return sts;
}
*key_set_id = key_set_id_;
if (key_set_id) *key_set_id = key_set_id_;
return KEY_ADDED;
}
}
@@ -465,13 +470,15 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) {
key_set_id->clear();
}
}
// Reserve the license ID to avoid collisions.
file_handle_->ReserveLicenseId(*key_set_id);
return true;
}
CdmResponseType CdmSession::StoreLicense() {
if (is_offline_) {
if (!GenerateKeySetId(&key_set_id_)) {
LOGE("CdmSession::StoreLicense: Unable to generate key set Id");
if (key_set_id_.empty()) {
LOGE("CdmSession::StoreLicense: No key set ID");
return UNKNOWN_ERROR;
}

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;