• 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 #ifndef SYSTEM_KEYMASTER_GOOGLE_KEYMASTER_UTILS_H_
18 #define SYSTEM_KEYMASTER_GOOGLE_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 <keymaster/serializable.h>
27 
28 namespace keymaster {
29 
30 /**
31  * Convert the specified time value into "Java time", which is a signed 64-bit integer representing
32  * elapsed milliseconds since Jan 1, 1970.
33  */
java_time(time_t time)34 inline int64_t java_time(time_t time) {
35     // The exact meaning of a time_t value is implementation-dependent.  If this code is ported to a
36     // platform that doesn't define it as "seconds since Jan 1, 1970 UTC", this function will have
37     // to be revised.
38     return time * 1000;
39 }
40 
41 /*
42  * Array Manipulation functions.  This set of templated inline functions provides some nice tools
43  * for operating on c-style arrays.  C-style arrays actually do have a defined size associated with
44  * them, as long as they are not allowed to decay to a pointer.  These template methods exploit this
45  * to allow size-based array operations without explicitly specifying the size.  If passed a pointer
46  * rather than an array, they'll fail to compile.
47  */
48 
49 /**
50  * Return the size in bytes of the array \p a.
51  */
array_size(const T (& a)[N])52 template <typename T, size_t N> inline size_t array_size(const T (&a)[N]) {
53     return sizeof(a);
54 }
55 
56 /**
57  * Return the number of elements in array \p a.
58  */
array_length(const T (&)[N])59 template <typename T, size_t N> inline size_t array_length(const T (&)[N]) {
60     return N;
61 }
62 
63 /**
64  * Duplicate the array \p a.  The memory for the new array is allocated and the caller takes
65  * responsibility.  Note that the dup is necessarily returned as a pointer, so size is lost.  Call
66  * array_length() on the original array to discover the size.
67  */
dup_array(const T (& a)[N])68 template <typename T, size_t N> inline T* dup_array(const T (&a)[N]) {
69     T* dup = new T[N];
70     if (dup != NULL) {
71         memcpy(dup, &a, array_size(a));
72     }
73     return dup;
74 }
75 
76 /**
77  * Duplicate the buffer \p buf.  The memory for the new buffer is allocated and the caller takes
78  * responsibility.
79  */
80 uint8_t* dup_buffer(const void* buf, size_t size);
81 
82 /**
83  * Copy the contents of array \p arr to \p dest.
84  */
copy_array(const T (& arr)[N],T * dest)85 template <typename T, size_t N> inline void copy_array(const T (&arr)[N], T* dest) {
86     for (size_t i = 0; i < N; ++i)
87         dest[i] = arr[i];
88 }
89 
90 /**
91  * Search array \p a for value \p val, returning true if found.  Note that this function is
92  * early-exit, meaning that it should not be used in contexts where timing analysis attacks could be
93  * a concern.
94  */
array_contains(const T (& a)[N],T val)95 template <typename T, size_t N> inline bool array_contains(const T (&a)[N], T val) {
96     for (size_t i = 0; i < N; ++i) {
97         if (a[i] == val) {
98             return true;
99         }
100     }
101     return false;
102 }
103 
104 /**
105  * Variant of memset() that uses GCC-specific pragmas to disable optimizations, so effect is not
106  * optimized away.  This is important because we often need to wipe blocks of sensitive data from
107  * memory.  As an additional convenience, this implementation avoids writing to NULL pointers.
108  */
109 #ifdef KEYMASTER_CLANG_TEST_BUILD
110 #define OPTIMIZE(x)
111 #else  // not KEYMASTER_CLANG_TEST_BUILD
112 #define OPTIMIZE(x) __attribute__((optimize(x)))
113 #endif  // not KEYMASTER_CLANG_TEST_BUILD
memset_s(void * s,int c,size_t n)114 inline OPTIMIZE("O0") void* memset_s(void* s, int c, size_t n) {
115     if (!s)
116         return s;
117     return memset(s, c, n);
118 }
119 #undef OPTIMIZE
120 
121 /**
122  * Variant of memcmp that has the same runtime regardless of whether the data matches (i.e. doesn't
123  * short-circuit).  Not an exact equivalent to memcmp because it doesn't return <0 if p1 < p2, just
124  * 0 for match and non-zero for non-match.
125  */
126 int memcmp_s(const void* p1, const void* p2, size_t length);
127 
128 /**
129  * Eraser clears buffers.  Construct it with a buffer or object and the destructor will ensure that
130  * it is zeroed.
131  */
132 class Eraser {
133   public:
134     /* Not implemented.  If this gets used, we want a link error. */
135     template <typename T> explicit Eraser(T* t);
136 
137     template <typename T>
Eraser(T & t)138     explicit Eraser(T& t)
139         : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {}
140 
Eraser(uint8_t (& arr)[N])141     template <size_t N> explicit Eraser(uint8_t (&arr)[N]) : buf_(arr), size_(N) {}
142 
Eraser(void * buf,size_t size)143     Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {}
~Eraser()144     ~Eraser() { memset_s(buf_, 0, size_); }
145 
146   private:
147     Eraser(const Eraser&);
148     void operator=(const Eraser&);
149 
150     uint8_t* buf_;
151     size_t size_;
152 };
153 
154 }  // namespace keymaster
155 
156 #endif  // SYSTEM_KEYMASTER_GOOGLE_KEYMASTER_UTILS_H_
157