Add support for SRM

[ Merge of http://go/wvgerrit/22980 ]

System Renewability Messages (SRM) contains a list of Key Selection
Vectors, which are HDCP Identifiers that have been revoked.
During HDCP negotiations a transmitter may authenticate a receiver
and verify that its unique identier is not present in the SRM.

This CL enables reporting of the current SRM version and whether SRM
updates are supported. It also loads SRM updates in the license
and specifies SRM version requirements when keys are loaded.

Test: All unittests other than some oemcrypto, request_license_test
passed. Those tests failed with or without this CL.

b/28955520

Change-Id: Id840078ea2deb01d9619c1cd8d367b50452f76cc
This commit is contained in:
Rahul Frias
2017-01-23 14:40:46 -08:00
parent 65a2c240de
commit 6a98f56412
4 changed files with 73 additions and 8 deletions

View File

@@ -59,7 +59,8 @@ class CryptoSession {
const std::string& mac_key_iv,
const std::string& mac_key,
const std::vector<CryptoKey>& key_array,
const std::string& provider_session_token);
const std::string& provider_session_token,
const std::string& srm_requirement);
virtual bool LoadCertificatePrivateKey(std::string& wrapped_key);
virtual bool RefreshKeys(const std::string& message,
const std::string& signature, int num_keys,
@@ -107,6 +108,10 @@ class CryptoSession {
virtual bool GetNumberOfOpenSessions(size_t* count);
virtual bool GetMaxNumberOfSessions(size_t* max);
virtual bool GetSrmVersion(uint16_t* srm_version);
virtual bool IsSrmUpdateSupported();
virtual bool LoadSrm(const std::string& srm);
virtual CdmResponseType GenericEncrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,

View File

@@ -460,7 +460,8 @@ CdmResponseType CryptoSession::LoadKeys(
const std::string& message, const std::string& signature,
const std::string& mac_key_iv, const std::string& mac_key,
const std::vector<CryptoKey>& keys,
const std::string& provider_session_token) {
const std::string& provider_session_token,
const std::string& srm_requirement) {
LOGV("CryptoSession::LoadKeys: Lock");
AutoLock auto_lock(crypto_lock_);
@@ -501,13 +502,15 @@ CdmResponseType CryptoSession::LoadKeys(
pst =
const_cast<uint8_t*>(msg) + GetOffset(message, provider_session_token);
}
uint8_t* srm_req = NULL;
if (!srm_requirement.empty())
srm_req = const_cast<uint8_t*>(msg) + GetOffset(message, srm_requirement);
LOGV("LoadKeys: id=%ld", (uint32_t)oec_session_id_);
OEMCryptoResult sts = OEMCrypto_LoadKeys(
oec_session_id_, msg, message.size(),
reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
enc_mac_key_iv, enc_mac_key, keys.size(), &load_keys[0], pst,
provider_session_token.length(),
NULL); // TODO(rfrias): http://b/28955520
provider_session_token.length(), srm_req);
if (OEMCrypto_SUCCESS == sts) {
if (!provider_session_token.empty()) {
@@ -1213,6 +1216,45 @@ bool CryptoSession::GetMaxNumberOfSessions(size_t* max) {
return true;
}
bool CryptoSession::GetSrmVersion(uint16_t* srm_version) {
LOGV("GetSrmVersion");
if (!initialized_) return false;
if (srm_version == NULL) {
LOGE("CryptoSession::GetSrmVersion: |srm_version| cannot be NULL");
return false;
}
OEMCryptoResult status = OEMCrypto_GetCurrentSRMVersion(srm_version);
if (OEMCrypto_SUCCESS != status) {
LOGW("OEMCrypto_GetCurrentSRMVersion fails with %d", status);
return false;
}
return true;
}
bool CryptoSession::IsSrmUpdateSupported() {
LOGV("IsSrmUpdateSupported");
if (!initialized_) return false;
return OEMCrypto_IsSRMUpdateSupported();
}
bool CryptoSession::LoadSrm(const std::string& srm) {
LOGV("LoadSrm");
if (!initialized_) return false;
if (srm.empty()) {
LOGE("CryptoSession::LoadSrm: |srm| cannot be empty");
return false;
}
OEMCryptoResult status = OEMCrypto_LoadSRM(
reinterpret_cast<const uint8_t*>(srm.data()), srm.size());
if (OEMCrypto_SUCCESS != status) {
LOGW("OEMCrypto_LoadSRM fails with %d", status);
return false;
}
return true;
}
CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,

View File

@@ -494,6 +494,8 @@ CdmResponseType CdmLicense::HandleKeyResponse(
return NO_CONTENT_KEY;
}
if (license.has_srm_update()) crypto_session_->LoadSrm(license.srm_update());
if (license.id().type() == video_widevine::OFFLINE &&
license.policy().can_persist())
is_offline_ = true;
@@ -511,7 +513,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
CdmResponseType resp = crypto_session_->LoadKeys(
signed_response.msg(), signed_response.signature(), mac_key_iv, mac_key,
key_array, provider_session_token_);
key_array, provider_session_token_, license.srm_requirement());
if (KEY_ADDED == resp) {
loaded_keys_.clear();
@@ -949,11 +951,18 @@ CdmResponseType CdmLicense::PrepareClientId(
}
}
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);
if (service_certificate_->IsRequired()) {
if (!service_certificate_->IsAvailable()) {
LOGE("CdmLicense::PrepareClientId: Service Certificate not staged");
return LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR;
}
EncryptedClientIdentification* encrypted_client_id =
license_request->mutable_encrypted_client_id();
CdmResponseType status;

View File

@@ -214,9 +214,13 @@ message License {
// 4cc code specifying the CENC protection scheme as defined in the CENC 3.0
// specification. Propagated from Widevine PSSH box. Optional.
optional uint32 protection_scheme = 7;
// Minimum HDCP SRM version needed for using this key on content sent to
// HDCP enabled outputs.
optional uint32 min_hdcp_srm_version = 8;
// 8 byte verification field "HDCPDATA" followed by unsigned 32 bit minimum
// HDCP SRM version. Additional details can be found in
// Widevine Modular DRM Security Integration Guide for CENC.
optional bytes srm_requirement = 8;
// If present this contains a signed SRM file that should be installed
// on the client device.
optional bytes srm_update = 9;
}
enum ProtocolVersion {
@@ -515,6 +519,11 @@ message ClientIdentification {
// storing the generation number in secure memory. For Details, see:
// Widevine Modular DRM Security Integration Guide for CENC
optional bool anti_rollback_usage_table = 6 [default = false];
// The client shall report |srm_version| if available.
optional uint32 srm_version = 7;
// A device may have SRM data, and report a version, but may not be capable
// of updating SRM data.
optional bool can_update_srm = 8 [default = false];
}
// Type of factory-provisioned device root of trust. Optional.