summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2015-05-26 08:31:37 -0600
committerShawn Willden <swillden@google.com>2015-05-26 10:21:38 -0600
commit0cb6942d3efb6c056f96321c82a4b3d86af601d6 (patch)
treecd34b5b3afdce65e41c47436944048cec90db97d /include
parent13fbe3e93247943c26e7ca2ed27b6d650282b8bf (diff)
downloadkeymaster-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.h34
-rw-r--r--include/keymaster/android_keymaster_utils.h94
-rw-r--r--include/keymaster/key_blob.h130
-rw-r--r--include/keymaster/keymaster_context.h110
-rw-r--r--include/keymaster/serializable.h3
-rw-r--r--include/keymaster/soft_keymaster_context.h52
-rw-r--r--include/keymaster/soft_keymaster_device.h3
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);