Regular sync.

Changes include:
1. Fix refreshkeys when handling renewal response.
2. Change ECM start detect method.
3. Fix signing key truncation.
4. Reformat C++ code.
5. Return license_id in LICENSE_CAS_READY payload.
6. Expose OEMCrypto API version in the license request.
7. Add support for newly added widevine cas ids.
8. Store content iv and encryption mode info to entitled key.
9. Upgrade ODK library to 16.4.
This commit is contained in:
huihli
2020-10-21 11:16:23 -07:00
parent 0f6db6f751
commit 2feec02df2
39 changed files with 703 additions and 546 deletions

View File

@@ -1,3 +1,5 @@
#include "widevine_cas_api.h"
#include <openssl/sha.h>
#include "ca_descriptor.pb.h"
@@ -6,11 +8,11 @@
#include "license_protocol.pb.h"
#include "log.h"
#include "string_conversions.h"
#include "widevine_cas_api.h"
#include "widevine_cas_session_map.h"
static constexpr char kBasePathPrefix[] = "/data/vendor/mediacas/IDM/widevine/";
static constexpr char kCertFileBase[] = "cert.bin";
constexpr char kBasePathPrefix[] = "/data/vendor/mediacas/IDM/widevine/";
constexpr char kCertFileBase[] = "cert.bin";
constexpr char kLicenseFileNameSuffix[] = ".lic";
namespace {
bool ReadFileFromStorage(wvutil::FileSystem& file_system,
@@ -42,7 +44,7 @@ bool RemoveFile(wvutil::FileSystem& file_system, const std::string& filename) {
if (!file_system.Exists(filename)) {
return false;
}
if(!file_system.Remove(filename)){
if (!file_system.Remove(filename)) {
return false;
}
return true;
@@ -62,9 +64,9 @@ bool StoreFile(wvutil::FileSystem& file_system, const std::string& filename,
return true;
}
std::string GenerateLicenseFilename(const std::string& id_data_from_media_id,
std::string GenerateLicenseFilename(const std::string& content_id,
const std::string& provider_id) {
std::string data(id_data_from_media_id + provider_id);
std::string data(content_id + provider_id);
std::string hash;
hash.resize(SHA256_DIGEST_LENGTH);
const unsigned char* input =
@@ -72,7 +74,7 @@ std::string GenerateLicenseFilename(const std::string& id_data_from_media_id,
unsigned char* output = reinterpret_cast<unsigned char*>(&hash[0]);
SHA256(input, data.size(), output);
return std::string(std::string(kBasePathPrefix) + wvutil::b2a_hex(hash) +
std::string(".lic"));
std::string(kLicenseFileNameSuffix));
}
} // namespace
@@ -87,13 +89,6 @@ class MediaContext : public CasMediaId {
const std::string content_id() override { return pssh_.content_id(); }
const std::string provider_id() override { return pssh_.provider(); }
const int group_ids_size() override { return pssh_.group_ids_size(); }
const std::string group_id() override {
if (group_ids_size() > 0) {
return pssh_.group_ids(0);
}
return "";
}
CasStatus initialize(const std::string& init_data) override {
if (!pssh_.ParseFromString(init_data)) {
@@ -134,21 +129,15 @@ void WidevineCas::OnTimerEvent() {
// Delete expired license after firing expired event in policy_engine
if (cas_license_->IsExpired() && (media_id_.get() != nullptr)) {
std::string filename;
if (media_id_->group_ids_size() > 0) {
filename = GenerateLicenseFilename(media_id_->group_id(),
media_id_->provider_id());
} else {
filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
}
if (!file_system_->Exists(filename)) {
LOGI("No expired license file stored in disk");
}else{
if(RemoveFile(*file_system_, filename)) {
LOGI("Remove expired license file from disk successfully.");
}
std::string filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
if (!file_system_->Exists(filename)) {
LOGI("No expired license file stored in disk");
} else {
if (RemoveFile(*file_system_, filename)) {
LOGI("Remove expired license file from disk successfully.");
}
}
}
}
}
@@ -306,21 +295,16 @@ CasStatus WidevineCas::handleProvisioningResponse(const std::string& response) {
}
CasStatus WidevineCas::generateEntitlementRequest(
const std::string& init_data, std::string* entitlement_request) {
const std::string& init_data, std::string* entitlement_request,
std::string& license_id) {
media_id_ = CasMediaId::create();
CasStatus status = media_id_->initialize(init_data);
if (!status.ok()) {
return status;
}
std::string license_file;
std::string filename;
if (media_id_->group_ids_size() > 0) {
filename = GenerateLicenseFilename(media_id_->group_id(),
media_id_->provider_id());
} else {
filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
}
std::string filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
if (ReadFileFromStorage(*file_system_, filename, &license_file)) {
CasStatus status =
cas_license_->HandleStoredLicense(wrapped_rsa_key_, license_file);
@@ -329,14 +313,16 @@ CasStatus WidevineCas::generateEntitlementRequest(
// delete the stored license file.
std::unique_lock<std::mutex> locker(lock_);
if (cas_license_->IsExpired()) {
if(!RemoveFile(*file_system_, filename)) {
if (!RemoveFile(*file_system_, filename)) {
return CasStatus(CasStatusCode::kInvalidLicenseFile,
"unable to remove expired license file from disk");
}
LOGI("Remove expired license file from disk successfully.");
return CasStatus(CasStatusCode::kCasLicenseError,
"license is expired, unable to process emm");
"license is expired, unable to process emm");
}
license_id =
filename.substr(0, filename.size() - strlen(kLicenseFileNameSuffix));
policy_timer_.Start(this, 1);
has_license_ = true;
return HandleDeferredECMs();
@@ -355,7 +341,7 @@ CasStatus WidevineCas::generateEntitlementRequest(
}
CasStatus WidevineCas::handleEntitlementResponse(const std::string& response,
std::string& license_id) {
std::string& license_id) {
if (response.empty()) {
return CasStatus(CasStatusCode::kCasLicenseError,
"empty entitlement response");
@@ -380,18 +366,12 @@ CasStatus WidevineCas::handleEntitlementResponse(const std::string& response,
}
if (!device_file.empty()) {
std::string filename;
if (media_id_->group_ids_size() > 0) {
filename = GenerateLicenseFilename(media_id_->group_id(),
media_id_->provider_id());
} else {
filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
}
std::string filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
StoreFile(*file_system_, filename, device_file);
// license_id will be the filename without ".lic" extension.
license_id = filename.substr(0,
filename.size() - std::string(".lic").size());
license_id =
filename.substr(0, filename.size() - strlen(kLicenseFileNameSuffix));
}
}
return status;
@@ -421,47 +401,34 @@ CasStatus WidevineCas::handleEntitlementRenewalResponse(
return status;
}
if (!device_file.empty()) {
std::string filename;
if (media_id_->group_ids_size() > 0) {
filename = GenerateLicenseFilename(media_id_->group_id(),
media_id_->provider_id());
} else {
filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
}
StoreFile(*file_system_, filename, device_file);
// license_id will be the filename without ".lic" extension.
license_id = filename.substr(0,
filename.size() - std::string(".lic").size());
std::string filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
StoreFile(*file_system_, filename, device_file);
// license_id will be the filename without ".lic" extension.
license_id =
filename.substr(0, filename.size() - std::string(".lic").size());
}
return CasStatusCode::kNoError;
}
CasStatus WidevineCas::RemoveLicense(const std::string file_name) {
// Check if the license is in use. If it is, besides removing the license,
// update policy in current license. Else, we just directly remove it.
if (nullptr == media_id_.get() ) {
return CasStatus(CasStatusCode::kCasLicenseError, "No media id");
if (nullptr == media_id_.get()) {
return CasStatus(CasStatusCode::kCasLicenseError, "No media id");
}
// Remove the license file given the file_name user provides.
if (!RemoveFile(*file_system_, file_name)) {
return CasStatus(CasStatusCode::kInvalidLicenseFile,
return CasStatus(CasStatusCode::kInvalidLicenseFile,
"unable to remove license file from disk");
}
LOGI("Remove license file from disk successfully.");
std::string used_license_filename;
if (media_id_->group_ids_size() > 0) {
used_license_filename = GenerateLicenseFilename(media_id_->group_id(),
media_id_->provider_id());
} else {
used_license_filename = GenerateLicenseFilename(media_id_->content_id(),
media_id_->provider_id());
}
std::string used_license_filename = GenerateLicenseFilename(
media_id_->content_id(), media_id_->provider_id());
if (file_name.compare(used_license_filename) == 0) {
// Update license policy for the in-used license. Plugin will not allowed to
// play stream, store and renew license unless a new plugin instance is created.
// play stream, store and renew license unless a new plugin instance is
// created.
std::unique_lock<std::mutex> locker(lock_);
cas_license_->UpdateLicenseForLicenseRemove();
}
@@ -479,7 +446,7 @@ CasStatus WidevineCas::ProcessCAPrivateData(const CasData& private_data,
return CasStatus(CasStatusCode::kInvalidParameter,
"missing output buffer for init_data");
}
// Parse provider, content id and group id from CA descriptor.
// Parse provider and content id from CA descriptor.
video_widevine::CaDescriptorPrivateData descriptor;
descriptor.ParseFromArray(private_data.data(), private_data.size());
if (!descriptor.has_content_id() || !descriptor.has_provider()) {
@@ -491,10 +458,6 @@ CasStatus WidevineCas::ProcessCAPrivateData(const CasData& private_data,
video_widevine::WidevinePsshData pssh;
pssh.set_provider(descriptor.provider());
pssh.set_content_id(descriptor.content_id());
// group id is optional in ca_descriptor.
if (descriptor.has_group_id()) {
pssh.add_group_ids(descriptor.group_id());
}
pssh.set_type(video_widevine::WidevinePsshData::ENTITLEMENT);
pssh.SerializeToString(init_data);
return CasStatusCode::kNoError;