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 */
java_time(time_t time)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 */
array_size(const T (& a)[N])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 */
array_length(const T (&)[N])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 */
dup_array(const T (& a)[N])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 */
copy_array(const T (& arr)[N],T * dest)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 */
array_contains(const T (& a)[N],T val)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
memset_s(void * s,int c,size_t n)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>
Eraser(T & t)138 explicit Eraser(T& t)
139 : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {}
140
Eraser(uint8_t (& arr)[N])141 template <size_t N> explicit Eraser(uint8_t (&arr)[N]) : buf_(arr), size_(N) {}
142
Eraser(void * buf,size_t size)143 Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {}
~Eraser()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