Add a function named has_encrypted_client_id() check.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=231629247
This commit is contained in:
Fang Yu
2019-01-30 11:07:03 -08:00
parent f234dd036d
commit 1a4cad05a2
23 changed files with 572 additions and 166 deletions

View File

@@ -80,6 +80,7 @@ cc_library(
"//common:drm_service_certificate",
"//common:sha_util",
"//common:status",
"//common:vmp_checker",
"//license_server_sdk/internal:sdk",
"//protos/public:device_certificate_status_proto",
"//protos/public:errors_proto",
@@ -111,6 +112,7 @@ cc_library(
"//common:sha_util",
"//common:status",
"//common:verified_media_pipeline",
"//common:vmp_checker",
"//license_server_sdk/internal:sdk",
"//protos/public:client_identification_proto",
"//protos/public:device_certificate_status_proto",

View File

@@ -17,6 +17,7 @@
#include "common/error_space.h"
#include "common/sha_util.h"
#include "common/status.h"
#include "common/vmp_checker.h"
#include "license_server_sdk/internal/generate_error_response.h"
#include "protos/public/device_certificate_status.pb.h"
#include "protos/public/errors.pb.h"
@@ -32,6 +33,7 @@ using widevine::kCertificateTypeProduction;
using widevine::kCertificateTypeTesting;
using widevine::ProvisionedDeviceInfo;
using widevine::SignedDeviceCertificateStatusList;
using widevine::VmpChecker;
using widevine::crypto_util::EncryptAesCbc;
namespace error = widevine::error;
@@ -89,7 +91,8 @@ WvPLStatus WvPLSDKEnvironment::SetDrmServiceCertificate(
if (wvpl_status.ok()) {
is_service_certificate_loaded_ = true;
}
return wvpl_status;
return VmpChecker::Instance()->SelectCertificateType(
drm_root_certificate()->type());
}
bool WvPLSDKEnvironment::GenerateErrorResponse(

View File

@@ -127,7 +127,9 @@ class WvPLSDKEnvironment {
const widevine::ProvisionedDeviceInfo& provisioned_device_info);
static std::map<std::string, std::string>* GetConfigValue();
friend class WvPLSDKSession;
friend class WvPLProxySession;
friend class WvPLProxySessionTest;
friend class WvPLSessionTest;
};

View File

@@ -58,6 +58,58 @@ using widevine::WidevinePsshData;
namespace error = widevine::error;
namespace {
void CopyHdcpSrmRule(
widevine_server::wv_pl_sdk::HdcpSrmRule hdcp_srm_rule,
License::KeyContainer::OutputProtection* output_protection) {
DCHECK(output_protection);
if (output_protection == nullptr) {
return;
}
switch (hdcp_srm_rule) {
case widevine_server::wv_pl_sdk::HDCP_SRM_RULE_NONE:
output_protection->set_hdcp_srm_rule(
License::KeyContainer::OutputProtection::HDCP_SRM_RULE_NONE);
break;
case widevine_server::wv_pl_sdk::CURRENT_SRM:
output_protection->set_hdcp_srm_rule(
License::KeyContainer::OutputProtection::CURRENT_SRM);
break;
default:
break;
}
}
// Copy the |cgms_value| into the key container.
void CopyCGMS(widevine_server::wv_pl_sdk::CGMS cgms_value,
License::KeyContainer::OutputProtection* output_protection) {
DCHECK(output_protection);
if (output_protection == nullptr) {
return;
}
switch (cgms_value) {
case widevine_server::wv_pl_sdk::CGMS_NONE:
output_protection->set_cgms_flags(
License::KeyContainer::OutputProtection::CGMS_NONE);
break;
case widevine_server::wv_pl_sdk::COPY_FREE:
output_protection->set_cgms_flags(
License::KeyContainer::OutputProtection::COPY_FREE);
break;
case widevine_server::wv_pl_sdk::COPY_ONCE:
output_protection->set_cgms_flags(
License::KeyContainer::OutputProtection::COPY_ONCE);
break;
case widevine_server::wv_pl_sdk::COPY_NEVER:
output_protection->set_cgms_flags(
License::KeyContainer::OutputProtection::COPY_NEVER);
break;
default:
break;
}
}
} // namespace
namespace widevine_server {
namespace wv_pl_sdk {
namespace {
@@ -224,6 +276,10 @@ void WvPLSDKSession::CopySessionState(
if (session_state == nullptr) {
return;
}
if (!has_session_state_) {
// Do not populate SessionState protobuf if WvPLSessionState was not set.
return;
}
if (wvpl_session_state.license_counter() > 0) {
session_state->set_license_counter(wvpl_session_state.license_counter());
}
@@ -315,49 +371,64 @@ void WvPLSDKSession::CopyHDCP(
}
void WvPLSDKSession::CopyOutputProtection(
const WvPLKey& wvpl_key, License::KeyContainer* sdk_key_container) {
DCHECK(sdk_key_container);
if (!sdk_key_container) {
return;
}
const WvPLOutputProtection& wvpl_output_protection,
License::KeyContainer::OutputProtection* output_protection) {
// Transfer HDCP from required output protection value.
CopyHDCP(wvpl_key.output_protection().hdcp(),
sdk_key_container->mutable_required_protection());
CopyHDCP(wvpl_output_protection.hdcp(), output_protection);
CopySecurityLevel(wvpl_key.output_protection(), wvpl_key.track_type(),
sdk_key_container);
output_protection->set_disable_analog_output(
wvpl_output_protection.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(
if (wvpl_output_protection.disable_digital_output()) {
output_protection->set_hdcp(
License::KeyContainer::OutputProtection::HDCP_NO_DIGITAL_OUTPUT);
}
// 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());
CopyCGMS(wvpl_output_protection.cgms(), output_protection);
CopyHdcpSrmRule(wvpl_output_protection.hdcp_srm_rule(), output_protection);
if (wvpl_output_protection.hdcp() != HDCP_NONE) {
CopyHDCP(wvpl_output_protection.hdcp(), output_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_output_protection.disable_analog_output()) {
output_protection->set_disable_analog_output(
wvpl_output_protection.disable_analog_output());
}
if (wvpl_key.requested_output_protection().disable_digital_output()) {
sdk_key_container->mutable_requested_protection()->set_hdcp(
if (wvpl_output_protection.disable_digital_output()) {
output_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());
if (wvpl_output_protection.cgms() != CGMS_NONE) {
CopyCGMS(wvpl_output_protection.cgms(), output_protection);
}
}
void WvPLSDKSession::CopyKey(const WvPLKey& wvpl_key,
License::KeyContainer* sdk_key_container) {
DCHECK(sdk_key_container);
if (!sdk_key_container) {
return;
}
sdk_key_container->set_id(wvpl_key.key_id());
sdk_key_container->set_key(wvpl_key.key_bytes());
switch (wvpl_key.key_type()) {
case CONTENT:
sdk_key_container->set_type(License::KeyContainer::CONTENT);
break;
case ENTITLEMENT:
sdk_key_container->set_type(License::KeyContainer::ENTITLEMENT);
break;
default:
break;
}
CopySecurityLevel(wvpl_key.output_protection(), wvpl_key.track_type(),
sdk_key_container);
CopyOutputProtection(wvpl_key.output_protection(),
sdk_key_container->mutable_required_protection());
CopyOutputProtection(wvpl_key.requested_output_protection(),
sdk_key_container->mutable_requested_protection());
// Transfer Video resultion constraints.
const std::vector<WvPLVideoResolutionConstraint>& video_constraints =
wvpl_key.video_resolution_constraints();
@@ -372,35 +443,6 @@ void WvPLSDKSession::CopyOutputProtection(
}
}
void WvPLSDKSession::CopyCGMS(
CGMS cgms_value,
License::KeyContainer::OutputProtection* output_protection) {
DCHECK(output_protection);
if (output_protection == nullptr) {
return;
}
switch (cgms_value) {
case CGMS_NONE:
output_protection->set_cgms_flags(
License::KeyContainer::OutputProtection::CGMS_NONE);
break;
case COPY_FREE:
output_protection->set_cgms_flags(
License::KeyContainer::OutputProtection::COPY_FREE);
break;
case COPY_ONCE:
output_protection->set_cgms_flags(
License::KeyContainer::OutputProtection::COPY_ONCE);
break;
case COPY_NEVER:
output_protection->set_cgms_flags(
License::KeyContainer::OutputProtection::COPY_NEVER);
break;
default:
break;
}
}
void WvPLSDKSession::CopyProvisionedDeviceInfo(
const WvPLDeviceInfo& wvpl_device_info,
widevine::ProvisionedDeviceInfo* device_info) {
@@ -454,6 +496,8 @@ WvPLStatus WvPLSDKSession::ParseLicenseRequest() {
if (signed_message_request_from_cdm_ != nullptr) {
switch (signed_message_request_from_cdm_->type()) {
case SignedMessage::LICENSE_REQUEST:
// TODO(user): Add CAS enum(s) to message_type_ in wvpl_types.h.
case SignedMessage::CAS_LICENSE_REQUEST:
message_type_ = LICENSE_REQUEST;
DCHECK(signed_message_request_from_cdm_);
sdk_license_request_ = absl::make_unique<LicenseRequest>();
@@ -497,6 +541,7 @@ WvPLStatus WvPLSDKSession::ParseLicenseRequest() {
"Unable to decrypt EncryptedClientIdentification in "
"the license request");
}
has_encrypted_client_id_ = true;
has_client_id_ = true;
}
if (client_id_->has_token() &&
@@ -526,8 +571,20 @@ WvPLStatus WvPLSDKSession::ParseLicenseRequest() {
has_pssh_data_ = true;
}
}
request_type_ =
static_cast<LicenseRequestType>(sdk_license_request_->type());
switch (sdk_license_request_->type()) {
case LicenseRequest::NEW:
request_type_ = LicenseRequestType::NEW;
break;
case LicenseRequest::RENEWAL:
request_type_ = LicenseRequestType::RENEWAL;
break;
case LicenseRequest::RELEASE:
request_type_ = LicenseRequestType::RELEASE;
break;
default:
request_type_ = LicenseRequestType::REQUEST_TYPE_UNSPECIFIED;
break;
}
}
return OkStatus();
}
@@ -551,6 +608,7 @@ WvPLStatus WvPLSDKSession::GetClientInfo(WvPLClientInfo* client_info) const {
error_space, widevine::MISSING_CLIENT_ID,
"ClientIdentification is not found in the license request");
}
switch (client_id_->client_capabilities().max_hdcp_version()) {
case ClientIdentification::ClientCapabilities::HDCP_NONE:
client_info->set_max_hdcp_version(HDCP_NONE);
@@ -607,8 +665,20 @@ WvPLStatus WvPLSDKSession::VerifyRemoteAttestation() {
signed_message_request_from_cdm_->msg(),
signed_message_request_from_cdm_->remote_attestation(),
&remote_attestation_cert_serial_number_);
if (!ra_status.ok()) {
if (ra_status.error_message().find(
"remote-attestation-client-id-decrypt-failed") != std::string::npos) {
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"Remote Attestation Certificate decryption failed");
}
return ra_status;
}
if (remote_attestation_cert_serial_number_.empty()) {
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"remote_attestation_cert_serial_number is empty");
}
return OkStatus();
}
return OkStatus();
}
WvPLStatus WvPLSDKSession::GetClientCapabilities(
@@ -700,7 +770,7 @@ WvPLStatus WvPLSDKSession::GetPsshData(
return WvPLStatus(error_space, error::INVALID_ARGUMENT,
"sdk_license_request_ is null");
}
if (request_type() == LicenseRequestType::NEW) {
if (sdk_license_request_->type() == LicenseRequest::NEW) {
ContentInfo content_info;
WvPLStatus status = widevine::ParseContentId(
sdk_license_request_->content_id(), &content_info);
@@ -754,14 +824,12 @@ WvPLStatus WvPLSDKSession::GetPsshData(
content_info.content_info_entry(i).key_ids(idx));
}
}
return status;
} 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 OkStatus();
@@ -836,6 +904,20 @@ uint32_t WvPLSDKSession::GetSystemId() const {
return *system_id_;
}
std::string WvPLSDKSession::session_id() const {
DCHECK(sdk_license_request_);
const LicenseRequest::ContentIdentification& content_id =
sdk_license_request_->content_id();
if (content_id.existing_license().license_id().has_session_id())
return content_id.existing_license().license_id().session_id();
else if (content_id.has_widevine_pssh_data())
return content_id.widevine_pssh_data().request_id();
else if (content_id.has_webm_key_id())
return content_id.webm_key_id().request_id();
else
return std::string();
}
bool WvPLSDKSession::is_offline_license() const {
DCHECK(sdk_license_request_);
if (sdk_license_request_ == nullptr) return false;
@@ -846,13 +928,12 @@ bool WvPLSDKSession::is_offline_license() const {
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() ==
if (content_id.has_widevine_pssh_data()) {
return content_id.widevine_pssh_data().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_webm_key_id()) {
return content_id.webm_key_id().license_type() == widevine::OFFLINE;
}
if (content_id.has_existing_license()) {
return content_id.existing_license().license_id().type() ==

View File

@@ -113,6 +113,39 @@ class WvPLSDKSession {
*/
virtual bool is_offline_license() const;
/**
* A session id that remains constant throughout a session. All license
* and heartbeat requests in a session have the same session id.
*
* @return string.
*/
virtual std::string session_id() const;
/**
* Returns the license request contains client id or not.
*
* @return bool.
*/
virtual bool has_client_id() const { return has_client_id_; }
/**
* Returns true if remote_attestation_cert_serial_number is not empty.
* Otherwise return false.
*
* @return bool.
*/
virtual bool remote_attestation_verified() {
return !remote_attestation_cert_serial_number_.empty();
}
/**
* Returns true if license request has encrypted_client_id. Otherwise return
* false.
*
* @return bool.
*/
virtual bool has_encrypted_client_id() { return has_encrypted_client_id_; }
protected:
const widevine::DrmRootCertificate* drm_root_certificate_;
std::string user_agent_;
@@ -132,6 +165,9 @@ class WvPLSDKSession {
std::string remote_attestation_cert_serial_number_;
std::unique_ptr<widevine::LicenseRequest> sdk_license_request_;
LicenseRequestType request_type_;
bool has_session_state_ = false;
bool has_encrypted_client_id_ = false;
virtual WvPLStatus VerifyRemoteAttestation();
// Returns the WvPL Client Capabilities information for the license request
@@ -140,11 +176,25 @@ class WvPLSDKSession {
const widevine::ClientIdentification& client_id,
WvPLClientCapabilities* client_capabilities) const;
// Copies/translates the output protection from a WvPL Key into an SDK
// Copy and translates the Key fields from a WvPL Key into an SDK
// key container.
// Copies
// (1) key id
// (2) key
// (3) video_resolution_constraints
// (4) output protection using CopyOutputProtection
// (5) security_level using CopySecurityLevel
// Translates
// (1) key type
void CopyKey(const WvPLKey& wvpl_key,
widevine::License_KeyContainer* sdk_key_container);
// Copies/translates output_protection in WvPL Key into an SDK key container.
void CopyOutputProtection(
const WvPLKey& wvpl_key,
widevine::License_KeyContainer* sdk_key_container);
const WvPLOutputProtection& wvpl_output_protection,
widevine::License_KeyContainer_OutputProtection* output_protection);
// Copies/translatessecurity_level in WvPL Key into an SDK key container.
virtual void CopySecurityLevel(
const WvPLOutputProtection& output_protection, TrackType track_type,
widevine::License_KeyContainer* key_container);
@@ -154,12 +204,6 @@ class WvPLSDKSession {
virtual void CopyPlaybackPolicy(const WvPLPlaybackPolicy& wvpl_policy,
widevine::License_Policy* sdk_policy);
// Copy the |cgms_value| into the key container. A helper function for
// GenerateLicenseRequestAsJSON.
virtual void CopyCGMS(
CGMS cgms_value,
widevine::License_KeyContainer_OutputProtection* output_protection);
// Copy the |hdcp_value| into the key container.
virtual void CopyHDCP(
HDCP hdcp_value,

View File

@@ -20,6 +20,7 @@
// TODO(user) Split wvpl_types.h into wvpl_common_types.h ,
// wvpl_license_sdk_types.h, wvpl_proxy_sdk_types.h and
// wvpl_packager_sdk_types.h.
// TODO(user) Expose Hdcpsrmrule into WvPLHdcpSrmRule.java.
namespace widevine_server {
namespace wv_pl_sdk {
@@ -40,6 +41,7 @@ enum KeyType {
ENTITLEMENT = 2
};
// LINT.IfChange
enum LicenseType {
STREAMING = 1,
OFFLINE = 2,
@@ -48,6 +50,7 @@ enum LicenseType {
/**
* Represents the type of message. This struct is used by Proxy SDK.
*/
// LINT.IfChange
enum MessageType {
UNKNOWN = 0,
LICENSE_REQUEST = 1,
@@ -95,6 +98,11 @@ enum SecurityLevel {
HW_SECURE_ALL = 5
};
enum HdcpSrmRule {
HDCP_SRM_RULE_NONE = 0,
CURRENT_SRM = 1,
};
enum DeviceSecurityLevel {
DEVICE_LEVEL_UNSPECIFIED = 0,
DEVICE_LEVEL_1 = 1,
@@ -125,6 +133,41 @@ enum AnalogOutputCapabilities {
ANALOG_OUTPUT_SUPPORTS_CGMS_A = 3,
};
/*
* Defines the type wrapper for wvpl request.
*/
struct WvPLRequestType {
WvPLRequestType() {
message_type_ = UNKNOWN;
license_type_ = STREAMING;
license_request_type_ = REQUEST_TYPE_UNSPECIFIED;
}
void set_message_type(MessageType message_type) {
message_type_ = message_type;
}
MessageType message_type() const { return message_type_; }
void set_license_type(LicenseType license_type) {
license_type_ = license_type;
}
LicenseType license_type() const { return license_type_; }
void set_license_request_type(LicenseRequestType license_request_type) {
license_request_type_ = license_request_type;
}
LicenseRequestType license_request_type() const {
return license_request_type_;
}
// Type of the message, default value is UNKNOWN.
MessageType message_type_;
// Type of the license, default value is Streaming.
LicenseType license_type_;
// Type of the license request, default value is REQUEST_TYPE_UNSPECIFIED.
LicenseRequestType license_request_type_;
};
struct WvPLPlaybackPolicy {
WvPLPlaybackPolicy() {
license_duration_seconds_ = 0;
@@ -370,6 +413,7 @@ struct WvPLVideoResolutionConstraint {
struct WvPLOutputProtection {
WvPLOutputProtection() {
hdcp_ = HDCP_NONE;
hdcp_srm_rule_ = HDCP_SRM_RULE_NONE;
secure_data_path_ = false;
security_level_ = SECURITY_LEVEL_UNDEFINED;
disable_analog_output_ = false;
@@ -412,9 +456,17 @@ struct WvPLOutputProtection {
CGMS cgms() const { return cgms_; }
void set_hdcp_srm_rule(HdcpSrmRule hdcp_srm_rule) {
hdcp_srm_rule_ = hdcp_srm_rule;
}
HdcpSrmRule hdcp_srm_rule() const { return hdcp_srm_rule_; }
// Indicates whether HDCP is required on digital outputs. Default is None.
HDCP hdcp_;
HdcpSrmRule hdcp_srm_rule_;
// Crypto operations and handling of the media must be performed within a
// hardware backed trusted environment. Default is false.
bool secure_data_path_;
@@ -932,6 +984,83 @@ struct WvPLWidevinePsshData {
std::list<WvPLEntitledKey> entitled_keys_;
};
struct WvPLCasKey {
WvPLCasKey() {}
void set_odd_key_id(const std::string& odd_key_id) {
odd_key_id_ = odd_key_id;
}
const std::string& odd_key_id() const { return odd_key_id_; }
void set_odd_key_bytes(const std::string& odd_key_bytes) {
odd_key_bytes_ = odd_key_bytes;
}
const std::string& odd_key_bytes() const { return odd_key_bytes_; }
void set_even_key_id(const std::string& even_key_id) {
even_key_id_ = even_key_id;
}
const std::string& even_key_id() const { return even_key_id_; }
void set_even_key_bytes(const std::string& even_key_bytes) {
even_key_bytes_ = even_key_bytes;
}
const std::string& even_key_bytes() const { return even_key_bytes_; }
void set_track_type(const TrackType track_type) { track_type_ = track_type; }
TrackType track_type() const { return track_type_; }
void set_output_protection(const WvPLOutputProtection& out_prot) {
output_protection_ = out_prot;
}
void set_requested_output_protection(const WvPLOutputProtection& out_prot) {
requested_output_protection_ = out_prot;
}
const WvPLOutputProtection& output_protection() const {
return output_protection_;
}
const WvPLOutputProtection& requested_output_protection() const {
return requested_output_protection_;
}
WvPLOutputProtection* mutable_output_protection() {
return &output_protection_;
}
WvPLOutputProtection* mutable_requested_output_protection() {
return &requested_output_protection_;
}
void set_key_type(const KeyType key_type) { key_type_ = key_type; }
KeyType key_type() const { return key_type_; }
// 'Odd' Key slot identifier.
std::string odd_key_id_;
// 'Odd' Key slot.
std::string odd_key_bytes_;
// 'Even' Key slot identifier.
std::string even_key_id_;
// 'Even' Key slot.
std::string even_key_bytes_;
// track type.
TrackType track_type_ = TRACK_TYPE_UNSPECIFIED;
// Required output protection.
WvPLOutputProtection output_protection_;
// Requested output protection.
WvPLOutputProtection requested_output_protection_;
// Key type from the KeyType enumeration.
KeyType key_type_ = ENTITLEMENT;
};
} // namespace wv_pl_sdk
} // namespace widevine_server