diff options
author | Shawn Willden <swillden@google.com> | 2020-12-06 19:20:41 -0700 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2020-12-09 16:26:41 -0700 |
commit | f73e952ea46e4ff394efa1c77bab4cfecba301ed (patch) | |
tree | f59f83accc5327ffeb7724d077fa134eb54a6663 /security/keymint/support/include | |
parent | 8523de7588208ab10c605c7d783885c5b0c56fc7 (diff) |
Move keymint to android.hardware.security.
Test: VtsAidlKeyMintTargetTest
Change-Id: I2498073aa834584229e9a4955a97f279a94d1dd5
Diffstat (limited to 'security/keymint/support/include')
6 files changed, 961 insertions, 0 deletions
diff --git a/security/keymint/support/include/keymint_support/attestation_record.h b/security/keymint/support/include/keymint_support/attestation_record.h new file mode 100644 index 0000000000..d71624c978 --- /dev/null +++ b/security/keymint/support/include/keymint_support/attestation_record.h @@ -0,0 +1,87 @@ +/* + * Copyright 2020 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. + */ + +#pragma once + +#include <android/hardware/security/keymint/ErrorCode.h> +#include <android/hardware/security/keymint/IKeyMintDevice.h> + +#include <keymint_support/attestation_record.h> +#include <keymint_support/authorization_set.h> +#include <keymint_support/openssl_utils.h> + +namespace android::hardware::security::keymint { + +class AuthorizationSet; + +/** + * 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"; + +enum keymint_verified_boot_t { + KM_VERIFIED_BOOT_VERIFIED = 0, + KM_VERIFIED_BOOT_SELF_SIGNED = 1, + KM_VERIFIED_BOOT_UNVERIFIED = 2, + KM_VERIFIED_BOOT_FAILED = 3, +}; + +struct RootOfTrust { + SecurityLevel security_level; + vector<uint8_t> verified_boot_key; + vector<uint8_t> verified_boot_hash; + keymint_verified_boot_t verified_boot_state; + bool device_locked; +}; + +struct AttestationRecord { + RootOfTrust root_of_trust; + uint32_t attestation_version; + SecurityLevel attestation_security_level; + uint32_t keymint_version; + SecurityLevel keymint_security_level; + std::vector<uint8_t> attestation_challenge; + AuthorizationSet software_enforced; + AuthorizationSet hardware_enforced; + std::vector<uint8_t> 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* keymint_version, SecurityLevel* keymint_security_level, + std::vector<uint8_t>* attestation_challenge, + AuthorizationSet* software_enforced, + AuthorizationSet* tee_enforced, // + std::vector<uint8_t>* unique_id); + +ErrorCode parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len, + std::vector<uint8_t>* verified_boot_key, + keymint_verified_boot_t* verified_boot_state, bool* device_locked, + std::vector<uint8_t>* verified_boot_hash); + +} // namespace android::hardware::security::keymint diff --git a/security/keymint/support/include/keymint_support/authorization_set.h b/security/keymint/support/include/keymint_support/authorization_set.h new file mode 100644 index 0000000000..97e10224d3 --- /dev/null +++ b/security/keymint/support/include/keymint_support/authorization_set.h @@ -0,0 +1,320 @@ +/* + * Copyright 2020 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_KM4_AUTHORIZATION_SET_H_ +#define SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_ + +#include <vector> + +#include <android/hardware/security/keymint/BlockMode.h> +#include <android/hardware/security/keymint/Digest.h> +#include <android/hardware/security/keymint/EcCurve.h> +#include <android/hardware/security/keymint/PaddingMode.h> + +#include <keymint_support/keymint_tags.h> + +namespace android::hardware::security::keymint { + +using std::vector; + +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 vector<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) noexcept : data_(std::move(other.data_)) {} + + // Constructor from vector<KeyParameter> + AuthorizationSet(const vector<KeyParameter>& other) { *this = other; } + + // Copy assignment. + AuthorizationSet& operator=(const AuthorizationSet& other) { + data_ = other.data_; + return *this; + } + + // Move assignment. + AuthorizationSet& operator=(AuthorizationSet&& other) noexcept { + data_ = std::move(other.data_); + return *this; + } + + AuthorizationSet& operator=(const vector<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 vector.*/ + 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(); } + + /** + * Modifies this Authorization set such that it only keeps the entries for which doKeep + * returns true. + */ + void Filter(std::function<bool(const KeyParameter&)> doKeep); + /** + * 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 <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) { + std::move(set.begin(), set.end(), std::back_inserter(*this)); + } + + /** + * 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 append(Iterator begin, Iterator end) { + while (begin != end) { + push_back(*begin); + ++begin; + } + } + + vector<KeyParameter> vector_data() const { + vector<KeyParameter> result(begin(), end()); + 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) { + vector<uint8_t> new_blob(data, data + data_length); + push_back(ttag, 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); + } + + template <Tag tag> + AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, char* data, + size_t data_length) { + return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length); + } + + template <Tag tag, size_t size> + AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, + const char (&data)[size]) { + return Authorization(ttag, reinterpret_cast<const uint8_t*>(&data[0]), + size - 1); // drop the terminating '\0' + } + + AuthorizationSetBuilder& Authorizations(const AuthorizationSet& set) { + for (const auto& entry : set) { + push_back(entry); + } + return *this; + } + + 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& TripleDesKey(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& TripleDesEncryptionKey(uint32_t key_size); + + AuthorizationSetBuilder& SigningKey(); + AuthorizationSetBuilder& EncryptionKey(); + + AuthorizationSetBuilder& NoDigestOrPadding(); + + AuthorizationSetBuilder& EcbMode(); + AuthorizationSetBuilder& GcmModeMinMacLen(uint32_t minMacLength); + AuthorizationSetBuilder& GcmModeMacLen(uint32_t macLength); + + AuthorizationSetBuilder& BlockMode(std::initializer_list<BlockMode> blockModes); + AuthorizationSetBuilder& Digest(std::vector<Digest> digests); + AuthorizationSetBuilder& Padding(std::initializer_list<PaddingMode> paddings); + + 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)...}); + } +}; + +} // namespace android::hardware::security::keymint + +#endif // SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_ diff --git a/security/keymint/support/include/keymint_support/key_param_output.h b/security/keymint/support/include/keymint_support/key_param_output.h new file mode 100644 index 0000000000..82c9689329 --- /dev/null +++ b/security/keymint/support/include/keymint_support/key_param_output.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 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_KEYMINT_SUPPORT_INCLUDE_KEY_PARAM_OUTPUT_H_ +#define HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEY_PARAM_OUTPUT_H_ + +#include <iostream> +#include <vector> + +#include <android/hardware/security/keymint/Algorithm.h> +#include <android/hardware/security/keymint/BlockMode.h> +#include <android/hardware/security/keymint/Digest.h> +#include <android/hardware/security/keymint/EcCurve.h> +#include <android/hardware/security/keymint/ErrorCode.h> +#include <android/hardware/security/keymint/HardwareAuthenticatorType.h> +#include <android/hardware/security/keymint/KeyCharacteristics.h> +#include <android/hardware/security/keymint/KeyOrigin.h> +#include <android/hardware/security/keymint/KeyParameter.h> +#include <android/hardware/security/keymint/KeyPurpose.h> +#include <android/hardware/security/keymint/PaddingMode.h> +#include <android/hardware/security/keymint/SecurityLevel.h> +#include <android/hardware/security/keymint/Tag.h> +#include <android/hardware/security/keymint/TagType.h> + +#include "keymint_tags.h" + +namespace android::hardware::security::keymint { + +inline ::std::ostream& operator<<(::std::ostream& os, Algorithm value) { + return os << toString(value); +} + +inline ::std::ostream& operator<<(::std::ostream& os, BlockMode value) { + return os << toString(value); +} + +inline ::std::ostream& operator<<(::std::ostream& os, Digest value) { + return os << toString(value); +} + +inline ::std::ostream& operator<<(::std::ostream& os, EcCurve value) { + return os << toString(value); +} + +inline ::std::ostream& operator<<(::std::ostream& os, ErrorCode value) { + return os << toString(value); +} + +inline ::std::ostream& operator<<(::std::ostream& os, KeyOrigin value) { + return os << toString(value); +} + +inline ::std::ostream& operator<<(::std::ostream& os, PaddingMode value) { + return os << toString(value); +} + +inline ::std::ostream& operator<<(::std::ostream& os, SecurityLevel value) { + return os << toString(value); +} + +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 ::std::vector<KeyParameter>& set); +::std::ostream& operator<<(::std::ostream& os, const KeyParameter& param); + +inline ::std::ostream& operator<<(::std::ostream& os, const KeyCharacteristics& value) { + return os << "SW: " << value.softwareEnforced << ::std::endl + << "HW: " << value.hardwareEnforced << ::std::endl; +} + +inline ::std::ostream& operator<<(::std::ostream& os, KeyPurpose value) { + return os << toString(value); +} + +inline ::std::ostream& operator<<(::std::ostream& os, Tag tag) { + return os << toString(tag); +} + +} // namespace android::hardware::security::keymint + +#endif // HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEY_PARAM_OUTPUT_H_ diff --git a/security/keymint/support/include/keymint_support/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h new file mode 100644 index 0000000000..f23e4f2ce2 --- /dev/null +++ b/security/keymint/support/include/keymint_support/keymint_tags.h @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2019 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_KEYMINT_SUPPORT_INCLUDE_KEYMINT_TAGS_H_ +#define HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEYMINT_TAGS_H_ + +#include <android/hardware/security/keymint/Algorithm.h> +#include <android/hardware/security/keymint/BlockMode.h> +#include <android/hardware/security/keymint/Digest.h> +#include <android/hardware/security/keymint/EcCurve.h> +#include <android/hardware/security/keymint/HardwareAuthenticatorType.h> +#include <android/hardware/security/keymint/KeyOrigin.h> +#include <android/hardware/security/keymint/KeyParameter.h> +#include <android/hardware/security/keymint/KeyPurpose.h> +#include <android/hardware/security/keymint/PaddingMode.h> +#include <android/hardware/security/keymint/SecurityLevel.h> +#include <android/hardware/security/keymint/Tag.h> +#include <android/hardware/security/keymint/TagType.h> + +namespace android::hardware::security::keymint { + +// 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. +// TODO(seleneh) we should delete this code when we stop supporting keymaster1 +// and deletes it. +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 + * keymint 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"); + } + operator Tag() const { return tag; } + int32_t maskedTag() { return static_cast<uint32_t>(tag) & 0x0FFFFFFF; } +}; + +template <Tag tag> +struct Tag2TypedTag { + typedef TypedTag<typeFromTag(tag), tag> type; +}; + +#define DECLARE_TYPED_TAG(name) \ + typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \ + static TAG_##name##_t TAG_##name; + +DECLARE_TYPED_TAG(ACTIVE_DATETIME); +DECLARE_TYPED_TAG(ALGORITHM); +DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY); +DECLARE_TYPED_TAG(APPLICATION_DATA); +DECLARE_TYPED_TAG(APPLICATION_ID); +DECLARE_TYPED_TAG(ASSOCIATED_DATA); +DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID); +DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE); +DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND); +DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE); +DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT); +DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER); +DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL); +DECLARE_TYPED_TAG(AUTH_TIMEOUT); +DECLARE_TYPED_TAG(BLOCK_MODE); +DECLARE_TYPED_TAG(BOOTLOADER_ONLY); +DECLARE_TYPED_TAG(BOOT_PATCHLEVEL); +DECLARE_TYPED_TAG(CALLER_NONCE); +DECLARE_TYPED_TAG(CONFIRMATION_TOKEN); +DECLARE_TYPED_TAG(CREATION_DATETIME); +DECLARE_TYPED_TAG(DEVICE_UNIQUE_ATTESTATION); +DECLARE_TYPED_TAG(DIGEST); +DECLARE_TYPED_TAG(EARLY_BOOT_ONLY); +DECLARE_TYPED_TAG(EC_CURVE); +DECLARE_TYPED_TAG(HARDWARE_TYPE); +DECLARE_TYPED_TAG(IDENTITY_CREDENTIAL_KEY); +DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID); +DECLARE_TYPED_TAG(INVALID); +DECLARE_TYPED_TAG(KEY_SIZE); +DECLARE_TYPED_TAG(MAC_LENGTH); +DECLARE_TYPED_TAG(MAX_USES_PER_BOOT); +DECLARE_TYPED_TAG(MIN_MAC_LENGTH); +DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS); +DECLARE_TYPED_TAG(NONCE); +DECLARE_TYPED_TAG(NO_AUTH_REQUIRED); +DECLARE_TYPED_TAG(ORIGIN); +DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME); +DECLARE_TYPED_TAG(OS_PATCHLEVEL); +DECLARE_TYPED_TAG(OS_VERSION); +DECLARE_TYPED_TAG(PADDING); +DECLARE_TYPED_TAG(PURPOSE); +DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION); +DECLARE_TYPED_TAG(ROLLBACK_RESISTANCE); +DECLARE_TYPED_TAG(ROOT_OF_TRUST); +DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT); +DECLARE_TYPED_TAG(STORAGE_KEY); +DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED); +DECLARE_TYPED_TAG(TRUSTED_USER_PRESENCE_REQUIRED); +DECLARE_TYPED_TAG(UNIQUE_ID); +DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED); +DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME); +DECLARE_TYPED_TAG(USER_AUTH_TYPE); +DECLARE_TYPED_TAG(USER_ID); +DECLARE_TYPED_TAG(USER_SECURE_ID); +DECLARE_TYPED_TAG(VENDOR_PATCHLEVEL); + +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_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_USER_ID_t, TAG_USER_SECURE_ID_t, + TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t, + TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, + TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_HARDWARE_TYPE_t, + TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_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_ATTESTATION_ID_BRAND_t, TAG_ATTESTATION_ID_DEVICE_t, + TAG_ATTESTATION_ID_PRODUCT_t, TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t, + TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, + TAG_DIGEST_t, TAG_PADDING_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t, + TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_CONFIRMATION_REQUIRED_t, + TAG_TRUSTED_USER_PRESENCE_REQUIRED_t>; + +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, longInteger) +MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, longInteger) +MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, longInteger) +MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, integer) +MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, integer) +MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, boolValue) +MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob) +MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob) + +// TODO(seleneh) change these MAKE_TAG_ENUM_VALUE_ACCESSOR back to the 2 parameter +// version when aidl supports union +#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name, field_type) \ + template <> \ + struct TypedTag2ValueType<decltype(typed_tag)> { \ + typedef field_type type; \ + }; \ + inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \ + ->const field_type& { \ + return *reinterpret_cast<const field_type*>(¶m.field_name); \ + } \ + inline auto accessTagValue(decltype(typed_tag), KeyParameter& param)->field_type& { \ + return *reinterpret_cast<field_type*>(¶m.field_name); \ + } + +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, integer, Algorithm) +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, integer, BlockMode) +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, integer, Digest) +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, integer, EcCurve) +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, integer, KeyOrigin) +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, integer, PaddingMode) +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, integer, KeyPurpose) +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, integer, HardwareAuthenticatorType) +MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, integer, SecurityLevel) + +template <TagType tag_type, Tag tag, typename ValueT> +inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) { + KeyParameter param; + param.tag = tag; + param.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.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. + * + * TODO(seleneh) replace this with std::optional. + */ +template <typename ValueT> +class NullOr { + using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, + std::remove_reference_t<ValueT>*, ValueT>; + + struct pointer_initializer { + static std::nullptr_t init() { return nullptr; } + }; + struct value_initializer { + static ValueT init() { return ValueT(); } + }; + struct value_pointer_deref_t { + static ValueT& deref(ValueT& v) { return v; } + }; + struct reference_deref_t { + static auto& deref(internal_t v) { return *v; } + }; + using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value || + std::is_pointer<ValueT>::value, + pointer_initializer, value_initializer>; + using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t, + value_pointer_deref_t>; + + public: + NullOr() : value_(initializer_t::init()), null_(true) {} + template <typename T> + NullOr(T&& value, typename std::enable_if< + !std::is_lvalue_reference<ValueT>::value && + std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value, + int>::type = 0) + : value_(std::forward<ValueT>(value)), null_(false) {} + template <typename T> + NullOr(T& value, typename std::enable_if< + std::is_lvalue_reference<ValueT>::value && + std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value, + int>::type = 0) + : value_(&value), null_(false) {} + + bool isOk() const { return !null_; } + + const ValueT& value() const& { return deref_t::deref(value_); } + ValueT& value() & { return deref_t::deref(value_); } + ValueT&& value() && { return std::move(deref_t::deref(value_)); } + + private: + internal_t value_; + bool null_; +}; + +template <typename T> +std::remove_reference_t<T> NullOrOr(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); +} + +} // namespace android::hardware::security::keymint + +#endif // HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEYMINT_TAGS_H_ diff --git a/security/keymint/support/include/keymint_support/keymint_utils.h b/security/keymint/support/include/keymint_support/keymint_utils.h new file mode 100644 index 0000000000..fda1b6c9b2 --- /dev/null +++ b/security/keymint/support/include/keymint_support/keymint_utils.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#ifndef HARDWARE_INTERFACES_KEYMINT_10_SUPPORT_KEYMINT_UTILS_H_ +#define HARDWARE_INTERFACES_KEYMINT_10_SUPPORT_KEYMINT_UTILS_H_ + +#include <android/hardware/security/keymint/HardwareAuthToken.h> + +namespace android::hardware::security::keymint { + +using std::vector; + +inline static std::vector<uint8_t> blob2vector(const uint8_t* data, const size_t length) { + std::vector<uint8_t> result(data, data + length); + return result; +} + +inline static std::vector<uint8_t> blob2vector(const std::string& value) { + vector<uint8_t> result(reinterpret_cast<const uint8_t*>(value.data()), + reinterpret_cast<const uint8_t*>(value.data()) + value.size()); + return result; +} + +HardwareAuthToken vector2AuthToken(const vector<uint8_t>& buffer); +vector<uint8_t> authToken2vector(const HardwareAuthToken& token); + +uint32_t getOsVersion(); +uint32_t getOsPatchlevel(); + +} // namespace android::hardware::security::keymint + +#endif // HARDWARE_INTERFACES_KEYMINT_10_SUPPORT_KEYMINT_UTILS_H_ diff --git a/security/keymint/support/include/keymint_support/openssl_utils.h b/security/keymint/support/include/keymint_support/openssl_utils.h new file mode 100644 index 0000000000..cb099680d4 --- /dev/null +++ b/security/keymint/support/include/keymint_support/openssl_utils.h @@ -0,0 +1,67 @@ +/* + * 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_KEYMINT_1_0_SUPPORT_OPENSSL_UTILS_H_ +#define HARDWARE_INTERFACES_KEYMINT_1_0_SUPPORT_OPENSSL_UTILS_H_ + +#include <android/hardware/security/keymint/Digest.h> + +#include <openssl/evp.h> +#include <openssl/x509.h> + +namespace android::hardware::security::keymint { + +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(Digest digest) { + switch (digest) { + case Digest::NONE: + return nullptr; + case Digest::MD5: + return EVP_md5(); + case Digest::SHA1: + return EVP_sha1(); + case Digest::SHA_2_224: + return EVP_sha224(); + case Digest::SHA_2_256: + return EVP_sha256(); + case Digest::SHA_2_384: + return EVP_sha384(); + case Digest::SHA_2_512: + return EVP_sha512(); + } + return nullptr; +} + +} // namespace android::hardware::security::keymint + +#endif // HARDWARE_INTERFACES_KEYMINT_1_0_SUPPORT_OPENSSL_UTILS_H_ |