[ Merge of http://go/wvgerrit/80484 ] Clang-format has been run on files in core/src. clang-format has been turned off for some blocks but otherwise no other changes have been made. Bug: 134365840 Test: WV unit/integration tests Change-Id: I6e509f25136f84d37de3d920084302f0f2c23dc4
316 lines
11 KiB
C++
316 lines
11 KiB
C++
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine Master
|
|
// License Agreement.
|
|
|
|
#include "client_identification.h"
|
|
|
|
#include <string>
|
|
|
|
#include "crypto_session.h"
|
|
#include "license_protocol.pb.h"
|
|
#include "log.h"
|
|
#include "properties.h"
|
|
#include "string_conversions.h"
|
|
#include "wv_cdm_constants.h"
|
|
|
|
namespace {
|
|
const std::string kKeyCompanyName = "company_name";
|
|
const std::string kKeyModelName = "model_name";
|
|
const std::string kKeyArchitectureName = "architecture_name";
|
|
const std::string kKeyDeviceName = "device_name";
|
|
const std::string kKeyProductName = "product_name";
|
|
const std::string kKeyBuildInfo = "build_info";
|
|
const std::string kKeyDeviceId = "device_id";
|
|
const std::string kKeyWvCdmVersion = "widevine_cdm_version";
|
|
const std::string kKeyOemCryptoSecurityPatchLevel =
|
|
"oem_crypto_security_patch_level";
|
|
const std::string kKeyOemCryptoBuildInformation =
|
|
"oem_crypto_build_information";
|
|
} // unnamed namespace
|
|
|
|
namespace wvcdm {
|
|
// Protobuf generated classes.
|
|
using video_widevine::ClientIdentification_ClientCapabilities;
|
|
using video_widevine::ClientIdentification_NameValue;
|
|
using video_widevine::EncryptedClientIdentification;
|
|
using video_widevine::ProvisioningOptions;
|
|
using video_widevine::ProvisioningRequest;
|
|
using video_widevine::ProvisioningResponse;
|
|
using video_widevine::SignedProvisioningMessage;
|
|
|
|
CdmResponseType ClientIdentification::Init(CryptoSession* crypto_session) {
|
|
if (crypto_session == NULL) {
|
|
LOGE("ClientIdentification::Init: crypto_session not provided");
|
|
return PARAMETER_NULL;
|
|
}
|
|
|
|
is_license_request_ = false;
|
|
crypto_session_ = crypto_session;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
CdmResponseType ClientIdentification::Init(const std::string& client_token,
|
|
const std::string& device_id,
|
|
CryptoSession* crypto_session) {
|
|
if (crypto_session == NULL) {
|
|
LOGE("ClientIdentification::Init: crypto_session not provided");
|
|
return PARAMETER_NULL;
|
|
}
|
|
|
|
if (client_token.empty()) {
|
|
LOGE("ClientIdentification::Init: crypto_session not provided");
|
|
return PARAMETER_NULL;
|
|
}
|
|
|
|
is_license_request_ = true;
|
|
device_id_ = device_id;
|
|
client_token_ = client_token;
|
|
crypto_session_ = crypto_session;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* Return the ClientIdentification message token type for provisioning request.
|
|
* NOTE: a DRM Cert should never be presented to the provisioning server.
|
|
*/
|
|
CdmResponseType ClientIdentification::Prepare(
|
|
const CdmAppParameterMap& app_parameters,
|
|
const std::string& provider_client_token,
|
|
video_widevine::ClientIdentification* client_id) {
|
|
if (is_license_request_) {
|
|
client_id->set_type(
|
|
video_widevine::ClientIdentification::DRM_DEVICE_CERTIFICATE);
|
|
client_id->set_token(client_token_);
|
|
} else {
|
|
video_widevine::ClientIdentification::TokenType token_type;
|
|
if (!GetProvisioningTokenType(&token_type)) {
|
|
LOGE(
|
|
"ClientIdentification::Prepare: failure getting provisioning token "
|
|
"type");
|
|
return CLIENT_IDENTIFICATION_TOKEN_ERROR_1;
|
|
}
|
|
client_id->set_type(token_type);
|
|
|
|
std::string token;
|
|
CdmResponseType status = crypto_session_->GetProvisioningToken(&token);
|
|
if (status != NO_ERROR) {
|
|
LOGE(
|
|
"ClientIdentification::Prepare: failure getting provisioning token: "
|
|
"%d",
|
|
status);
|
|
return status;
|
|
}
|
|
client_id->set_token(token);
|
|
}
|
|
|
|
ClientIdentification_NameValue* client_info;
|
|
if (is_license_request_) {
|
|
CdmAppParameterMap::const_iterator iter;
|
|
for (iter = app_parameters.begin(); iter != app_parameters.end(); iter++) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(iter->first);
|
|
client_info->set_value(iter->second);
|
|
}
|
|
}
|
|
std::string value;
|
|
if (Properties::GetCompanyName(&value)) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyCompanyName);
|
|
client_info->set_value(value);
|
|
}
|
|
if (Properties::GetModelName(&value)) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyModelName);
|
|
client_info->set_value(value);
|
|
}
|
|
if (Properties::GetArchitectureName(&value)) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyArchitectureName);
|
|
client_info->set_value(value);
|
|
}
|
|
if (Properties::GetDeviceName(&value)) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyDeviceName);
|
|
client_info->set_value(value);
|
|
}
|
|
if (Properties::GetProductName(&value)) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyProductName);
|
|
client_info->set_value(value);
|
|
}
|
|
if (Properties::GetBuildInfo(&value)) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyBuildInfo);
|
|
client_info->set_value(value);
|
|
}
|
|
if (Properties::GetWVCdmVersion(&value)) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyWvCdmVersion);
|
|
client_info->set_value(value);
|
|
}
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyOemCryptoSecurityPatchLevel);
|
|
client_info->set_value(
|
|
std::to_string((uint32_t)crypto_session_->GetSecurityPatchLevel()));
|
|
std::string oec_build_info;
|
|
if (crypto_session_->GetBuildInformation(&oec_build_info)) {
|
|
client_info = client_id->add_client_info();
|
|
client_info->set_name(kKeyOemCryptoBuildInformation);
|
|
client_info->set_value(oec_build_info);
|
|
}
|
|
if (!provider_client_token.empty()) {
|
|
client_id->set_provider_client_token(provider_client_token);
|
|
}
|
|
|
|
ClientIdentification_ClientCapabilities* client_capabilities =
|
|
client_id->mutable_client_capabilities();
|
|
|
|
client_capabilities->set_client_token(true);
|
|
|
|
if (is_license_request_) {
|
|
bool supports_usage_information;
|
|
if (crypto_session_->UsageInformationSupport(&supports_usage_information)) {
|
|
client_capabilities->set_session_token(supports_usage_information);
|
|
}
|
|
|
|
client_capabilities->set_anti_rollback_usage_table(
|
|
crypto_session_->IsAntiRollbackHwPresent());
|
|
}
|
|
|
|
uint32_t api_version = 0;
|
|
if (crypto_session_->GetApiVersion(&api_version)) {
|
|
client_capabilities->set_oem_crypto_api_version(api_version);
|
|
}
|
|
|
|
if (is_license_request_) {
|
|
CryptoSession::HdcpCapability current_version, max_version;
|
|
if (crypto_session_->GetHdcpCapabilities(¤t_version, &max_version) ==
|
|
NO_ERROR) {
|
|
switch (max_version) {
|
|
case HDCP_NONE:
|
|
client_capabilities->set_max_hdcp_version(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE);
|
|
break;
|
|
case HDCP_V1:
|
|
client_capabilities->set_max_hdcp_version(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1);
|
|
break;
|
|
case HDCP_V2:
|
|
client_capabilities->set_max_hdcp_version(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2);
|
|
break;
|
|
case HDCP_V2_1:
|
|
client_capabilities->set_max_hdcp_version(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1);
|
|
break;
|
|
case HDCP_V2_2:
|
|
client_capabilities->set_max_hdcp_version(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2);
|
|
break;
|
|
case HDCP_V2_3:
|
|
client_capabilities->set_max_hdcp_version(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_3);
|
|
break;
|
|
case HDCP_NO_DIGITAL_OUTPUT:
|
|
client_capabilities->set_max_hdcp_version(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NO_DIGITAL_OUTPUT);
|
|
break;
|
|
default:
|
|
LOGW(
|
|
"ClientIdentification::PrepareClientId: unexpected HDCP max "
|
|
"capability version %d",
|
|
max_version);
|
|
}
|
|
}
|
|
}
|
|
|
|
CryptoSession::SupportedCertificateTypes supported_certs;
|
|
if (crypto_session_->GetSupportedCertificateTypes(&supported_certs)) {
|
|
if (supported_certs.rsa_2048_bit) {
|
|
client_capabilities->add_supported_certificate_key_type(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_2048);
|
|
}
|
|
if (supported_certs.rsa_3072_bit) {
|
|
client_capabilities->add_supported_certificate_key_type(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_3072);
|
|
}
|
|
}
|
|
|
|
if (is_license_request_) {
|
|
client_capabilities->set_can_update_srm(
|
|
crypto_session_->IsSrmUpdateSupported());
|
|
uint16_t srm_version;
|
|
if (crypto_session_->GetSrmVersion(&srm_version) == NO_ERROR)
|
|
client_capabilities->set_srm_version(srm_version);
|
|
}
|
|
bool can_support_output;
|
|
bool can_disable_output;
|
|
bool can_support_cgms_a;
|
|
if (crypto_session_->GetAnalogOutputCapabilities(
|
|
&can_support_output, &can_disable_output, &can_support_cgms_a)) {
|
|
video_widevine::ClientIdentification_ClientCapabilities_AnalogOutputCapabilities
|
|
capabilities = video_widevine::
|
|
ClientIdentification_ClientCapabilities_AnalogOutputCapabilities_ANALOG_OUTPUT_NONE;
|
|
|
|
if (can_support_output) {
|
|
if (can_support_cgms_a) {
|
|
capabilities = video_widevine::
|
|
ClientIdentification_ClientCapabilities_AnalogOutputCapabilities_ANALOG_OUTPUT_SUPPORTS_CGMS_A;
|
|
} else {
|
|
capabilities = video_widevine::
|
|
ClientIdentification_ClientCapabilities_AnalogOutputCapabilities_ANALOG_OUTPUT_SUPPORTED;
|
|
}
|
|
}
|
|
client_capabilities->set_analog_output_capabilities(capabilities);
|
|
client_capabilities->set_can_disable_analog_output(can_disable_output);
|
|
} else {
|
|
client_capabilities->set_analog_output_capabilities(
|
|
video_widevine::
|
|
ClientIdentification_ClientCapabilities_AnalogOutputCapabilities_ANALOG_OUTPUT_UNKNOWN);
|
|
}
|
|
|
|
uint32_t version, tier;
|
|
if (crypto_session_->GetApiVersion(&version)) {
|
|
if (version >= OEM_CRYPTO_API_VERSION_SUPPORTS_RESOURCE_RATING_TIER) {
|
|
if (crypto_session_->GetResourceRatingTier(&tier)) {
|
|
client_capabilities->set_resource_rating_tier(tier);
|
|
}
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
bool ClientIdentification::GetProvisioningTokenType(
|
|
video_widevine::ClientIdentification::TokenType* token_type) {
|
|
CdmClientTokenType token = crypto_session_->GetPreProvisionTokenType();
|
|
switch (token) {
|
|
case kClientTokenKeybox:
|
|
*token_type = video_widevine::ClientIdentification::KEYBOX;
|
|
return true;
|
|
case kClientTokenOemCert:
|
|
*token_type =
|
|
video_widevine::ClientIdentification::OEM_DEVICE_CERTIFICATE;
|
|
return true;
|
|
case kClientTokenDrmCert:
|
|
default:
|
|
// shouldn't happen
|
|
LOGE(
|
|
"CertificateProvisioning::GetProvisioningTokenType: unexpected "
|
|
"provisioning type: %d",
|
|
token);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
} // namespace wvcdm
|