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 template <typename T> ArrayWrapper<T> array_range(T* begin, size_t length) {
    179     return ArrayWrapper<T>(begin, length);
    180 }
    181 
    182 /**
    183  * Convert any unsigned integer from network to host order.  We implement this here rather than
    184  * using the functions from arpa/inet.h because the TEE doesn't have inet.h.  This isn't the most
    185  * efficient implementation, but the compiler should unroll the loop and tighten it up.
    186  */
    187 template <typename T> T ntoh(T t) {
    188     const uint8_t* byte_ptr = reinterpret_cast<const uint8_t*>(&t);
    189     T retval = 0;
    190     for (size_t i = 0; i < sizeof(t); ++i) {
    191         retval <<= 8;
    192         retval |= byte_ptr[i];
    193     }
    194     return retval;
    195 }
    196 
    197 /**
    198  * Convert any unsigned integer from host to network order.  We implement this here rather than
    199  * using the functions from arpa/inet.h because the TEE doesn't have inet.h.  This isn't the most
    200  * efficient implementation, but the compiler should unroll the loop and tighten it up.
    201  */
    202 template <typename T> T hton(T t) {
    203     T retval;
    204     uint8_t* byte_ptr = reinterpret_cast<uint8_t*>(&retval);
    205     for (size_t i = sizeof(t); i > 0; --i) {
    206         byte_ptr[i - 1] = t & 0xFF;
    207         t >>= 8;
    208     }
    209     return retval;
    210 }
    211 
    212 /**
    213  * KeymasterKeyBlob is a very simple extension of the C struct keymaster_key_blob_t.  It manages its
    214  * own memory, which makes avoiding memory leaks much easier.
    215  */
    216 struct KeymasterKeyBlob : public keymaster_key_blob_t {
    217     KeymasterKeyBlob() {
    218         key_material = nullptr;
    219         key_material_size = 0;
    220     }
    221 
    222     KeymasterKeyBlob(const uint8_t* data, size_t size) {
    223         key_material_size = 0;
    224         key_material = dup_buffer(data, size);
    225         if (key_material)
    226             key_material_size = size;
    227     }
    228 
    229     explicit KeymasterKeyBlob(size_t size) {
    230         key_material_size = 0;
    231         key_material = new (std::nothrow) uint8_t[size];
    232         if (key_material)
    233             key_material_size = size;
    234     }
    235 
    236     explicit KeymasterKeyBlob(const keymaster_key_blob_t& blob) {
    237         key_material_size = 0;
    238         key_material = dup_buffer(blob.key_material, blob.key_material_size);
    239         if (key_material)
    240             key_material_size = blob.key_material_size;
    241     }
    242 
    243     KeymasterKeyBlob(const KeymasterKeyBlob& blob) {
    244         key_material_size = 0;
    245         key_material = dup_buffer(blob.key_material, blob.key_material_size);
    246         if (key_material)
    247             key_material_size = blob.key_material_size;
    248     }
    249 
    250     void operator=(const KeymasterKeyBlob& blob) {
    251         Clear();
    252         key_material = dup_buffer(blob.key_material, blob.key_material_size);
    253         key_material_size = blob.key_material_size;
    254     }
    255 
    256     ~KeymasterKeyBlob() { Clear(); }
    257 
    258     const uint8_t* begin() const { return key_material; }
    259     const uint8_t* end() const { return key_material + key_material_size; }
    260 
    261     void Clear() {
    262         memset_s(const_cast<uint8_t*>(key_material), 0, key_material_size);
    263         delete[] key_material;
    264         key_material = nullptr;
    265         key_material_size = 0;
    266     }
    267 
    268     const uint8_t* Reset(size_t new_size) {
    269         Clear();
    270         key_material = new (std::nothrow) uint8_t[new_size];
    271         if (key_material)
    272             key_material_size = new_size;
    273         return key_material;
    274     }
    275 
    276     // The key_material in keymaster_key_blob_t is const, which is the right thing in most
    277     // circumstances, but occasionally we do need to write into it.  This method exposes a non-const
    278     // version of the pointer.  Use sparingly.
    279     uint8_t* writable_data() { return const_cast<uint8_t*>(key_material); }
    280 
    281     keymaster_key_blob_t release() {
    282         keymaster_key_blob_t tmp = {key_material, key_material_size};
    283         key_material = nullptr;
    284         key_material_size = 0;
    285         return tmp;
    286     }
    287 
    288     size_t SerializedSize() const { return sizeof(uint32_t) + key_material_size; }
    289     uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const {
    290         return append_size_and_data_to_buf(buf, end, key_material, key_material_size);
    291     }
    292 
    293     bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
    294         Clear();
    295         UniquePtr<uint8_t[]> tmp;
    296         if (!copy_size_and_data_from_buf(buf_ptr, end, &key_material_size, &tmp)) {
    297             key_material = nullptr;
    298             key_material_size = 0;
    299             return false;
    300         }
    301         key_material = tmp.release();
    302         return true;
    303     }
    304 };
    305 
    306 struct Characteristics_Delete {
    307     void operator()(keymaster_key_characteristics_t* p) {
    308         keymaster_free_characteristics(p);
    309         free(p);
    310     }
    311 };
    312 
    313 struct Malloc_Delete {
    314     void operator()(void* p) { free(p); }
    315 };
    316 
    317 struct CertificateChainDelete {
    318     void operator()(keymaster_cert_chain_t* p) {
    319         if (!p)
    320             return;
    321         for (size_t i = 0; i < p->entry_count; ++i)
    322             delete[] p->entries[i].data;
    323         delete[] p->entries;
    324         delete p;
    325     }
    326 };
    327 
    328 keymaster_error_t EcKeySizeToCurve(uint32_t key_size_bits, keymaster_ec_curve_t* curve);
    329 keymaster_error_t EcCurveToKeySize(keymaster_ec_curve_t curve, uint32_t* key_size_bits);
    330 
    331 }  // namespace keymaster
    332 
    333 #endif  // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
    334