1 | /* Copyright (c) (2010-2012,2014-2022) Apple Inc. All rights reserved. |
2 | * |
3 | * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which |
4 | * is contained in the License.txt file distributed with corecrypto) and only to |
5 | * people who accept that license. IMPORTANT: Any license rights granted to you by |
6 | * Apple Inc. (if any) are limited to internal use within your organization only on |
7 | * devices and computers you own or control, for the sole purpose of verifying the |
8 | * security characteristics and correct functioning of the Apple Software. You may |
9 | * not, directly or indirectly, redistribute the Apple Software or any portions thereof. |
10 | */ |
11 | |
12 | #ifndef _CORECRYPTO_CC_H_ |
13 | #define _CORECRYPTO_CC_H_ |
14 | |
15 | #include <corecrypto/cc_config.h> |
16 | #include <corecrypto/cc_impl.h> |
17 | #include <corecrypto/cc_error.h> |
18 | |
19 | #include <string.h> |
20 | #include <stdint.h> |
21 | #include <stdbool.h> |
22 | #include <stddef.h> |
23 | #include <stdarg.h> |
24 | |
25 | CC_PTRCHECK_CAPABLE_HEADER() |
26 | |
27 | #if __has_feature(attribute_availability_with_replacement) |
28 | #if __has_feature(attribute_availability_bridgeos) |
29 | #ifndef __CC_BRIDGE_OS_DEPRECATED |
30 | #define __CC_BRIDGEOS_DEPRECATED(_dep, _msg) __attribute__((availability(bridgeos,deprecated=_dep, replacement=_msg))) |
31 | #endif |
32 | #endif |
33 | |
34 | #ifndef __CC_BRIDGEOS_DEPRECATED |
35 | #define __CC_BRIDGEOS_DEPRECATED(_dep, _msg) |
36 | #endif |
37 | |
38 | #define cc_deprecate_with_replacement(replacement_message, ios_version, macos_version, tvos_version, watchos_version, bridgeos_version) \ |
39 | __attribute__((availability(macos,deprecated=macos_version, replacement=replacement_message)))\ |
40 | __attribute__((availability(ios,deprecated=ios_version, replacement=replacement_message)))\ |
41 | __attribute__((availability(watchos,deprecated=watchos_version, replacement=replacement_message)))\ |
42 | __attribute__((availability(tvos,deprecated=tvos_version, replacement=replacement_message)))\ |
43 | __CC_BRIDGEOS_DEPRECATED(bridgeos_version, replacement_message) |
44 | |
45 | #define cc_unavailable() \ |
46 | __attribute__((availability(macos,unavailable)))\ |
47 | __attribute__((availability(ios,unavailable)))\ |
48 | __attribute__((availability(watchos,unavailable)))\ |
49 | __attribute__((availability(tvos,unavailable)))\ |
50 | __attribute__((availability(bridgeos,unavailable))) |
51 | |
52 | #if CC_PTRCHECK |
53 | #define cc_ptrcheck_unavailable() cc_unavailable() |
54 | #else |
55 | #define cc_ptrcheck_unavailable() |
56 | #endif |
57 | |
58 | #else /* !__has_feature(attribute_availability_with_replacement) */ |
59 | |
60 | #define cc_deprecate_with_replacement(replacement_message, ios_version, macos_version, tvos_version, watchos_version, bridgeos_version) |
61 | #define cc_unavailable() |
62 | #define cc_ptrcheck_unavailable() |
63 | |
64 | #endif /* __has_feature(attribute_availability_with_replacement) */ |
65 | |
66 | /* Provide a general purpose macro concat method. */ |
67 | #define cc_concat_(a, b) a##b |
68 | #define cc_concat(a, b) cc_concat_(a, b) |
69 | |
70 | #if defined(_MSC_VER) |
71 | #define __asm__(x) |
72 | #endif |
73 | |
74 | /* Manage asserts here because a few functions in header public files do use asserts */ |
75 | #if CORECRYPTO_DEBUG |
76 | #define cc_assert(x) assert(x) |
77 | #else |
78 | #define cc_assert(x) |
79 | #endif |
80 | |
81 | #if CC_KERNEL |
82 | #include <kern/assert.h> |
83 | #else |
84 | #include <assert.h> |
85 | #endif |
86 | |
87 | /* Provide a static assert that can be used to create compile-type failures. */ |
88 | #if __has_feature(c_static_assert) || __has_extension(c_static_assert) |
89 | #define cc_static_assert(e, m) _Static_assert(e, m) |
90 | #elif !defined(__GNUC__) |
91 | #define cc_static_assert(e, m) enum { cc_concat(static_assert_, __COUNTER__) = 1 / (int)(!!(e)) } |
92 | #else |
93 | #define cc_static_assert(e, m) |
94 | #endif |
95 | |
96 | /* Declare a struct element with a guarenteed alignment of _alignment_. |
97 | The resulting struct can be used to create arrays that are aligned by |
98 | a certain amount. */ |
99 | #define cc_aligned_struct(_alignment_) \ |
100 | typedef struct { \ |
101 | uint8_t b[_alignment_]; \ |
102 | } CC_ALIGNED(_alignment_) |
103 | |
104 | #if defined(__BIGGEST_ALIGNMENT__) |
105 | #define CC_MAX_ALIGNMENT ((size_t)__BIGGEST_ALIGNMENT__) |
106 | #else |
107 | #define CC_MAX_ALIGNMENT ((size_t)16) |
108 | #endif |
109 | |
110 | /* pads a given size to be a multiple of the biggest alignment for any type */ |
111 | #define cc_pad_align(_size_) ((_size_ + CC_MAX_ALIGNMENT - 1) & (~(CC_MAX_ALIGNMENT - 1))) |
112 | |
113 | /* number of array elements used in a cc_ctx_decl */ |
114 | #define cc_ctx_n(_type_, _size_) ((_size_ + sizeof(_type_) - 1) / sizeof(_type_)) |
115 | |
116 | /* sizeof of a context declared with cc_ctx_decl */ |
117 | #define cc_ctx_sizeof(_type_, _size_) sizeof(_type_[cc_ctx_n(_type_, _size_)]) |
118 | |
119 | // VLA warning opt-outs to help transition away from VLAs. |
120 | #if defined(__KEIL__) |
121 | #define CC_IGNORE_VLA_WARNINGS \ |
122 | #pragma push \ |
123 | #pragma diag_suppress 1057 |
124 | |
125 | #define CC_RESTORE_VLA_WARNINGS \ |
126 | #pragma pop |
127 | #else |
128 | #define CC_IGNORE_VLA_WARNINGS \ |
129 | _Pragma("GCC diagnostic push") \ |
130 | _Pragma("GCC diagnostic ignored \"-Wvla\"") |
131 | |
132 | #define CC_RESTORE_VLA_WARNINGS \ |
133 | _Pragma("GCC diagnostic pop") |
134 | #endif |
135 | |
136 | /* |
137 | 1. _alloca cannot be removed because this header file is compiled with both MSVC++ and with clang. |
138 | 2. The _MSC_VER version of cc_ctx_decl() is not compatible with the way *_decl macros as used in CommonCrypto, AppleKeyStore and SecurityFrameworks. To observe the incompatibilities and errors, use below definition. Corecrypto itself, accepts both definitions |
139 | #define cc_ctx_decl(_type_, _size_, _name_) _type_ _name_ ## _array[cc_ctx_n(_type_, (_size_))]; _type_ *_name_ = _name_ ## _array |
140 | 3. Never use sizeof() operator for the variables declared with cc_ctx_decl(), because it is not be compatible with the _MSC_VER version of cc_ctx_decl(). |
141 | */ |
142 | #if defined(_MSC_VER) |
143 | |
144 | #include <malloc.h> |
145 | #define cc_ctx_decl(_type_, _size_, _name_) _type_ * _name_ = (_type_ *) _alloca(sizeof(_type_) * cc_ctx_n(_type_, _size_) ) |
146 | |
147 | #else |
148 | |
149 | // Enable VLA warnings for internal uses of cc_ctx_decl(). |
150 | #if defined(DISABLE_INTERNAL_VLAS) && DISABLE_INTERNAL_VLAS |
151 | |
152 | #define cc_ctx_decl(_type_, _size_, _name_) \ |
153 | _type_ _name_ [cc_ctx_n(_type_, _size_)]; |
154 | |
155 | #else |
156 | |
157 | #define cc_ctx_decl(_type_, _size_, _name_) \ |
158 | CC_IGNORE_VLA_WARNINGS \ |
159 | _type_ _name_ [cc_ctx_n(_type_, _size_)]; \ |
160 | CC_RESTORE_VLA_WARNINGS |
161 | |
162 | #endif // DISABLE_INTERNAL_VLAS |
163 | |
164 | #endif // defined(_MSC_VER) |
165 | |
166 | #define cc_ctx_decl_field(_type_, _size_, _name_) \ |
167 | _type_ _name_ [cc_ctx_n(_type_, _size_)] |
168 | |
169 | // VLA warning opt-outs to help transition away from VLAs. |
170 | #define cc_ctx_decl_vla(_type_, _size_, _name_) \ |
171 | CC_IGNORE_VLA_WARNINGS \ |
172 | cc_ctx_decl(_type_, _size_, _name_); \ |
173 | CC_RESTORE_VLA_WARNINGS |
174 | |
175 | /*! |
176 | @brief cc_clear(len, dst) zeroizes array dst and it will not be optimized out. |
177 | @discussion It is used to clear sensitive data, particularly when the are defined in the stack |
178 | @param len number of bytes to be cleared in dst |
179 | @param dst input array |
180 | */ |
181 | CC_NONNULL((2)) |
182 | void cc_clear(size_t len, void *cc_sized_by(len) dst); |
183 | |
184 | #define cc_copy(_size_, _dst_, _src_) memcpy(_dst_, _src_, _size_) |
185 | |
186 | CC_INLINE CC_NONNULL((2)) |
187 | void cc_xor(size_t size, void *cc_sized_by(size) r, const void *cc_sized_by(size) s, const void *cc_sized_by(size) t) { |
188 | uint8_t *_r=(uint8_t *)r; |
189 | const uint8_t *_s=(const uint8_t *)s; |
190 | const uint8_t *_t=(const uint8_t *)t; |
191 | size_t _size = size; |
192 | while (_size--) { |
193 | _r[_size] = _s[_size] ^ _t[_size]; |
194 | } |
195 | } |
196 | |
197 | /*! |
198 | @brief cc_cmp_safe(num, pt1, pt2) compares two array ptr1 and ptr2 of num bytes. |
199 | @discussion The execution time/cycles is independent of the data and therefore guarantees no leak about the data. However, the execution time depends on num. |
200 | @param num number of bytes in each array |
201 | @param ptr1 input array |
202 | @param ptr2 input array |
203 | @return returns 0 if the num bytes starting at ptr1 are identical to the num bytes starting at ptr2 and 1 if they are different or if num is 0 (empty arrays). |
204 | */ |
205 | CC_NONNULL((2, 3)) |
206 | int cc_cmp_safe (size_t num, const void * cc_sized_by(num) ptr1, const void * cc_sized_by(num) ptr2); |
207 | |
208 | /* Exchange S and T of any value type. |
209 | NOTE: S and T are evaluated multiple times and MUST NOT be expressions. */ |
210 | #define CC_SWAP(S, T) do { \ |
211 | S ^= T; T ^= S; S ^= T; \ |
212 | } while (0) |
213 | |
214 | /* Return the maximum value between S and T. */ |
215 | #define CC_MAX(S, T) ({__typeof__(S) _cc_max_s = S; __typeof__(T) _cc_max_t = T; _cc_max_s > _cc_max_t ? _cc_max_s : _cc_max_t;}) |
216 | |
217 | /* Clone of CC_MAX() that evalutes S and T multiple times to allow nesting. */ |
218 | #define CC_MAX_EVAL(S, T) ((S) > (T) ? (S) : (T)) |
219 | |
220 | /* Return the minimum value between S and T. */ |
221 | #define CC_MIN(S, T) ({__typeof__(S) _cc_min_s = S; __typeof__(T) _cc_min_t = T; _cc_min_s <= _cc_min_t ? _cc_min_s : _cc_min_t;}) |
222 | |
223 | /* Clone of CC_MIN() that evalutes S and T multiple times to allow nesting. */ |
224 | #define CC_MIN_EVAL(S, T) ((S) < (T) ? (S) : (T)) |
225 | |
226 | /* |
227 | When building with "-nostdinc" (i.e. iboot), ptrauth.h is in a non-standard location. |
228 | This requires a new flag to be used when building iboot: -ibuiltininc which is not |
229 | yet available. |
230 | */ |
231 | #if __has_feature(ptrauth_calls) && (CC_KERNEL || CC_USE_L4 || CC_USE_SEPROM) |
232 | #include <ptrauth.h> |
233 | #define CC_SPTR(_sn_, _n_) \ |
234 | __ptrauth(ptrauth_key_process_independent_code, 1, ptrauth_string_discriminator("cc_" #_sn_ #_n_)) _n_ |
235 | #else |
236 | #define CC_SPTR(_sn_, _n_) _n_ |
237 | #endif |
238 | |
239 | // Similar to the iovec type used in scatter-gather APIs like readv() |
240 | // and writev(). |
241 | typedef struct cc_iovec { |
242 | const void *base; |
243 | size_t nbytes; |
244 | } cc_iovec_t; |
245 | |
246 | #endif /* _CORECRYPTO_CC_H_ */ |
247 | |