summaryrefslogtreecommitdiff
Diffstat
-rwxr-xr-x4.0/AmlogicKeymaster4Device.cpp571
-rwxr-xr-x4.0/android.hardware.keymaster@4.0-service.amlogic.rc4
-rwxr-xr-x4.0/service.cpp43
-rwxr-xr-x[-rw-r--r--]8efb1e1c-37e5-4326-a5d68c33726c7d57.ta11646
-rwxr-xr-xAmlogicKeymaster.cpp352
-rwxr-xr-x[-rw-r--r--]Android.mk125
-rw-r--r--aml_keymaster_device.cpp1021
-rw-r--r--aml_keymaster_device.h194
-rw-r--r--aml_keymaster_ipc.cpp128
-rw-r--r--aml_keymaster_ipc.h33
-rwxr-xr-xinclude/amlogic_keymaster/AmlogicKeymaster.h86
-rwxr-xr-xinclude/amlogic_keymaster/AmlogicKeymaster4Device.h105
-rwxr-xr-xinclude/amlogic_keymaster/amlogic_keymaster_messages.h222
-rwxr-xr-xinclude/amlogic_keymaster/ipc/amlogic_keymaster_ipc.h52
-rwxr-xr-x[-rw-r--r--]include/amlogic_keymaster/ipc/keymaster_ipc.h (renamed from keymaster_ipc.h)17
-rwxr-xr-xipc/amlogic_keymaster_ipc.cpp325
-rw-r--r--module.cpp61
-rw-r--r--unit_test/android_keymaster_messages_test.cpp732
-rw-r--r--unit_test/android_keymaster_test.cpp3976
-rw-r--r--unit_test/android_keymaster_test_utils.cpp902
-rw-r--r--unit_test/android_keymaster_test_utils.h470
-rw-r--r--unit_test/android_keymaster_utils.h306
-rw-r--r--unit_test/attestation_record.cpp690
-rw-r--r--unit_test/attestation_record.h62
-rw-r--r--unit_test/attestation_record_test.cpp145
-rw-r--r--unit_test/authorization_set_test.cpp745
-rw-r--r--unit_test/ecies_kem_test.cpp73
-rw-r--r--unit_test/gtest_main.cpp34
-rw-r--r--unit_test/hkdf_test.cpp78
-rw-r--r--unit_test/hmac_test.cpp84
-rw-r--r--unit_test/kdf1_test.cpp60
-rw-r--r--unit_test/kdf2_test.cpp86
-rw-r--r--unit_test/kdf_test.cpp46
-rw-r--r--unit_test/key_blob_test.cpp362
-rw-r--r--unit_test/keymaster0_engine.h103
-rw-r--r--unit_test/keymaster1_engine.h123
-rw-r--r--unit_test/keymaster_configuration_test.cpp68
-rw-r--r--unit_test/keymaster_enforcement_test.cpp872
-rw-r--r--unit_test/keymaster_tags.cpp173
-rw-r--r--unit_test/nist_curve_key_exchange_test.cpp219
-rw-r--r--unit_test/openssl_utils.h100
-rw-r--r--unit_test/sw_rsa_attest_root.key.pem15
42 files changed, 6493 insertions, 19016 deletions
diff --git a/unit_test/attestation_record.cpp b/unit_test/attestation_record.cpp
deleted file mode 100644
index 8ba5a8a..0000000
--- a/unit_test/attestation_record.cpp
+++ b/dev/null
@@ -1,690 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "attestation_record.h"
-
-#include <assert.h>
-
-#include <openssl/asn1t.h>
-
-#include "openssl_err.h"
-#include "openssl_utils.h"
-
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/keymaster_context.h>
-
-namespace keymaster {
-
-struct stack_st_ASN1_TYPE_Delete {
- void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
-};
-
-struct ASN1_STRING_Delete {
- void operator()(ASN1_STRING* p) { ASN1_STRING_free(p); }
-};
-
-struct ASN1_TYPE_Delete {
- void operator()(ASN1_TYPE* p) { ASN1_TYPE_free(p); }
-};
-
-#define ASN1_INTEGER_SET STACK_OF(ASN1_INTEGER)
-
-typedef struct km_root_of_trust {
- ASN1_OCTET_STRING* verified_boot_key;
- ASN1_BOOLEAN* device_locked;
- ASN1_ENUMERATED* verified_boot_state;
-} KM_ROOT_OF_TRUST;
-
-ASN1_SEQUENCE(KM_ROOT_OF_TRUST) = {
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_key, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, device_locked, ASN1_BOOLEAN),
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_state, ASN1_ENUMERATED),
-} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
-IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
-
-typedef struct km_auth_list {
- ASN1_INTEGER_SET* purpose;
- ASN1_INTEGER* algorithm;
- ASN1_INTEGER* key_size;
- ASN1_INTEGER_SET* digest;
- ASN1_INTEGER_SET* padding;
- ASN1_INTEGER_SET* kdf;
- ASN1_INTEGER* ec_curve;
- ASN1_INTEGER* rsa_public_exponent;
- ASN1_INTEGER* active_date_time;
- ASN1_INTEGER* origination_expire_date_time;
- ASN1_INTEGER* usage_expire_date_time;
- ASN1_NULL* no_auth_required;
- ASN1_INTEGER* user_auth_type;
- ASN1_INTEGER* auth_timeout;
- ASN1_NULL* allow_while_on_body;
- ASN1_NULL* all_applications;
- ASN1_OCTET_STRING* application_id;
- ASN1_INTEGER* creation_date_time;
- ASN1_INTEGER* origin;
- ASN1_NULL* rollback_resistant;
- KM_ROOT_OF_TRUST* root_of_trust;
- ASN1_INTEGER* os_version;
- ASN1_INTEGER* os_patchlevel;
-} KM_AUTH_LIST;
-
-ASN1_SEQUENCE(KM_AUTH_LIST) = {
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, kdf, ASN1_INTEGER, TAG_KDF.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
- TAG_RSA_PUBLIC_EXPONENT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
- TAG_ORIGINATION_EXPIRE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
- TAG_USAGE_EXPIRE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
- TAG_ALLOW_WHILE_ON_BODY.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, all_applications, ASN1_NULL, TAG_ALL_APPLICATIONS.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, application_id, ASN1_OCTET_STRING, TAG_APPLICATION_ID.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
- TAG_CREATION_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistant, ASN1_NULL, TAG_ROLLBACK_RESISTANT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.masked_tag()),
-} ASN1_SEQUENCE_END(KM_AUTH_LIST);
-IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
-
-typedef struct km_key_description {
- ASN1_INTEGER* attestation_version;
- ASN1_ENUMERATED* attestation_security_level;
- ASN1_INTEGER* keymaster_version;
- ASN1_ENUMERATED* keymaster_security_level;
- ASN1_OCTET_STRING* attestation_challenge;
- KM_AUTH_LIST* software_enforced;
- KM_AUTH_LIST* tee_enforced;
- ASN1_INTEGER* unique_id;
-} KM_KEY_DESCRIPTION;
-
-ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_version, ASN1_INTEGER),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_security_level, ASN1_ENUMERATED),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_version, ASN1_INTEGER),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_security_level, ASN1_ENUMERATED),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_challenge, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, unique_id, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, software_enforced, KM_AUTH_LIST),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, tee_enforced, KM_AUTH_LIST),
-} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
-IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
-
-struct KM_AUTH_LIST_Delete {
- void operator()(KM_AUTH_LIST* p) { KM_AUTH_LIST_free(p); }
-};
-
-struct KM_KEY_DESCRIPTION_Delete {
- void operator()(KM_KEY_DESCRIPTION* p) { KM_KEY_DESCRIPTION_free(p); }
-};
-
-static uint32_t get_uint32_value(const keymaster_key_param_t& param) {
- switch (keymaster_tag_get_type(param.tag)) {
- case KM_ENUM:
- case KM_ENUM_REP:
- return param.enumerated;
- case KM_UINT:
- case KM_UINT_REP:
- return param.integer;
- default:
- assert(false);
- return 0xFFFFFFFF;
- }
-}
-
-// Insert value in either the dest_integer or the dest_integer_set, whichever is provided.
-static keymaster_error_t insert_integer(ASN1_INTEGER* value, ASN1_INTEGER** dest_integer,
- ASN1_INTEGER_SET** dest_integer_set) {
- assert((dest_integer == nullptr) ^ (dest_integer_set == nullptr));
- assert(value);
-
- if (dest_integer_set) {
- if (!*dest_integer_set)
- *dest_integer_set = sk_ASN1_INTEGER_new_null();
- if (!*dest_integer_set)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!sk_ASN1_INTEGER_push(*dest_integer_set, value))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- return KM_ERROR_OK;
-
- } else if (dest_integer) {
- if (*dest_integer)
- ASN1_INTEGER_free(*dest_integer);
- *dest_integer = value;
- return KM_ERROR_OK;
- }
-
- assert(false); // Should never get here.
- return KM_ERROR_OK;
-}
-
-// Put the contents of the keymaster AuthorizationSet auth_list in to the ASN.1 record structure,
-// record.
-static keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIST* record) {
- assert(record);
-
- if (auth_list.empty())
- return KM_ERROR_OK;
-
- for (auto entry : auth_list) {
-
- ASN1_INTEGER_SET** integer_set = nullptr;
- ASN1_INTEGER** integer_ptr = nullptr;
- ASN1_OCTET_STRING** string_ptr = nullptr;
- ASN1_NULL** bool_ptr = nullptr;
-
- switch (entry.tag) {
-
- /* Ignored tags */
- case KM_TAG_INVALID:
- case KM_TAG_ASSOCIATED_DATA:
- case KM_TAG_NONCE:
- case KM_TAG_AUTH_TOKEN:
- case KM_TAG_MAC_LENGTH:
- case KM_TAG_ALL_USERS:
- case KM_TAG_USER_ID:
- case KM_TAG_USER_SECURE_ID:
- case KM_TAG_EXPORTABLE:
- case KM_TAG_RESET_SINCE_ID_ROTATION:
- case KM_TAG_ATTESTATION_CHALLENGE:
- case KM_TAG_BLOCK_MODE:
- case KM_TAG_CALLER_NONCE:
- case KM_TAG_MIN_MAC_LENGTH:
- case KM_TAG_ECIES_SINGLE_HASH_MODE:
- case KM_TAG_INCLUDE_UNIQUE_ID:
- case KM_TAG_BLOB_USAGE_REQUIREMENTS:
- case KM_TAG_BOOTLOADER_ONLY:
- case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
- case KM_TAG_MAX_USES_PER_BOOT:
- case KM_TAG_APPLICATION_DATA:
- case KM_TAG_UNIQUE_ID:
- case KM_TAG_ROOT_OF_TRUST:
- continue;
-
- /* Non-repeating enumerations */
- case KM_TAG_ALGORITHM:
- integer_ptr = &record->algorithm;
- break;
- case KM_TAG_EC_CURVE:
- integer_ptr = &record->ec_curve;
- break;
- case KM_TAG_USER_AUTH_TYPE:
- integer_ptr = &record->user_auth_type;
- break;
- case KM_TAG_ORIGIN:
- integer_ptr = &record->origin;
- break;
-
- /* Repeating enumerations */
- case KM_TAG_PURPOSE:
- integer_set = &record->purpose;
- break;
- case KM_TAG_PADDING:
- integer_set = &record->padding;
- break;
- case KM_TAG_DIGEST:
- integer_set = &record->digest;
- break;
- case KM_TAG_KDF:
- integer_set = &record->kdf;
- break;
-
- /* Non-repeating unsigned integers */
- case KM_TAG_KEY_SIZE:
- integer_ptr = &record->key_size;
- break;
- case KM_TAG_AUTH_TIMEOUT:
- integer_ptr = &record->auth_timeout;
- break;
- case KM_TAG_OS_VERSION:
- integer_ptr = &record->os_version;
- break;
- case KM_TAG_OS_PATCHLEVEL:
- integer_ptr = &record->os_patchlevel;
- break;
-
- /* Non-repeating long unsigned integers */
- case KM_TAG_RSA_PUBLIC_EXPONENT:
- integer_ptr = &record->rsa_public_exponent;
- break;
-
- /* Dates */
- case KM_TAG_ACTIVE_DATETIME:
- integer_ptr = &record->active_date_time;
- break;
- case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
- integer_ptr = &record->origination_expire_date_time;
- break;
- case KM_TAG_USAGE_EXPIRE_DATETIME:
- integer_ptr = &record->usage_expire_date_time;
- break;
- case KM_TAG_CREATION_DATETIME:
- integer_ptr = &record->creation_date_time;
- break;
-
- /* Booleans */
- case KM_TAG_NO_AUTH_REQUIRED:
- bool_ptr = &record->no_auth_required;
- break;
- case KM_TAG_ALL_APPLICATIONS:
- bool_ptr = &record->all_applications;
- break;
- case KM_TAG_ROLLBACK_RESISTANT:
- bool_ptr = &record->rollback_resistant;
- break;
- case KM_TAG_ALLOW_WHILE_ON_BODY:
- bool_ptr = &record->allow_while_on_body;
- break;
-
- /* Byte arrays*/
- case KM_TAG_APPLICATION_ID:
- string_ptr = &record->application_id;
- break;
- default:
- break;
- }
-
- keymaster_tag_type_t type = keymaster_tag_get_type(entry.tag);
- switch (type) {
- case KM_ENUM:
- case KM_ENUM_REP:
- case KM_UINT:
- case KM_UINT_REP: {
- assert((keymaster_tag_repeatable(entry.tag) && integer_set) ||
- (!keymaster_tag_repeatable(entry.tag) && integer_ptr));
-
- UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(ASN1_INTEGER_new());
- if (!value.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!ASN1_INTEGER_set(value.get(), get_uint32_value(entry)))
- return TranslateLastOpenSslError();
-
- insert_integer(value.release(), integer_ptr, integer_set);
- break;
- }
-
- case KM_ULONG:
- case KM_ULONG_REP:
- case KM_DATE: {
- assert((keymaster_tag_repeatable(entry.tag) && integer_set) ||
- (!keymaster_tag_repeatable(entry.tag) && integer_ptr));
-
- UniquePtr<BIGNUM, BIGNUM_Delete> bn_value(BN_new());
- if (!bn_value.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- if (type == KM_DATE) {
- if (!BN_set_u64(bn_value.get(), entry.date_time)) {
- return TranslateLastOpenSslError();
- }
- } else {
- if (!BN_set_u64(bn_value.get(), entry.long_integer)) {
- return TranslateLastOpenSslError();
- }
- }
-
- UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(
- BN_to_ASN1_INTEGER(bn_value.get(), nullptr));
- if (!value.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- insert_integer(value.release(), integer_ptr, integer_set);
- break;
- }
-
- case KM_BOOL:
- assert(bool_ptr);
- if (!*bool_ptr)
- *bool_ptr = ASN1_NULL_new();
- if (!*bool_ptr)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- break;
-
- /* Byte arrays*/
- case KM_BYTES:
- assert(string_ptr);
- if (!*string_ptr)
- *string_ptr = ASN1_OCTET_STRING_new();
- if (!*string_ptr)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!ASN1_OCTET_STRING_set(*string_ptr, entry.blob.data, entry.blob.data_length))
- return TranslateLastOpenSslError();
- break;
-
- default:
- return KM_ERROR_UNIMPLEMENTED;
- }
- }
-
- keymaster_ec_curve_t ec_curve;
- uint32_t key_size;
- if (auth_list.Contains(TAG_ALGORITHM, KM_ALGORITHM_EC) && //
- !auth_list.Contains(TAG_EC_CURVE) && //
- auth_list.GetTagValue(TAG_KEY_SIZE, &key_size)) {
- // This must be a keymaster1 key. It's an EC key with no curve. Insert the curve.
-
- keymaster_error_t error = EcKeySizeToCurve(key_size, &ec_curve);
- if (error != KM_ERROR_OK)
- return error;
-
- UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(ASN1_INTEGER_new());
- if (!value.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- if (!ASN1_INTEGER_set(value.get(), ec_curve))
- return TranslateLastOpenSslError();
-
- insert_integer(value.release(), &record->ec_curve, nullptr);
- }
-
- return KM_ERROR_OK;
-}
-
-// Construct an ASN1.1 DER-encoded attestation record containing the values from sw_enforced and
-// tee_enforced.
-keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
- const AuthorizationSet& sw_enforced,
- const AuthorizationSet& tee_enforced,
- const KeymasterContext& context,
- UniquePtr<uint8_t[]>* asn1_key_desc,
- size_t* asn1_key_desc_len) {
- assert(asn1_key_desc && asn1_key_desc_len);
-
- UniquePtr<KM_KEY_DESCRIPTION, KM_KEY_DESCRIPTION_Delete> key_desc(KM_KEY_DESCRIPTION_new());
- if (!key_desc.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- keymaster_security_level_t keymaster_security_level;
- uint32_t keymaster_version = UINT32_MAX;
- if (tee_enforced.empty()) {
- // Software key.
- keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
- keymaster_version = 2;
- } else {
- keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
- switch (context.GetSecurityLevel()) {
- case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT:
- // We're running in a TEE, so the key is KM2.
- keymaster_version = 2;
- break;
-
- case KM_SECURITY_LEVEL_SOFTWARE:
- // We're running in software, wrapping some KM hardware. Is it KM0 or KM1? KM1 keys
- // have the purpose in the tee_enforced list. It's possible that a key could be created
- // without a purpose, which would fool this test into reporting it's a KM0 key. That
- // corner case doesn't matter much, because purpose-less keys are not usable anyway.
- // Also, KM1 TEEs should disappear rapidly.
- keymaster_version = tee_enforced.Contains(TAG_PURPOSE) ? 1 : 0;
- break;
- }
-
- if (keymaster_version == UINT32_MAX)
- return KM_ERROR_UNKNOWN_ERROR;
- }
-
- if (!ASN1_INTEGER_set(key_desc->attestation_version, 1) ||
- !ASN1_ENUMERATED_set(key_desc->attestation_security_level, context.GetSecurityLevel()) ||
- !ASN1_INTEGER_set(key_desc->keymaster_version, keymaster_version) ||
- !ASN1_ENUMERATED_set(key_desc->keymaster_security_level, keymaster_security_level))
- return TranslateLastOpenSslError();
-
- keymaster_blob_t attestation_challenge = {nullptr, 0};
- if (!attestation_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge))
- return KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
- if (!ASN1_OCTET_STRING_set(key_desc->attestation_challenge, attestation_challenge.data,
- attestation_challenge.data_length))
- return TranslateLastOpenSslError();
-
- keymaster_error_t error = build_auth_list(sw_enforced, key_desc->software_enforced);
- if (error != KM_ERROR_OK)
- return error;
-
- error = build_auth_list(tee_enforced, key_desc->tee_enforced);
- if (error != KM_ERROR_OK)
- return error;
-
- // Only check tee_enforced for TAG_INCLUDE_UNIQUE_ID. If we don't have hardware we can't
- // generate unique IDs.
- if (tee_enforced.GetTagValue(TAG_INCLUDE_UNIQUE_ID)) {
- uint64_t creation_datetime;
- // Only check sw_enforced for TAG_CREATION_DATETIME, since it shouldn't be in tee_enforced,
- // since this implementation has no secure wall clock.
- if (!sw_enforced.GetTagValue(TAG_CREATION_DATETIME, &creation_datetime)) {
- LOG_E("Unique ID cannot be created without creation datetime", 0);
- return KM_ERROR_INVALID_KEY_BLOB;
- }
-
- keymaster_blob_t application_id = {nullptr, 0};
- sw_enforced.GetTagValue(TAG_APPLICATION_ID, &application_id);
-
- Buffer unique_id;
- error = context.GenerateUniqueId(
- creation_datetime, application_id,
- attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION), &unique_id);
- if (error != KM_ERROR_OK)
- return error;
-
- key_desc->unique_id = ASN1_OCTET_STRING_new();
- if (!key_desc->unique_id ||
- !ASN1_OCTET_STRING_set(key_desc->unique_id, unique_id.peek_read(),
- unique_id.available_read()))
- return TranslateLastOpenSslError();
- }
-
- int len = i2d_KM_KEY_DESCRIPTION(key_desc.get(), nullptr);
- if (len < 0)
- return TranslateLastOpenSslError();
- *asn1_key_desc_len = len;
- asn1_key_desc->reset(new uint8_t[*asn1_key_desc_len]);
- if (!asn1_key_desc->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- uint8_t* p = asn1_key_desc->get();
- len = i2d_KM_KEY_DESCRIPTION(key_desc.get(), &p);
- if (len < 0)
- return TranslateLastOpenSslError();
-
- return KM_ERROR_OK;
-}
-
-// Copy all enumerated values with the specified tag from stack to auth_list.
-static bool get_repeated_enums(const stack_st_ASN1_INTEGER* stack, keymaster_tag_t tag,
- AuthorizationSet* auth_list) {
- assert(keymaster_tag_get_type(tag) == KM_ENUM_REP);
- for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) {
- if (!auth_list->push_back(
- keymaster_param_enum(tag, ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i)))))
- return false;
- }
- return true;
-}
-
-// Add the specified integer tag/value pair to auth_list.
-template <keymaster_tag_type_t Type, keymaster_tag_t Tag, typename KeymasterEnum>
-static bool get_enum(const ASN1_INTEGER* asn1_int, TypedEnumTag<Type, Tag, KeymasterEnum> tag,
- AuthorizationSet* auth_list) {
- if (!asn1_int)
- return true;
- return auth_list->push_back(tag, static_cast<KeymasterEnum>(ASN1_INTEGER_get(asn1_int)));
-}
-
-// Add the specified ulong tag/value pair to auth_list.
-static bool get_ulong(const ASN1_INTEGER* asn1_int, keymaster_tag_t tag,
- AuthorizationSet* auth_list) {
- if (!asn1_int)
- return true;
- UniquePtr<BIGNUM, BIGNUM_Delete> bn(ASN1_INTEGER_to_BN(asn1_int, nullptr));
- if (!bn.get())
- return false;
- uint64_t ulong = BN_get_word(bn.get());
- return auth_list->push_back(keymaster_param_long(tag, ulong));
-}
-
-// Extract the values from the specified ASN.1 record and place them in auth_list.
-static keymaster_error_t extract_auth_list(const KM_AUTH_LIST* record,
- AuthorizationSet* auth_list) {
- if (!record)
- return KM_ERROR_OK;
-
- // Purpose
- if (!get_repeated_enums(record->purpose, TAG_PURPOSE, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Algorithm
- if (!get_enum(record->algorithm, TAG_ALGORITHM, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Key size
- if (record->key_size && !auth_list->push_back(TAG_KEY_SIZE, ASN1_INTEGER_get(record->key_size)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Digest
- if (!get_repeated_enums(record->digest, TAG_DIGEST, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Padding
- if (!get_repeated_enums(record->padding, TAG_PADDING, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // EC curve
- if (!get_enum(record->ec_curve, TAG_EC_CURVE, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // RSA public exponent
- if (!get_ulong(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Active date time
- if (!get_ulong(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Origination expire date time
- if (!get_ulong(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME,
- auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Usage Expire date time
- if (!get_ulong(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // No auth required
- if (record->no_auth_required && !auth_list->push_back(TAG_NO_AUTH_REQUIRED))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // User auth type
- if (!get_enum(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Auth timeout
- if (record->auth_timeout &&
- !auth_list->push_back(TAG_AUTH_TIMEOUT, ASN1_INTEGER_get(record->auth_timeout)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // All applications
- if (record->all_applications && !auth_list->push_back(TAG_ALL_APPLICATIONS))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Application ID
- if (record->application_id &&
- !auth_list->push_back(TAG_APPLICATION_ID, record->application_id->data,
- record->application_id->length))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Creation date time
- if (!get_ulong(record->creation_date_time, TAG_CREATION_DATETIME, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Origin
- if (!get_enum(record->origin, TAG_ORIGIN, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Rollback resistant
- if (record->rollback_resistant && !auth_list->push_back(TAG_ROLLBACK_RESISTANT))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Root of trust
- if (record->root_of_trust) {
- KM_ROOT_OF_TRUST* rot = record->root_of_trust;
- if (!rot->verified_boot_key)
- return KM_ERROR_INVALID_KEY_BLOB;
-
- // Other root of trust fields are not mapped to auth set entries.
- }
-
- // OS Version
- if (record->os_version &&
- !auth_list->push_back(TAG_OS_VERSION, ASN1_INTEGER_get(record->os_version)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // OS Patch level
- if (record->os_patchlevel &&
- !auth_list->push_back(TAG_OS_PATCHLEVEL, ASN1_INTEGER_get(record->os_patchlevel)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- return KM_ERROR_OK;
-}
-
-// Parse the DER-encoded attestation record, placing the results in keymaster_version,
-// attestation_challenge, software_enforced, tee_enforced and unique_id.
-keymaster_error_t parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
- uint32_t* attestation_version, //
- keymaster_security_level_t* attestation_security_level,
- uint32_t* keymaster_version,
- keymaster_security_level_t* keymaster_security_level,
- keymaster_blob_t* attestation_challenge,
- AuthorizationSet* software_enforced,
- AuthorizationSet* tee_enforced,
- keymaster_blob_t* unique_id) {
- const uint8_t* p = asn1_key_desc;
- UniquePtr<KM_KEY_DESCRIPTION, KM_KEY_DESCRIPTION_Delete> record(
- d2i_KM_KEY_DESCRIPTION(nullptr, &p, asn1_key_desc_len));
- if (!record.get())
- return TranslateLastOpenSslError();
-
- *attestation_version = ASN1_INTEGER_get(record->attestation_version);
- *attestation_security_level = static_cast<keymaster_security_level_t>(
- ASN1_ENUMERATED_get(record->attestation_security_level));
- *keymaster_version = ASN1_INTEGER_get(record->keymaster_version);
- *keymaster_security_level = static_cast<keymaster_security_level_t>(
- ASN1_ENUMERATED_get(record->keymaster_security_level));
-
- attestation_challenge->data =
- dup_buffer(record->attestation_challenge->data, record->attestation_challenge->length);
- attestation_challenge->data_length = record->attestation_challenge->length;
-
- unique_id->data = dup_buffer(record->unique_id->data, record->unique_id->length);
- unique_id->data_length = record->unique_id->length;
-
- keymaster_error_t error = extract_auth_list(record->software_enforced, software_enforced);
- if (error != KM_ERROR_OK)
- return error;
-
- return extract_auth_list(record->tee_enforced, tee_enforced);
-}
-
-} // namepace keymaster