Fix media_cas_proxy_sdk build issue.

Add example binary for testing building the SDK after 'git clone' from our repo.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=227583629
This commit is contained in:
Fang Yu
2019-01-02 14:37:34 -08:00
parent a991e2dbb3
commit 79f14e6e0b
76 changed files with 2072 additions and 1513 deletions

View File

@@ -23,7 +23,7 @@ cc_library(
"wvpl_types.h",
],
deps = [
"//util:status",
"//common:status",
],
)
@@ -40,12 +40,13 @@ cc_library(
# TODO(user): Refactor these deps as classes that derive from WvPLSDKSession may not rely on license SDK(s).
":wvpl_types",
"//base",
"//util:status",
"@abseil_repo//absl/memory",
"//common:client_cert",
"//common:error_space",
"//common:remote_attestation_verifier",
"//common:drm_root_certificate",
"//common:drm_service_certificate",
"//common:error_space",
"//common:remote_attestation_verifier",
"//common:status",
"//common:verified_media_pipeline",
"//license_server_sdk/internal:sdk",
"//protos/public:client_identification_proto",
@@ -54,6 +55,7 @@ cc_library(
"//protos/public:license_protocol_proto",
"//protos/public:license_server_sdk_proto",
"//protos/public:provisioned_device_info_proto",
"//protos/public:widevine_pssh_proto",
],
)
@@ -71,13 +73,13 @@ cc_library(
"//base",
"@abseil_repo//absl/strings",
"@abseil_repo//absl/synchronization",
"//util:status",
"//common:aes_cbc_util",
"//common:device_status_list",
"//common:drm_root_certificate",
"//common:error_space",
"//common:drm_service_certificate",
"//common:sha_util",
"//common:status",
"//license_server_sdk/internal:sdk",
"//protos/public:device_certificate_status_proto",
"//protos/public:errors_proto",
@@ -96,9 +98,9 @@ cc_library(
deps = [
":wvpl_types",
"//base",
"@abseil_repo//absl/memory",
"@abseil_repo//absl/strings",
"@abseil_repo//absl/synchronization",
"//util:status",
"//common:aes_cbc_util",
"//common:client_cert",
"//common:device_status_list",
@@ -107,6 +109,7 @@ cc_library(
"//common:error_space",
"//common:remote_attestation_verifier",
"//common:sha_util",
"//common:status",
"//common:verified_media_pipeline",
"//license_server_sdk/internal:sdk",
"//protos/public:client_identification_proto",
@@ -115,5 +118,6 @@ cc_library(
"//protos/public:license_protocol_proto",
"//protos/public:license_server_sdk_proto",
"//protos/public:provisioned_device_info_proto",
"//protos/public:widevine_pssh_proto",
],
)

View File

@@ -10,16 +10,15 @@
#include "glog/logging.h"
#include "absl/strings/escaping.h"
#include "absl/synchronization/mutex.h"
#include "util/status.h"
#include "common/aes_cbc_util.h"
#include "common/device_status_list.h"
#include "common/drm_service_certificate.h"
#include "common/error_space.h"
#include "common/sha_util.h"
#include "common/status.h"
#include "license_server_sdk/internal/generate_error_response.h"
#include "protos/public/errors.pb.h"
namespace util = widevine::util;
using widevine::DeviceCertificateStatus;
using widevine::DeviceCertificateStatusList;
using widevine::DeviceStatusList;
@@ -32,6 +31,8 @@ using widevine::ProvisionedDeviceInfo;
using widevine::SignedDeviceCertificateStatusList;
using widevine::crypto_util::EncryptAesCbc;
namespace error = widevine::error;
namespace widevine_server {
namespace wv_pl_sdk {
@@ -93,9 +94,9 @@ bool WvPLSDKEnvironment::GenerateErrorResponse(
WvPLStatus WvPLSDKEnvironment::LookupDeviceInfo(
uint32_t system_id, ProvisionedDeviceInfo* provisioned_device_info) {
WvPLStatus status = util::OkStatus();
WvPLStatus status;
if (provisioned_device_info == nullptr) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"provisioned_device_info should not be null");
}
const ProvisionedDeviceInfoMap& device_info_map =
@@ -114,7 +115,7 @@ WvPLStatus WvPLSDKEnvironment::LookupDeviceInfo(
WvPLStatus WvPLSDKEnvironment::UpdateProvisionedDeviceInfoMap(
const DeviceCertificateStatusList& certificate_status_list) {
WvPLStatus status = util::OkStatus();
WvPLStatus status;
for (const DeviceCertificateStatus& cert_status :
certificate_status_list.certificate_status()) {
if (cert_status.has_device_info()) {
@@ -145,11 +146,11 @@ WvPLStatus WvPLSDKEnvironment::GenerateSignature(const std::string& plain_text,
std::string* signature) {
DCHECK(signature);
if (plain_text.empty()) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"Plain_text for signature is empty.");
}
if (signature == nullptr) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"Signature must not be null.");
}
const std::map<std::string, std::string>* config_values = GetConfigValue();
@@ -161,31 +162,30 @@ WvPLStatus WvPLSDKEnvironment::GenerateSignature(const std::string& plain_text,
if (it != config_values->end()) {
provider_iv = absl::HexStringToBytes((*it).second);
if (provider_iv.empty()) {
return WvPLStatus(error_space, util::error::NOT_FOUND,
"Provider IV is empty.");
return WvPLStatus(error_space, error::NOT_FOUND, "Provider IV is empty.");
}
}
it = config_values->find(kProviderKey);
if (it != config_values->end()) {
provider_key = absl::HexStringToBytes((*it).second);
if (provider_key.empty()) {
return WvPLStatus(error_space, util::error::NOT_FOUND,
return WvPLStatus(error_space, error::NOT_FOUND,
"Provider Key is empty.");
}
}
std::string hashed_text = widevine::Sha1_Hash(plain_text);
if (hashed_text.empty()) {
return util::Status(error_space, util::error::INVALID_ARGUMENT,
"Hash for signature is empty.");
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"Hash for signature is empty.");
} else {
*signature = EncryptAesCbc(provider_key, provider_iv, hashed_text);
if (signature->empty()) {
return util::Status(error_space, util::error::INVALID_ARGUMENT,
"Generated signature failed");
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"Generated signature failed");
}
}
return util::OkStatus();
return WvPLStatus();
}
std::map<std::string, std::string>* WvPLSDKEnvironment::config_values_ =
new std::map<std::string, std::string>();
@@ -200,7 +200,7 @@ void WvPLSDKEnvironment::SetConfigValue(
WvPLStatus WvPLSDKEnvironment::SetDeviceCertificateStatusList(
const std::string& cert_list) const {
WvPLStatus status = util::OkStatus();
WvPLStatus status;
SignedDeviceCertificateStatusList device_certificate_status_list;
std::string decoded_certificate_status_list;
std::string device_certicate_status_list;
@@ -210,9 +210,9 @@ WvPLStatus WvPLSDKEnvironment::SetDeviceCertificateStatusList(
if (!status.ok()) return status;
DeviceCertificateStatusList certificate_status_list;
if (!certificate_status_list.ParseFromString(device_certicate_status_list)) {
return util::Status(error_space,
widevine::INVALID_CERTIFICATE_STATUS_LIST,
"certificate status list parse error");
return WvPLStatus(error_space,
widevine::INVALID_CERTIFICATE_STATUS_LIST,
"certificate status list parse error");
}
status = DeviceStatusList::Instance()->UpdateStatusList(
drm_root_certificate_->public_key(), decoded_certificate_status_list,

View File

@@ -8,21 +8,24 @@
#include "sdk/external/common/wvpl/wvpl_sdk_session.h"
#include "glog/logging.h"
#include "util/status.h"
#include "absl/memory/memory.h"
#include "common/client_cert.h"
#include "common/drm_service_certificate.h"
#include "common/error_space.h"
#include "common/remote_attestation_verifier.h"
#include "common/status.h"
#include "common/verified_media_pipeline.h"
#include "license_server_sdk/internal/parse_content_id.h"
#include "sdk/external/common/wvpl/wvpl_sdk_environment.h"
#include "sdk/external/common/wvpl/wvpl_types.h"
#include "protos/public/errors.pb.h"
#include "protos/public/license_protocol.pb.h"
#include "protos/public/provisioned_device_info.pb.h"
#include "protos/public/widevine_pssh.pb.h"
// TODO(user): Mark getProvisionedDeviceInfo as deprecated, move the
// implementation of isChromeCDM, getcontentid, parsePsshdata in wvpl_session
// and wvpl_proxy_session to base class.
// implementation of isChromeCDM in wvpl_session and wvpl_proxy_session to base
// class.
// TODO(user): Set SerialNumber and ServiceId field of WvPLDeviceInfo in
// getDeviceInfo function.
// TODO(user): Move the related Copy* function test cases to
@@ -31,23 +34,27 @@
// signed_message_request_from_cdm_ when create session.
// TODO(user): Move all the protected memeber variables to private and use
// getter and setter to access it.
// TODO(user): Try to avoid virtual private function like parsepsshdata.
// TODO(user): (b/119566765) Refactor ParseLicenseRequest and break it into
// different classes.
namespace util = widevine::util;
using widevine::ClientCert;
using widevine::ClientIdentification;
using widevine::ContentInfo;
using widevine::DrmRootCertificate;
using widevine::DrmServiceCertificate;
using widevine::error_space;
using widevine::KeyboxClientCert;
using widevine::License;
using widevine::LicenseRequest;
using widevine::LicenseType;
using widevine::OkStatus;
using widevine::ProvisionedDeviceInfo;
using widevine::RemoteAttestationVerifier;
using widevine::SessionInit;
using widevine::SignedMessage;
using widevine::WidevinePsshData;
namespace error = widevine::error;
namespace widevine_server {
namespace wv_pl_sdk {
@@ -59,7 +66,7 @@ WvPLSDKSession::~WvPLSDKSession() {}
WvPLStatus WvPLSDKSession::AddKey(const WvPLKey& key) {
keys_.push_back(key);
return util::OkStatus();
return OkStatus();
}
void WvPLSDKSession::CopyPlaybackPolicy(const WvPLPlaybackPolicy& wvpl_policy,
@@ -227,6 +234,11 @@ void WvPLSDKSession::CopyHDCP(
output_protection->set_hdcp(
License::KeyContainer::OutputProtection::HDCP_NONE);
break;
case HDCP_NO_DIGITAL_OUTPUT:
output_protection->set_hdcp(
License::KeyContainer::OutputProtection::HDCP_NO_DIGITAL_OUTPUT);
output_protection->set_disable_digital_output(true);
break;
default:
break;
}
@@ -306,23 +318,40 @@ void WvPLSDKSession::CopyOutputProtection(
CopyHDCP(wvpl_key.output_protection().hdcp(),
sdk_key_container->mutable_required_protection());
// Transfer HDCP from requested output protection value.
CopyHDCP(wvpl_key.requested_output_protection().hdcp(),
sdk_key_container->mutable_requested_protection());
CopySecurityLevel(wvpl_key.output_protection(), wvpl_key.track_type(),
sdk_key_container);
sdk_key_container->mutable_requested_protection()->set_disable_analog_output(
sdk_key_container->mutable_required_protection()->set_disable_analog_output(
wvpl_key.output_protection().disable_analog_output());
sdk_key_container->mutable_required_protection()->set_disable_digital_output(
wvpl_key.output_protection().disable_digital_output());
if (wvpl_key.output_protection().disable_digital_output()) {
sdk_key_container->mutable_required_protection()->set_hdcp(
License::KeyContainer::OutputProtection::HDCP_NO_DIGITAL_OUTPUT);
}
CopyCGMS(wvpl_key.output_protection().cgms(),
sdk_key_container->mutable_requested_protection());
// Transfer HDCP from requested output protection value.
CopyCGMS(wvpl_key.output_protection().cgms(),
sdk_key_container->mutable_required_protection());
if (wvpl_key.requested_output_protection().hdcp() != HDCP_NONE) {
CopyHDCP(wvpl_key.requested_output_protection().hdcp(),
sdk_key_container->mutable_requested_protection());
}
if (wvpl_key.requested_output_protection().disable_analog_output()) {
sdk_key_container->mutable_requested_protection()
->set_disable_analog_output(
wvpl_key.requested_output_protection().disable_analog_output());
}
if (wvpl_key.requested_output_protection().disable_digital_output()) {
sdk_key_container->mutable_requested_protection()->set_hdcp(
License::KeyContainer::OutputProtection::HDCP_NO_DIGITAL_OUTPUT);
}
if (wvpl_key.requested_output_protection().cgms() != CGMS_NONE) {
CopyCGMS(wvpl_key.requested_output_protection().cgms(),
sdk_key_container->mutable_requested_protection());
}
// Transfer Video resultion constraints.
const std::vector<WvPLVideoResolutionConstraint>& video_constraints =
wvpl_key.video_resolution_constraints();
@@ -400,7 +429,7 @@ void WvPLSDKSession::CopyProvisionedDeviceInfo(
}
WvPLStatus WvPLSDKSession::ParseLicenseRequest() {
WvPLStatus status = util::OkStatus();
WvPLStatus status;
if (license_request_from_cdm_.empty() && sdk_license_request_ == nullptr) {
return WvPLStatus(error_space, widevine::SIGNED_MESSAGE_PARSE_ERROR,
"License request from cdm is empty or null");
@@ -491,7 +520,7 @@ WvPLStatus WvPLSDKSession::ParseLicenseRequest() {
}
request_type_ = sdk_license_request_->type();
}
return util::OkStatus();
return OkStatus();
}
bool WvPLSDKSession::IsChromeCDM() const {
@@ -503,9 +532,9 @@ bool WvPLSDKSession::IsChromeCDM() const {
}
WvPLStatus WvPLSDKSession::GetClientInfo(WvPLClientInfo* client_info) const {
WvPLStatus status = util::OkStatus();
WvPLStatus status;
if (client_info == nullptr) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"client_info is NULL");
}
if (!has_client_id_) {
@@ -557,11 +586,11 @@ WvPLStatus WvPLSDKSession::GetClientInfo(WvPLClientInfo* client_info) const {
WvPLStatus WvPLSDKSession::VerifyRemoteAttestation() {
DCHECK(signed_message_request_from_cdm_);
if (!signed_message_request_from_cdm_->has_remote_attestation()) {
return WvPLStatus(error_space, util::error::INTERNAL,
return WvPLStatus(error_space, error::INTERNAL,
"Remote Attestation not specified");
} else if (!signed_message_request_from_cdm_->remote_attestation()
.has_certificate()) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"Remote Attestation Certificate not specified");
} else {
WvPLStatus ra_status =
@@ -570,14 +599,14 @@ WvPLStatus WvPLSDKSession::VerifyRemoteAttestation() {
signed_message_request_from_cdm_->remote_attestation(),
&remote_attestation_cert_serial_number_);
}
return util::OkStatus();
return OkStatus();
}
WvPLStatus WvPLSDKSession::GetClientCapabilities(
WvPLClientCapabilities* client_capabilities) const {
WvPLStatus status = util::OkStatus();
WvPLStatus status;
if (client_capabilities == nullptr) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"client_capabilities is NULL");
}
if (!has_client_id_) {
@@ -592,9 +621,9 @@ WvPLStatus WvPLSDKSession::GetClientCapabilities(
WvPLStatus WvPLSDKSession::GetWvPLClientCapabilities(
const widevine::ClientIdentification& client_id,
WvPLClientCapabilities* client_capabilities) const {
WvPLStatus status = util::OkStatus();
WvPLStatus status;
if (client_capabilities == nullptr) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"client_capabilities is NULL");
}
@@ -653,22 +682,86 @@ WvPLStatus WvPLSDKSession::GetPsshData(
WvPLWidevinePsshData* wvpl_widevine_pssh_data) const {
DCHECK(wvpl_widevine_pssh_data);
if (wvpl_widevine_pssh_data == nullptr) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"wvpl_widevine_pssh_data is null");
}
if (!has_pssh_data_) {
// TODO(b/115784237): Fix calling ParsePsshData within base class.
WvPLStatus status = ParsePsshData(wvpl_widevine_pssh_data);
return status;
DCHECK(sdk_license_request_);
if (sdk_license_request_ == nullptr) {
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"sdk_license_request_ is null");
}
if (request_type() == LicenseRequest::NEW) {
ContentInfo content_info;
WvPLStatus status = widevine::ParseContentId(
sdk_license_request_->content_id(), &content_info);
if (!status.ok()) {
return WvPLStatus(error_space, error::INTERNAL,
"Failed to get pssh data. GetContentInfo() failed.");
}
if (content_info.content_info_entry().empty()) {
return WvPLStatus(error_space, error::INTERNAL,
"Failed to get pssh data. ContentInfo is empty.");
}
WidevinePsshData wv_pssh;
if (content_info.init_data_type() ==
LicenseRequest::ContentIdentification::InitData::CENC) {
for (size_t i = 0; i < content_info.content_info_entry().size(); ++i) {
if (!content_info.content_info_entry(i).has_pssh()) {
return WvPLStatus(error_space,
widevine::INVALID_WIDEVINE_PSSH_DATA,
"wvpl_widevine_pssh_data is empty");
}
if (content_info.content_info_entry(i).pssh().has_widevine_data()) {
wv_pssh = content_info.content_info_entry(i).pssh().widevine_data();
}
if (wv_pssh.has_content_id()) {
wvpl_widevine_pssh_data->set_content_id(wv_pssh.content_id());
}
for (int idx = 0; idx < wv_pssh.key_ids().size(); ++idx) {
wvpl_widevine_pssh_data->set_key_id(wv_pssh.key_ids(idx));
}
for (int idx = 0; idx < wv_pssh.entitled_keys().size(); ++idx) {
WvPLEntitledKey wvpl_entitled_key;
wvpl_entitled_key.set_entitlement_key_id(
wv_pssh.entitled_keys(idx).entitlement_key_id());
wvpl_entitled_key.set_key_id(wv_pssh.entitled_keys(idx).key_id());
wvpl_entitled_key.set_key_bytes(wv_pssh.entitled_keys(idx).key());
wvpl_entitled_key.set_entitlement_key_iv(
wv_pssh.entitled_keys(idx).iv());
wvpl_entitled_key.set_entitlement_key_size_bytes(
wv_pssh.entitled_keys(idx).entitlement_key_size_bytes());
wvpl_widevine_pssh_data->add_entitled_key(wvpl_entitled_key);
}
}
return status;
} else if (content_info.init_data_type() ==
LicenseRequest::ContentIdentification::InitData::WEBM) {
for (size_t i = 0; i < content_info.content_info_entry().size(); ++i) {
for (int idx = 0;
idx < content_info.content_info_entry(i).key_ids().size();
++idx) {
wvpl_widevine_pssh_data->set_key_id(
content_info.content_info_entry(i).key_ids(idx));
}
}
} else {
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"Failed to get pssh data. Widevine PSSH not found.");
}
}
// A PSSH with the widevine header wasn't found, so return error.
return WvPLStatus(error_space, error::NOT_FOUND,
"Failed to get pssh data. Widevine PSSH not found.");
}
*wvpl_widevine_pssh_data = pssh_data_;
return util::OkStatus();
return OkStatus();
}
WvPLStatus WvPLSDKSession::GetDeviceInfo(WvPLDeviceInfo* device_info) const {
WvPLStatus status = util::OkStatus();
WvPLStatus status;
if (device_info == nullptr) {
return WvPLStatus(error_space, util::error::INVALID_ARGUMENT,
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"device_info is NULL");
}
if (!HasSystemId()) {
@@ -733,5 +826,31 @@ uint32_t WvPLSDKSession::GetSystemId() const {
CHECK(system_id_);
return *system_id_;
}
bool WvPLSDKSession::is_offline_license() const {
DCHECK(sdk_license_request_);
if (sdk_license_request_ == nullptr) return false;
if (!sdk_license_request_->has_content_id()) return false;
const LicenseRequest::ContentIdentification& content_id =
sdk_license_request_->content_id();
if (content_id.has_init_data()) {
return content_id.init_data().license_type() == widevine::OFFLINE;
}
if (content_id.has_cenc_id_deprecated()) {
return content_id.cenc_id_deprecated().license_type() ==
widevine::OFFLINE;
}
if (content_id.has_webm_id_deprecated()) {
return content_id.webm_id_deprecated().license_type() ==
widevine::OFFLINE;
}
if (content_id.has_existing_license()) {
return content_id.existing_license().license_id().type() ==
widevine::OFFLINE;
}
return false;
}
} // namespace wv_pl_sdk
} // namespace widevine_server

View File

@@ -105,6 +105,13 @@ class WvPLSDKSession {
return request_type_;
}
/**
* Returns true if the license type is offline, otherwise return false.
*
* @return bool.
*/
virtual bool is_offline_license() const;
protected:
const widevine::DrmRootCertificate* drm_root_certificate_;
std::string user_agent_;
@@ -206,14 +213,6 @@ class WvPLSDKSession {
private:
std::unique_ptr<uint32_t> system_id_;
/**
* Parses WvPLWidevinePsshData in the new license request.
*
* @return WvPLStatus - Status::OK if success, else error.
*/
virtual WvPLStatus ParsePsshData(
WvPLWidevinePsshData* wvpl_widevine_pssh_data) const = 0;
};
} // namespace wv_pl_sdk

View File

@@ -15,7 +15,7 @@
#include <memory>
#include <vector>
#include "util/status.h"
#include "common/status.h"
// TODO(user) Split wvpl_types.h into wvpl_common_types.h ,
// wvpl_license_sdk_types.h, wvpl_proxy_sdk_types.h and
@@ -23,7 +23,7 @@
namespace widevine_server {
namespace wv_pl_sdk {
typedef widevine::util::Status WvPLStatus;
typedef widevine::Status WvPLStatus;
typedef uint32_t uint32_t;
typedef int64_t int64_t;