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 #pragma once
18
19 #include <stdint.h>
20 #include <time.h> // for time_t.
21
22 #include <hardware/keymaster_defs.h>
23
24 #include <keymaster/UniquePtr.h>
25 #include <keymaster/mem.h>
26 #include <keymaster/serializable.h>
27
28 #ifndef __has_cpp_attribute
29 #define __has_cpp_attribute(x) 0
30 #endif
31
32 // Mark intentional fallthroughts in switch statements to silence
33 // -Wimplicit-fallthrough.
34 #if __has_cpp_attribute(clang::fallthrough)
35 #define FALLTHROUGH [[clang::fallthrough]]
36 #else
37 #define FALLTHROUGH
38 #endif
39
40 namespace keymaster {
41
42 /**
43 * Convert the specified time value into "Java time", which is a signed 64-bit integer representing
44 * elapsed milliseconds since Jan 1, 1970.
45 */
java_time(time_t time)46 inline int64_t java_time(time_t time) {
47 // The exact meaning of a time_t value is implementation-dependent. If this code is ported to a
48 // platform that doesn't define it as "seconds since Jan 1, 1970 UTC", this function will have
49 // to be revised.
50 return static_cast<int64_t>(time) * 1000;
51 }
52
53 /**
54 * Convert any unsigned integer from network to host order. We implement this here rather than
55 * using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most
56 * efficient implementation, but the compiler should unroll the loop and tighten it up.
57 */
ntoh(T t)58 template <typename T> T ntoh(T t) {
59 const uint8_t* byte_ptr = reinterpret_cast<const uint8_t*>(&t);
60 T retval = 0;
61 for (size_t i = 0; i < sizeof(t); ++i) {
62 retval <<= 8;
63 retval |= byte_ptr[i];
64 }
65 return retval;
66 }
67
68 /**
69 * Convert any unsigned integer from host to network order. We implement this here rather than
70 * using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most
71 * efficient implementation, but the compiler should unroll the loop and tighten it up.
72 */
hton(T t)73 template <typename T> T hton(T t) {
74 T retval;
75 uint8_t* byte_ptr = reinterpret_cast<uint8_t*>(&retval);
76 for (size_t i = sizeof(t); i > 0; --i) {
77 byte_ptr[i - 1] = t & 0xFF;
78 t >>= 8;
79 }
80 return retval;
81 }
82
accessBlobData(const keymaster_key_blob_t * blob)83 inline const uint8_t* const& accessBlobData(const keymaster_key_blob_t* blob) {
84 return blob->key_material;
85 }
accessBlobData(keymaster_key_blob_t * blob)86 inline const uint8_t*& accessBlobData(keymaster_key_blob_t* blob) {
87 return blob->key_material;
88 }
accessBlobSize(const keymaster_key_blob_t * blob)89 inline const size_t& accessBlobSize(const keymaster_key_blob_t* blob) {
90 return blob->key_material_size;
91 }
accessBlobSize(keymaster_key_blob_t * blob)92 inline size_t& accessBlobSize(keymaster_key_blob_t* blob) {
93 return blob->key_material_size;
94 }
95
accessBlobData(const keymaster_blob_t * blob)96 inline const uint8_t* const& accessBlobData(const keymaster_blob_t* blob) {
97 return blob->data;
98 }
accessBlobData(keymaster_blob_t * blob)99 inline const uint8_t*& accessBlobData(keymaster_blob_t* blob) {
100 return blob->data;
101 }
accessBlobSize(const keymaster_blob_t * blob)102 inline const size_t& accessBlobSize(const keymaster_blob_t* blob) {
103 return blob->data_length;
104 }
accessBlobSize(keymaster_blob_t * blob)105 inline size_t& accessBlobSize(keymaster_blob_t* blob) {
106 return blob->data_length;
107 }
108
109 /**
110 * TKeymasterBlob is a very simple extension of the C structs keymaster_blob_t and
111 * keymaster_key_blob_t. It manages its own memory, which makes avoiding memory leaks
112 * much easier.
113 */
114 template <typename BlobType> struct TKeymasterBlob : public BlobType {
TKeymasterBlobTKeymasterBlob115 TKeymasterBlob() {
116 accessBlobData(this) = nullptr;
117 accessBlobSize(this) = 0;
118 }
119
TKeymasterBlobTKeymasterBlob120 TKeymasterBlob(const uint8_t* data, size_t size) {
121 accessBlobSize(this) = 0;
122 accessBlobData(this) = dup_buffer(data, size);
123 if (accessBlobData(this)) accessBlobSize(this) = size;
124 }
125
TKeymasterBlobTKeymasterBlob126 explicit TKeymasterBlob(size_t size) {
127 accessBlobSize(this) = 0;
128 accessBlobData(this) = new (std::nothrow) uint8_t[size];
129 if (accessBlobData(this)) accessBlobSize(this) = size;
130 }
131
TKeymasterBlobTKeymasterBlob132 explicit TKeymasterBlob(const BlobType& blob) {
133 accessBlobSize(this) = 0;
134 accessBlobData(this) = dup_buffer(accessBlobData(&blob), accessBlobSize(&blob));
135 if (accessBlobData(this)) accessBlobSize(this) = accessBlobSize(&blob);
136 }
137
TKeymasterBlobTKeymasterBlob138 template <size_t N> explicit TKeymasterBlob(const uint8_t (&data)[N]) {
139 accessBlobSize(this) = 0;
140 accessBlobData(this) = dup_buffer(data, N);
141 if (accessBlobData(this)) accessBlobSize(this) = N;
142 }
143
TKeymasterBlobTKeymasterBlob144 TKeymasterBlob(const TKeymasterBlob& blob) {
145 accessBlobSize(this) = 0;
146 accessBlobData(this) = dup_buffer(accessBlobData(&blob), accessBlobSize(&blob));
147 if (accessBlobData(this)) accessBlobSize(this) = accessBlobSize(&blob);
148 }
149
TKeymasterBlobTKeymasterBlob150 TKeymasterBlob(TKeymasterBlob&& rhs) {
151 accessBlobSize(this) = accessBlobSize(&rhs);
152 accessBlobData(this) = accessBlobData(&rhs);
153 accessBlobSize(&rhs) = 0;
154 accessBlobData(&rhs) = nullptr;
155 }
156
157 TKeymasterBlob& operator=(const TKeymasterBlob& blob) {
158 if (this != &blob) {
159 Clear();
160 accessBlobData(this) = dup_buffer(accessBlobData(&blob), accessBlobSize(&blob));
161 accessBlobSize(this) = accessBlobSize(&blob);
162 }
163 return *this;
164 }
165
166 TKeymasterBlob& operator=(TKeymasterBlob&& rhs) {
167 if (this != &rhs) {
168 Clear();
169 accessBlobSize(this) = accessBlobSize(&rhs);
170 accessBlobData(this) = accessBlobData(&rhs);
171 accessBlobSize(&rhs) = 0;
172 accessBlobData(&rhs) = nullptr;
173 }
174 return *this;
175 }
176
~TKeymasterBlobTKeymasterBlob177 ~TKeymasterBlob() { Clear(); }
178
beginTKeymasterBlob179 const uint8_t* begin() const { return accessBlobData(this); }
endTKeymasterBlob180 const uint8_t* end() const { return accessBlobData(this) + accessBlobSize(this); }
181
sizeTKeymasterBlob182 size_t size() const { return accessBlobSize(this); }
183
ClearTKeymasterBlob184 void Clear() {
185 if (accessBlobSize(this)) {
186 memset_s(const_cast<uint8_t*>(accessBlobData(this)), 0, accessBlobSize(this));
187 }
188 delete[] accessBlobData(this);
189 accessBlobData(this) = nullptr;
190 accessBlobSize(this) = 0;
191 }
192
ResetTKeymasterBlob193 const uint8_t* Reset(size_t new_size) {
194 Clear();
195 accessBlobData(this) = new (std::nothrow) uint8_t[new_size];
196 if (accessBlobData(this)) accessBlobSize(this) = new_size;
197 return accessBlobData(this);
198 }
199
200 // The key_material in keymaster_key_blob_t is const, which is the right thing in most
201 // circumstances, but occasionally we do need to write into it. This method exposes a non-const
202 // version of the pointer. Use sparingly.
writable_dataTKeymasterBlob203 uint8_t* writable_data() { return const_cast<uint8_t*>(accessBlobData(this)); }
204
releaseTKeymasterBlob205 BlobType release() {
206 BlobType tmp = {accessBlobData(this), accessBlobSize(this)};
207 accessBlobData(this) = nullptr;
208 accessBlobSize(this) = 0;
209 return tmp;
210 }
211
SerializedSizeTKeymasterBlob212 size_t SerializedSize() const { return sizeof(uint32_t) + accessBlobSize(this); }
SerializeTKeymasterBlob213 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const {
214 return append_size_and_data_to_buf(buf, end, accessBlobData(this), accessBlobSize(this));
215 }
216
DeserializeTKeymasterBlob217 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
218 Clear();
219 UniquePtr<uint8_t[]> tmp;
220 if (!copy_size_and_data_from_buf(buf_ptr, end, &accessBlobSize(this), &tmp)) {
221 accessBlobData(this) = nullptr;
222 accessBlobSize(this) = 0;
223 return false;
224 }
225 accessBlobData(this) = tmp.release();
226 return true;
227 }
228 };
229
230 typedef TKeymasterBlob<keymaster_blob_t> KeymasterBlob;
231 typedef TKeymasterBlob<keymaster_key_blob_t> KeymasterKeyBlob;
232
233 struct Characteristics_Delete {
operatorCharacteristics_Delete234 void operator()(keymaster_key_characteristics_t* p) {
235 keymaster_free_characteristics(p);
236 free(p);
237 }
238 };
239
240 keymaster_error_t EcKeySizeToCurve(uint32_t key_size_bits, keymaster_ec_curve_t* curve);
241 keymaster_error_t EcCurveToKeySize(keymaster_ec_curve_t curve, uint32_t* key_size_bits);
242
243 template <class F> class final_action {
244 public:
final_action(F f)245 explicit final_action(F f) : f_(move(f)) {}
~final_action()246 ~final_action() { f_(); }
247
248 private:
249 F f_;
250 };
251
finally(const F & f)252 template <class F> inline final_action<F> finally(const F& f) {
253 return final_action<F>(f);
254 }
255
256 struct CertificateChain : public keymaster_cert_chain_t {
CertificateChainCertificateChain257 CertificateChain() : keymaster_cert_chain_t{} {}
258
259 /**
260 * Create a chain with space allocated for `length` certificates. If allocation fails,
261 * `entries` will be null.
262 */
CertificateChainCertificateChain263 explicit CertificateChain(size_t length) : keymaster_cert_chain_t{} {
264 entries = new (std::nothrow) keymaster_blob_t[length];
265 if (!entries) return;
266 entry_count = length;
267 for (size_t i = 0; i < entry_count; ++i) {
268 entries[i] = {};
269 }
270 }
271
CertificateChainCertificateChain272 CertificateChain(CertificateChain&& other) : keymaster_cert_chain_t{} { *this = move(other); }
273
~CertificateChainCertificateChain274 ~CertificateChain() { Clear(); }
275
276 CertificateChain& operator=(CertificateChain&& other) {
277 Clear();
278 (keymaster_cert_chain_t&)(*this) = (keymaster_cert_chain_t&)(other);
279 (keymaster_cert_chain_t&)(other) = {};
280 return *this;
281 }
282
283 /**
284 * Clone `other`. If anything fails, `entries` will be null.
285 */
cloneCertificateChain286 static CertificateChain clone(const keymaster_cert_chain_t& other) {
287 CertificateChain retval;
288 retval.entry_count = other.entry_count;
289 retval.entries = new (std::nothrow) keymaster_blob_t[retval.entry_count];
290 if (!retval.entries) return {};
291
292 for (auto& entry : retval) {
293 entry = {};
294 }
295
296 for (size_t i = 0; i < retval.entry_count; ++i) {
297 retval.entries[i].data_length = other.entries[i].data_length;
298 retval.entries[i].data = new (std::nothrow) uint8_t[retval.entries[i].data_length];
299 if (!retval.entries[i].data) return {};
300
301 memcpy(const_cast<uint8_t*>(retval.entries[i].data), other.entries[i].data,
302 retval.entries[i].data_length);
303 }
304
305 return retval;
306 }
307
308 explicit operator bool() { return entries; }
309
beginCertificateChain310 keymaster_blob_t* begin() { return entries; }
beginCertificateChain311 const keymaster_blob_t* begin() const { return entries; }
endCertificateChain312 keymaster_blob_t* end() { return entries + entry_count; }
endCertificateChain313 const keymaster_blob_t* end() const { return entries + entry_count; }
314
315 // Insert the provided blob at the front of the chain. CertificateChain takes ownership of the
316 // contents of `new_entry`.
push_frontCertificateChain317 bool push_front(const keymaster_blob_t& new_entry) {
318 keymaster_blob_t* new_entries = new keymaster_blob_t[entry_count + 1];
319 if (!new_entries) return false;
320
321 new_entries[0] = new_entry;
322 for (size_t i = 1; i < entry_count + 1; ++i) {
323 new_entries[i] = entries[i - 1];
324 }
325
326 delete[] entries;
327 entries = new_entries;
328 ++entry_count;
329 return true;
330 }
331
releaseCertificateChain332 keymaster_cert_chain_t release() {
333 keymaster_cert_chain_t retval = *this;
334 entries = nullptr;
335 entry_count = 0;
336 return retval;
337 }
338
ClearCertificateChain339 void Clear() {
340 if (entries) {
341 for (size_t i = 0; i < entry_count; ++i) {
342 delete[] entries[i].data;
343 }
344 delete[] entries;
345 }
346 entry_count = 0;
347 entries = nullptr;
348 }
349 };
350
351 // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to GeneralizedTime
352 // 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
353 constexpr int64_t kUndefinedExpirationDateTime = 253402300799000;
354
355 // A confirmation token is the output of HMAC-SHA256. */
356 constexpr size_t kConfirmationTokenSize = 32;
357
358 // Defined in hardware/interfaces/confirmationui/1.0/IConfirmationResultCallback.hal
359 constexpr const char kConfirmationTokenMessageTag[] = "confirmation token";
360
361 constexpr size_t kConfirmationTokenMessageTagSize = sizeof(kConfirmationTokenMessageTag) - 1;
362
363 // Maximum supported size for CBOR which includes prompt and
364 // extra_data as returned by the ConfirmationUI. See
365 // https://source.android.com/security/protected-confirmation/implementation
366 constexpr size_t kConfirmationMessageMaxSize = 6144;
367
368 } // namespace keymaster
369