42 files changed, 6493 insertions, 19016 deletions
diff --git a/unit_test/android_keymaster_utils.h b/unit_test/android_keymaster_utils.h deleted file mode 100644 index b957dd1..0000000 --- a/unit_test/android_keymaster_utils.h +++ b/dev/null @@ -1,306 +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_ANDROID_KEYMASTER_UTILS_H_ -#define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_ - -#include <stdint.h> -#include <string.h> -#include <time.h> // for time_t. - -#include <UniquePtr.h> - -#include <hardware/keymaster_defs.h> -#include <keymaster/serializable.h> - -namespace keymaster { - -/** - * Convert the specified time value into "Java time", which is a signed 64-bit integer representing - * elapsed milliseconds since Jan 1, 1970. - */ -inline int64_t java_time(time_t time) { - // The exact meaning of a time_t value is implementation-dependent. If this code is ported to a - // platform that doesn't define it as "seconds since Jan 1, 1970 UTC", this function will have - // to be revised. - return time * 1000; -} - -/* - * Array Manipulation functions. This set of templated inline functions provides some nice tools - * for operating on c-style arrays. C-style arrays actually do have a defined size associated with - * them, as long as they are not allowed to decay to a pointer. These template methods exploit this - * to allow size-based array operations without explicitly specifying the size. If passed a pointer - * rather than an array, they'll fail to compile. - */ - -/** - * 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]) { - 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]) { - return N; -} - -/** - * Duplicate the array \p a. The memory for the new array is allocated and the caller takes - * responsibility. - */ -template <typename T> inline T* dup_array(const T* a, size_t n) { - T* dup = new (std::nothrow) T[n]; - if (dup) - for (size_t i = 0; i < n; ++i) - dup[i] = a[i]; - return dup; -} - -/** - * Duplicate the array \p a. The memory for the new array is allocated and the caller takes - * 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]) { - return dup_array(a, N); -} - -/** - * Duplicate the buffer \p buf. The memory for the new buffer is allocated and the caller takes - * responsibility. - */ -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) { - for (size_t i = 0; i < N; ++i) - dest[i] = arr[i]; -} - -/** - * Search array \p a for value \p val, returning true if found. Note that this function is - * 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) { - for (size_t i = 0; i < N; ++i) { - if (a[i] == val) { - return true; - } - } - return false; -} - -/** - * Variant of memset() that uses GCC-specific pragmas to disable optimizations, so effect is not - * optimized away. This is important because we often need to wipe blocks of sensitive data from - * memory. As an additional convenience, this implementation avoids writing to NULL pointers. - */ -#ifdef __clang__ -#define OPTNONE __attribute__((optnone)) -#else // not __clang__ -#define OPTNONE __attribute__((optimize("O0"))) -#endif // not __clang__ -inline OPTNONE void* memset_s(void* s, int c, size_t n) { - if (!s) - return s; - return memset(s, c, n); -} -#undef OPTNONE - -/** - * Variant of memcmp that has the same runtime regardless of whether the data matches (i.e. doesn't - * short-circuit). Not an exact equivalent to memcmp because it doesn't return <0 if p1 < p2, just - * 0 for match and non-zero for non-match. - */ -int memcmp_s(const void* p1, const void* p2, size_t length); - -/** - * Eraser clears buffers. Construct it with a buffer or object and the destructor will ensure that - * it is zeroed. - */ -class Eraser { - public: - /* Not implemented. If this gets used, we want a link error. */ - template <typename T> explicit Eraser(T* t); - - template <typename T> - explicit Eraser(T& t) - : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {} - - 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_); } - - private: - Eraser(const Eraser&); - void operator=(const Eraser&); - - uint8_t* buf_; - size_t size_; -}; - -/** - * ArrayWrapper is a trivial wrapper around a C-style array that provides begin() and end() - * methods. This is primarily to facilitate range-based iteration on arrays. It does not copy, nor - * does it take ownership; it just holds pointers. - */ -template <typename T> class ArrayWrapper { - public: - ArrayWrapper(T* array, size_t size) : begin_(array), end_(array + size) {} - - T* begin() { return begin_; } - T* end() { return end_; } - - private: - T* begin_; - T* end_; -}; - -/** - * Convert any unsigned integer from network to host order. We implement this here rather than - * using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most - * efficient implementation, but the compiler should unroll the loop and tighten it up. - */ -template <typename T> T ntoh(T t) { - const uint8_t* byte_ptr = reinterpret_cast<const uint8_t*>(&t); - T retval = 0; - for (size_t i = 0; i < sizeof(t); ++i) { - retval <<= 8; - retval |= byte_ptr[i]; - } - return retval; -} - -/** - * Convert any unsigned integer from host to network order. We implement this here rather than - * using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most - * efficient implementation, but the compiler should unroll the loop and tighten it up. - */ -template <typename T> T hton(T t) { - T retval; - uint8_t* byte_ptr = reinterpret_cast<uint8_t*>(&retval); - for (size_t i = sizeof(t); i > 0; --i) { - byte_ptr[i - 1] = t & 0xFF; - t >>= 8; - } - 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_size = 0; - key_material = dup_buffer(data, size); - if (key_material) - key_material_size = size; - } - - explicit KeymasterKeyBlob(size_t size) { - key_material_size = 0; - key_material = new (std::nothrow) uint8_t[size]; - if (key_material) - key_material_size = size; - } - - explicit KeymasterKeyBlob(const keymaster_key_blob_t& blob) { - key_material_size = 0; - key_material = dup_buffer(blob.key_material, blob.key_material_size); - if (key_material) - key_material_size = blob.key_material_size; - } - - KeymasterKeyBlob(const KeymasterKeyBlob& blob) { - key_material_size = 0; - key_material = dup_buffer(blob.key_material, blob.key_material_size); - if (key_material) - key_material_size = blob.key_material_size; - } - - void operator=(const KeymasterKeyBlob& blob) { - Clear(); - 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 (std::nothrow) uint8_t[new_size]; - if (key_material) - 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_ |