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