/rust/registry/src/index.crates.io-6f17d22bba15001f/ring-0.17.14/crypto/internal.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef OPENSSL_HEADER_CRYPTO_INTERNAL_H |
16 | | #define OPENSSL_HEADER_CRYPTO_INTERNAL_H |
17 | | |
18 | | #include <ring-core/base.h> // Must be first. |
19 | | |
20 | | #include "ring-core/check.h" |
21 | | |
22 | | #if defined(__clang__) |
23 | | // Don't require prototypes for functions defined in C that are only |
24 | | // used from Rust. |
25 | | #pragma GCC diagnostic ignored "-Wmissing-prototypes" |
26 | | #endif |
27 | | |
28 | | #if defined(__GNUC__) && \ |
29 | | (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 |
30 | | // |alignas| and |alignof| were added in C11. GCC added support in version 4.8. |
31 | | // Testing for __STDC_VERSION__/__cplusplus doesn't work because 4.7 already |
32 | | // reports support for C11. |
33 | 0 | #define alignas(x) __attribute__ ((aligned (x))) |
34 | | #elif defined(_MSC_VER) && !defined(__clang__) |
35 | | #define alignas(x) __declspec(align(x)) |
36 | | #else |
37 | | #include <stdalign.h> |
38 | | #endif |
39 | | |
40 | | #if defined(__clang__) || defined(__GNUC__) |
41 | | #define RING_NOINLINE __attribute__((noinline)) |
42 | | #elif defined(_MSC_VER) |
43 | | #define RING_NOINLINE __declspec(noinline) |
44 | | #else |
45 | | #define RING_NOINLINE |
46 | | #endif |
47 | | |
48 | | // Some C compilers require a useless cast when dealing with arrays for the |
49 | | // reason explained in |
50 | | // https://gustedt.wordpress.com/2011/02/12/const-and-arrays/ |
51 | | #if defined(__clang__) || defined(_MSC_VER) |
52 | | #define RING_CORE_POINTLESS_ARRAY_CONST_CAST(cast) |
53 | | #else |
54 | | #define RING_CORE_POINTLESS_ARRAY_CONST_CAST(cast) cast |
55 | | #endif |
56 | | |
57 | | // `uint8_t` isn't guaranteed to be 'unsigned char' and only 'char' and |
58 | | // 'unsigned char' are allowed to alias according to ISO C. |
59 | | typedef unsigned char aliasing_uint8_t; |
60 | | |
61 | | #if (!defined(_MSC_VER) || defined(__clang__)) && defined(OPENSSL_64_BIT) |
62 | | #define BORINGSSL_HAS_UINT128 |
63 | | typedef __int128_t int128_t; |
64 | | typedef __uint128_t uint128_t; |
65 | | #endif |
66 | | |
67 | | // GCC-like compilers indicate SSE2 with |__SSE2__|. MSVC leaves the caller to |
68 | | // know that x86_64 has SSE2, and uses _M_IX86_FP to indicate SSE2 on x86. |
69 | | // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170 |
70 | | #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) |
71 | | # if defined(_MSC_VER) && !defined(__clang__) |
72 | | # if defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) |
73 | | # define OPENSSL_SSE2 |
74 | | # else |
75 | | # error "SSE2 is required." |
76 | | # endif |
77 | | # elif !defined(__SSE2__) |
78 | | # error "SSE2 is required." |
79 | | # endif |
80 | | #endif |
81 | | |
82 | | // For convenience in testing the fallback code, we allow disabling SSE2 |
83 | | // intrinsics via |OPENSSL_NO_SSE2_FOR_TESTING|. We require SSE2 on x86 and |
84 | | // x86_64, so we would otherwise need to test such code on a non-x86 platform. |
85 | | // |
86 | | // This does not remove the above requirement for SSE2 support with assembly |
87 | | // optimizations. It only disables some intrinsics-based optimizations so that |
88 | | // we can test the fallback code on CI. |
89 | | #if defined(OPENSSL_SSE2) && defined(OPENSSL_NO_SSE2_FOR_TESTING) |
90 | | #undef OPENSSL_SSE2 |
91 | | #endif |
92 | | |
93 | | // Pointer utility functions. |
94 | | |
95 | | // buffers_alias returns one if |a| and |b| alias and zero otherwise. |
96 | | static inline int buffers_alias(const void *a, size_t a_bytes, |
97 | 0 | const void *b, size_t b_bytes) { |
98 | 0 | // Cast |a| and |b| to integers. In C, pointer comparisons between unrelated |
99 | 0 | // objects are undefined whereas pointer to integer conversions are merely |
100 | 0 | // implementation-defined. We assume the implementation defined it in a sane |
101 | 0 | // way. |
102 | 0 | uintptr_t a_u = (uintptr_t)a; |
103 | 0 | uintptr_t b_u = (uintptr_t)b; |
104 | 0 | return a_u + a_bytes > b_u && b_u + b_bytes > a_u; |
105 | 0 | } Unexecuted instantiation: curve25519.c:buffers_alias Unexecuted instantiation: aes_nohw.c:buffers_alias Unexecuted instantiation: montgomery.c:buffers_alias Unexecuted instantiation: montgomery_inv.c:buffers_alias Unexecuted instantiation: gfp_p384.c:buffers_alias Unexecuted instantiation: limbs.c:buffers_alias Unexecuted instantiation: mem.c:buffers_alias Unexecuted instantiation: poly1305.c:buffers_alias Unexecuted instantiation: cpu_intel.c:buffers_alias Unexecuted instantiation: curve25519_64_adx.c:buffers_alias Unexecuted instantiation: p256-nistz.c:buffers_alias Unexecuted instantiation: ecp_nistz.c:buffers_alias |
106 | | |
107 | | |
108 | | // Constant-time utility functions. |
109 | | // |
110 | | // The following methods return a bitmask of all ones (0xff...f) for true and 0 |
111 | | // for false. This is useful for choosing a value based on the result of a |
112 | | // conditional in constant time. For example, |
113 | | // |
114 | | // if (a < b) { |
115 | | // c = a; |
116 | | // } else { |
117 | | // c = b; |
118 | | // } |
119 | | // |
120 | | // can be written as |
121 | | // |
122 | | // crypto_word_t lt = constant_time_lt_w(a, b); |
123 | | // c = constant_time_select_w(lt, a, b); |
124 | | |
125 | | #if defined(__GNUC__) || defined(__clang__) |
126 | | #pragma GCC diagnostic push |
127 | | #pragma GCC diagnostic ignored "-Wconversion" |
128 | | #pragma GCC diagnostic ignored "-Wsign-conversion" |
129 | | #endif |
130 | | #if defined(_MSC_VER) && !defined(__clang__) |
131 | | #pragma warning(push) |
132 | | // '=': conversion from 'crypto_word_t' to 'uint8_t', possible loss of data |
133 | | #pragma warning(disable: 4242) |
134 | | // 'initializing': conversion from 'crypto_word_t' to 'uint8_t', ... |
135 | | #pragma warning(disable: 4244) |
136 | | #endif |
137 | | |
138 | | // crypto_word_t is the type that most constant-time functions use. Ideally we |
139 | | // would like it to be |size_t|, but NaCl builds in 64-bit mode with 32-bit |
140 | | // pointers, which means that |size_t| can be 32 bits when |BN_ULONG| is 64 |
141 | | // bits. Since we want to be able to do constant-time operations on a |
142 | | // |BN_ULONG|, |crypto_word_t| is defined as an unsigned value with the native |
143 | | // word length. |
144 | | #if defined(OPENSSL_64_BIT) |
145 | | typedef uint64_t crypto_word_t; |
146 | 0 | #define CRYPTO_WORD_BITS (64u) |
147 | | #elif defined(OPENSSL_32_BIT) |
148 | | typedef uint32_t crypto_word_t; |
149 | | #define CRYPTO_WORD_BITS (32u) |
150 | | #else |
151 | | #error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" |
152 | | #endif |
153 | | |
154 | 0 | #define CONSTTIME_TRUE_W ~((crypto_word_t)0) |
155 | | #define CONSTTIME_FALSE_W ((crypto_word_t)0) |
156 | | |
157 | | // value_barrier_w returns |a|, but prevents GCC and Clang from reasoning about |
158 | | // the returned value. This is used to mitigate compilers undoing constant-time |
159 | | // code, until we can express our requirements directly in the language. |
160 | | // |
161 | | // Note the compiler is aware that |value_barrier_w| has no side effects and |
162 | | // always has the same output for a given input. This allows it to eliminate |
163 | | // dead code, move computations across loops, and vectorize. |
164 | 0 | static inline crypto_word_t value_barrier_w(crypto_word_t a) { |
165 | 0 | #if defined(__GNUC__) || defined(__clang__) |
166 | 0 | __asm__("" : "+r"(a) : /* no inputs */); |
167 | 0 | #endif |
168 | 0 | return a; |
169 | 0 | } Unexecuted instantiation: curve25519.c:value_barrier_w Unexecuted instantiation: aes_nohw.c:value_barrier_w Unexecuted instantiation: montgomery.c:value_barrier_w Unexecuted instantiation: montgomery_inv.c:value_barrier_w Unexecuted instantiation: gfp_p384.c:value_barrier_w Unexecuted instantiation: limbs.c:value_barrier_w Unexecuted instantiation: mem.c:value_barrier_w Unexecuted instantiation: poly1305.c:value_barrier_w Unexecuted instantiation: cpu_intel.c:value_barrier_w Unexecuted instantiation: curve25519_64_adx.c:value_barrier_w Unexecuted instantiation: p256-nistz.c:value_barrier_w Unexecuted instantiation: ecp_nistz.c:value_barrier_w |
170 | | |
171 | | // value_barrier_u32 behaves like |value_barrier_w| but takes a |uint32_t|. |
172 | 0 | static inline uint32_t value_barrier_u32(uint32_t a) { |
173 | 0 | #if defined(__GNUC__) || defined(__clang__) |
174 | 0 | __asm__("" : "+r"(a) : /* no inputs */); |
175 | 0 | #endif |
176 | 0 | return a; |
177 | 0 | } Unexecuted instantiation: curve25519.c:value_barrier_u32 Unexecuted instantiation: aes_nohw.c:value_barrier_u32 Unexecuted instantiation: montgomery.c:value_barrier_u32 Unexecuted instantiation: montgomery_inv.c:value_barrier_u32 Unexecuted instantiation: gfp_p384.c:value_barrier_u32 Unexecuted instantiation: limbs.c:value_barrier_u32 Unexecuted instantiation: mem.c:value_barrier_u32 Unexecuted instantiation: poly1305.c:value_barrier_u32 Unexecuted instantiation: cpu_intel.c:value_barrier_u32 Unexecuted instantiation: curve25519_64_adx.c:value_barrier_u32 Unexecuted instantiation: p256-nistz.c:value_barrier_u32 Unexecuted instantiation: ecp_nistz.c:value_barrier_u32 |
178 | | |
179 | | // |value_barrier_u8| could be defined as above, but compilers other than |
180 | | // clang seem to still materialize 0x00..00MM instead of reusing 0x??..??MM. |
181 | | |
182 | | // constant_time_msb_w returns the given value with the MSB copied to all the |
183 | | // other bits. |
184 | 0 | static inline crypto_word_t constant_time_msb_w(crypto_word_t a) { |
185 | 0 | return 0u - (a >> (sizeof(a) * 8 - 1)); |
186 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_msb_w Unexecuted instantiation: aes_nohw.c:constant_time_msb_w Unexecuted instantiation: montgomery.c:constant_time_msb_w Unexecuted instantiation: montgomery_inv.c:constant_time_msb_w Unexecuted instantiation: gfp_p384.c:constant_time_msb_w Unexecuted instantiation: limbs.c:constant_time_msb_w Unexecuted instantiation: mem.c:constant_time_msb_w Unexecuted instantiation: poly1305.c:constant_time_msb_w Unexecuted instantiation: cpu_intel.c:constant_time_msb_w Unexecuted instantiation: curve25519_64_adx.c:constant_time_msb_w Unexecuted instantiation: p256-nistz.c:constant_time_msb_w Unexecuted instantiation: ecp_nistz.c:constant_time_msb_w |
187 | | |
188 | | // constant_time_is_zero returns 0xff..f if a == 0 and 0 otherwise. |
189 | 0 | static inline crypto_word_t constant_time_is_zero_w(crypto_word_t a) { |
190 | | // Here is an SMT-LIB verification of this formula: |
191 | | // |
192 | | // (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32) |
193 | | // (bvand (bvnot a) (bvsub a #x00000001)) |
194 | | // ) |
195 | | // |
196 | | // (declare-fun a () (_ BitVec 32)) |
197 | | // |
198 | | // (assert (not (= (= #x00000001 (bvlshr (is_zero a) #x0000001f)) (= a #x00000000)))) |
199 | | // (check-sat) |
200 | | // (get-model) |
201 | 0 | return constant_time_msb_w(~a & (a - 1)); |
202 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_is_zero_w Unexecuted instantiation: aes_nohw.c:constant_time_is_zero_w Unexecuted instantiation: montgomery.c:constant_time_is_zero_w Unexecuted instantiation: montgomery_inv.c:constant_time_is_zero_w Unexecuted instantiation: gfp_p384.c:constant_time_is_zero_w Unexecuted instantiation: limbs.c:constant_time_is_zero_w Unexecuted instantiation: mem.c:constant_time_is_zero_w Unexecuted instantiation: poly1305.c:constant_time_is_zero_w Unexecuted instantiation: cpu_intel.c:constant_time_is_zero_w Unexecuted instantiation: curve25519_64_adx.c:constant_time_is_zero_w Unexecuted instantiation: p256-nistz.c:constant_time_is_zero_w Unexecuted instantiation: ecp_nistz.c:constant_time_is_zero_w |
203 | | |
204 | 0 | static inline crypto_word_t constant_time_is_nonzero_w(crypto_word_t a) { |
205 | 0 | return ~constant_time_is_zero_w(a); |
206 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_is_nonzero_w Unexecuted instantiation: aes_nohw.c:constant_time_is_nonzero_w Unexecuted instantiation: montgomery.c:constant_time_is_nonzero_w Unexecuted instantiation: montgomery_inv.c:constant_time_is_nonzero_w Unexecuted instantiation: gfp_p384.c:constant_time_is_nonzero_w Unexecuted instantiation: limbs.c:constant_time_is_nonzero_w Unexecuted instantiation: mem.c:constant_time_is_nonzero_w Unexecuted instantiation: poly1305.c:constant_time_is_nonzero_w Unexecuted instantiation: cpu_intel.c:constant_time_is_nonzero_w Unexecuted instantiation: curve25519_64_adx.c:constant_time_is_nonzero_w Unexecuted instantiation: p256-nistz.c:constant_time_is_nonzero_w Unexecuted instantiation: ecp_nistz.c:constant_time_is_nonzero_w |
207 | | |
208 | | // constant_time_eq_w returns 0xff..f if a == b and 0 otherwise. |
209 | | static inline crypto_word_t constant_time_eq_w(crypto_word_t a, |
210 | 0 | crypto_word_t b) { |
211 | 0 | return constant_time_is_zero_w(a ^ b); |
212 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_eq_w Unexecuted instantiation: aes_nohw.c:constant_time_eq_w Unexecuted instantiation: montgomery.c:constant_time_eq_w Unexecuted instantiation: montgomery_inv.c:constant_time_eq_w Unexecuted instantiation: gfp_p384.c:constant_time_eq_w Unexecuted instantiation: limbs.c:constant_time_eq_w Unexecuted instantiation: mem.c:constant_time_eq_w Unexecuted instantiation: poly1305.c:constant_time_eq_w Unexecuted instantiation: cpu_intel.c:constant_time_eq_w Unexecuted instantiation: curve25519_64_adx.c:constant_time_eq_w Unexecuted instantiation: p256-nistz.c:constant_time_eq_w Unexecuted instantiation: ecp_nistz.c:constant_time_eq_w |
213 | | |
214 | | // constant_time_select_w returns (mask & a) | (~mask & b). When |mask| is all |
215 | | // 1s or all 0s (as returned by the methods above), the select methods return |
216 | | // either |a| (if |mask| is nonzero) or |b| (if |mask| is zero). |
217 | | static inline crypto_word_t constant_time_select_w(crypto_word_t mask, |
218 | | crypto_word_t a, |
219 | 0 | crypto_word_t b) { |
220 | | // Clang recognizes this pattern as a select. While it usually transforms it |
221 | | // to a cmov, it sometimes further transforms it into a branch, which we do |
222 | | // not want. |
223 | | // |
224 | | // Hiding the value of the mask from the compiler evades this transformation. |
225 | 0 | mask = value_barrier_w(mask); |
226 | 0 | return (mask & a) | (~mask & b); |
227 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_select_w Unexecuted instantiation: aes_nohw.c:constant_time_select_w Unexecuted instantiation: montgomery.c:constant_time_select_w Unexecuted instantiation: montgomery_inv.c:constant_time_select_w Unexecuted instantiation: gfp_p384.c:constant_time_select_w Unexecuted instantiation: limbs.c:constant_time_select_w Unexecuted instantiation: mem.c:constant_time_select_w Unexecuted instantiation: poly1305.c:constant_time_select_w Unexecuted instantiation: cpu_intel.c:constant_time_select_w Unexecuted instantiation: curve25519_64_adx.c:constant_time_select_w Unexecuted instantiation: p256-nistz.c:constant_time_select_w Unexecuted instantiation: ecp_nistz.c:constant_time_select_w |
228 | | |
229 | | // constant_time_select_8 acts like |constant_time_select| but operates on |
230 | | // 8-bit values. |
231 | | static inline uint8_t constant_time_select_8(crypto_word_t mask, uint8_t a, |
232 | 0 | uint8_t b) { |
233 | | // |mask| is a word instead of |uint8_t| to avoid materializing 0x000..0MM |
234 | | // Making both |mask| and its value barrier |uint8_t| would allow the compiler |
235 | | // to materialize 0x????..?MM instead, but only clang is that clever. |
236 | | // However, vectorization of bitwise operations seems to work better on |
237 | | // |uint8_t| than a mix of |uint64_t| and |uint8_t|, so |m| is cast to |
238 | | // |uint8_t| after the value barrier but before the bitwise operations. |
239 | 0 | uint8_t m = value_barrier_w(mask); |
240 | 0 | return (m & a) | (~m & b); |
241 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_select_8 Unexecuted instantiation: aes_nohw.c:constant_time_select_8 Unexecuted instantiation: montgomery.c:constant_time_select_8 Unexecuted instantiation: montgomery_inv.c:constant_time_select_8 Unexecuted instantiation: gfp_p384.c:constant_time_select_8 Unexecuted instantiation: limbs.c:constant_time_select_8 Unexecuted instantiation: mem.c:constant_time_select_8 Unexecuted instantiation: poly1305.c:constant_time_select_8 Unexecuted instantiation: cpu_intel.c:constant_time_select_8 Unexecuted instantiation: curve25519_64_adx.c:constant_time_select_8 Unexecuted instantiation: p256-nistz.c:constant_time_select_8 Unexecuted instantiation: ecp_nistz.c:constant_time_select_8 |
242 | | |
243 | | // constant_time_conditional_memcpy copies |n| bytes from |src| to |dst| if |
244 | | // |mask| is 0xff..ff and does nothing if |mask| is 0. The |n|-byte memory |
245 | | // ranges at |dst| and |src| must not overlap, as when calling |memcpy|. |
246 | | static inline void constant_time_conditional_memcpy(void *dst, const void *src, |
247 | | const size_t n, |
248 | 0 | const crypto_word_t mask) { |
249 | 0 | debug_assert_nonsecret(!buffers_alias(dst, n, src, n)); |
250 | 0 | uint8_t *out = (uint8_t *)dst; |
251 | 0 | const uint8_t *in = (const uint8_t *)src; |
252 | 0 | for (size_t i = 0; i < n; i++) { |
253 | 0 | out[i] = constant_time_select_8(mask, in[i], out[i]); |
254 | 0 | } |
255 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_conditional_memcpy Unexecuted instantiation: aes_nohw.c:constant_time_conditional_memcpy Unexecuted instantiation: montgomery.c:constant_time_conditional_memcpy Unexecuted instantiation: montgomery_inv.c:constant_time_conditional_memcpy Unexecuted instantiation: gfp_p384.c:constant_time_conditional_memcpy Unexecuted instantiation: limbs.c:constant_time_conditional_memcpy Unexecuted instantiation: mem.c:constant_time_conditional_memcpy Unexecuted instantiation: poly1305.c:constant_time_conditional_memcpy Unexecuted instantiation: cpu_intel.c:constant_time_conditional_memcpy Unexecuted instantiation: curve25519_64_adx.c:constant_time_conditional_memcpy Unexecuted instantiation: p256-nistz.c:constant_time_conditional_memcpy Unexecuted instantiation: ecp_nistz.c:constant_time_conditional_memcpy |
256 | | |
257 | | // constant_time_conditional_memxor xors |n| bytes from |src| to |dst| if |
258 | | // |mask| is 0xff..ff and does nothing if |mask| is 0. The |n|-byte memory |
259 | | // ranges at |dst| and |src| must not overlap, as when calling |memcpy|. |
260 | | static inline void constant_time_conditional_memxor(void *dst, const void *src, |
261 | | size_t n, |
262 | 0 | const crypto_word_t mask) { |
263 | 0 | debug_assert_nonsecret(!buffers_alias(dst, n, src, n)); |
264 | 0 | aliasing_uint8_t *out = dst; |
265 | 0 | const aliasing_uint8_t *in = src; |
266 | | #if defined(__GNUC__) && !defined(__clang__) |
267 | | // gcc 13.2.0 doesn't automatically vectorize this loop regardless of barrier |
268 | | typedef aliasing_uint8_t v32u8 __attribute__((vector_size(32), aligned(1), may_alias)); |
269 | | size_t n_vec = n&~(size_t)31; |
270 | | v32u8 masks = ((aliasing_uint8_t)mask-(v32u8){}); // broadcast |
271 | | for (size_t i = 0; i < n_vec; i += 32) { |
272 | | *(v32u8*)&out[i] ^= masks & *(v32u8 const*)&in[i]; |
273 | | } |
274 | | out += n_vec; |
275 | | n -= n_vec; |
276 | | #endif |
277 | 0 | for (size_t i = 0; i < n; i++) { |
278 | 0 | out[i] ^= value_barrier_w(mask) & in[i]; |
279 | 0 | } |
280 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_conditional_memxor Unexecuted instantiation: aes_nohw.c:constant_time_conditional_memxor Unexecuted instantiation: montgomery.c:constant_time_conditional_memxor Unexecuted instantiation: montgomery_inv.c:constant_time_conditional_memxor Unexecuted instantiation: gfp_p384.c:constant_time_conditional_memxor Unexecuted instantiation: limbs.c:constant_time_conditional_memxor Unexecuted instantiation: mem.c:constant_time_conditional_memxor Unexecuted instantiation: poly1305.c:constant_time_conditional_memxor Unexecuted instantiation: cpu_intel.c:constant_time_conditional_memxor Unexecuted instantiation: curve25519_64_adx.c:constant_time_conditional_memxor Unexecuted instantiation: p256-nistz.c:constant_time_conditional_memxor Unexecuted instantiation: ecp_nistz.c:constant_time_conditional_memxor |
281 | | |
282 | | #if defined(BORINGSSL_CONSTANT_TIME_VALIDATION) |
283 | | |
284 | | // CONSTTIME_SECRET takes a pointer and a number of bytes and marks that region |
285 | | // of memory as secret. Secret data is tracked as it flows to registers and |
286 | | // other parts of a memory. If secret data is used as a condition for a branch, |
287 | | // or as a memory index, it will trigger warnings in valgrind. |
288 | | #define CONSTTIME_SECRET(ptr, len) VALGRIND_MAKE_MEM_UNDEFINED(ptr, len) |
289 | | |
290 | | // CONSTTIME_DECLASSIFY takes a pointer and a number of bytes and marks that |
291 | | // region of memory as public. Public data is not subject to constant-time |
292 | | // rules. |
293 | | #define CONSTTIME_DECLASSIFY(ptr, len) VALGRIND_MAKE_MEM_DEFINED(ptr, len) |
294 | | |
295 | | #else |
296 | | |
297 | | #define CONSTTIME_SECRET(ptr, len) |
298 | | #define CONSTTIME_DECLASSIFY(ptr, len) |
299 | | |
300 | | #endif // BORINGSSL_CONSTANT_TIME_VALIDATION |
301 | | |
302 | 0 | static inline crypto_word_t constant_time_declassify_w(crypto_word_t v) { |
303 | 0 | // Return |v| through a value barrier to be safe. Valgrind-based constant-time |
304 | 0 | // validation is partly to check the compiler has not undone any constant-time |
305 | 0 | // work. Any place |BORINGSSL_CONSTANT_TIME_VALIDATION| influences |
306 | 0 | // optimizations, this validation is inaccurate. |
307 | 0 | // |
308 | 0 | // However, by sending pointers through valgrind, we likely inhibit escape |
309 | 0 | // analysis. On local variables, particularly booleans, we likely |
310 | 0 | // significantly impact optimizations. |
311 | 0 | // |
312 | 0 | // Thus, to be safe, stick a value barrier, in hopes of comparably inhibiting |
313 | 0 | // compiler analysis. |
314 | 0 | CONSTTIME_DECLASSIFY(&v, sizeof(v)); |
315 | 0 | return value_barrier_w(v); |
316 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_declassify_w Unexecuted instantiation: aes_nohw.c:constant_time_declassify_w Unexecuted instantiation: montgomery.c:constant_time_declassify_w Unexecuted instantiation: montgomery_inv.c:constant_time_declassify_w Unexecuted instantiation: gfp_p384.c:constant_time_declassify_w Unexecuted instantiation: limbs.c:constant_time_declassify_w Unexecuted instantiation: mem.c:constant_time_declassify_w Unexecuted instantiation: poly1305.c:constant_time_declassify_w Unexecuted instantiation: cpu_intel.c:constant_time_declassify_w Unexecuted instantiation: curve25519_64_adx.c:constant_time_declassify_w Unexecuted instantiation: p256-nistz.c:constant_time_declassify_w Unexecuted instantiation: ecp_nistz.c:constant_time_declassify_w |
317 | | |
318 | 0 | static inline int constant_time_declassify_int(int v) { |
319 | 0 | OPENSSL_STATIC_ASSERT(sizeof(uint32_t) == sizeof(int), |
320 | 0 | "int is not the same size as uint32_t"); |
321 | 0 | // See comment above. |
322 | 0 | CONSTTIME_DECLASSIFY(&v, sizeof(v)); |
323 | 0 | return value_barrier_u32((uint32_t)v); |
324 | 0 | } Unexecuted instantiation: curve25519.c:constant_time_declassify_int Unexecuted instantiation: aes_nohw.c:constant_time_declassify_int Unexecuted instantiation: montgomery.c:constant_time_declassify_int Unexecuted instantiation: montgomery_inv.c:constant_time_declassify_int Unexecuted instantiation: gfp_p384.c:constant_time_declassify_int Unexecuted instantiation: limbs.c:constant_time_declassify_int Unexecuted instantiation: mem.c:constant_time_declassify_int Unexecuted instantiation: poly1305.c:constant_time_declassify_int Unexecuted instantiation: cpu_intel.c:constant_time_declassify_int Unexecuted instantiation: curve25519_64_adx.c:constant_time_declassify_int Unexecuted instantiation: p256-nistz.c:constant_time_declassify_int Unexecuted instantiation: ecp_nistz.c:constant_time_declassify_int |
325 | | |
326 | | #if defined(_MSC_VER) && !defined(__clang__) |
327 | | // '=': conversion from 'int64_t' to 'int32_t', possible loss of data |
328 | | #pragma warning(pop) |
329 | | #endif |
330 | | #if defined(__GNUC__) || defined(__clang__) |
331 | | #pragma GCC diagnostic pop |
332 | | #endif |
333 | | |
334 | | // declassify_assert behaves like |assert| but declassifies the result of |
335 | | // evaluating |expr|. This allows the assertion to branch on the (presumably |
336 | | // public) result, but still ensures that values leading up to the computation |
337 | | // were secret. |
338 | 0 | #define declassify_assert(expr) dev_assert_secret(constant_time_declassify_int(expr)) |
339 | | |
340 | | // Endianness conversions. |
341 | | |
342 | | #if defined(__GNUC__) && __GNUC__ >= 2 |
343 | 0 | static inline uint32_t CRYPTO_bswap4(uint32_t x) { |
344 | 0 | return __builtin_bswap32(x); |
345 | 0 | } Unexecuted instantiation: curve25519.c:CRYPTO_bswap4 Unexecuted instantiation: aes_nohw.c:CRYPTO_bswap4 Unexecuted instantiation: montgomery.c:CRYPTO_bswap4 Unexecuted instantiation: montgomery_inv.c:CRYPTO_bswap4 Unexecuted instantiation: gfp_p384.c:CRYPTO_bswap4 Unexecuted instantiation: limbs.c:CRYPTO_bswap4 Unexecuted instantiation: mem.c:CRYPTO_bswap4 Unexecuted instantiation: poly1305.c:CRYPTO_bswap4 Unexecuted instantiation: cpu_intel.c:CRYPTO_bswap4 Unexecuted instantiation: curve25519_64_adx.c:CRYPTO_bswap4 Unexecuted instantiation: p256-nistz.c:CRYPTO_bswap4 Unexecuted instantiation: ecp_nistz.c:CRYPTO_bswap4 |
346 | | |
347 | 0 | static inline uint64_t CRYPTO_bswap8(uint64_t x) { |
348 | 0 | return __builtin_bswap64(x); |
349 | 0 | } Unexecuted instantiation: curve25519.c:CRYPTO_bswap8 Unexecuted instantiation: aes_nohw.c:CRYPTO_bswap8 Unexecuted instantiation: montgomery.c:CRYPTO_bswap8 Unexecuted instantiation: montgomery_inv.c:CRYPTO_bswap8 Unexecuted instantiation: gfp_p384.c:CRYPTO_bswap8 Unexecuted instantiation: limbs.c:CRYPTO_bswap8 Unexecuted instantiation: mem.c:CRYPTO_bswap8 Unexecuted instantiation: poly1305.c:CRYPTO_bswap8 Unexecuted instantiation: cpu_intel.c:CRYPTO_bswap8 Unexecuted instantiation: curve25519_64_adx.c:CRYPTO_bswap8 Unexecuted instantiation: p256-nistz.c:CRYPTO_bswap8 Unexecuted instantiation: ecp_nistz.c:CRYPTO_bswap8 |
350 | | #elif defined(_MSC_VER) |
351 | | #pragma warning(push, 3) |
352 | | #include <stdlib.h> |
353 | | #pragma warning(pop) |
354 | | #pragma intrinsic(_byteswap_ulong) |
355 | | static inline uint32_t CRYPTO_bswap4(uint32_t x) { |
356 | | return _byteswap_ulong(x); |
357 | | } |
358 | | #endif |
359 | | |
360 | | #if !defined(RING_CORE_NOSTDLIBINC) |
361 | | #include <string.h> |
362 | | #endif |
363 | | |
364 | 0 | static inline void *OPENSSL_memcpy(void *dst, const void *src, size_t n) { |
365 | 0 | #if !defined(RING_CORE_NOSTDLIBINC) |
366 | 0 | if (n == 0) { |
367 | 0 | return dst; |
368 | 0 | } |
369 | 0 | return memcpy(dst, src, n); |
370 | | #else |
371 | | aliasing_uint8_t *d = dst; |
372 | | const aliasing_uint8_t *s = src; |
373 | | for (size_t i = 0; i < n; ++i) { |
374 | | d[i] = s[i]; |
375 | | } |
376 | | return dst; |
377 | | #endif |
378 | 0 | } Unexecuted instantiation: curve25519.c:OPENSSL_memcpy Unexecuted instantiation: aes_nohw.c:OPENSSL_memcpy Unexecuted instantiation: montgomery.c:OPENSSL_memcpy Unexecuted instantiation: montgomery_inv.c:OPENSSL_memcpy Unexecuted instantiation: gfp_p384.c:OPENSSL_memcpy Unexecuted instantiation: limbs.c:OPENSSL_memcpy Unexecuted instantiation: mem.c:OPENSSL_memcpy Unexecuted instantiation: poly1305.c:OPENSSL_memcpy Unexecuted instantiation: cpu_intel.c:OPENSSL_memcpy Unexecuted instantiation: curve25519_64_adx.c:OPENSSL_memcpy Unexecuted instantiation: p256-nistz.c:OPENSSL_memcpy Unexecuted instantiation: ecp_nistz.c:OPENSSL_memcpy |
379 | | |
380 | 0 | static inline void *OPENSSL_memset(void *dst, int c, size_t n) { |
381 | 0 | #if !defined(RING_CORE_NOSTDLIBINC) |
382 | 0 | if (n == 0) { |
383 | 0 | return dst; |
384 | 0 | } |
385 | 0 | return memset(dst, c, n); |
386 | | #else |
387 | | aliasing_uint8_t *d = dst; |
388 | | for (size_t i = 0; i < n; ++i) { |
389 | | d[i] = (aliasing_uint8_t)c; |
390 | | } |
391 | | return dst; |
392 | | #endif |
393 | 0 | } Unexecuted instantiation: curve25519.c:OPENSSL_memset Unexecuted instantiation: aes_nohw.c:OPENSSL_memset Unexecuted instantiation: montgomery.c:OPENSSL_memset Unexecuted instantiation: montgomery_inv.c:OPENSSL_memset Unexecuted instantiation: gfp_p384.c:OPENSSL_memset Unexecuted instantiation: limbs.c:OPENSSL_memset Unexecuted instantiation: mem.c:OPENSSL_memset Unexecuted instantiation: poly1305.c:OPENSSL_memset Unexecuted instantiation: cpu_intel.c:OPENSSL_memset Unexecuted instantiation: curve25519_64_adx.c:OPENSSL_memset Unexecuted instantiation: p256-nistz.c:OPENSSL_memset Unexecuted instantiation: ecp_nistz.c:OPENSSL_memset |
394 | | |
395 | | |
396 | | // Loads and stores. |
397 | | // |
398 | | // The following functions load and store sized integers with the specified |
399 | | // endianness. They use |memcpy|, and so avoid alignment or strict aliasing |
400 | | // requirements on the input and output pointers. |
401 | | |
402 | | #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) |
403 | | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
404 | | #define RING_BIG_ENDIAN |
405 | | #endif |
406 | | #endif |
407 | | |
408 | 0 | static inline uint32_t CRYPTO_load_u32_le(const void *in) { |
409 | 0 | uint32_t v; |
410 | 0 | OPENSSL_memcpy(&v, in, sizeof(v)); |
411 | | #if defined(RING_BIG_ENDIAN) |
412 | | return CRYPTO_bswap4(v); |
413 | | #else |
414 | 0 | return v; |
415 | 0 | #endif |
416 | 0 | } Unexecuted instantiation: curve25519.c:CRYPTO_load_u32_le Unexecuted instantiation: aes_nohw.c:CRYPTO_load_u32_le Unexecuted instantiation: montgomery.c:CRYPTO_load_u32_le Unexecuted instantiation: montgomery_inv.c:CRYPTO_load_u32_le Unexecuted instantiation: gfp_p384.c:CRYPTO_load_u32_le Unexecuted instantiation: limbs.c:CRYPTO_load_u32_le Unexecuted instantiation: mem.c:CRYPTO_load_u32_le Unexecuted instantiation: poly1305.c:CRYPTO_load_u32_le Unexecuted instantiation: cpu_intel.c:CRYPTO_load_u32_le Unexecuted instantiation: curve25519_64_adx.c:CRYPTO_load_u32_le Unexecuted instantiation: p256-nistz.c:CRYPTO_load_u32_le Unexecuted instantiation: ecp_nistz.c:CRYPTO_load_u32_le |
417 | | |
418 | 0 | static inline void CRYPTO_store_u32_le(void *out, uint32_t v) { |
419 | | #if defined(RING_BIG_ENDIAN) |
420 | | v = CRYPTO_bswap4(v); |
421 | | #endif |
422 | 0 | OPENSSL_memcpy(out, &v, sizeof(v)); |
423 | 0 | } Unexecuted instantiation: curve25519.c:CRYPTO_store_u32_le Unexecuted instantiation: aes_nohw.c:CRYPTO_store_u32_le Unexecuted instantiation: montgomery.c:CRYPTO_store_u32_le Unexecuted instantiation: montgomery_inv.c:CRYPTO_store_u32_le Unexecuted instantiation: gfp_p384.c:CRYPTO_store_u32_le Unexecuted instantiation: limbs.c:CRYPTO_store_u32_le Unexecuted instantiation: mem.c:CRYPTO_store_u32_le Unexecuted instantiation: poly1305.c:CRYPTO_store_u32_le Unexecuted instantiation: cpu_intel.c:CRYPTO_store_u32_le Unexecuted instantiation: curve25519_64_adx.c:CRYPTO_store_u32_le Unexecuted instantiation: p256-nistz.c:CRYPTO_store_u32_le Unexecuted instantiation: ecp_nistz.c:CRYPTO_store_u32_le |
424 | | |
425 | 0 | static inline uint32_t CRYPTO_load_u32_be(const void *in) { |
426 | 0 | uint32_t v; |
427 | 0 | OPENSSL_memcpy(&v, in, sizeof(v)); |
428 | 0 | #if !defined(RING_BIG_ENDIAN) |
429 | 0 | return CRYPTO_bswap4(v); |
430 | | #else |
431 | | return v; |
432 | | #endif |
433 | 0 | } Unexecuted instantiation: curve25519.c:CRYPTO_load_u32_be Unexecuted instantiation: aes_nohw.c:CRYPTO_load_u32_be Unexecuted instantiation: montgomery.c:CRYPTO_load_u32_be Unexecuted instantiation: montgomery_inv.c:CRYPTO_load_u32_be Unexecuted instantiation: gfp_p384.c:CRYPTO_load_u32_be Unexecuted instantiation: limbs.c:CRYPTO_load_u32_be Unexecuted instantiation: mem.c:CRYPTO_load_u32_be Unexecuted instantiation: poly1305.c:CRYPTO_load_u32_be Unexecuted instantiation: cpu_intel.c:CRYPTO_load_u32_be Unexecuted instantiation: curve25519_64_adx.c:CRYPTO_load_u32_be Unexecuted instantiation: p256-nistz.c:CRYPTO_load_u32_be Unexecuted instantiation: ecp_nistz.c:CRYPTO_load_u32_be |
434 | | |
435 | 0 | static inline void CRYPTO_store_u32_be(void *out, uint32_t v) { |
436 | 0 | #if !defined(RING_BIG_ENDIAN) |
437 | 0 | v = CRYPTO_bswap4(v); |
438 | 0 | #endif |
439 | 0 | OPENSSL_memcpy(out, &v, sizeof(v)); |
440 | 0 | } Unexecuted instantiation: curve25519.c:CRYPTO_store_u32_be Unexecuted instantiation: aes_nohw.c:CRYPTO_store_u32_be Unexecuted instantiation: montgomery.c:CRYPTO_store_u32_be Unexecuted instantiation: montgomery_inv.c:CRYPTO_store_u32_be Unexecuted instantiation: gfp_p384.c:CRYPTO_store_u32_be Unexecuted instantiation: limbs.c:CRYPTO_store_u32_be Unexecuted instantiation: mem.c:CRYPTO_store_u32_be Unexecuted instantiation: poly1305.c:CRYPTO_store_u32_be Unexecuted instantiation: cpu_intel.c:CRYPTO_store_u32_be Unexecuted instantiation: curve25519_64_adx.c:CRYPTO_store_u32_be Unexecuted instantiation: p256-nistz.c:CRYPTO_store_u32_be Unexecuted instantiation: ecp_nistz.c:CRYPTO_store_u32_be |
441 | | |
442 | | // Runtime CPU feature support |
443 | | |
444 | | #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) |
445 | | // OPENSSL_ia32cap_P contains the Intel CPUID bits when running on an x86 or |
446 | | // x86-64 system. |
447 | | // |
448 | | // Index 0: |
449 | | // EDX for CPUID where EAX = 1 |
450 | | // Bit 30 is used to indicate an Intel CPU |
451 | | // Index 1: |
452 | | // ECX for CPUID where EAX = 1 |
453 | | // Index 2: |
454 | | // EBX for CPUID where EAX = 7, ECX = 0 |
455 | | // Bit 14 (for removed feature MPX) is used to indicate a preference for ymm |
456 | | // registers over zmm even when zmm registers are supported |
457 | | // Index 3: |
458 | | // ECX for CPUID where EAX = 7, ECX = 0 |
459 | | // |
460 | | // Note: the CPUID bits are pre-adjusted for the OSXSAVE bit and the XMM, YMM, |
461 | | // and AVX512 bits in XCR0, so it is not necessary to check those. (WARNING: See |
462 | | // caveats in cpu_intel.c.) |
463 | | #if defined(OPENSSL_X86_64) |
464 | | extern uint32_t avx2_available; |
465 | | extern uint32_t adx_bmi2_available; |
466 | | #endif |
467 | | #endif |
468 | | |
469 | | |
470 | | #if defined(OPENSSL_ARM) |
471 | | extern alignas(4) uint32_t neon_available; |
472 | | #endif // OPENSSL_ARM |
473 | | |
474 | | #endif // OPENSSL_HEADER_CRYPTO_INTERNAL_H |