Support Keybox, DRM Cert, and OEM Cert for Client ID

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

Add GetClientToken(), GetProvisioningToken(), GetPreProvisionTokenType()
to CryptoSession.  They return the correct token bytes and token type
for preparing the ClientIdentification message for provisioning and
license server transactions.

Also refactor service certificate handling.

OEM certs are introduced in Provisioning 3.0

b/30811184

* Address build breaks

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

This addresses issues introduced by http://go/wvgerrit/22900

b/30811184

* When http://go/wvgerrit/18012 was merged (ag/1446934) some changes
were not merged for mapErrors-inl.h. These changes are included in this CL.

* When ag/1678104 was reverse merged to http//go/wvgerrit/21981/ a variable
was renamed and some comments were added to add clarity in cdm_engine.cpp.
These changes are included in this CL.

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

Change-Id: Ie0215509f2f985f2a610f5a4c865db47edec8662
This commit is contained in:
Rahul Frias
2017-01-20 15:46:15 -08:00
parent 7c01f954da
commit 2812c3d2ac
21 changed files with 898 additions and 382 deletions

View File

@@ -54,6 +54,26 @@ CryptoSession::~CryptoSession() {
Terminate();
}
bool CryptoSession::GetProvisioningMethod(CdmClientTokenType* token_type) {
OEMCrypto_ProvisioningMethod method;
switch (method = OEMCrypto_GetProvisioningMethod(requested_security_level_)) {
case OEMCrypto_OEMCertificate:
*token_type = kClientTokenOemCert;
break;
case OEMCrypto_Keybox:
*token_type = kClientTokenKeybox;
break;
case OEMCrypto_DrmCertificate:
*token_type = kClientTokenDrmCert;
break;
case OEMCrypto_ProvisioningError:
default:
LOGE("OEMCrypto_GetProvisioningMethod failed", method);
return false;
}
return true;
}
void CryptoSession::Init() {
LOGV("CryptoSession::Init");
AutoLock auto_lock(crypto_lock_);
@@ -66,6 +86,9 @@ void CryptoSession::Init() {
}
initialized_ = true;
}
if (!GetProvisioningMethod(&pre_provision_token_type_)) {
initialized_ = false;
}
}
void CryptoSession::Terminate() {
@@ -85,35 +108,79 @@ void CryptoSession::Terminate() {
initialized_ = false;
}
bool CryptoSession::ValidateKeybox() {
LOGV("CryptoSession::ValidateKeybox: Lock");
AutoLock auto_lock(crypto_lock_);
if (!initialized_) {
return false;
bool CryptoSession::GetTokenFromKeybox(std::string* token) {
OEMCryptoResult status;
std::string temp_buffer(KEYBOX_KEY_DATA_SIZE, '\0');
// lock is held by caller
size_t buf_size = temp_buffer.size();
uint8_t* buf = reinterpret_cast<uint8_t*>(&temp_buffer[0]);
status = OEMCrypto_GetKeyData(buf, &buf_size, requested_security_level_);
if (status == OEMCrypto_SUCCESS) {
token->swap(temp_buffer);
return true;
}
OEMCryptoResult result = OEMCrypto_IsKeyboxValid(requested_security_level_);
return (OEMCrypto_SUCCESS == result);
return false;
}
bool CryptoSession::GetToken(std::string* token) {
if (!token) {
LOGE("CryptoSession::GetToken : No token passed to method.");
bool CryptoSession::GetTokenFromOemCert(std::string* token) {
OEMCryptoResult status;
std::string temp_buffer(CERTIFICATE_DATA_SIZE, '\0');
// lock is held by caller
bool retrying = false;
while (true) {
size_t buf_size = temp_buffer.size();
uint8_t* buf = reinterpret_cast<uint8_t*>(&temp_buffer[0]);
status = OEMCrypto_GetOEMPublicCertificate(oec_session_id_, buf, &buf_size);
if (OEMCrypto_SUCCESS == status) {
token->swap(temp_buffer);
return true;
}
if (OEMCrypto_ERROR_SHORT_BUFFER && !retrying) {
temp_buffer.resize(buf_size);
retrying = true;
continue;
}
return false;
}
uint8_t buf[KEYBOX_KEY_DATA_SIZE];
size_t bufSize = sizeof(buf);
LOGV("CryptoSession::GetToken: Lock");
}
bool CryptoSession::GetClientToken(std::string* token) {
if (!token) {
LOGE("CryptoSession::GetClientToken : No token passed to method.");
return false;
}
LOGV("CryptoSession::GetClientToken: Lock");
AutoLock auto_lock(crypto_lock_);
if (!initialized_) {
return false;
}
OEMCryptoResult sts =
OEMCrypto_GetKeyData(buf, &bufSize, requested_security_level_);
if (OEMCrypto_SUCCESS != sts) {
// Only keybox is used for client token. All other cases use DRM Cert.
if (pre_provision_token_type_ != kClientTokenKeybox) {
return false;
}
return GetTokenFromKeybox(token);
}
bool CryptoSession::GetProvisioningToken(std::string* token) {
if (!token) {
LOGE("CryptoSession::GetProvisioningToken : No token passed to method.");
return false;
}
LOGV("CryptoSession::GetProvisioningToken: Lock");
AutoLock auto_lock(crypto_lock_);
if (!initialized_) {
return false;
}
if (pre_provision_token_type_ == kClientTokenKeybox) {
return GetTokenFromKeybox(token);
} else if (pre_provision_token_type_ == kClientTokenOemCert) {
return GetTokenFromOemCert(token);
} else {
return false;
}
token->assign((const char*)buf, (size_t)bufSize);
return true;
}
CdmSecurityLevel CryptoSession::GetSecurityLevel() {
@@ -160,11 +227,13 @@ bool CryptoSession::GetDeviceUniqueId(std::string* device_id) {
if (!initialized_) {
return false;
}
OEMCryptoResult sts =
if (pre_provision_token_type_ == kClientTokenKeybox) {
OEMCryptoResult sts =
OEMCrypto_GetDeviceID(&id[0], &id_length, requested_security_level_);
if (OEMCrypto_SUCCESS != sts) {
return false;
if (OEMCrypto_SUCCESS != sts) {
return false;
}
}
device_id->assign(reinterpret_cast<char*>(&id[0]), id_length);
@@ -312,6 +381,7 @@ bool CryptoSession::PrepareRequest(const std::string& message,
return false;
}
// TODO(gmorgan): rework this for OEM certs.
if (!Properties::use_certificates_as_identification() || is_provisioning) {
if (!GenerateDerivedKeys(message)) return false;