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