Version 17.1

Updates to OEMCrypto API and OPK reference implementation.
This commit is contained in:
Fred Gylys-Colwell
2022-06-26 20:46:35 -07:00
parent 5e1f940c81
commit 1ec4f64360
134 changed files with 4508 additions and 5931 deletions

View File

@@ -30,42 +30,31 @@ NO_IGNORE_RESULT static bool IsSupportedDrmKeyType(AsymmetricKeyType key_type) {
return key_type == DRM_RSA_PRIVATE_KEY || key_type == DRM_ECC_PRIVATE_KEY;
}
/* In OEMCrypto version 16.5 and forward, key control blocks are expected to be
* clear. Caller ensures the pointer is not NULL. */
NO_IGNORE_RESULT static bool IsExpectedClearKeyControlBlockVersion(
const ODK_NonceValues* nonce_values) {
if (nonce_values->api_major_version == 16) {
return nonce_values->api_minor_version >= 5;
}
return nonce_values->api_major_version >= 17;
}
OEMCryptoResult OPKI_InitializeSession(OEMCryptoSession* session,
OEMCrypto_SESSION session_id) {
if (session == NULL) return OEMCrypto_ERROR_INVALID_CONTEXT;
session->session_id = session_id;
session->state = SESSION_INVALID;
session->drm_private_key = NULL;
session->prov40_oem_private_key = NULL;
session->mac_key_client = NULL;
session->mac_key_server = NULL;
session->encryption_key = NULL;
session->refresh_valid = false;
session->license_type = OEMCrypto_ContentLicense;
session->current_content_key_index = CONTENT_KEYS_PER_SESSION;
for (int i = 0; i < CONTENT_KEYS_PER_SESSION; i++) {
session->content_keys[i] = NULL;
}
session->num_content_keys = 0;
for (int i = 0; i < ENTITLEMENT_KEYS_PER_SESSION; i++) {
session->entitlement_keys[i] = NULL;
}
session->num_entitlement_keys = 0;
session->valid_srm_version = false;
session->timer_start = 0;
session->decrypt_hash.compute_hash = false;
session->decrypt_hash.current_hash = 0;
session->decrypt_hash.given_hash = 0;
session->decrypt_hash.current_frame_number = 0;
session->decrypt_hash.bad_frame_number = 0;
session->decrypt_hash.hash_error = OEMCrypto_SUCCESS;
session->allowed_schemes = kSign_RSASSA_PSS;
session->prov40_oem_allowed_schemes = kSign_RSASSA_PSS;
session->decrypt_started = false;
session->nonce_created = false;
session->request_signed = false;
session->response_loaded = false;
memset(session->license_request_hash, 0, ODK_SHA256_HASH_SIZE);
RETURN_INVALID_CONTEXT_IF_NULL(session);
*session = (OEMCryptoSession){
.session_id = session_id,
.state = SESSION_INVALID,
.license_type = OEMCrypto_ContentLicense,
.current_content_key_index = CONTENT_KEYS_PER_SESSION,
.decrypt_hash =
(DecryptHash){
.hash_error = OEMCrypto_SUCCESS,
},
.allowed_schemes = kSign_RSASSA_PSS,
.prov40_oem_allowed_schemes = kSign_RSASSA_PSS,
};
OEMCryptoResult result = ODK_InitializeSessionValues(
&session->timer_limits, &session->clock_values, &session->nonce_values,
API_MAJOR_VERSION, session->session_id);
@@ -614,7 +603,7 @@ OEMCryptoResult OPKI_GenerateCertSignature(OEMCryptoSession* session,
}
switch (signature_type) {
case CERT_SIGNATURE_OEM:
// TODO(b/180530495): implement this.
// TODO(b/225216277): implement this.
// return SignMessageWithOEMPrivateKey(message, message_length, signature,
// signature_length);
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
@@ -715,8 +704,7 @@ OEMCryptoResult OPKI_InstallKey(OEMCryptoSession* session,
const uint8_t* key_control_iv) {
if (session == NULL || key_id == NULL || key_id_length == 0 ||
key_id_length > KEY_ID_MAX_SIZE || key_data == NULL ||
key_data_length == 0 || key_data_iv == NULL || key_control == NULL ||
key_control_iv == NULL) {
key_data_length == 0 || key_data_iv == NULL || key_control == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
uint8_t raw_key_control[KEY_CONTROL_SIZE];
@@ -772,7 +760,23 @@ OEMCryptoResult OPKI_InstallKey(OEMCryptoSession* session,
result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
goto cleanup;
}
if (CheckApiVersionAtMost(&session->nonce_values, 16, 4)) {
/* To address backwards compatibility issues with a v16.x server SDK bug, the
* exact rules for determining whether a KCB is encrypted or clear have
* changed.
*
* Original behavior:
* - Version <= 16.4.x --> KCB encrypted
* - Version >= 16.5.x --> KCB clear
* New behavior:
* - No KCB IV --> KCB clear
* - KCB IV --> KCB encrypted
*/
if (key_control_iv != NULL) {
if (IsExpectedClearKeyControlBlockVersion(&session->nonce_values)) {
LOGW("Unexpected encrypted KCB: response_odk_version = %u.%u",
session->nonce_values.api_major_version,
session->nonce_values.api_minor_version);
}
/* We use the first 128 bits regardless of the license type to decrypt the
key control. */
result = WTPI_C1_AESCBCDecrypt(current_key->key_handle, KEY_SIZE_128,
@@ -784,6 +788,11 @@ OEMCryptoResult OPKI_InstallKey(OEMCryptoSession* session,
goto cleanup;
}
} else {
if (!IsExpectedClearKeyControlBlockVersion(&session->nonce_values)) {
LOGW("Unexpected clear KCB: response_odk_version = %u.%u",
session->nonce_values.api_major_version,
session->nonce_values.api_minor_version);
}
memcpy(raw_key_control, key_control, KEY_CONTROL_SIZE);
}