blob: b957dd1b59c77a6cc8b593ebef813227ac04c726
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_ANDROID_KEYMASTER_UTILS_H_ |
18 | #define SYSTEM_KEYMASTER_ANDROID_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 <hardware/keymaster_defs.h> |
27 | #include <keymaster/serializable.h> |
28 | |
29 | namespace keymaster { |
30 | |
31 | /** |
32 | * Convert the specified time value into "Java time", which is a signed 64-bit integer representing |
33 | * elapsed milliseconds since Jan 1, 1970. |
34 | */ |
35 | inline int64_t java_time(time_t time) { |
36 | // The exact meaning of a time_t value is implementation-dependent. If this code is ported to a |
37 | // platform that doesn't define it as "seconds since Jan 1, 1970 UTC", this function will have |
38 | // to be revised. |
39 | return time * 1000; |
40 | } |
41 | |
42 | /* |
43 | * Array Manipulation functions. This set of templated inline functions provides some nice tools |
44 | * for operating on c-style arrays. C-style arrays actually do have a defined size associated with |
45 | * them, as long as they are not allowed to decay to a pointer. These template methods exploit this |
46 | * to allow size-based array operations without explicitly specifying the size. If passed a pointer |
47 | * rather than an array, they'll fail to compile. |
48 | */ |
49 | |
50 | /** |
51 | * Return the size in bytes of the array \p a. |
52 | */ |
53 | template <typename T, size_t N> inline size_t array_size(const T(&a)[N]) { |
54 | return sizeof(a); |
55 | } |
56 | |
57 | /** |
58 | * Return the number of elements in array \p a. |
59 | */ |
60 | template <typename T, size_t N> inline size_t array_length(const T(&)[N]) { |
61 | return N; |
62 | } |
63 | |
64 | /** |
65 | * Duplicate the array \p a. The memory for the new array is allocated and the caller takes |
66 | * responsibility. |
67 | */ |
68 | template <typename T> inline T* dup_array(const T* a, size_t n) { |
69 | T* dup = new (std::nothrow) T[n]; |
70 | if (dup) |
71 | for (size_t i = 0; i < n; ++i) |
72 | dup[i] = a[i]; |
73 | return dup; |
74 | } |
75 | |
76 | /** |
77 | * Duplicate the array \p a. The memory for the new array is allocated and the caller takes |
78 | * responsibility. Note that the dup is necessarily returned as a pointer, so size is lost. Call |
79 | * array_length() on the original array to discover the size. |
80 | */ |
81 | template <typename T, size_t N> inline T* dup_array(const T(&a)[N]) { |
82 | return dup_array(a, N); |
83 | } |
84 | |
85 | /** |
86 | * Duplicate the buffer \p buf. The memory for the new buffer is allocated and the caller takes |
87 | * responsibility. |
88 | */ |
89 | uint8_t* dup_buffer(const void* buf, size_t size); |
90 | |
91 | /** |
92 | * Copy the contents of array \p arr to \p dest. |
93 | */ |
94 | template <typename T, size_t N> inline void copy_array(const T(&arr)[N], T* dest) { |
95 | for (size_t i = 0; i < N; ++i) |
96 | dest[i] = arr[i]; |
97 | } |
98 | |
99 | /** |
100 | * Search array \p a for value \p val, returning true if found. Note that this function is |
101 | * early-exit, meaning that it should not be used in contexts where timing analysis attacks could be |
102 | * a concern. |
103 | */ |
104 | template <typename T, size_t N> inline bool array_contains(const T(&a)[N], T val) { |
105 | for (size_t i = 0; i < N; ++i) { |
106 | if (a[i] == val) { |
107 | return true; |
108 | } |
109 | } |
110 | return false; |
111 | } |
112 | |
113 | /** |
114 | * Variant of memset() that uses GCC-specific pragmas to disable optimizations, so effect is not |
115 | * optimized away. This is important because we often need to wipe blocks of sensitive data from |
116 | * memory. As an additional convenience, this implementation avoids writing to NULL pointers. |
117 | */ |
118 | #ifdef __clang__ |
119 | #define OPTNONE __attribute__((optnone)) |
120 | #else // not __clang__ |
121 | #define OPTNONE __attribute__((optimize("O0"))) |
122 | #endif // not __clang__ |
123 | inline OPTNONE void* memset_s(void* s, int c, size_t n) { |
124 | if (!s) |
125 | return s; |
126 | return memset(s, c, n); |
127 | } |
128 | #undef OPTNONE |
129 | |
130 | /** |
131 | * Variant of memcmp that has the same runtime regardless of whether the data matches (i.e. doesn't |
132 | * short-circuit). Not an exact equivalent to memcmp because it doesn't return <0 if p1 < p2, just |
133 | * 0 for match and non-zero for non-match. |
134 | */ |
135 | int memcmp_s(const void* p1, const void* p2, size_t length); |
136 | |
137 | /** |
138 | * Eraser clears buffers. Construct it with a buffer or object and the destructor will ensure that |
139 | * it is zeroed. |
140 | */ |
141 | class Eraser { |
142 | public: |
143 | /* Not implemented. If this gets used, we want a link error. */ |
144 | template <typename T> explicit Eraser(T* t); |
145 | |
146 | template <typename T> |
147 | explicit Eraser(T& t) |
148 | : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {} |
149 | |
150 | template <size_t N> explicit Eraser(uint8_t(&arr)[N]) : buf_(arr), size_(N) {} |
151 | |
152 | Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {} |
153 | ~Eraser() { memset_s(buf_, 0, size_); } |
154 | |
155 | private: |
156 | Eraser(const Eraser&); |
157 | void operator=(const Eraser&); |
158 | |
159 | uint8_t* buf_; |
160 | size_t size_; |
161 | }; |
162 | |
163 | /** |
164 | * ArrayWrapper is a trivial wrapper around a C-style array that provides begin() and end() |
165 | * methods. This is primarily to facilitate range-based iteration on arrays. It does not copy, nor |
166 | * does it take ownership; it just holds pointers. |
167 | */ |
168 | template <typename T> class ArrayWrapper { |
169 | public: |
170 | ArrayWrapper(T* array, size_t size) : begin_(array), end_(array + size) {} |
171 | |
172 | T* begin() { return begin_; } |
173 | T* end() { return end_; } |
174 | |
175 | private: |
176 | T* begin_; |
177 | T* end_; |
178 | }; |
179 | |
180 | /** |
181 | * Convert any unsigned integer from network to host order. We implement this here rather than |
182 | * using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most |
183 | * efficient implementation, but the compiler should unroll the loop and tighten it up. |
184 | */ |
185 | template <typename T> T ntoh(T t) { |
186 | const uint8_t* byte_ptr = reinterpret_cast<const uint8_t*>(&t); |
187 | T retval = 0; |
188 | for (size_t i = 0; i < sizeof(t); ++i) { |
189 | retval <<= 8; |
190 | retval |= byte_ptr[i]; |
191 | } |
192 | return retval; |
193 | } |
194 | |
195 | /** |
196 | * Convert any unsigned integer from host to network order. We implement this here rather than |
197 | * using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most |
198 | * efficient implementation, but the compiler should unroll the loop and tighten it up. |
199 | */ |
200 | template <typename T> T hton(T t) { |
201 | T retval; |
202 | uint8_t* byte_ptr = reinterpret_cast<uint8_t*>(&retval); |
203 | for (size_t i = sizeof(t); i > 0; --i) { |
204 | byte_ptr[i - 1] = t & 0xFF; |
205 | t >>= 8; |
206 | } |
207 | return retval; |
208 | } |
209 | |
210 | /** |
211 | * KeymasterKeyBlob is a very simple extension of the C struct keymaster_key_blob_t. It manages its |
212 | * own memory, which makes avoiding memory leaks much easier. |
213 | */ |
214 | struct KeymasterKeyBlob : public keymaster_key_blob_t { |
215 | KeymasterKeyBlob() { |
216 | key_material = nullptr; |
217 | key_material_size = 0; |
218 | } |
219 | |
220 | KeymasterKeyBlob(const uint8_t* data, size_t size) { |
221 | key_material_size = 0; |
222 | key_material = dup_buffer(data, size); |
223 | if (key_material) |
224 | key_material_size = size; |
225 | } |
226 | |
227 | explicit KeymasterKeyBlob(size_t size) { |
228 | key_material_size = 0; |
229 | key_material = new (std::nothrow) uint8_t[size]; |
230 | if (key_material) |
231 | key_material_size = size; |
232 | } |
233 | |
234 | explicit KeymasterKeyBlob(const keymaster_key_blob_t& blob) { |
235 | key_material_size = 0; |
236 | key_material = dup_buffer(blob.key_material, blob.key_material_size); |
237 | if (key_material) |
238 | key_material_size = blob.key_material_size; |
239 | } |
240 | |
241 | KeymasterKeyBlob(const KeymasterKeyBlob& blob) { |
242 | key_material_size = 0; |
243 | key_material = dup_buffer(blob.key_material, blob.key_material_size); |
244 | if (key_material) |
245 | key_material_size = blob.key_material_size; |
246 | } |
247 | |
248 | void operator=(const KeymasterKeyBlob& blob) { |
249 | Clear(); |
250 | key_material = dup_buffer(blob.key_material, blob.key_material_size); |
251 | key_material_size = blob.key_material_size; |
252 | } |
253 | |
254 | ~KeymasterKeyBlob() { Clear(); } |
255 | |
256 | const uint8_t* begin() const { return key_material; } |
257 | const uint8_t* end() const { return key_material + key_material_size; } |
258 | |
259 | void Clear() { |
260 | memset_s(const_cast<uint8_t*>(key_material), 0, key_material_size); |
261 | delete[] key_material; |
262 | key_material = nullptr; |
263 | key_material_size = 0; |
264 | } |
265 | |
266 | const uint8_t* Reset(size_t new_size) { |
267 | Clear(); |
268 | key_material = new (std::nothrow) uint8_t[new_size]; |
269 | if (key_material) |
270 | key_material_size = new_size; |
271 | return key_material; |
272 | } |
273 | |
274 | // The key_material in keymaster_key_blob_t is const, which is the right thing in most |
275 | // circumstances, but occasionally we do need to write into it. This method exposes a non-const |
276 | // version of the pointer. Use sparingly. |
277 | uint8_t* writable_data() { return const_cast<uint8_t*>(key_material); } |
278 | |
279 | keymaster_key_blob_t release() { |
280 | keymaster_key_blob_t tmp = {key_material, key_material_size}; |
281 | key_material = nullptr; |
282 | key_material_size = 0; |
283 | return tmp; |
284 | } |
285 | |
286 | size_t SerializedSize() const { return sizeof(uint32_t) + key_material_size; } |
287 | uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const { |
288 | return append_size_and_data_to_buf(buf, end, key_material, key_material_size); |
289 | } |
290 | |
291 | bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) { |
292 | Clear(); |
293 | UniquePtr<uint8_t[]> tmp; |
294 | if (!copy_size_and_data_from_buf(buf_ptr, end, &key_material_size, &tmp)) { |
295 | key_material = nullptr; |
296 | key_material_size = 0; |
297 | return false; |
298 | } |
299 | key_material = tmp.release(); |
300 | return true; |
301 | } |
302 | }; |
303 | |
304 | } // namespace keymaster |
305 | |
306 | #endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_ |
307 |