[ Merge of http://go/wvgerrit/48720 ] The device ID does not need to be sent in the client identification information as it is either present in other fields or ignored by the license service. This also allows for build information to be reported during provisioning for devices with OEM certificates. Bug: 78578351 Test: WV unit/integration tests. GtsMediaTestCases. Change-Id: I708c63d34f0e2df7e465154d12096a394a1b23d7
274 lines
9.9 KiB
C++
274 lines
9.9 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 "crypto_session.h"
|
|
#include "license_protocol.pb.h"
|
|
#include "log.h"
|
|
#include "properties.h"
|
|
#include "string_conversions.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";
|
|
} // 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,
|
|
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;
|
|
if (!crypto_session_->GetProvisioningToken(&token)) {
|
|
LOGE("ClientIdentification::Prepare: failure getting provisioning token");
|
|
return CLIENT_IDENTIFICATION_TOKEN_ERROR_2;
|
|
}
|
|
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);
|
|
std::stringstream ss;
|
|
ss << (uint32_t)crypto_session_->GetSecurityPatchLevel();
|
|
client_info->set_value(ss.str());
|
|
|
|
ClientIdentification_ClientCapabilities* client_capabilities =
|
|
client_id->mutable_client_capabilities();
|
|
|
|
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)) {
|
|
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_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))
|
|
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);
|
|
}
|
|
|
|
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
|