Merge "Support provisioning 3.0" into oc-mr1-dev

This commit is contained in:
Rahul Frias
2017-07-24 05:38:49 +00:00
committed by Android (Google) Code Review
13 changed files with 506 additions and 61 deletions

View File

@@ -55,7 +55,8 @@ void CertificateProvisioning::ComposeJsonRequestAsQueryString(
*/
bool CertificateProvisioning::GetProvisioningTokenType(
ClientIdentification::TokenType* token_type) {
switch (crypto_session_.GetPreProvisionTokenType()) {
CdmClientTokenType token = crypto_session_.GetPreProvisionTokenType();
switch (token) {
case kClientTokenKeybox:
*token_type = ClientIdentification::KEYBOX;
return true;
@@ -65,22 +66,23 @@ bool CertificateProvisioning::GetProvisioningTokenType(
case kClientTokenDrmCert:
default:
// shouldn't happen
LOGE("CertificateProvisioning::GetProvisioningTokenType: unexpected "
"provisioning type: %d", token);
return false;
}
}
/*
* Fill in the appropriate field relating to stable IDs in the provisioning
* request, no more than one of |stable_id|, |provider_id|, and |spoid|. It is
* also valid (though deprecated) to fill in none of these in order to leave the
* stable ID behavior up to the provisioning server.
* Fill in the appropriate SPOID (Stable Per-Origin IDentifier) option.
* One of spoid, provider_id or stable_id will be passed to the provisioning
* server for determining a unique per origin ID for the device.
* It is also valid (though deprecated) to leave the settings unset.
*/
bool CertificateProvisioning::FillStableIdField(
const std::string& origin,
const std::string& spoid,
bool CertificateProvisioning::SetSpoidParameter(
const std::string& origin, const std::string& spoid,
ProvisioningRequest* request) {
if (!request) {
LOGE("CertificateProvisioning::FillStableIdField : No request buffer "
LOGE("CertificateProvisioning::SetSpoidParameter: No request buffer "
"passed to method.");
return false;
}
@@ -160,21 +162,6 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
client_id->set_token(token);
client_id->set_type(token_type);
#if 0 // TODO(gmorgan) in progress - encrypt ClientIdentification.
if (encrypt) {
EncryptedClientIdentification* encrypted_client_id =
provisioning_request->mutable_encrypted_client_id();
CdmResponseType sts;
sts = EncryptClientId(client_id, encrypted_client_id, certificate);
if (NO_ERROR == sts) {
provisioning_request->clear_client_id();
} else {
provisioning_request->clear_encrypted_client_id();
}
return sts;
}
#endif
uint32_t nonce;
if (!crypto_session_.GenerateNonce(&nonce)) {
LOGE("GetProvisioningRequest: fails to generate a nonce");
@@ -204,7 +191,7 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
cert_type_ = cert_type;
options->set_certificate_authority(cert_authority);
if (!FillStableIdField(origin, spoid, &provisioning_request)) {
if (!SetSpoidParameter(origin, spoid, &provisioning_request)) {
return CERT_PROVISIONING_GET_KEYBOX_ERROR_2;
}
@@ -326,11 +313,13 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
const std::string& enc_rsa_key = provisioning_response.device_rsa_key();
const std::string& nonce = provisioning_response.nonce();
const std::string& rsa_key_iv = provisioning_response.device_rsa_key_iv();
const std::string& wrapping_key = (provisioning_response.has_wrapping_key()) ?
provisioning_response.wrapping_key() : std::string();
const std::string& signature = signed_response.signature();
std::string wrapped_rsa_key;
if (!crypto_session_.RewrapDeviceRSAKey(signed_message, signature, nonce,
enc_rsa_key, rsa_key_iv,
&wrapped_rsa_key)) {
if (!crypto_session_.RewrapCertificate(signed_message, signature, nonce,
enc_rsa_key, rsa_key_iv, wrapping_key,
&wrapped_rsa_key)) {
LOGE("HandleProvisioningResponse: RewrapDeviceRSAKey fails");
return CERT_PROVISIONING_RESPONSE_ERROR_6;
}

View File

@@ -162,7 +162,15 @@ bool CryptoSession::GetTokenFromKeybox(std::string* token) {
}
bool CryptoSession::GetTokenFromOemCert(std::string* token) {
if (token == NULL) {
LOGE("CryptoSession::GetTokenFromOemCert: token not provided ");
return false;
}
OEMCryptoResult status;
if (!oem_token_.empty()) {
token->assign(oem_token_);
return true;
}
std::string temp_buffer(CERTIFICATE_DATA_SIZE, '\0');
// lock is held by caller
bool retrying = false;
@@ -171,7 +179,9 @@ bool CryptoSession::GetTokenFromOemCert(std::string* token) {
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);
temp_buffer.resize(buf_size);
oem_token_.assign(temp_buffer);
token->assign(temp_buffer);
return true;
}
if (OEMCrypto_ERROR_SHORT_BUFFER && !retrying) {
@@ -568,8 +578,8 @@ 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 (!Properties::use_certificates_as_identification() ||
(is_provisioning && (pre_provision_token_type_ == kClientTokenKeybox))) {
if (!GenerateDerivedKeys(message)) return false;
if (!GenerateSignature(message, signature)) return false;
@@ -739,8 +749,15 @@ bool CryptoSession::LoadCertificatePrivateKey(std::string& wrapped_key) {
LOGV("CryptoSession::LoadCertificatePrivateKey: Lock");
AutoLock auto_lock(crypto_lock_);
// Call OEMCrypto_GetOEMPublicCertificate before OEMCrypto_LoadDeviceRSAKey
// so it caches the OEMCrypto Public Key and then throw away result
std::string temp_buffer(CERTIFICATE_DATA_SIZE, '\0');
size_t buf_size = temp_buffer.size();
uint8_t* buf = reinterpret_cast<uint8_t*>(&temp_buffer[0]);
OEMCryptoResult sts =
OEMCrypto_GetOEMPublicCertificate(oec_session_id_, buf, &buf_size);
LOGV("LoadDeviceRSAKey: id=%ld", (uint32_t)oec_session_id_);
OEMCryptoResult sts;
M_TIME(
sts = OEMCrypto_LoadDeviceRSAKey(
oec_session_id_,
@@ -1458,6 +1475,34 @@ bool CryptoSession::SetDestinationBufferType() {
return true;
}
bool CryptoSession::RewrapCertificate(const std::string& signed_message,
const std::string& signature,
const std::string& nonce,
const std::string& private_key,
const std::string& iv,
const std::string& wrapping_key,
std::string* wrapped_private_key) {
LOGV("CryptoSession::RewrapCertificate, session id=%ld",
static_cast<uint32_t>(oec_session_id_));
if (pre_provision_token_type_ == kClientTokenKeybox) {
return RewrapDeviceRSAKey(signed_message, signature, nonce, private_key,
iv, wrapped_private_key);
} else if (pre_provision_token_type_ == kClientTokenOemCert) {
return RewrapDeviceRSAKey30(signed_message, nonce, private_key, iv,
wrapping_key, wrapped_private_key);
} else {
LOGE("CryptoSession::RewrapCertificate, Bad pre-provision type=%d: "
"session id=%ld", pre_provision_token_type_,
static_cast<uint32_t>(oec_session_id_));
return false;
}
}
bool CryptoSession::RewrapDeviceRSAKey(const std::string& message,
const std::string& signature,
const std::string& nonce,
@@ -1531,6 +1576,57 @@ bool CryptoSession::RewrapDeviceRSAKey(const std::string& message,
return true;
}
bool CryptoSession::RewrapDeviceRSAKey30(const std::string& message,
const std::string& nonce,
const std::string& private_key,
const std::string& iv,
const std::string& wrapping_key,
std::string* wrapped_private_key) {
LOGV("CryptoSession::RewrapDeviceRSAKey30, session id=%ld",
static_cast<uint32_t>(oec_session_id_));
const uint8_t* signed_msg = reinterpret_cast<const uint8_t*>(message.data());
const uint8_t* msg_private_key = NULL;
const uint8_t* msg_iv = NULL;
const uint32_t* msg_nonce = NULL;
const uint8_t* msg_wrapping_key = NULL;
if (private_key.size() >= MAC_KEY_SIZE && iv.size() >= KEY_IV_SIZE) {
msg_private_key = signed_msg + GetOffset(message, private_key);
msg_iv = signed_msg + GetOffset(message, iv);
msg_nonce = reinterpret_cast<const uint32_t*>(signed_msg +
GetOffset(message, nonce));
msg_wrapping_key = signed_msg + GetOffset(message, wrapping_key);
}
// Gets wrapped_rsa_key_length by passing NULL as uint8_t* wrapped_rsa_key
// and 0 as wrapped_rsa_key_length.
size_t wrapped_private_key_length = 0;
OEMCryptoResult status = OEMCrypto_RewrapDeviceRSAKey30(
oec_session_id_, msg_nonce, msg_wrapping_key, wrapping_key.size(),
msg_private_key, private_key.size(), msg_iv, NULL,
&wrapped_private_key_length);
if (status != OEMCrypto_ERROR_SHORT_BUFFER) {
LOGE("OEMCrypto_RewrapDeviceRSAKey30 failed getting wrapped key length");
return false;
}
wrapped_private_key->resize(wrapped_private_key_length);
status = OEMCrypto_RewrapDeviceRSAKey30(
oec_session_id_, msg_nonce, msg_wrapping_key, wrapping_key.size(),
msg_private_key, private_key.size(), msg_iv,
reinterpret_cast<uint8_t*>(&(*wrapped_private_key)[0]),
&wrapped_private_key_length);
wrapped_private_key->resize(wrapped_private_key_length);
if (OEMCrypto_SUCCESS != status) {
LOGE("OEMCrypto_RewrapDeviceRSAKey fails with %d", status);
return false;
}
return true;
}
bool CryptoSession::GetHdcpCapabilities(HdcpCapability* current,
HdcpCapability* max) {
LOGV("GetHdcpCapabilities: id=%ld", (uint32_t)oec_session_id_);