1 /* 2 * Copyright 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SYSTEM_KEYMASTER_GOOGLE_KEYMASTER_UTILS_H_ 18 #define SYSTEM_KEYMASTER_GOOGLE_KEYMASTER_UTILS_H_ 19 20 #include <stdint.h> 21 #include <string.h> 22 #include <time.h> // for time_t. 23 24 #include <UniquePtr.h> 25 26 #include <keymaster/serializable.h> 27 28 namespace keymaster { 29 30 /** 31 * Convert the specified time value into "Java time", which is a signed 64-bit integer representing 32 * elapsed milliseconds since Jan 1, 1970. 33 */ 34 inline int64_t java_time(time_t time) { 35 // The exact meaning of a time_t value is implementation-dependent. If this code is ported to a 36 // platform that doesn't define it as "seconds since Jan 1, 1970 UTC", this function will have 37 // to be revised. 38 return time * 1000; 39 } 40 41 /* 42 * Array Manipulation functions. This set of templated inline functions provides some nice tools 43 * for operating on c-style arrays. C-style arrays actually do have a defined size associated with 44 * them, as long as they are not allowed to decay to a pointer. These template methods exploit this 45 * to allow size-based array operations without explicitly specifying the size. If passed a pointer 46 * rather than an array, they'll fail to compile. 47 */ 48 49 /** 50 * Return the size in bytes of the array \p a. 51 */ 52 template <typename T, size_t N> inline size_t array_size(const T (&a)[N]) { 53 return sizeof(a); 54 } 55 56 /** 57 * Return the number of elements in array \p a. 58 */ 59 template <typename T, size_t N> inline size_t array_length(const T (&)[N]) { 60 return N; 61 } 62 63 /** 64 * Duplicate the array \p a. The memory for the new array is allocated and the caller takes 65 * responsibility. Note that the dup is necessarily returned as a pointer, so size is lost. Call 66 * array_length() on the original array to discover the size. 67 */ 68 template <typename T, size_t N> inline T* dup_array(const T (&a)[N]) { 69 T* dup = new T[N]; 70 if (dup != NULL) { 71 memcpy(dup, &a, array_size(a)); 72 } 73 return dup; 74 } 75 76 /** 77 * Duplicate the buffer \p buf. The memory for the new buffer is allocated and the caller takes 78 * responsibility. 79 */ 80 uint8_t* dup_buffer(const void* buf, size_t size); 81 82 /** 83 * Copy the contents of array \p arr to \p dest. 84 */ 85 template <typename T, size_t N> inline void copy_array(const T (&arr)[N], T* dest) { 86 for (size_t i = 0; i < N; ++i) 87 dest[i] = arr[i]; 88 } 89 90 /** 91 * Search array \p a for value \p val, returning true if found. Note that this function is 92 * early-exit, meaning that it should not be used in contexts where timing analysis attacks could be 93 * a concern. 94 */ 95 template <typename T, size_t N> inline bool array_contains(const T (&a)[N], T val) { 96 for (size_t i = 0; i < N; ++i) { 97 if (a[i] == val) { 98 return true; 99 } 100 } 101 return false; 102 } 103 104 /** 105 * Variant of memset() that uses GCC-specific pragmas to disable optimizations, so effect is not 106 * optimized away. This is important because we often need to wipe blocks of sensitive data from 107 * memory. As an additional convenience, this implementation avoids writing to NULL pointers. 108 */ 109 #ifdef KEYMASTER_CLANG_TEST_BUILD 110 #define OPTIMIZE(x) 111 #else // not KEYMASTER_CLANG_TEST_BUILD 112 #define OPTIMIZE(x) __attribute__((optimize(x))) 113 #endif // not KEYMASTER_CLANG_TEST_BUILD 114 inline OPTIMIZE("O0") void* memset_s(void* s, int c, size_t n) { 115 if (!s) 116 return s; 117 return memset(s, c, n); 118 } 119 #undef OPTIMIZE 120 121 /** 122 * Variant of memcmp that has the same runtime regardless of whether the data matches (i.e. doesn't 123 * short-circuit). Not an exact equivalent to memcmp because it doesn't return <0 if p1 < p2, just 124 * 0 for match and non-zero for non-match. 125 */ 126 int memcmp_s(const void* p1, const void* p2, size_t length); 127 128 /** 129 * Eraser clears buffers. Construct it with a buffer or object and the destructor will ensure that 130 * it is zeroed. 131 */ 132 class Eraser { 133 public: 134 /* Not implemented. If this gets used, we want a link error. */ 135 template <typename T> explicit Eraser(T* t); 136 137 template <typename T> 138 explicit Eraser(T& t) 139 : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {} 140 141 template <size_t N> explicit Eraser(uint8_t (&arr)[N]) : buf_(arr), size_(N) {} 142 143 Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {} 144 ~Eraser() { memset_s(buf_, 0, size_); } 145 146 private: 147 Eraser(const Eraser&); 148 void operator=(const Eraser&); 149 150 uint8_t* buf_; 151 size_t size_; 152 }; 153 154 } // namespace keymaster 155 156 #endif // SYSTEM_KEYMASTER_GOOGLE_KEYMASTER_UTILS_H_ 157