Home | History | Annotate | Download | only in keymaster
      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 static_cast<int64_t>(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) : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {}
    148 
    149     template <size_t N> explicit Eraser(uint8_t (&arr)[N]) : buf_(arr), size_(N) {}
    150 
    151     Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {}
    152     ~Eraser() { memset_s(buf_, 0, size_); }
    153 
    154   private:
    155     Eraser(const Eraser&);
    156     void operator=(const Eraser&);
    157 
    158     uint8_t* buf_;
    159     size_t size_;
    160 };
    161 
    162 /**
    163  * ArrayWrapper is a trivial wrapper around a C-style array that provides begin() and end()
    164  * methods. This is primarily to facilitate range-based iteration on arrays.  It does not copy, nor
    165  * does it take ownership; it just holds pointers.
    166  */
    167 template <typename T> class ArrayWrapper {
    168   public:
    169     ArrayWrapper(T* array, size_t size) : begin_(array), end_(array + size) {}
    170 
    171     T* begin() { return begin_; }
    172     T* end() { return end_; }
    173 
    174   private:
    175     T* begin_;
    176     T* end_;
    177 };
    178 
    179 template <typename T> ArrayWrapper<T> array_range(T* begin, size_t length) {
    180     return ArrayWrapper<T>(begin, length);
    181 }
    182 
    183 template <typename T, size_t n> ArrayWrapper<T> array_range(T (&a)[n]) {
    184     return ArrayWrapper<T>(a, n);
    185 }
    186 
    187 /**
    188  * Convert any unsigned integer from network to host order.  We implement this here rather than
    189  * using the functions from arpa/inet.h because the TEE doesn't have inet.h.  This isn't the most
    190  * efficient implementation, but the compiler should unroll the loop and tighten it up.
    191  */
    192 template <typename T> T ntoh(T t) {
    193     const uint8_t* byte_ptr = reinterpret_cast<const uint8_t*>(&t);
    194     T retval = 0;
    195     for (size_t i = 0; i < sizeof(t); ++i) {
    196         retval <<= 8;
    197         retval |= byte_ptr[i];
    198     }
    199     return retval;
    200 }
    201 
    202 /**
    203  * Convert any unsigned integer from host to network order.  We implement this here rather than
    204  * using the functions from arpa/inet.h because the TEE doesn't have inet.h.  This isn't the most
    205  * efficient implementation, but the compiler should unroll the loop and tighten it up.
    206  */
    207 template <typename T> T hton(T t) {
    208     T retval;
    209     uint8_t* byte_ptr = reinterpret_cast<uint8_t*>(&retval);
    210     for (size_t i = sizeof(t); i > 0; --i) {
    211         byte_ptr[i - 1] = t & 0xFF;
    212         t >>= 8;
    213     }
    214     return retval;
    215 }
    216 
    217 /**
    218  * KeymasterKeyBlob is a very simple extension of the C struct keymaster_key_blob_t.  It manages its
    219  * own memory, which makes avoiding memory leaks much easier.
    220  */
    221 struct KeymasterKeyBlob : public keymaster_key_blob_t {
    222     KeymasterKeyBlob() {
    223         key_material = nullptr;
    224         key_material_size = 0;
    225     }
    226 
    227     KeymasterKeyBlob(const uint8_t* data, size_t size) {
    228         key_material_size = 0;
    229         key_material = dup_buffer(data, size);
    230         if (key_material)
    231             key_material_size = size;
    232     }
    233 
    234     explicit KeymasterKeyBlob(size_t size) {
    235         key_material_size = 0;
    236         key_material = new (std::nothrow) uint8_t[size];
    237         if (key_material)
    238             key_material_size = size;
    239     }
    240 
    241     explicit KeymasterKeyBlob(const keymaster_key_blob_t& 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     KeymasterKeyBlob(const KeymasterKeyBlob& blob) {
    249         key_material_size = 0;
    250         key_material = dup_buffer(blob.key_material, blob.key_material_size);
    251         if (key_material)
    252             key_material_size = blob.key_material_size;
    253     }
    254 
    255     void operator=(const KeymasterKeyBlob& blob) {
    256         Clear();
    257         key_material = dup_buffer(blob.key_material, blob.key_material_size);
    258         key_material_size = blob.key_material_size;
    259     }
    260 
    261     ~KeymasterKeyBlob() { Clear(); }
    262 
    263     const uint8_t* begin() const { return key_material; }
    264     const uint8_t* end() const { return key_material + key_material_size; }
    265 
    266     void Clear() {
    267         memset_s(const_cast<uint8_t*>(key_material), 0, key_material_size);
    268         delete[] key_material;
    269         key_material = nullptr;
    270         key_material_size = 0;
    271     }
    272 
    273     const uint8_t* Reset(size_t new_size) {
    274         Clear();
    275         key_material = new (std::nothrow) uint8_t[new_size];
    276         if (key_material)
    277             key_material_size = new_size;
    278         return key_material;
    279     }
    280 
    281     // The key_material in keymaster_key_blob_t is const, which is the right thing in most
    282     // circumstances, but occasionally we do need to write into it.  This method exposes a non-const
    283     // version of the pointer.  Use sparingly.
    284     uint8_t* writable_data() { return const_cast<uint8_t*>(key_material); }
    285 
    286     keymaster_key_blob_t release() {
    287         keymaster_key_blob_t tmp = {key_material, key_material_size};
    288         key_material = nullptr;
    289         key_material_size = 0;
    290         return tmp;
    291     }
    292 
    293     size_t SerializedSize() const { return sizeof(uint32_t) + key_material_size; }
    294     uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const {
    295         return append_size_and_data_to_buf(buf, end, key_material, key_material_size);
    296     }
    297 
    298     bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
    299         Clear();
    300         UniquePtr<uint8_t[]> tmp;
    301         if (!copy_size_and_data_from_buf(buf_ptr, end, &key_material_size, &tmp)) {
    302             key_material = nullptr;
    303             key_material_size = 0;
    304             return false;
    305         }
    306         key_material = tmp.release();
    307         return true;
    308     }
    309 };
    310 
    311 struct Characteristics_Delete {
    312     void operator()(keymaster_key_characteristics_t* p) {
    313         keymaster_free_characteristics(p);
    314         free(p);
    315     }
    316 };
    317 
    318 struct Malloc_Delete {
    319     void operator()(void* p) { free(p); }
    320 };
    321 
    322 struct CertificateChainDelete {
    323     void operator()(keymaster_cert_chain_t* p) {
    324         if (!p)
    325             return;
    326         for (size_t i = 0; i < p->entry_count; ++i)
    327             delete[] p->entries[i].data;
    328         delete[] p->entries;
    329         delete p;
    330     }
    331 };
    332 
    333 keymaster_error_t EcKeySizeToCurve(uint32_t key_size_bits, keymaster_ec_curve_t* curve);
    334 keymaster_error_t EcCurveToKeySize(keymaster_ec_curve_t curve, uint32_t* key_size_bits);
    335 
    336 }  // namespace keymaster
    337 
    338 #endif  // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
    339