diff options
author | Shawn Willden <swillden@google.com> | 2015-05-26 08:31:37 -0600 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2015-05-26 10:21:38 -0600 |
commit | 0cb6942d3efb6c056f96321c82a4b3d86af601d6 (patch) | |
tree | cd34b5b3afdce65e41c47436944048cec90db97d /include | |
parent | 13fbe3e93247943c26e7ca2ed27b6d650282b8bf (diff) | |
download | keymaster-0cb6942d3efb6c056f96321c82a4b3d86af601d6.tar.gz |
Revert "Revert "Large refactor to move context out of AndroidKeymaster.""
This reverts commit 13fbe3e93247943c26e7ca2ed27b6d650282b8bf.
Bug: 20912868, 19799085
Change-Id: Iadd6ce5cbe94956c2a2fe277f1bf5b108e4bcf57
Diffstat (limited to 'include')
-rw-r--r-- | include/keymaster/android_keymaster.h | 34 | ||||
-rw-r--r-- | include/keymaster/android_keymaster_utils.h | 94 | ||||
-rw-r--r-- | include/keymaster/key_blob.h | 130 | ||||
-rw-r--r-- | include/keymaster/keymaster_context.h | 110 | ||||
-rw-r--r-- | include/keymaster/serializable.h | 3 | ||||
-rw-r--r-- | include/keymaster/soft_keymaster_context.h | 52 | ||||
-rw-r--r-- | include/keymaster/soft_keymaster_device.h | 3 |
7 files changed, 262 insertions, 164 deletions
diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h index 7f8e65f..c7a3f41 100644 --- a/include/keymaster/android_keymaster.h +++ b/include/keymaster/android_keymaster.h @@ -23,7 +23,7 @@ namespace keymaster { class Key; -class UnencryptedKeyBlob; +class KeymasterContext; class OperationTable; /** @@ -46,7 +46,7 @@ class OperationTable; */ class AndroidKeymaster { public: - AndroidKeymaster(size_t operation_table_size); + AndroidKeymaster(KeymasterContext* context, size_t operation_table_size); virtual ~AndroidKeymaster(); void SupportedAlgorithms(SupportedResponse<keymaster_algorithm_t>* response) const; @@ -61,7 +61,7 @@ class AndroidKeymaster { void SupportedExportFormats(keymaster_algorithm_t algorithm, SupportedResponse<keymaster_key_format_t>* response) const; - virtual keymaster_error_t AddRngEntropy(const AddEntropyRequest& request) = 0; + keymaster_error_t AddRngEntropy(const AddEntropyRequest& request); void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response); void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request, GetKeyCharacteristicsResponse* response); @@ -74,30 +74,12 @@ class AndroidKeymaster { void GetVersion(const GetVersionRequest& request, GetVersionResponse* response); private: - virtual bool is_enforced(keymaster_tag_t tag) = 0; - virtual bool is_hardware() = 0; - virtual keymaster_key_param_t RootOfTrustTag() = 0; - virtual keymaster_key_blob_t MasterKey() = 0; - virtual void GenerateNonce(uint8_t* nonce, size_t length) = 0; - - keymaster_error_t SerializeKey(const Key* key, keymaster_key_origin_t origin, - keymaster_key_blob_t* keymaster_blob, AuthorizationSet* enforced, - AuthorizationSet* unenforced); - Key* LoadKey(const keymaster_key_blob_t& key, const AuthorizationSet& client_params, - keymaster_algorithm_t* algorithm, keymaster_error_t* error); - UnencryptedKeyBlob* LoadKeyBlob(const keymaster_key_blob_t& key, - const AuthorizationSet& client_params, - keymaster_error_t* error); - - keymaster_error_t SetAuthorizations(const AuthorizationSet& key_description, - keymaster_key_origin_t origin, AuthorizationSet* enforced, - AuthorizationSet* unenforced); - keymaster_error_t BuildHiddenAuthorizations(const AuthorizationSet& input_set, - AuthorizationSet* hidden); - - void AddAuthorization(const keymaster_key_param_t& auth, AuthorizationSet* enforced, - AuthorizationSet* unenforced); + keymaster_error_t LoadKey(const keymaster_key_blob_t& key_blob, + const AuthorizationSet& additional_params, + AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced, + keymaster_algorithm_t* algorithm, UniquePtr<Key>* key); + UniquePtr<KeymasterContext> context_; UniquePtr<OperationTable> operation_table_; }; diff --git a/include/keymaster/android_keymaster_utils.h b/include/keymaster/android_keymaster_utils.h index 20afcdd..c636f5c 100644 --- a/include/keymaster/android_keymaster_utils.h +++ b/include/keymaster/android_keymaster_utils.h @@ -23,6 +23,7 @@ #include <UniquePtr.h> +#include <hardware/keymaster_defs.h> #include <keymaster/serializable.h> namespace keymaster { @@ -49,14 +50,14 @@ inline int64_t java_time(time_t time) { /** * Return the size in bytes of the array \p a. */ -template <typename T, size_t N> inline size_t array_size(const T (&a)[N]) { +template <typename T, size_t N> inline size_t array_size(const T(&a)[N]) { return sizeof(a); } /** * Return the number of elements in array \p a. */ -template <typename T, size_t N> inline size_t array_length(const T (&)[N]) { +template <typename T, size_t N> inline size_t array_length(const T(&)[N]) { return N; } @@ -77,7 +78,7 @@ template <typename T> inline T* dup_array(const T* a, size_t n) { * responsibility. Note that the dup is necessarily returned as a pointer, so size is lost. Call * array_length() on the original array to discover the size. */ -template <typename T, size_t N> inline T* dup_array(const T (&a)[N]) { +template <typename T, size_t N> inline T* dup_array(const T(&a)[N]) { return dup_array(a, N); } @@ -90,7 +91,7 @@ uint8_t* dup_buffer(const void* buf, size_t size); /** * Copy the contents of array \p arr to \p dest. */ -template <typename T, size_t N> inline void copy_array(const T (&arr)[N], T* dest) { +template <typename T, size_t N> inline void copy_array(const T(&arr)[N], T* dest) { for (size_t i = 0; i < N; ++i) dest[i] = arr[i]; } @@ -100,7 +101,7 @@ template <typename T, size_t N> inline void copy_array(const T (&arr)[N], T* des * early-exit, meaning that it should not be used in contexts where timing analysis attacks could be * a concern. */ -template <typename T, size_t N> inline bool array_contains(const T (&a)[N], T val) { +template <typename T, size_t N> inline bool array_contains(const T(&a)[N], T val) { for (size_t i = 0; i < N; ++i) { if (a[i] == val) { return true; @@ -144,9 +145,9 @@ class Eraser { template <typename T> explicit Eraser(T& t) - : buf_(reinterpret_cast<uint8_t*> (&t)), size_(sizeof(t)) {} + : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {} - template <size_t N> explicit Eraser(uint8_t (&arr)[N]) : buf_(arr), size_(N) {} + template <size_t N> explicit Eraser(uint8_t(&arr)[N]) : buf_(arr), size_(N) {} Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {} ~Eraser() { memset_s(buf_, 0, size_); } @@ -206,6 +207,85 @@ template <typename T> T hton(T t) { return retval; } +/** + * KeymasterKeyBlob is a very simple extension of the C struct keymaster_key_blob_t. It manages its + * own memory, which makes avoiding memory leaks much easier. + */ +struct KeymasterKeyBlob : public keymaster_key_blob_t { + KeymasterKeyBlob() { + key_material = nullptr; + key_material_size = 0; + } + + KeymasterKeyBlob(const uint8_t* data, size_t size) { + key_material = dup_buffer(data, size); + key_material_size = size; + } + + explicit KeymasterKeyBlob(size_t size) { + key_material = new uint8_t[size]; + key_material_size = size; + } + + explicit KeymasterKeyBlob(const keymaster_key_blob_t& blob) { + key_material = dup_buffer(blob.key_material, blob.key_material_size); + key_material_size = blob.key_material_size; + } + + KeymasterKeyBlob(const KeymasterKeyBlob& blob) { + key_material = dup_buffer(blob.key_material, blob.key_material_size); + key_material_size = blob.key_material_size; + } + + ~KeymasterKeyBlob() { Clear(); } + + const uint8_t* begin() const { return key_material; } + const uint8_t* end() const { return key_material + key_material_size; } + + void Clear() { + memset_s(const_cast<uint8_t*>(key_material), 0, key_material_size); + delete[] key_material; + key_material = nullptr; + key_material_size = 0; + } + + const uint8_t* Reset(size_t new_size) { + Clear(); + key_material = new uint8_t[new_size]; + key_material_size = new_size; + return key_material; + } + + // The key_material in keymaster_key_blob_t is const, which is the right thing in most + // circumstances, but occasionally we do need to write into it. This method exposes a non-const + // version of the pointer. Use sparingly. + uint8_t* writable_data() { return const_cast<uint8_t*>(key_material); } + + keymaster_key_blob_t release() { + keymaster_key_blob_t tmp = {key_material, key_material_size}; + key_material = nullptr; + key_material_size = 0; + return tmp; + } + + size_t SerializedSize() const { return sizeof(uint32_t) + key_material_size; } + uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const { + return append_size_and_data_to_buf(buf, end, key_material, key_material_size); + } + + bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) { + Clear(); + UniquePtr<uint8_t[]> tmp; + if (!copy_size_and_data_from_buf(buf_ptr, end, &key_material_size, &tmp)) { + key_material = nullptr; + key_material_size = 0; + return false; + } + key_material = tmp.release(); + return true; + } +}; + } // namespace keymaster #endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_ diff --git a/include/keymaster/key_blob.h b/include/keymaster/key_blob.h deleted file mode 100644 index b2a3778..0000000 --- a/include/keymaster/key_blob.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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_KEYMASTER_KEY_BLOB_H_ -#define SYSTEM_KEYMASTER_KEY_BLOB_H_ - -#include <cstddef> - -#include <stdint.h> - -#include <UniquePtr.h> - -#include <hardware/keymaster_defs.h> -#include <keymaster/android_keymaster_utils.h> -#include <keymaster/authorization_set.h> -#include <keymaster/serializable.h> - -namespace keymaster { - -/** - * This class represents a Keymaster key blob, including authorization sets and encrypted key - * material. It serializes and deserializes blob arrays, and provides access to the data in the - * blob. - */ -class KeyBlob : public Serializable { - public: - static const size_t NONCE_LENGTH = 12; - static const size_t TAG_LENGTH = 128 / 8; - - /** - * Create a KeyBlob, extracting the enforced and unenforced sets. The KeyBlob does *not* take - * ownership of \p key_blob. - * - * IMPORTANT: After constructing a KeyBlob, call error() to verify that the blob is usable. - */ - KeyBlob(const uint8_t* key_blob, size_t key_blob_length); - - /** - * Create a KeyBlob, extracting the enforced and unenforced sets. The KeyBlob does *not* take - * ownership of \p key_blob's contents. - * - * IMPORTANT: After constructing a KeyBlob, call error() to verify that the blob is usable. - */ - KeyBlob(const keymaster_key_blob_t& key_blob); - - ~KeyBlob() { - ClearKeyData(); - // AuthorizationSets clear themselves. - } - - size_t SerializedSize() const; - uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; - bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); - - /** - * Returns KM_ERROR_OK if all is well, or an appropriate error code if there is a problem. This - * error code should be checked after construction or deserialization, and if it does not return - * KM_ERROR_OK, then don't call any other methods. - */ - inline keymaster_error_t error() { return error_; } - - inline const uint8_t* nonce() const { return nonce_.get(); } - inline const uint8_t* encrypted_key_material() const { return encrypted_key_material_.get(); } - inline size_t key_material_length() const { return key_material_length_; } - inline const uint8_t* tag() const { return tag_.get(); } - - inline const AuthorizationSet& enforced() const { return enforced_; } - inline const AuthorizationSet& unenforced() const { return unenforced_; } - inline keymaster_algorithm_t algorithm() const { return algorithm_; } - inline size_t key_size_bits() const { return key_size_bits_; } - keymaster_key_origin_t origin() const; - bool is_hardware() const; - - protected: - /** - * Create a KeyBlob containing the specified authorization data. - * - * IMPORTANT: After constructing a KeyBlob, call error() to verify that the blob is usable. - */ - KeyBlob(const AuthorizationSet& enforced, const AuthorizationSet& unenforced); - - /** - * Set encrypted key and supporting nonce and tag. Takes ownership of all arguments. - */ - void SetEncryptedKey(uint8_t* encrypted_key_material, size_t encrypted_key_material_length, - uint8_t* nonce, uint8_t* tag); - - keymaster_error_t error_; - - private: - void ClearKeyData() { - // None of these are sensitive, but clear them anyway. - if (encrypted_key_material_.get()) - memset_s(encrypted_key_material_.get(), 0, key_material_length_); - if (nonce_.get()) - memset_s(nonce_.get(), 0, NONCE_LENGTH); - if (tag_.get()) - memset_s(tag_.get(), 0, TAG_LENGTH); - } - - bool DeserializeUnversionedBlob(const uint8_t** buf_ptr, const uint8_t* end); - - bool ExtractKeyCharacteristics(); - - UniquePtr<uint8_t[]> nonce_; - UniquePtr<uint8_t[]> encrypted_key_material_; - UniquePtr<uint8_t[]> tag_; - size_t key_material_length_; - AuthorizationSet enforced_; - AuthorizationSet unenforced_; - keymaster_algorithm_t algorithm_; - uint32_t key_size_bits_; -}; - -} // namespace keymaster - -#endif // SYSTEM_KEYMASTER_KEY_BLOB_H_ diff --git a/include/keymaster/keymaster_context.h b/include/keymaster/keymaster_context.h new file mode 100644 index 0000000..68410f8 --- /dev/null +++ b/include/keymaster/keymaster_context.h @@ -0,0 +1,110 @@ +/* + * Copyright 2015 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_KEYMASTER_KEYMASTER_CONTEXT_H_ +#define SYSTEM_KEYMASTER_KEYMASTER_CONTEXT_H_ + +#include <assert.h> + +#include <keymaster/authorization_set.h> +#include <keymaster/android_keymaster_utils.h> + +namespace keymaster { + +/** + * KeymasterContext provides a singleton abstract interface that encapsulates various + * environment-dependent elements of AndroidKeymaster. + * + * AndroidKeymaster runs in multiple contexts. Primarily: + * + * - In a trusted execution environment (TEE) as a "secure hardware" implementation. In this + * context keys are wrapped with an master key that never leaves the TEE, TEE-specific routines + * are used for random number generation, all AndroidKeymaster-enforced authorizations are + * considered hardware-enforced, and there's a bootloader-provided root of trust. + * + * - In the non-secure world as a software-only implementation. In this context keys are not + * encrypted (though they are integrity-checked) because there is no place to securely store a + * key, OpenSSL is used for random number generation, no AndroidKeymaster-enforced authorizations + * are considered hardware enforced and the root of trust is a static string. + * + * - In the non-secure world as a hybrid implementation fronting a less-capable hardware + * implementation. For example, a keymaster0 hardware implementation. In this context keys are + * not encrypted by AndroidKeymaster, but some may be opaque blobs provided by the backing + * hardware, but blobs that lack the extended authorization lists of keymaster1. In addition, + * keymaster0 lacks many features of keymaster1, including modes of operation related to the + * backing keymaster0 keys. AndroidKeymaster must extend the blobs to add authorization lists, + * and must provide the missing operation mode implementations in software, which means that + * authorization lists are partially hardware-enforced (the bits that are enforced by the + * underlying keymaster0) and partially software-enforced (the rest). OpenSSL is used for number + * generation and the root of trust is a static string. + * + * More contexts are possible. + */ +class KeymasterContext { + public: + KeymasterContext() {} + virtual ~KeymasterContext() {}; + + /** + * CreateKeyBlob takes authorization sets and key material and produces a key blob and hardware + * and software authorization lists ready to be returned to the AndroidKeymaster client + * (Keystore, generally). The blob is integrity-checked and may be encrypted, depending on the + * needs of the context. + * + * This method is generally called only by KeyFactory subclassses. + */ + virtual keymaster_error_t CreateKeyBlob(const AuthorizationSet& key_description, + keymaster_key_origin_t origin, + const KeymasterKeyBlob& key_material, + KeymasterKeyBlob* blob, AuthorizationSet* hw_enforced, + AuthorizationSet* sw_enforced) const = 0; + + /** + * ParseKeyBlob takes a blob and extracts authorization sets and key material, returning an + * error if the blob fails integrity checking or decryption. Note that the returned key + * material may itself be an opaque blob usable only by secure hardware (in the hybrid case). + * + * This method is called by AndroidKeymaster. + */ + virtual keymaster_error_t ParseKeyBlob(const KeymasterKeyBlob& blob, + const AuthorizationSet& additional_params, + KeymasterKeyBlob* key_material, + AuthorizationSet* hw_enforced, + AuthorizationSet* sw_enforced) const = 0; + + /** + * Adds entropy to the Cryptographic Pseudo Random Number Generator used to generate key + * material, and other cryptographic protocol elements. Note that if the underlying CPRNG + * tracks the size of its entropy pool, it should not assume that the provided data contributes + * any entropy, and it should also ensure that data provided through this interface cannot + * "poison" the CPRNG outputs, making them predictable. + */ + virtual keymaster_error_t AddRngEntropy(const uint8_t* buf, size_t length) const = 0; + + /** + * Generates \p length random bytes, placing them in \p buf. + */ + virtual keymaster_error_t GenerateRandom(uint8_t* buf, size_t length) const = 0; + + private: + // Uncopyable. + KeymasterContext(const KeymasterContext&); + void operator=(const KeymasterContext&); +}; + +} // namespace keymaster + +#endif // SYSTEM_KEYMASTER_KEYMASTER_CONTEXT_H_ diff --git a/include/keymaster/serializable.h b/include/keymaster/serializable.h index b183367..e996fd8 100644 --- a/include/keymaster/serializable.h +++ b/include/keymaster/serializable.h @@ -194,6 +194,9 @@ class Buffer : public Serializable { return Reinitialize(buffer.peek_read(), buffer.available_read()); } + const uint8_t* begin() const { return peek_read(); } + const uint8_t* end() const { return peek_read() + available_read(); } + void Clear(); size_t available_write() const; diff --git a/include/keymaster/soft_keymaster_context.h b/include/keymaster/soft_keymaster_context.h new file mode 100644 index 0000000..1dba59d --- /dev/null +++ b/include/keymaster/soft_keymaster_context.h @@ -0,0 +1,52 @@ +/* + * Copyright 2015 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_KEYMASTER_SOFT_KEYMASTER_CONTEXT_H_ +#define SYSTEM_KEYMASTER_SOFT_KEYMASTER_CONTEXT_H_ + +#include <memory> + +#include <keymaster/keymaster_context.h> + +namespace keymaster { + +class SoftKeymasterKeyRegistrations; + +/** + * SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster. + */ +class SoftKeymasterContext : public KeymasterContext { + public: + SoftKeymasterContext(); + + keymaster_error_t CreateKeyBlob(const AuthorizationSet& auths, keymaster_key_origin_t origin, + const KeymasterKeyBlob& key_material, KeymasterKeyBlob* blob, + AuthorizationSet* hw_enforced, + AuthorizationSet* sw_enforced) const override; + keymaster_error_t ParseKeyBlob(const KeymasterKeyBlob& blob, + const AuthorizationSet& additional_params, + KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced, + AuthorizationSet* sw_enforced) const override; + keymaster_error_t AddRngEntropy(const uint8_t* buf, size_t length) const override; + keymaster_error_t GenerateRandom(uint8_t* buf, size_t length) const override; + + private: + std::unique_ptr<SoftKeymasterKeyRegistrations> registrations_; +}; + +} // namespace keymaster + +#endif // SYSTEM_KEYMASTER_SOFT_KEYMASTER_CONTEXT_H_ diff --git a/include/keymaster/soft_keymaster_device.h b/include/keymaster/soft_keymaster_device.h index 58dd2d9..44e64e9 100644 --- a/include/keymaster/soft_keymaster_device.h +++ b/include/keymaster/soft_keymaster_device.h @@ -51,7 +51,8 @@ class SoftKeymasterDevice { } private: - static keymaster_error_t ExtractSigningParams(const void* signing_params, + static keymaster_error_t ExtractSigningParams(const keymaster1_device_t* dev, + const void* signing_params, const uint8_t* key_blob, size_t key_blob_length, AuthorizationSet* auth_set); static void StoreDefaultNewKeyParams(AuthorizationSet* auth_set); |