mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 15:58:43 +00:00
Revert "Revert "Add keymaster VTS tests.""
This reverts commit 8e10baee45.
Test: Tests pass, except known failures with in-progress vendor fixes
Change-Id: Ia95c1444100e123fa65d095b001878cf9040d0c4
This commit is contained in:
@@ -698,14 +698,21 @@ Return<ErrorCode> KeymasterDevice::abort(uint64_t operationHandle) {
|
||||
return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
|
||||
}
|
||||
|
||||
IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* /* name */) {
|
||||
IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* name) {
|
||||
keymaster2_device_t* dev = nullptr;
|
||||
|
||||
uint32_t version;
|
||||
bool supports_ec;
|
||||
bool supports_all_digests;
|
||||
auto rc = keymaster_device_initialize(&dev, &version, &supports_ec, &supports_all_digests);
|
||||
if (rc) return nullptr;
|
||||
ALOGI("Fetching keymaster device name %s", name);
|
||||
|
||||
uint32_t version = -1;
|
||||
bool supports_ec = false;
|
||||
bool supports_all_digests = false;
|
||||
|
||||
if (name && strcmp(name, "softwareonly") == 0) {
|
||||
dev = (new SoftKeymasterDevice(new SoftwareOnlyHidlKeymasterContext))->keymaster2_device();
|
||||
} else if (name && strcmp(name, "default") == 0) {
|
||||
auto rc = keymaster_device_initialize(&dev, &version, &supports_ec, &supports_all_digests);
|
||||
if (rc) return nullptr;
|
||||
}
|
||||
|
||||
auto kmrc = ::keymaster::ConfigureDevice(dev);
|
||||
if (kmrc != KM_ERROR_OK) {
|
||||
|
||||
39
keymaster/3.0/vts/functional/Android.mk
Normal file
39
keymaster/3.0/vts/functional/Android.mk
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (C) 2017 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.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := keymaster_hidl_hal_test
|
||||
LOCAL_SRC_FILES := \
|
||||
authorization_set.cpp \
|
||||
attestation_record.cpp \
|
||||
key_param_output.cpp \
|
||||
keymaster_hidl_hal_test.cpp \
|
||||
keystore_tags_utils.cpp \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
android.hardware.keymaster@3.0 \
|
||||
libcrypto \
|
||||
libhidlbase \
|
||||
liblog \
|
||||
libsoftkeymasterdevice \
|
||||
libutils \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
VtsHalHidlTargetTestBase \
|
||||
|
||||
LOCAL_CFLAGS := -Wall -Werror
|
||||
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
289
keymaster/3.0/vts/functional/attestation_record.cpp
Normal file
289
keymaster/3.0/vts/functional/attestation_record.cpp
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "openssl_utils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace keymaster {
|
||||
namespace V3_0 {
|
||||
|
||||
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;
|
||||
ASN1_OCTET_STRING* attestation_application_id;
|
||||
} KM_AUTH_LIST;
|
||||
|
||||
ASN1_SEQUENCE(KM_AUTH_LIST) = {
|
||||
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
|
||||
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
|
||||
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
|
||||
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, kdf, ASN1_INTEGER, TAG_KDF.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
|
||||
TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
|
||||
TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
|
||||
TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL, TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, all_applications, ASN1_NULL, TAG_ALL_APPLICATIONS.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, application_id, ASN1_OCTET_STRING, TAG_APPLICATION_ID.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER, TAG_CREATION_DATETIME.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistant, ASN1_NULL, TAG_ROLLBACK_RESISTANT.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
|
||||
TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
|
||||
} 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);
|
||||
|
||||
template <Tag tag>
|
||||
void copyAuthTag(const stack_st_ASN1_INTEGER* stack, TypedTag<TagType::ENUM_REP, tag> ttag,
|
||||
AuthorizationSet* auth_list) {
|
||||
typedef typename TypedTag2ValueType<decltype(ttag)>::type ValueT;
|
||||
for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) {
|
||||
auth_list->push_back(
|
||||
ttag, static_cast<ValueT>(ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i))));
|
||||
}
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ENUM, tag> ttag,
|
||||
AuthorizationSet* auth_list) {
|
||||
typedef typename TypedTag2ValueType<decltype(ttag)>::type ValueT;
|
||||
if (!asn1_int) return;
|
||||
auth_list->push_back(ttag, static_cast<ValueT>(ASN1_INTEGER_get(asn1_int)));
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::UINT, tag> ttag,
|
||||
AuthorizationSet* auth_list) {
|
||||
if (!asn1_int) return;
|
||||
auth_list->push_back(ttag, ASN1_INTEGER_get(asn1_int));
|
||||
}
|
||||
|
||||
BIGNUM* construct_uint_max() {
|
||||
BIGNUM* value = BN_new();
|
||||
BIGNUM_Ptr one(BN_new());
|
||||
BN_one(one.get());
|
||||
BN_lshift(value, one.get(), 32);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t BignumToUint64(BIGNUM* num) {
|
||||
static_assert((sizeof(BN_ULONG) == sizeof(uint32_t)) || (sizeof(BN_ULONG) == sizeof(uint64_t)),
|
||||
"This implementation only supports 32 and 64-bit BN_ULONG");
|
||||
if (sizeof(BN_ULONG) == sizeof(uint32_t)) {
|
||||
BIGNUM_Ptr uint_max(construct_uint_max());
|
||||
BIGNUM_Ptr hi(BN_new()), lo(BN_new());
|
||||
BN_CTX_Ptr ctx(BN_CTX_new());
|
||||
BN_div(hi.get(), lo.get(), num, uint_max.get(), ctx.get());
|
||||
return static_cast<uint64_t>(BN_get_word(hi.get())) << 32 | BN_get_word(lo.get());
|
||||
} else if (sizeof(BN_ULONG) == sizeof(uint64_t)) {
|
||||
return BN_get_word(num);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ULONG, tag> ttag,
|
||||
AuthorizationSet* auth_list) {
|
||||
if (!asn1_int) return;
|
||||
BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
|
||||
auth_list->push_back(ttag, BignumToUint64(num.get()));
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::DATE, tag> ttag,
|
||||
AuthorizationSet* auth_list) {
|
||||
if (!asn1_int) return;
|
||||
BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
|
||||
auth_list->push_back(ttag, BignumToUint64(num.get()));
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
void copyAuthTag(const ASN1_NULL* asn1_null, TypedTag<TagType::BOOL, tag> ttag,
|
||||
AuthorizationSet* auth_list) {
|
||||
if (!asn1_null) return;
|
||||
auth_list->push_back(ttag);
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
void copyAuthTag(const ASN1_OCTET_STRING* asn1_string, TypedTag<TagType::BYTES, tag> ttag,
|
||||
AuthorizationSet* auth_list) {
|
||||
if (!asn1_string) return;
|
||||
hidl_vec<uint8_t> buf;
|
||||
buf.setToExternal(asn1_string->data, asn1_string->length);
|
||||
auth_list->push_back(ttag, buf);
|
||||
}
|
||||
|
||||
// Extract the values from the specified ASN.1 record and place them in auth_list.
|
||||
static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
|
||||
if (!record) return ErrorCode::OK;
|
||||
|
||||
copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
|
||||
copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
|
||||
copyAuthTag(record->all_applications, TAG_ALL_APPLICATIONS, auth_list);
|
||||
copyAuthTag(record->application_id, TAG_APPLICATION_ID, auth_list);
|
||||
copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
|
||||
copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
|
||||
copyAuthTag(record->digest, TAG_DIGEST, auth_list);
|
||||
copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
|
||||
copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
|
||||
copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
|
||||
copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
|
||||
copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
|
||||
copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
|
||||
copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
|
||||
copyAuthTag(record->padding, TAG_PADDING, auth_list);
|
||||
copyAuthTag(record->purpose, TAG_PURPOSE, auth_list);
|
||||
copyAuthTag(record->rollback_resistant, TAG_ROLLBACK_RESISTANT, auth_list);
|
||||
copyAuthTag(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list);
|
||||
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
|
||||
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
|
||||
|
||||
return ErrorCode::OK;
|
||||
}
|
||||
|
||||
MAKE_OPENSSL_PTR_TYPE(KM_KEY_DESCRIPTION)
|
||||
|
||||
// Parse the DER-encoded attestation record, placing the results in keymaster_version,
|
||||
// attestation_challenge, software_enforced, tee_enforced and unique_id.
|
||||
ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
|
||||
uint32_t* attestation_version, //
|
||||
SecurityLevel* attestation_security_level,
|
||||
uint32_t* keymaster_version,
|
||||
SecurityLevel* keymaster_security_level,
|
||||
hidl_vec<uint8_t>* attestation_challenge,
|
||||
AuthorizationSet* software_enforced,
|
||||
AuthorizationSet* tee_enforced, //
|
||||
hidl_vec<uint8_t>* unique_id) {
|
||||
const uint8_t* p = asn1_key_desc;
|
||||
KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, asn1_key_desc_len));
|
||||
if (!record.get()) return ErrorCode::UNKNOWN_ERROR;
|
||||
|
||||
*attestation_version = ASN1_INTEGER_get(record->attestation_version);
|
||||
*attestation_security_level =
|
||||
static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->attestation_security_level));
|
||||
*keymaster_version = ASN1_INTEGER_get(record->keymaster_version);
|
||||
*keymaster_security_level =
|
||||
static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->keymaster_security_level));
|
||||
|
||||
attestation_challenge->setToExternal(record->attestation_challenge->data,
|
||||
record->attestation_challenge->length);
|
||||
|
||||
unique_id->setToExternal(record->unique_id->data, record->unique_id->length);
|
||||
|
||||
ErrorCode error = extract_auth_list(record->software_enforced, software_enforced);
|
||||
if (error != ErrorCode::OK) return error;
|
||||
|
||||
return extract_auth_list(record->tee_enforced, tee_enforced);
|
||||
}
|
||||
|
||||
} // namespace V3_0
|
||||
} // namespace keymaster
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
57
keymaster/3.0/vts/functional/attestation_record.h
Normal file
57
keymaster/3.0/vts/functional/attestation_record.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_ATTESTATION_RECORD_H_
|
||||
#define HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_ATTESTATION_RECORD_H_
|
||||
|
||||
#include "authorization_set.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace keymaster {
|
||||
namespace V3_0 {
|
||||
|
||||
/**
|
||||
* The OID for Android attestation records. For the curious, it breaks down as follows:
|
||||
*
|
||||
* 1 = ISO
|
||||
* 3 = org
|
||||
* 6 = DoD (Huh? OIDs are weird.)
|
||||
* 1 = IANA
|
||||
* 4 = Private
|
||||
* 1 = Enterprises
|
||||
* 11129 = Google
|
||||
* 2 = Google security
|
||||
* 1 = certificate extension
|
||||
* 17 = Android attestation extension.
|
||||
*/
|
||||
static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17";
|
||||
|
||||
ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
|
||||
uint32_t* attestation_version, //
|
||||
SecurityLevel* attestation_security_level,
|
||||
uint32_t* keymaster_version,
|
||||
SecurityLevel* keymaster_security_level,
|
||||
hidl_vec<uint8_t>* attestation_challenge,
|
||||
AuthorizationSet* software_enforced,
|
||||
AuthorizationSet* tee_enforced, //
|
||||
hidl_vec<uint8_t>* unique_id);
|
||||
} // namespace V3_0
|
||||
} // namespace keymaster
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_ATTESTATION_RECORD_H_
|
||||
422
keymaster/3.0/vts/functional/authorization_set.cpp
Normal file
422
keymaster/3.0/vts/functional/authorization_set.cpp
Normal file
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "authorization_set.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <istream>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace keymaster {
|
||||
namespace V3_0 {
|
||||
|
||||
inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
|
||||
if (a.tag != b.tag) return a.tag < b.tag;
|
||||
int retval;
|
||||
switch (typeFromTag(a.tag)) {
|
||||
case TagType::INVALID:
|
||||
case TagType::BOOL:
|
||||
return false;
|
||||
case TagType::ENUM:
|
||||
case TagType::ENUM_REP:
|
||||
case TagType::UINT:
|
||||
case TagType::UINT_REP:
|
||||
return a.f.integer < b.f.integer;
|
||||
case TagType::ULONG:
|
||||
case TagType::ULONG_REP:
|
||||
return a.f.longInteger < b.f.longInteger;
|
||||
case TagType::DATE:
|
||||
return a.f.dateTime < b.f.dateTime;
|
||||
case TagType::BIGNUM:
|
||||
case TagType::BYTES:
|
||||
// Handle the empty cases.
|
||||
if (a.blob.size() == 0) return b.blob.size() != 0;
|
||||
if (b.blob.size() == 0) return false;
|
||||
|
||||
retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
|
||||
if (retval == 0) {
|
||||
// One is the prefix of the other, so the longer wins
|
||||
return a.blob.size() < b.blob.size();
|
||||
} else {
|
||||
return retval < 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
|
||||
if (a.tag != b.tag) return false;
|
||||
|
||||
switch (typeFromTag(a.tag)) {
|
||||
case TagType::INVALID:
|
||||
case TagType::BOOL:
|
||||
return true;
|
||||
case TagType::ENUM:
|
||||
case TagType::ENUM_REP:
|
||||
case TagType::UINT:
|
||||
case TagType::UINT_REP:
|
||||
return a.f.integer == b.f.integer;
|
||||
case TagType::ULONG:
|
||||
case TagType::ULONG_REP:
|
||||
return a.f.longInteger == b.f.longInteger;
|
||||
case TagType::DATE:
|
||||
return a.f.dateTime == b.f.dateTime;
|
||||
case TagType::BIGNUM:
|
||||
case TagType::BYTES:
|
||||
if (a.blob.size() != b.blob.size()) return false;
|
||||
return a.blob.size() == 0 || memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AuthorizationSet::Sort() {
|
||||
std::sort(data_.begin(), data_.end(), keyParamLess);
|
||||
}
|
||||
|
||||
void AuthorizationSet::Deduplicate() {
|
||||
if (data_.empty()) return;
|
||||
|
||||
Sort();
|
||||
std::vector<KeyParameter> result;
|
||||
|
||||
auto curr = data_.begin();
|
||||
auto prev = curr++;
|
||||
for (; curr != data_.end(); ++prev, ++curr) {
|
||||
if (prev->tag == Tag::INVALID) continue;
|
||||
|
||||
if (!keyParamEqual(*prev, *curr)) {
|
||||
result.emplace_back(std::move(*prev));
|
||||
}
|
||||
}
|
||||
result.emplace_back(std::move(*prev));
|
||||
|
||||
std::swap(data_, result);
|
||||
}
|
||||
|
||||
void AuthorizationSet::Union(const AuthorizationSet& other) {
|
||||
data_.insert(data_.end(), other.data_.begin(), other.data_.end());
|
||||
Deduplicate();
|
||||
}
|
||||
|
||||
void AuthorizationSet::Subtract(const AuthorizationSet& other) {
|
||||
Deduplicate();
|
||||
|
||||
auto i = other.begin();
|
||||
while (i != other.end()) {
|
||||
int pos = -1;
|
||||
do {
|
||||
pos = find(i->tag, pos);
|
||||
if (pos != -1 && keyParamEqual(*i, data_[pos])) {
|
||||
data_.erase(data_.begin() + pos);
|
||||
break;
|
||||
}
|
||||
} while (pos != -1);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
int AuthorizationSet::find(Tag tag, int begin) const {
|
||||
auto iter = data_.begin() + (1 + begin);
|
||||
|
||||
while (iter != data_.end() && iter->tag != tag)
|
||||
++iter;
|
||||
|
||||
if (iter != data_.end()) return iter - data_.begin();
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool AuthorizationSet::erase(int index) {
|
||||
auto pos = data_.begin() + index;
|
||||
if (pos != data_.end()) {
|
||||
data_.erase(pos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyParameter& AuthorizationSet::operator[](int at) {
|
||||
return data_[at];
|
||||
}
|
||||
|
||||
const KeyParameter& AuthorizationSet::operator[](int at) const {
|
||||
return data_[at];
|
||||
}
|
||||
|
||||
void AuthorizationSet::Clear() {
|
||||
data_.clear();
|
||||
}
|
||||
|
||||
size_t AuthorizationSet::GetTagCount(Tag tag) const {
|
||||
size_t count = 0;
|
||||
for (int pos = -1; (pos = find(tag, pos)) != -1;)
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
|
||||
int pos = find(tag);
|
||||
if (pos == -1) return {};
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
/**
|
||||
* Persistent format is:
|
||||
* | 32 bit indirect_size |
|
||||
* --------------------------------
|
||||
* | indirect_size bytes of data | this is where the blob data is stored
|
||||
* --------------------------------
|
||||
* | 32 bit element_count | number of entries
|
||||
* | 32 bit elements_size | total bytes used by entries (entries have variable length)
|
||||
* --------------------------------
|
||||
* | elementes_size bytes of data | where the elements are stored
|
||||
*/
|
||||
|
||||
/**
|
||||
* Persistent format of blobs and bignums:
|
||||
* | 32 bit tag |
|
||||
* | 32 bit blob_length |
|
||||
* | 32 bit indirect_offset |
|
||||
*/
|
||||
|
||||
struct OutStreams {
|
||||
std::ostream& indirect;
|
||||
std::ostream& elements;
|
||||
};
|
||||
|
||||
OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) {
|
||||
uint32_t buffer;
|
||||
|
||||
// write blob_length
|
||||
auto blob_length = blob.size();
|
||||
if (blob_length > std::numeric_limits<uint32_t>::max()) {
|
||||
out.elements.setstate(std::ios_base::badbit);
|
||||
return out;
|
||||
}
|
||||
buffer = blob_length;
|
||||
out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
|
||||
|
||||
// write indirect_offset
|
||||
auto offset = out.indirect.tellp();
|
||||
if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() ||
|
||||
static_cast<uint32_t>((std::numeric_limits<uint32_t>::max() - offset)) <
|
||||
blob_length) { // overflow check
|
||||
out.elements.setstate(std::ios_base::badbit);
|
||||
return out;
|
||||
}
|
||||
buffer = offset;
|
||||
out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
|
||||
|
||||
// write blob to indirect stream
|
||||
if (blob_length) out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename T> OutStreams& serializeParamValue(OutStreams& out, const T& value) {
|
||||
out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T));
|
||||
return out;
|
||||
}
|
||||
|
||||
OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
|
||||
// skip invalid entries.
|
||||
return out;
|
||||
}
|
||||
template <typename T> OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) {
|
||||
out.elements.write(reinterpret_cast<const char*>(¶m.tag), sizeof(int32_t));
|
||||
return serializeParamValue(out, accessTagValue(ttag, param));
|
||||
}
|
||||
|
||||
template <typename... T> struct choose_serializer;
|
||||
template <typename... Tags> struct choose_serializer<MetaList<Tags...>> {
|
||||
static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
|
||||
return choose_serializer<Tags...>::serialize(out, param);
|
||||
}
|
||||
};
|
||||
template <> struct choose_serializer<> {
|
||||
static OutStreams& serialize(OutStreams& out, const KeyParameter&) { return out; }
|
||||
};
|
||||
template <TagType tag_type, Tag tag, typename... Tail>
|
||||
struct choose_serializer<TypedTag<tag_type, tag>, Tail...> {
|
||||
static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
|
||||
if (param.tag == tag) {
|
||||
return V3_0::serialize(TypedTag<tag_type, tag>(), out, param);
|
||||
} else {
|
||||
return choose_serializer<Tail...>::serialize(out, param);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
|
||||
return choose_serializer<all_tags_t>::serialize(out, param);
|
||||
}
|
||||
|
||||
std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
|
||||
std::stringstream indirect;
|
||||
std::stringstream elements;
|
||||
OutStreams streams = {indirect, elements};
|
||||
for (const auto& param : params) {
|
||||
serialize(streams, param);
|
||||
}
|
||||
if (indirect.bad() || elements.bad()) {
|
||||
out.setstate(std::ios_base::badbit);
|
||||
return out;
|
||||
}
|
||||
auto pos = indirect.tellp();
|
||||
if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
|
||||
out.setstate(std::ios_base::badbit);
|
||||
return out;
|
||||
}
|
||||
uint32_t indirect_size = pos;
|
||||
pos = elements.tellp();
|
||||
if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
|
||||
out.setstate(std::ios_base::badbit);
|
||||
return out;
|
||||
}
|
||||
uint32_t elements_size = pos;
|
||||
uint32_t element_count = params.size();
|
||||
|
||||
out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));
|
||||
|
||||
pos = out.tellp();
|
||||
if (indirect_size) out << indirect.rdbuf();
|
||||
assert(out.tellp() - pos == indirect_size);
|
||||
|
||||
out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t));
|
||||
out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t));
|
||||
|
||||
pos = out.tellp();
|
||||
if (elements_size) out << elements.rdbuf();
|
||||
assert(out.tellp() - pos == elements_size);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
struct InStreams {
|
||||
std::istream& indirect;
|
||||
std::istream& elements;
|
||||
};
|
||||
|
||||
InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) {
|
||||
uint32_t blob_length = 0;
|
||||
uint32_t offset = 0;
|
||||
in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t));
|
||||
blob->resize(blob_length);
|
||||
in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t));
|
||||
in.indirect.seekg(offset);
|
||||
in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size());
|
||||
return in;
|
||||
}
|
||||
|
||||
template <typename T> InStreams& deserializeParamValue(InStreams& in, T* value) {
|
||||
in.elements.read(reinterpret_cast<char*>(value), sizeof(T));
|
||||
return in;
|
||||
}
|
||||
|
||||
InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
|
||||
// there should be no invalid KeyParamaters but if handle them as zero sized.
|
||||
return in;
|
||||
}
|
||||
|
||||
template <typename T> InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) {
|
||||
return deserializeParamValue(in, &accessTagValue(ttag, *param));
|
||||
}
|
||||
|
||||
template <typename... T> struct choose_deserializer;
|
||||
template <typename... Tags> struct choose_deserializer<MetaList<Tags...>> {
|
||||
static InStreams& deserialize(InStreams& in, KeyParameter* param) {
|
||||
return choose_deserializer<Tags...>::deserialize(in, param);
|
||||
}
|
||||
};
|
||||
template <> struct choose_deserializer<> {
|
||||
static InStreams& deserialize(InStreams& in, KeyParameter*) {
|
||||
// encountered an unknown tag -> fail parsing
|
||||
in.elements.setstate(std::ios_base::badbit);
|
||||
return in;
|
||||
}
|
||||
};
|
||||
template <TagType tag_type, Tag tag, typename... Tail>
|
||||
struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> {
|
||||
static InStreams& deserialize(InStreams& in, KeyParameter* param) {
|
||||
if (param->tag == tag) {
|
||||
return V3_0::deserialize(TypedTag<tag_type, tag>(), in, param);
|
||||
} else {
|
||||
return choose_deserializer<Tail...>::deserialize(in, param);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
InStreams& deserialize(InStreams& in, KeyParameter* param) {
|
||||
in.elements.read(reinterpret_cast<char*>(¶m->tag), sizeof(Tag));
|
||||
return choose_deserializer<all_tags_t>::deserialize(in, param);
|
||||
}
|
||||
|
||||
std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) {
|
||||
uint32_t indirect_size = 0;
|
||||
in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t));
|
||||
std::string indirect_buffer(indirect_size, '\0');
|
||||
if (indirect_buffer.size() != indirect_size) {
|
||||
in.setstate(std::ios_base::badbit);
|
||||
return in;
|
||||
}
|
||||
in.read(&indirect_buffer[0], indirect_buffer.size());
|
||||
|
||||
uint32_t element_count = 0;
|
||||
in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t));
|
||||
uint32_t elements_size = 0;
|
||||
in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t));
|
||||
|
||||
std::string elements_buffer(elements_size, '\0');
|
||||
if (elements_buffer.size() != elements_size) {
|
||||
in.setstate(std::ios_base::badbit);
|
||||
return in;
|
||||
}
|
||||
in.read(&elements_buffer[0], elements_buffer.size());
|
||||
|
||||
if (in.bad()) return in;
|
||||
|
||||
// TODO write one-shot stream buffer to avoid copying here
|
||||
std::stringstream indirect(indirect_buffer);
|
||||
std::stringstream elements(elements_buffer);
|
||||
InStreams streams = {indirect, elements};
|
||||
|
||||
params->resize(element_count);
|
||||
|
||||
for (uint32_t i = 0; i < element_count; ++i) {
|
||||
deserialize(streams, &(*params)[i]);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
void AuthorizationSet::Serialize(std::ostream* out) const {
|
||||
serialize(*out, data_);
|
||||
}
|
||||
|
||||
void AuthorizationSet::Deserialize(std::istream* in) {
|
||||
deserialize(*in, &data_);
|
||||
}
|
||||
|
||||
} // namespace V3_0
|
||||
} // namespace keymaster
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
420
keymaster/3.0/vts/functional/authorization_set.h
Normal file
420
keymaster/3.0/vts/functional/authorization_set.h
Normal file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_AUTHORIZATION_SET_H_
|
||||
#define HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_AUTHORIZATION_SET_H_
|
||||
|
||||
#include "keymaster_tags.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace keymaster {
|
||||
namespace V3_0 {
|
||||
|
||||
class AuthorizationSetBuilder;
|
||||
|
||||
/**
|
||||
* An ordered collection of KeyParameters. It provides memory ownership and some convenient
|
||||
* functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters.
|
||||
* For serialization, wrap the backing store of this structure in a hidl_vec<KeyParameter>.
|
||||
*/
|
||||
class AuthorizationSet {
|
||||
public:
|
||||
typedef KeyParameter value_type;
|
||||
|
||||
/**
|
||||
* Construct an empty, dynamically-allocated, growable AuthorizationSet.
|
||||
*/
|
||||
AuthorizationSet(){};
|
||||
|
||||
// Copy constructor.
|
||||
AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
|
||||
|
||||
// Move constructor.
|
||||
AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {}
|
||||
|
||||
// Constructor from hidl_vec<KeyParameter>
|
||||
AuthorizationSet(const hidl_vec<KeyParameter>& other) { *this = other; }
|
||||
|
||||
// Copy assignment.
|
||||
AuthorizationSet& operator=(const AuthorizationSet& other) {
|
||||
data_ = other.data_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Move assignment.
|
||||
AuthorizationSet& operator=(AuthorizationSet&& other) {
|
||||
data_ = std::move(other.data_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
AuthorizationSet& operator=(const hidl_vec<KeyParameter>& other) {
|
||||
if (other.size() > 0) {
|
||||
data_.resize(other.size());
|
||||
for (size_t i = 0; i < data_.size(); ++i) {
|
||||
/* This makes a deep copy even of embedded blobs.
|
||||
* See assignment operator/copy constructor of hidl_vec.*/
|
||||
data_[i] = other[i];
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear existing authorization set data
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
~AuthorizationSet() = default;
|
||||
|
||||
/**
|
||||
* Returns the size of the set.
|
||||
*/
|
||||
size_t size() const { return data_.size(); }
|
||||
|
||||
/**
|
||||
* Returns true if the set is empty.
|
||||
*/
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
/**
|
||||
* Returns the data in the set, directly. Be careful with this.
|
||||
*/
|
||||
const KeyParameter* data() const { return data_.data(); }
|
||||
|
||||
/**
|
||||
* Sorts the set
|
||||
*/
|
||||
void Sort();
|
||||
|
||||
/**
|
||||
* Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
|
||||
* AuthorizationSetBuilder).
|
||||
*/
|
||||
void Deduplicate();
|
||||
|
||||
/**
|
||||
* Adds all elements from \p set that are not already present in this AuthorizationSet. As a
|
||||
* side-effect, if \p set is not null this AuthorizationSet will end up sorted.
|
||||
*/
|
||||
void Union(const AuthorizationSet& set);
|
||||
|
||||
/**
|
||||
* Removes all elements in \p set from this AuthorizationSet.
|
||||
*/
|
||||
void Subtract(const AuthorizationSet& set);
|
||||
|
||||
/**
|
||||
* Returns the offset of the next entry that matches \p tag, starting from the element after \p
|
||||
* begin. If not found, returns -1.
|
||||
*/
|
||||
int find(Tag tag, int begin = -1) const;
|
||||
|
||||
/**
|
||||
* Removes the entry at the specified index. Returns true if successful, false if the index was
|
||||
* out of bounds.
|
||||
*/
|
||||
bool erase(int index);
|
||||
|
||||
/**
|
||||
* Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
|
||||
*/
|
||||
std::vector<KeyParameter>::const_iterator begin() const { return data_.begin(); }
|
||||
|
||||
/**
|
||||
* Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
|
||||
*/
|
||||
std::vector<KeyParameter>::const_iterator end() const { return data_.end(); }
|
||||
|
||||
/**
|
||||
* Returns the nth element of the set.
|
||||
* Like for std::vector::operator[] there is no range check performed. Use of out of range
|
||||
* indices is undefined.
|
||||
*/
|
||||
KeyParameter& operator[](int n);
|
||||
|
||||
/**
|
||||
* Returns the nth element of the set.
|
||||
* Like for std::vector::operator[] there is no range check performed. Use of out of range
|
||||
* indices is undefined.
|
||||
*/
|
||||
const KeyParameter& operator[](int n) const;
|
||||
|
||||
/**
|
||||
* Returns true if the set contains at least one instance of \p tag
|
||||
*/
|
||||
bool Contains(Tag tag) const { return find(tag) != -1; }
|
||||
|
||||
template <typename T> bool Contains(T tag) const { return find(tag) != -1; }
|
||||
|
||||
template <TagType tag_type, Tag tag, typename ValueT>
|
||||
bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
|
||||
for (const auto& param : data_) {
|
||||
auto entry = authorizationValue(ttag, param);
|
||||
if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns the number of \p tag entries.
|
||||
*/
|
||||
size_t GetTagCount(Tag tag) const;
|
||||
|
||||
template <typename T>
|
||||
inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
|
||||
auto entry = GetEntry(tag);
|
||||
if (entry.isOk()) return authorizationValue(tag, entry.value());
|
||||
return {};
|
||||
}
|
||||
|
||||
void push_back(const KeyParameter& param) { data_.push_back(param); }
|
||||
void push_back(KeyParameter&& param) { data_.push_back(std::move(param)); }
|
||||
|
||||
void push_back(const AuthorizationSet& set) {
|
||||
for (auto& entry : set) {
|
||||
push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(AuthorizationSet&& set) {
|
||||
move(set.begin(), set.end());
|
||||
set.Clear();
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
void push_back(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data, size_t data_length) {
|
||||
hidl_vec<uint8_t> new_blob;
|
||||
new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
|
||||
push_back(ttag, std::move(new_blob));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the tag and enumerated value to the set.
|
||||
* "val" may be exactly one parameter unless a boolean parameter is added.
|
||||
* In this case "val" is omitted. This condition is checked at compile time by Authorization()
|
||||
*/
|
||||
template <typename TypedTagT, typename... Value> void push_back(TypedTagT tag, Value&&... val) {
|
||||
push_back(Authorization(tag, std::forward<Value>(val)...));
|
||||
}
|
||||
|
||||
template <typename Iterator> void push_back(Iterator begin, Iterator end) {
|
||||
while (begin != end) {
|
||||
push_back(*begin);
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator> void move(Iterator begin, Iterator end) {
|
||||
std::move(begin, end, std::back_inserter(data_));
|
||||
}
|
||||
|
||||
hidl_vec<KeyParameter> hidl_data() const {
|
||||
hidl_vec<KeyParameter> result;
|
||||
result.setToExternal(const_cast<KeyParameter*>(data()), size());
|
||||
return result;
|
||||
}
|
||||
|
||||
void Serialize(std::ostream* out) const;
|
||||
void Deserialize(std::istream* in);
|
||||
|
||||
private:
|
||||
NullOr<const KeyParameter&> GetEntry(Tag tag) const;
|
||||
|
||||
std::vector<KeyParameter> data_;
|
||||
};
|
||||
|
||||
class AuthorizationSetBuilder : public AuthorizationSet {
|
||||
public:
|
||||
template <typename TagType, typename... ValueType>
|
||||
AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) {
|
||||
push_back(ttag, std::forward<ValueType>(value)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data,
|
||||
size_t data_length) {
|
||||
hidl_vec<uint8_t> new_blob;
|
||||
new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
|
||||
push_back(ttag, std::move(new_blob));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const char* data,
|
||||
size_t data_length) {
|
||||
return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length);
|
||||
}
|
||||
|
||||
AuthorizationSetBuilder& Authorizations(AuthorizationSet&& set);
|
||||
AuthorizationSetBuilder& Authorizations(const AuthorizationSet& set);
|
||||
|
||||
AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
|
||||
AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
|
||||
AuthorizationSetBuilder& EcdsaKey(EcCurve curve);
|
||||
AuthorizationSetBuilder& AesKey(uint32_t key_size);
|
||||
AuthorizationSetBuilder& HmacKey(uint32_t key_size);
|
||||
|
||||
AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
|
||||
AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
|
||||
AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
|
||||
AuthorizationSetBuilder& EcdsaSigningKey(EcCurve curve);
|
||||
AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
|
||||
|
||||
AuthorizationSetBuilder& SigningKey();
|
||||
AuthorizationSetBuilder& EncryptionKey();
|
||||
AuthorizationSetBuilder& NoDigestOrPadding();
|
||||
AuthorizationSetBuilder& EcbMode();
|
||||
|
||||
AuthorizationSetBuilder& BlockMode(std::initializer_list<BlockMode> block_modes);
|
||||
AuthorizationSetBuilder& Digest(std::initializer_list<Digest> digests);
|
||||
AuthorizationSetBuilder& Padding(std::initializer_list<PaddingMode> padding_modes);
|
||||
|
||||
// The following forwarding templates enable BlockMode,Digest and Padding to be called with a
|
||||
// variable number of arguments; no need to wrap them in braces to make them an initalizer_list.
|
||||
template <typename... T> AuthorizationSetBuilder& BlockMode(T&&... a) {
|
||||
return BlockMode({std::forward<T>(a)...});
|
||||
}
|
||||
template <typename... T> AuthorizationSetBuilder& Digest(T&&... a) {
|
||||
return Digest({std::forward<T>(a)...});
|
||||
}
|
||||
template <typename... T> AuthorizationSetBuilder& Padding(T&&... a) {
|
||||
return Padding({std::forward<T>(a)...});
|
||||
}
|
||||
};
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::Authorizations(AuthorizationSet&& set) {
|
||||
move(set.begin(), set.end());
|
||||
set.Clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder&
|
||||
AuthorizationSetBuilder::Authorizations(const AuthorizationSet& set) {
|
||||
push_back(set.begin(), set.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
|
||||
uint64_t public_exponent) {
|
||||
Authorization(TAG_ALGORITHM, Algorithm::RSA);
|
||||
Authorization(TAG_KEY_SIZE, key_size);
|
||||
Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
|
||||
Authorization(TAG_ALGORITHM, Algorithm::EC);
|
||||
Authorization(TAG_KEY_SIZE, key_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(EcCurve curve) {
|
||||
Authorization(TAG_ALGORITHM, Algorithm::EC);
|
||||
Authorization(TAG_EC_CURVE, curve);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
|
||||
Authorization(TAG_ALGORITHM, Algorithm::AES);
|
||||
return Authorization(TAG_KEY_SIZE, key_size);
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
|
||||
Authorization(TAG_ALGORITHM, Algorithm::HMAC);
|
||||
Authorization(TAG_KEY_SIZE, key_size);
|
||||
return SigningKey();
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
|
||||
uint64_t public_exponent) {
|
||||
RsaKey(key_size, public_exponent);
|
||||
return SigningKey();
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder&
|
||||
AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) {
|
||||
RsaKey(key_size, public_exponent);
|
||||
return EncryptionKey();
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
|
||||
EcdsaKey(key_size);
|
||||
return SigningKey();
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(EcCurve curve) {
|
||||
EcdsaKey(curve);
|
||||
return SigningKey();
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
|
||||
AesKey(key_size);
|
||||
return EncryptionKey();
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
|
||||
Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
|
||||
return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
|
||||
Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT);
|
||||
return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT);
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
|
||||
Authorization(TAG_DIGEST, Digest::NONE);
|
||||
return Authorization(TAG_PADDING, PaddingMode::NONE);
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
|
||||
return BlockMode(BlockMode::ECB);
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder&
|
||||
AuthorizationSetBuilder::BlockMode(std::initializer_list<V3_0::BlockMode> block_modes) {
|
||||
for (auto block_mode : block_modes) {
|
||||
Authorization(TAG_BLOCK_MODE, block_mode);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder&
|
||||
AuthorizationSetBuilder::Digest(std::initializer_list<V3_0::Digest> digests) {
|
||||
for (auto digest : digests) {
|
||||
Authorization(TAG_DIGEST, digest);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AuthorizationSetBuilder&
|
||||
AuthorizationSetBuilder::Padding(std::initializer_list<V3_0::PaddingMode> padding_modes) {
|
||||
for (auto padding : padding_modes) {
|
||||
Authorization(TAG_PADDING, padding);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace V3_0
|
||||
} // namespace keymaster
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_AUTHORIZATION_SET_H_
|
||||
131
keymaster/3.0/vts/functional/key_param_output.cpp
Normal file
131
keymaster/3.0/vts/functional/key_param_output.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 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 "key_param_output.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
||||
namespace keymaster {
|
||||
namespace V3_0 {
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const hidl_vec<KeyParameter>& set) {
|
||||
if (set.size() == 0) {
|
||||
os << "(Empty)" << ::std::endl;
|
||||
} else {
|
||||
os << "\n";
|
||||
for (size_t i = 0; i < set.size(); ++i)
|
||||
os << set[i] << ::std::endl;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, ErrorCode value) {
|
||||
return os << (int)value;
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, Digest value) {
|
||||
return os << stringify(value);
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, Algorithm value) {
|
||||
return os << stringify(value);
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, BlockMode value) {
|
||||
return os << stringify(value);
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, PaddingMode value) {
|
||||
return os << stringify(value);
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, KeyOrigin value) {
|
||||
return os << stringify(value);
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, KeyPurpose value) {
|
||||
return os << stringify(value);
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, EcCurve value) {
|
||||
return os << stringify(value);
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const KeyParameter& param) {
|
||||
os << stringifyTag(param.tag) << ": ";
|
||||
switch (typeFromTag(param.tag)) {
|
||||
case TagType::INVALID:
|
||||
return os << " Invalid";
|
||||
case TagType::UINT_REP:
|
||||
case TagType::UINT:
|
||||
return os << param.f.integer;
|
||||
case TagType::ENUM_REP:
|
||||
case TagType::ENUM:
|
||||
switch (param.tag) {
|
||||
case Tag::ALGORITHM:
|
||||
return os << param.f.algorithm;
|
||||
case Tag::BLOCK_MODE:
|
||||
return os << param.f.blockMode;
|
||||
case Tag::PADDING:
|
||||
return os << param.f.paddingMode;
|
||||
case Tag::DIGEST:
|
||||
return os << param.f.digest;
|
||||
case Tag::EC_CURVE:
|
||||
return os << (int)param.f.ecCurve;
|
||||
case Tag::ORIGIN:
|
||||
return os << param.f.origin;
|
||||
case Tag::BLOB_USAGE_REQUIREMENTS:
|
||||
return os << (int)param.f.keyBlobUsageRequirements;
|
||||
case Tag::PURPOSE:
|
||||
return os << param.f.purpose;
|
||||
default:
|
||||
return os << " UNKNOWN ENUM " << param.f.integer;
|
||||
}
|
||||
case TagType::ULONG_REP:
|
||||
case TagType::ULONG:
|
||||
return os << param.f.longInteger;
|
||||
case TagType::DATE:
|
||||
return os << param.f.dateTime;
|
||||
case TagType::BOOL:
|
||||
return os << "true";
|
||||
case TagType::BIGNUM:
|
||||
os << " Bignum: ";
|
||||
for (size_t i = 0; i < param.blob.size(); ++i) {
|
||||
os << ::std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
|
||||
}
|
||||
return os;
|
||||
case TagType::BYTES:
|
||||
os << " Bytes: ";
|
||||
for (size_t i = 0; i < param.blob.size(); ++i) {
|
||||
os << ::std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
return os << "UNKNOWN TAG TYPE!";
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const KeyCharacteristics& chars) {
|
||||
return os << "SW: " << chars.softwareEnforced << ::std::endl
|
||||
<< "TEE: " << chars.teeEnforced << ::std::endl;
|
||||
}
|
||||
|
||||
} // namespace V3_0
|
||||
} // namespace keymaster
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
50
keymaster/3.0/vts/functional/key_param_output.h
Normal file
50
keymaster/3.0/vts/functional/key_param_output.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 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 <iostream>
|
||||
|
||||
#include <android/hardware/keymaster/3.0/types.h>
|
||||
|
||||
#include "keymaster_tags.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace keymaster {
|
||||
namespace V3_0 {
|
||||
|
||||
template <typename ValueT>
|
||||
::std::ostream& operator<<(::std::ostream& os, const NullOr<ValueT>& value) {
|
||||
if (!value.isOk()) {
|
||||
os << "(value not present)";
|
||||
} else {
|
||||
os << value.value();
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const hidl_vec<KeyParameter>& set);
|
||||
::std::ostream& operator<<(::std::ostream& os, BlockMode value);
|
||||
::std::ostream& operator<<(::std::ostream& os, Digest value);
|
||||
::std::ostream& operator<<(::std::ostream& os, EcCurve value);
|
||||
::std::ostream& operator<<(::std::ostream& os, ErrorCode value);
|
||||
::std::ostream& operator<<(::std::ostream& os, PaddingMode value);
|
||||
::std::ostream& operator<<(::std::ostream& os, const KeyCharacteristics& value);
|
||||
::std::ostream& operator<<(::std::ostream& os, const KeyParameter& value);
|
||||
|
||||
} // namespace V3_0
|
||||
} // namespace keymaster
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
3911
keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
Normal file
3911
keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
450
keymaster/3.0/vts/functional/keymaster_tags.h
Normal file
450
keymaster/3.0/vts/functional/keymaster_tags.h
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* Copyright 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
|
||||
#define SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
|
||||
|
||||
/**
|
||||
* This header contains various definitions that make working with keymaster tags safer and easier.
|
||||
*
|
||||
* It makes use of a fair amount of template metaprogramming. The metaprogramming serves the purpose
|
||||
* of making it impossible to make certain classes of mistakes when operating on keymaster
|
||||
* authorizations. For example, it's an error to create a KeyParameter with tag == Tag::PURPOSE
|
||||
* and then to assign Algorithm::RSA to algorithm element of its union. But because the user
|
||||
* must choose the union field, there could be a mismatch which the compiler has now way to
|
||||
* diagnose.
|
||||
*
|
||||
* The machinery in this header solves these problems by describing which union field corresponds
|
||||
* to which Tag. Central to this mechanism is the template TypedTag. It has zero size and binds a
|
||||
* numeric Tag to a type that the compiler understands. By means of the macro DECLARE_TYPED_TAG,
|
||||
* we declare types for each of the tags defined in hardware/interfaces/keymaster/2.0/types.hal.
|
||||
*
|
||||
* The macro DECLARE_TYPED_TAG(name) generates a typename TAG_name_t and a zero sized instance
|
||||
* TAG_name. Once these typed tags have been declared we define metafunctions mapping the each tag
|
||||
* to its value c++ type and the correct union element of KeyParameter. This is done by means of
|
||||
* the macros MAKE_TAG_*VALUE_ACCESSOR, which generates TypedTag2ValueType, a metafunction mapping
|
||||
* a typed tag to the corresponding c++ type, and access function, accessTagValue returning a
|
||||
* reference to the correct element of KeyParameter.
|
||||
* E.g.:
|
||||
* given "KeyParameter param;" then "accessTagValue(TAG_PURPOSE, param)"
|
||||
* yields a reference to param.f.purpose
|
||||
* If used in an assignment the compiler can now check the compatibility of the assigned value.
|
||||
*
|
||||
* For convenience we also provide the constructor like function Authorization().
|
||||
* Authorization takes a typed tag and a value and checks at compile time whether the value given
|
||||
* is suitable for the given tag. At runtime it creates a new KeyParameter initialized with the
|
||||
* given tag and value and returns it by value.
|
||||
*
|
||||
* The second convenience function, authorizationValue, allows access to the KeyParameter value in
|
||||
* a safe way. It takes a typed tag and a KeyParameter and returns a reference to the value wrapped
|
||||
* by NullOr. NullOr has out-of-band information about whether it is save to access the wrapped
|
||||
* reference.
|
||||
* E.g.:
|
||||
* auto param = Authorization(TAG_ALGORITM, Algorithm::RSA);
|
||||
* auto value1 = authorizationValue(TAG_PURPOSE, param);
|
||||
* auto value2 = authorizationValue(TAG_ALGORITM, param);
|
||||
* value1.isOk() yields false, but value2.isOk() yields true, thus value2.value() is save to access.
|
||||
*/
|
||||
|
||||
#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
|
||||
#include <hardware/hw_auth_token.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace keymaster {
|
||||
namespace V3_0 {
|
||||
|
||||
// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have. We
|
||||
// need these old values to be able to support old keys that use them.
|
||||
static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
|
||||
static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
|
||||
|
||||
constexpr TagType typeFromTag(Tag tag) {
|
||||
return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
|
||||
}
|
||||
|
||||
/**
|
||||
* TypedTag is a templatized version of Tag, which provides compile-time checking of keymaster tag
|
||||
* types. Instances are convertible to Tag, so they can be used wherever Tag is expected, and
|
||||
* because they encode the tag type it's possible to create function overloads that only operate on
|
||||
* tags with a particular type.
|
||||
*/
|
||||
template <TagType tag_type, Tag tag> struct TypedTag {
|
||||
inline TypedTag() {
|
||||
// Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
|
||||
// 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile
|
||||
// error (no match for template specialization StaticAssert<false>), with no run-time cost.
|
||||
static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type");
|
||||
}
|
||||
constexpr operator Tag() { return tag; }
|
||||
constexpr long maskedTag() {
|
||||
return static_cast<long>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0x0fffffff));
|
||||
}
|
||||
};
|
||||
|
||||
template <Tag tag> struct Tag2TypedTag { typedef TypedTag<typeFromTag(tag), tag> type; };
|
||||
|
||||
template <Tag tag> struct Tag2String;
|
||||
|
||||
#define _TAGS_STRINGIFY(x) #x
|
||||
#define TAGS_STRINGIFY(x) _TAGS_STRINGIFY(x)
|
||||
|
||||
#define DECLARE_TYPED_TAG(name) \
|
||||
typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
|
||||
extern TAG_##name##_t TAG_##name; \
|
||||
template <> struct Tag2String<Tag::name> { \
|
||||
static const char* value() { return "Tag::" TAGS_STRINGIFY(name); } \
|
||||
}
|
||||
|
||||
DECLARE_TYPED_TAG(INVALID);
|
||||
DECLARE_TYPED_TAG(KEY_SIZE);
|
||||
DECLARE_TYPED_TAG(MAC_LENGTH);
|
||||
DECLARE_TYPED_TAG(CALLER_NONCE);
|
||||
DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
|
||||
DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
|
||||
DECLARE_TYPED_TAG(ECIES_SINGLE_HASH_MODE);
|
||||
DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
|
||||
DECLARE_TYPED_TAG(ACTIVE_DATETIME);
|
||||
DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
|
||||
DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
|
||||
DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
|
||||
DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
|
||||
DECLARE_TYPED_TAG(ALL_USERS);
|
||||
DECLARE_TYPED_TAG(USER_ID);
|
||||
DECLARE_TYPED_TAG(USER_SECURE_ID);
|
||||
DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
|
||||
DECLARE_TYPED_TAG(AUTH_TIMEOUT);
|
||||
DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
|
||||
DECLARE_TYPED_TAG(ALL_APPLICATIONS);
|
||||
DECLARE_TYPED_TAG(APPLICATION_ID);
|
||||
DECLARE_TYPED_TAG(APPLICATION_DATA);
|
||||
DECLARE_TYPED_TAG(CREATION_DATETIME);
|
||||
DECLARE_TYPED_TAG(ROLLBACK_RESISTANT);
|
||||
DECLARE_TYPED_TAG(ROOT_OF_TRUST);
|
||||
DECLARE_TYPED_TAG(ASSOCIATED_DATA);
|
||||
DECLARE_TYPED_TAG(NONCE);
|
||||
DECLARE_TYPED_TAG(AUTH_TOKEN);
|
||||
DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
|
||||
DECLARE_TYPED_TAG(OS_VERSION);
|
||||
DECLARE_TYPED_TAG(OS_PATCHLEVEL);
|
||||
DECLARE_TYPED_TAG(UNIQUE_ID);
|
||||
DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
|
||||
DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
|
||||
DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
|
||||
|
||||
DECLARE_TYPED_TAG(PURPOSE);
|
||||
DECLARE_TYPED_TAG(ALGORITHM);
|
||||
DECLARE_TYPED_TAG(BLOCK_MODE);
|
||||
DECLARE_TYPED_TAG(DIGEST);
|
||||
DECLARE_TYPED_TAG(PADDING);
|
||||
DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
|
||||
DECLARE_TYPED_TAG(ORIGIN);
|
||||
DECLARE_TYPED_TAG(USER_AUTH_TYPE);
|
||||
DECLARE_TYPED_TAG(KDF);
|
||||
DECLARE_TYPED_TAG(EC_CURVE);
|
||||
|
||||
template <typename... Elems> struct MetaList {};
|
||||
|
||||
using all_tags_t = MetaList<
|
||||
TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
|
||||
TAG_RSA_PUBLIC_EXPONENT_t, TAG_ECIES_SINGLE_HASH_MODE_t, TAG_INCLUDE_UNIQUE_ID_t,
|
||||
TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
|
||||
TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_ALL_USERS_t, TAG_USER_ID_t,
|
||||
TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
|
||||
TAG_ALL_APPLICATIONS_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t,
|
||||
TAG_ROLLBACK_RESISTANT_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
|
||||
TAG_AUTH_TOKEN_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
|
||||
TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t,
|
||||
TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
|
||||
TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_KDF_t, TAG_EC_CURVE_t>;
|
||||
|
||||
/* implementation in keystore_utils.cpp */
|
||||
extern const char* stringifyTag(Tag tag);
|
||||
|
||||
template <typename TypedTagType> struct TypedTag2ValueType;
|
||||
|
||||
#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
|
||||
template <Tag tag> struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
|
||||
typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
|
||||
}; \
|
||||
template <Tag tag> \
|
||||
inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \
|
||||
->const decltype(param.field_name)& { \
|
||||
return param.field_name; \
|
||||
} \
|
||||
template <Tag tag> \
|
||||
inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) \
|
||||
->decltype(param.field_name)& { \
|
||||
return param.field_name; \
|
||||
}
|
||||
|
||||
MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger)
|
||||
MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger)
|
||||
MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime)
|
||||
MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer)
|
||||
MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer)
|
||||
MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue)
|
||||
MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
|
||||
MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
|
||||
|
||||
#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \
|
||||
template <> struct TypedTag2ValueType<decltype(typed_tag)> { \
|
||||
typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
|
||||
}; \
|
||||
inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \
|
||||
->const decltype(param.field_name)& { \
|
||||
return param.field_name; \
|
||||
} \
|
||||
inline auto accessTagValue(decltype(typed_tag), KeyParameter& param) \
|
||||
->decltype(param.field_name)& { \
|
||||
return param.field_name; \
|
||||
}
|
||||
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_KDF, f.keyDerivationFunction)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose)
|
||||
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType)
|
||||
|
||||
template <TagType tag_type, Tag tag, typename ValueT>
|
||||
inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
|
||||
KeyParameter param;
|
||||
param.tag = tag;
|
||||
param.f.longInteger = 0;
|
||||
accessTagValue(ttag, param) = std::forward<ValueT>(value);
|
||||
return param;
|
||||
}
|
||||
|
||||
// the boolean case
|
||||
template <Tag tag> inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
|
||||
KeyParameter param;
|
||||
param.tag = tag;
|
||||
param.f.boolValue = true;
|
||||
return param;
|
||||
}
|
||||
|
||||
template <typename... Pack> struct FirstOrNoneHelper;
|
||||
template <typename First> struct FirstOrNoneHelper<First> { typedef First type; };
|
||||
template <> struct FirstOrNoneHelper<> {
|
||||
struct type {};
|
||||
};
|
||||
|
||||
template <typename... Pack> using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
|
||||
|
||||
template <TagType tag_type, Tag tag, typename... Args>
|
||||
inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
|
||||
static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
|
||||
"TagType::BOOL Authorizations do not take parameters. Presence is truth.");
|
||||
static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
|
||||
"Authorization other then TagType::BOOL take exactly one parameter.");
|
||||
static_assert(
|
||||
tag_type == TagType::BOOL ||
|
||||
std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
|
||||
typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
|
||||
"Invalid argument type for given tag.");
|
||||
|
||||
return makeKeyParameter(ttag, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
|
||||
* of band. Note that if the wrapped value is a reference it is unsafe to access the value if
|
||||
* !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
|
||||
* wrapped value. In this case the pointer will be NULL though, and the value will be default
|
||||
* constructed.
|
||||
*/
|
||||
template <typename ValueT> class NullOr {
|
||||
template <typename T> struct reference_initializer {
|
||||
static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
|
||||
};
|
||||
template <typename T> struct pointer_initializer {
|
||||
static T init() { return nullptr; }
|
||||
};
|
||||
template <typename T> struct value_initializer {
|
||||
static T init() { return T(); }
|
||||
};
|
||||
template <typename T>
|
||||
using initializer_t =
|
||||
std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
|
||||
std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
|
||||
value_initializer<T>>>;
|
||||
|
||||
public:
|
||||
NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
|
||||
NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
|
||||
|
||||
bool isOk() const { return !null_; }
|
||||
|
||||
const ValueT& value() const & { return value_; }
|
||||
ValueT& value() & { return value_; }
|
||||
ValueT&& value() && { return std::move(value_); }
|
||||
|
||||
private:
|
||||
ValueT value_;
|
||||
bool null_;
|
||||
};
|
||||
|
||||
template <typename T> std::remove_reference_t<T> NullOrOr(NullOr<T>&& v) {
|
||||
if (v.isOk()) return v;
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename Head, typename... Tail>
|
||||
std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
|
||||
if (head.isOk()) return head;
|
||||
return NullOrOr(std::forward<Tail>(tail)...);
|
||||
}
|
||||
|
||||
template <typename Default, typename Wrapped>
|
||||
std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
|
||||
static_assert(std::is_convertible<std::remove_reference_t<Default>,
|
||||
std::remove_reference_t<Wrapped>>::value,
|
||||
"Type of default value must match the type wrapped by NullOr");
|
||||
if (optional.isOk()) return optional.value();
|
||||
return def;
|
||||
}
|
||||
|
||||
template <TagType tag_type, Tag tag>
|
||||
inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&>
|
||||
authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
|
||||
if (tag != param.tag) return {};
|
||||
return accessTagValue(ttag, param);
|
||||
}
|
||||
|
||||
inline const char* stringify(Digest digest) {
|
||||
switch (digest) {
|
||||
case Digest::NONE:
|
||||
return "None";
|
||||
case Digest::MD5:
|
||||
return "Md5";
|
||||
case Digest::SHA1:
|
||||
return "Sha1";
|
||||
case Digest::SHA_2_224:
|
||||
return "Sha224";
|
||||
case Digest::SHA_2_256:
|
||||
return "Sha256";
|
||||
case Digest::SHA_2_384:
|
||||
return "Sha384";
|
||||
case Digest::SHA_2_512:
|
||||
return "Sha512";
|
||||
}
|
||||
return "UNKNOWN DIGEST!";
|
||||
}
|
||||
|
||||
inline const char* stringify(Algorithm algorithm) {
|
||||
switch (algorithm) {
|
||||
case Algorithm::RSA:
|
||||
return "Rsa";
|
||||
case Algorithm::EC:
|
||||
return "Ec";
|
||||
case Algorithm::AES:
|
||||
return "Aes";
|
||||
case Algorithm::HMAC:
|
||||
return "Hmac";
|
||||
}
|
||||
return "UNKNOWN ALGORITHM";
|
||||
}
|
||||
|
||||
inline const char* stringify(BlockMode block_mode) {
|
||||
switch (block_mode) {
|
||||
case BlockMode::ECB:
|
||||
return "Ecb";
|
||||
case BlockMode::CBC:
|
||||
return "Cbc";
|
||||
case BlockMode::CTR:
|
||||
return "Ctr";
|
||||
case BlockMode::GCM:
|
||||
return "Gcm";
|
||||
}
|
||||
return "UNKNOWN BLOCK MODE";
|
||||
}
|
||||
|
||||
inline const char* stringify(PaddingMode padding) {
|
||||
switch (padding) {
|
||||
case PaddingMode::NONE:
|
||||
return "None";
|
||||
case PaddingMode::RSA_OAEP:
|
||||
return "RsaOaep";
|
||||
case PaddingMode::RSA_PSS:
|
||||
return "RsaPss";
|
||||
case PaddingMode::RSA_PKCS1_1_5_ENCRYPT:
|
||||
return "RsaPkcs115Encrypt";
|
||||
case PaddingMode::RSA_PKCS1_1_5_SIGN:
|
||||
return "RsaPkcs115Sign";
|
||||
case PaddingMode::PKCS7:
|
||||
return "Pkcs7";
|
||||
}
|
||||
return "UNKNOWN PADDING MODE";
|
||||
}
|
||||
|
||||
inline const char* stringify(KeyOrigin origin) {
|
||||
switch (origin) {
|
||||
case KeyOrigin::GENERATED:
|
||||
return "Generated";
|
||||
case KeyOrigin::DERIVED:
|
||||
return "Derived";
|
||||
case KeyOrigin::IMPORTED:
|
||||
return "Imported";
|
||||
case KeyOrigin::UNKNOWN:
|
||||
return "UNKNOWN (keymaster0 didn't record it)";
|
||||
}
|
||||
return "UNKOWN KEY ORIGIN VALUE";
|
||||
}
|
||||
|
||||
inline const char* stringify(KeyPurpose purpose) {
|
||||
switch (purpose) {
|
||||
case KeyPurpose::ENCRYPT:
|
||||
return "Encrypt";
|
||||
case KeyPurpose::DECRYPT:
|
||||
return "Decrypt";
|
||||
case KeyPurpose::SIGN:
|
||||
return "Sign";
|
||||
case KeyPurpose::VERIFY:
|
||||
return "Verify";
|
||||
case KeyPurpose::DERIVE_KEY:
|
||||
return "DeriveKey";
|
||||
case KeyPurpose::WRAP_KEY:
|
||||
return "WrapKey";
|
||||
};
|
||||
return "UNKNOWN KEY PURPOSE";
|
||||
}
|
||||
|
||||
inline const char* stringify(EcCurve curve) {
|
||||
switch (curve) {
|
||||
case EcCurve::P_224:
|
||||
return "P_224";
|
||||
case EcCurve::P_256:
|
||||
return "P_256";
|
||||
case EcCurve::P_384:
|
||||
return "P_384";
|
||||
case EcCurve::P_521:
|
||||
return "P_521";
|
||||
}
|
||||
return "UNKNOWN EC CURVE";
|
||||
}
|
||||
|
||||
} // namespace V3_0
|
||||
} // namespace keymaster
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
|
||||
50
keymaster/3.0/vts/functional/keystore_tags_utils.cpp
Normal file
50
keymaster/3.0/vts/functional/keystore_tags_utils.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
**
|
||||
** 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 "keymaster_tags.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace keymaster {
|
||||
namespace V3_0 {
|
||||
|
||||
template <typename TagList> struct TagStringifier;
|
||||
|
||||
template <typename... Tags> struct TagStringifier<MetaList<Tags...>> {
|
||||
template <TagType tag_type, Tag tag>
|
||||
static TypedTag<tag_type, tag> chooseString(TypedTag<tag_type, tag> ttag, Tag runtime_tag,
|
||||
const char** result) {
|
||||
if (tag == runtime_tag) {
|
||||
*result = Tag2String<tag>::value();
|
||||
}
|
||||
return ttag;
|
||||
}
|
||||
static const char* stringify(Tag tag) {
|
||||
const char* result = "unknown tag";
|
||||
[](Tags&&...) {}(chooseString(Tags(), tag, &result)...);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
const char* stringifyTag(Tag tag) {
|
||||
return TagStringifier<all_tags_t>::stringify(tag);
|
||||
}
|
||||
|
||||
} // namespace V3_0
|
||||
} // namespace keymaster
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
52
keymaster/3.0/vts/functional/openssl_utils.h
Normal file
52
keymaster/3.0/vts/functional/openssl_utils.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
template <typename T, void (*F)(T*)> struct UniquePtrDeleter {
|
||||
void operator()(T* p) const { F(p); }
|
||||
};
|
||||
|
||||
typedef UniquePtrDeleter<EVP_PKEY, EVP_PKEY_free> EVP_PKEY_Delete;
|
||||
|
||||
#define MAKE_OPENSSL_PTR_TYPE(type) \
|
||||
typedef std::unique_ptr<type, UniquePtrDeleter<type, type##_free>> type##_Ptr;
|
||||
|
||||
MAKE_OPENSSL_PTR_TYPE(ASN1_OBJECT)
|
||||
MAKE_OPENSSL_PTR_TYPE(EVP_PKEY)
|
||||
MAKE_OPENSSL_PTR_TYPE(RSA)
|
||||
MAKE_OPENSSL_PTR_TYPE(X509)
|
||||
MAKE_OPENSSL_PTR_TYPE(BN_CTX)
|
||||
|
||||
typedef std::unique_ptr<BIGNUM, UniquePtrDeleter<BIGNUM, BN_free>> BIGNUM_Ptr;
|
||||
|
||||
inline const EVP_MD* openssl_digest(android::hardware::keymaster::V3_0::Digest digest) {
|
||||
switch (digest) {
|
||||
case android::hardware::keymaster::V3_0::Digest::NONE:
|
||||
return nullptr;
|
||||
case android::hardware::keymaster::V3_0::Digest::MD5:
|
||||
return EVP_md5();
|
||||
case android::hardware::keymaster::V3_0::Digest::SHA1:
|
||||
return EVP_sha1();
|
||||
case android::hardware::keymaster::V3_0::Digest::SHA_2_224:
|
||||
return EVP_sha224();
|
||||
case android::hardware::keymaster::V3_0::Digest::SHA_2_256:
|
||||
return EVP_sha256();
|
||||
case android::hardware::keymaster::V3_0::Digest::SHA_2_384:
|
||||
return EVP_sha384();
|
||||
case android::hardware::keymaster::V3_0::Digest::SHA_2_512:
|
||||
return EVP_sha512();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
Reference in New Issue
Block a user