• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /**
241  * Attempt to determine an arbitrary elliptic curve from a key size.  If the key size
242  * is ambiguous, KM_ERROR_UNSUPPORTED_KEY_SIZE is returned.
243  */
244 keymaster_error_t EllipticKeySizeToCurve(uint32_t key_size_bits, keymaster_ec_curve_t* curve);
245 
246 /**
247  * Attempt to determine an ECDSA curve from a key size, where the key is know to be
248  * an ECDSA (i.e. non-Edwards) specifically.
249  */
250 keymaster_error_t EcKeySizeToCurve(uint32_t key_size_bits, keymaster_ec_curve_t* curve);
251 
252 keymaster_error_t EcCurveToKeySize(keymaster_ec_curve_t curve, uint32_t* key_size_bits);
253 
254 template <class F> class final_action {
255   public:
final_action(F f)256     explicit final_action(F f) : f_(move(f)) {}
~final_action()257     ~final_action() { f_(); }
258 
259   private:
260     F f_;
261 };
262 
finally(const F & f)263 template <class F> inline final_action<F> finally(const F& f) {
264     return final_action<F>(f);
265 }
266 
267 struct CertificateChain : public keymaster_cert_chain_t {
CertificateChainCertificateChain268     CertificateChain() : keymaster_cert_chain_t{} {}
269 
270     /**
271      * Create a chain with space allocated for `length` certificates.  If allocation fails,
272      * `entries` will be null.
273      */
CertificateChainCertificateChain274     explicit CertificateChain(size_t length) : keymaster_cert_chain_t{} {
275         entries = new (std::nothrow) keymaster_blob_t[length];
276         if (!entries) return;
277         entry_count = length;
278         for (size_t i = 0; i < entry_count; ++i) {
279             entries[i] = {};
280         }
281     }
282 
CertificateChainCertificateChain283     CertificateChain(CertificateChain&& other) : keymaster_cert_chain_t{} { *this = move(other); }
284 
~CertificateChainCertificateChain285     ~CertificateChain() { Clear(); }
286 
287     CertificateChain& operator=(CertificateChain&& other) {
288         Clear();
289         (keymaster_cert_chain_t&)(*this) = (keymaster_cert_chain_t&)(other);
290         (keymaster_cert_chain_t&)(other) = {};
291         return *this;
292     }
293 
294     /**
295      * Clone `other`.  If anything fails, `entries` will be null.
296      */
cloneCertificateChain297     static CertificateChain clone(const keymaster_cert_chain_t& other) {
298         CertificateChain retval;
299         retval.entry_count = other.entry_count;
300         retval.entries = new (std::nothrow) keymaster_blob_t[retval.entry_count];
301         if (!retval.entries) return {};
302 
303         for (auto& entry : retval) {
304             entry = {};
305         }
306 
307         for (size_t i = 0; i < retval.entry_count; ++i) {
308             retval.entries[i].data_length = other.entries[i].data_length;
309             retval.entries[i].data = new (std::nothrow) uint8_t[retval.entries[i].data_length];
310             if (!retval.entries[i].data) return {};
311 
312             memcpy(const_cast<uint8_t*>(retval.entries[i].data), other.entries[i].data,
313                    retval.entries[i].data_length);
314         }
315 
316         return retval;
317     }
318 
319     explicit operator bool() { return entries; }
320 
beginCertificateChain321     keymaster_blob_t* begin() { return entries; }
beginCertificateChain322     const keymaster_blob_t* begin() const { return entries; }
endCertificateChain323     keymaster_blob_t* end() { return entries + entry_count; }
endCertificateChain324     const keymaster_blob_t* end() const { return entries + entry_count; }
325 
326     // Insert the provided blob at the front of the chain.  CertificateChain takes ownership of the
327     // contents of `new_entry`.
push_frontCertificateChain328     bool push_front(const keymaster_blob_t& new_entry) {
329         keymaster_blob_t* new_entries = new (std::nothrow) keymaster_blob_t[entry_count + 1];
330         if (!new_entries) return false;
331 
332         new_entries[0] = new_entry;
333         for (size_t i = 1; i < entry_count + 1; ++i) {
334             new_entries[i] = entries[i - 1];
335         }
336 
337         delete[] entries;
338         entries = new_entries;
339         ++entry_count;
340         return true;
341     }
342 
releaseCertificateChain343     keymaster_cert_chain_t release() {
344         keymaster_cert_chain_t retval = *this;
345         entries = nullptr;
346         entry_count = 0;
347         return retval;
348     }
349 
ClearCertificateChain350     void Clear() {
351         if (entries) {
352             for (size_t i = 0; i < entry_count; ++i) {
353                 delete[] entries[i].data;
354             }
355             delete[] entries;
356         }
357         entry_count = 0;
358         entries = nullptr;
359     }
360 };
361 
362 // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to GeneralizedTime
363 // 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
364 constexpr int64_t kUndefinedExpirationDateTime = 253402300799000;
365 
366 // A confirmation token is the output of HMAC-SHA256. */
367 constexpr size_t kConfirmationTokenSize = 32;
368 
369 // Defined in hardware/interfaces/confirmationui/1.0/IConfirmationResultCallback.hal
370 constexpr const char kConfirmationTokenMessageTag[] = "confirmation token";
371 
372 constexpr size_t kConfirmationTokenMessageTagSize = sizeof(kConfirmationTokenMessageTag) - 1;
373 
374 // Maximum supported size for CBOR which includes prompt and
375 // extra_data as returned by the ConfirmationUI. See
376 // https://source.android.com/security/protected-confirmation/implementation
377 constexpr size_t kConfirmationMessageMaxSize = 6144;
378 
379 }  // namespace keymaster
380