/work/mbedtls-2.28.8/library/constant_time.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * Constant-time functions |
3 | | * |
4 | | * Copyright The Mbed TLS Contributors |
5 | | * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later |
6 | | */ |
7 | | |
8 | | /* |
9 | | * The following functions are implemented without using comparison operators, as those |
10 | | * might be translated to branches by some compilers on some platforms. |
11 | | */ |
12 | | |
13 | | #include "common.h" |
14 | | #include "constant_time_internal.h" |
15 | | #include "mbedtls/constant_time.h" |
16 | | #include "mbedtls/error.h" |
17 | | #include "mbedtls/platform_util.h" |
18 | | |
19 | | #if defined(MBEDTLS_BIGNUM_C) |
20 | | #include "mbedtls/bignum.h" |
21 | | #endif |
22 | | |
23 | | #if defined(MBEDTLS_SSL_TLS_C) |
24 | | #include "mbedtls/ssl_internal.h" |
25 | | #endif |
26 | | |
27 | | #if defined(MBEDTLS_RSA_C) |
28 | | #include "mbedtls/rsa.h" |
29 | | #endif |
30 | | |
31 | | #if defined(MBEDTLS_BASE64_C) |
32 | | #include "constant_time_invasive.h" |
33 | | #endif |
34 | | |
35 | | #include <string.h> |
36 | | |
37 | | int mbedtls_ct_memcmp(const void *a, |
38 | | const void *b, |
39 | | size_t n) |
40 | 0 | { |
41 | 0 | size_t i; |
42 | 0 | volatile const unsigned char *A = (volatile const unsigned char *) a; |
43 | 0 | volatile const unsigned char *B = (volatile const unsigned char *) b; |
44 | 0 | volatile unsigned char diff = 0; |
45 | |
|
46 | 0 | for (i = 0; i < n; i++) { |
47 | | /* Read volatile data in order before computing diff. |
48 | | * This avoids IAR compiler warning: |
49 | | * 'the order of volatile accesses is undefined ..' */ |
50 | 0 | unsigned char x = A[i], y = B[i]; |
51 | 0 | diff |= x ^ y; |
52 | 0 | } |
53 | |
|
54 | 0 | return (int) diff; |
55 | 0 | } |
56 | | |
57 | | unsigned mbedtls_ct_uint_mask(unsigned value) |
58 | 0 | { |
59 | | /* MSVC has a warning about unary minus on unsigned, but this is |
60 | | * well-defined and precisely what we want to do here */ |
61 | | #if defined(_MSC_VER) |
62 | | #pragma warning( push ) |
63 | | #pragma warning( disable : 4146 ) |
64 | | #endif |
65 | 0 | return -((value | -value) >> (sizeof(value) * 8 - 1)); |
66 | | #if defined(_MSC_VER) |
67 | | #pragma warning( pop ) |
68 | | #endif |
69 | 0 | } |
70 | | |
71 | | #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || \ |
72 | | defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) |
73 | | |
74 | | size_t mbedtls_ct_size_mask(size_t value) |
75 | 0 | { |
76 | | /* MSVC has a warning about unary minus on unsigned integer types, |
77 | | * but this is well-defined and precisely what we want to do here. */ |
78 | | #if defined(_MSC_VER) |
79 | | #pragma warning( push ) |
80 | | #pragma warning( disable : 4146 ) |
81 | | #endif |
82 | 0 | return -((value | -value) >> (sizeof(value) * 8 - 1)); |
83 | | #if defined(_MSC_VER) |
84 | | #pragma warning( pop ) |
85 | | #endif |
86 | 0 | } |
87 | | |
88 | | #endif /* defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || |
89 | | defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) */ |
90 | | |
91 | | #if defined(MBEDTLS_BIGNUM_C) |
92 | | |
93 | | mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value) |
94 | 0 | { |
95 | | /* MSVC has a warning about unary minus on unsigned, but this is |
96 | | * well-defined and precisely what we want to do here */ |
97 | | #if defined(_MSC_VER) |
98 | | #pragma warning( push ) |
99 | | #pragma warning( disable : 4146 ) |
100 | | #endif |
101 | 0 | return -((value | -value) >> (sizeof(value) * 8 - 1)); |
102 | | #if defined(_MSC_VER) |
103 | | #pragma warning( pop ) |
104 | | #endif |
105 | 0 | } |
106 | | |
107 | | #endif /* MBEDTLS_BIGNUM_C */ |
108 | | |
109 | | #if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || \ |
110 | | defined(MBEDTLS_CIPHER_MODE_CBC) |
111 | | |
112 | | /** Constant-flow mask generation for "less than" comparison: |
113 | | * - if \p x < \p y, return all-bits 1, that is (size_t) -1 |
114 | | * - otherwise, return all bits 0, that is 0 |
115 | | * |
116 | | * This function can be used to write constant-time code by replacing branches |
117 | | * with bit operations using masks. |
118 | | * |
119 | | * \param x The first value to analyze. |
120 | | * \param y The second value to analyze. |
121 | | * |
122 | | * \return All-bits-one if \p x is less than \p y, otherwise zero. |
123 | | */ |
124 | | static size_t mbedtls_ct_size_mask_lt(size_t x, |
125 | | size_t y) |
126 | 0 | { |
127 | | /* This has the most significant bit set if and only if x < y */ |
128 | 0 | const size_t sub = x - y; |
129 | | |
130 | | /* sub1 = (x < y) ? 1 : 0 */ |
131 | 0 | const size_t sub1 = sub >> (sizeof(sub) * 8 - 1); |
132 | | |
133 | | /* mask = (x < y) ? 0xff... : 0x00... */ |
134 | 0 | const size_t mask = mbedtls_ct_size_mask(sub1); |
135 | |
|
136 | 0 | return mask; |
137 | 0 | } |
138 | | |
139 | | size_t mbedtls_ct_size_mask_ge(size_t x, |
140 | | size_t y) |
141 | 0 | { |
142 | 0 | return ~mbedtls_ct_size_mask_lt(x, y); |
143 | 0 | } |
144 | | |
145 | | #endif /* defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || |
146 | | defined(MBEDTLS_CIPHER_MODE_CBC) */ |
147 | | |
148 | | #if defined(MBEDTLS_BASE64_C) |
149 | | |
150 | | /* Return 0xff if low <= c <= high, 0 otherwise. |
151 | | * |
152 | | * Constant flow with respect to c. |
153 | | */ |
154 | | MBEDTLS_STATIC_TESTABLE |
155 | | unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low, |
156 | | unsigned char high, |
157 | | unsigned char c) |
158 | 0 | { |
159 | | /* low_mask is: 0 if low <= c, 0x...ff if low > c */ |
160 | 0 | unsigned low_mask = ((unsigned) c - low) >> 8; |
161 | | /* high_mask is: 0 if c <= high, 0x...ff if c > high */ |
162 | 0 | unsigned high_mask = ((unsigned) high - c) >> 8; |
163 | 0 | return ~(low_mask | high_mask) & 0xff; |
164 | 0 | } |
165 | | |
166 | | #endif /* MBEDTLS_BASE64_C */ |
167 | | |
168 | | unsigned mbedtls_ct_size_bool_eq(size_t x, |
169 | | size_t y) |
170 | 0 | { |
171 | | /* diff = 0 if x == y, non-zero otherwise */ |
172 | 0 | const size_t diff = x ^ y; |
173 | | |
174 | | /* MSVC has a warning about unary minus on unsigned integer types, |
175 | | * but this is well-defined and precisely what we want to do here. */ |
176 | | #if defined(_MSC_VER) |
177 | | #pragma warning( push ) |
178 | | #pragma warning( disable : 4146 ) |
179 | | #endif |
180 | | |
181 | | /* diff_msb's most significant bit is equal to x != y */ |
182 | 0 | const size_t diff_msb = (diff | (size_t) -diff); |
183 | |
|
184 | | #if defined(_MSC_VER) |
185 | | #pragma warning( pop ) |
186 | | #endif |
187 | | |
188 | | /* diff1 = (x != y) ? 1 : 0 */ |
189 | 0 | const unsigned diff1 = diff_msb >> (sizeof(diff_msb) * 8 - 1); |
190 | |
|
191 | 0 | return 1 ^ diff1; |
192 | 0 | } |
193 | | |
194 | | #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) |
195 | | |
196 | | /** Constant-flow "greater than" comparison: |
197 | | * return x > y |
198 | | * |
199 | | * This is equivalent to \p x > \p y, but is likely to be compiled |
200 | | * to code using bitwise operation rather than a branch. |
201 | | * |
202 | | * \param x The first value to analyze. |
203 | | * \param y The second value to analyze. |
204 | | * |
205 | | * \return 1 if \p x greater than \p y, otherwise 0. |
206 | | */ |
207 | | static unsigned mbedtls_ct_size_gt(size_t x, |
208 | | size_t y) |
209 | 0 | { |
210 | | /* Return the sign bit (1 for negative) of (y - x). */ |
211 | 0 | return (y - x) >> (sizeof(size_t) * 8 - 1); |
212 | 0 | } |
213 | | |
214 | | #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ |
215 | | |
216 | | #if defined(MBEDTLS_BIGNUM_C) |
217 | | |
218 | | unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x, |
219 | | const mbedtls_mpi_uint y) |
220 | 0 | { |
221 | 0 | mbedtls_mpi_uint ret; |
222 | 0 | mbedtls_mpi_uint cond; |
223 | | |
224 | | /* |
225 | | * Check if the most significant bits (MSB) of the operands are different. |
226 | | */ |
227 | 0 | cond = (x ^ y); |
228 | | /* |
229 | | * If the MSB are the same then the difference x-y will be negative (and |
230 | | * have its MSB set to 1 during conversion to unsigned) if and only if x<y. |
231 | | */ |
232 | 0 | ret = (x - y) & ~cond; |
233 | | /* |
234 | | * If the MSB are different, then the operand with the MSB of 1 is the |
235 | | * bigger. (That is if y has MSB of 1, then x<y is true and it is false if |
236 | | * the MSB of y is 0.) |
237 | | */ |
238 | 0 | ret |= y & cond; |
239 | | |
240 | |
|
241 | 0 | ret = ret >> (sizeof(mbedtls_mpi_uint) * 8 - 1); |
242 | |
|
243 | 0 | return (unsigned) ret; |
244 | 0 | } |
245 | | |
246 | | #endif /* MBEDTLS_BIGNUM_C */ |
247 | | |
248 | | unsigned mbedtls_ct_uint_if(unsigned condition, |
249 | | unsigned if1, |
250 | | unsigned if0) |
251 | 0 | { |
252 | 0 | unsigned mask = mbedtls_ct_uint_mask(condition); |
253 | 0 | return (mask & if1) | (~mask & if0); |
254 | 0 | } |
255 | | |
256 | | #if defined(MBEDTLS_BIGNUM_C) |
257 | | |
258 | | void mbedtls_ct_mpi_uint_cond_assign(size_t n, |
259 | | mbedtls_mpi_uint *dest, |
260 | | const mbedtls_mpi_uint *src, |
261 | | unsigned char condition) |
262 | 0 | { |
263 | 0 | size_t i; |
264 | | |
265 | | /* MSVC has a warning about unary minus on unsigned integer types, |
266 | | * but this is well-defined and precisely what we want to do here. */ |
267 | | #if defined(_MSC_VER) |
268 | | #pragma warning( push ) |
269 | | #pragma warning( disable : 4146 ) |
270 | | #endif |
271 | | |
272 | | /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */ |
273 | 0 | const mbedtls_mpi_uint mask = -condition; |
274 | |
|
275 | | #if defined(_MSC_VER) |
276 | | #pragma warning( pop ) |
277 | | #endif |
278 | |
|
279 | 0 | for (i = 0; i < n; i++) { |
280 | 0 | dest[i] = (src[i] & mask) | (dest[i] & ~mask); |
281 | 0 | } |
282 | 0 | } |
283 | | |
284 | | #endif /* MBEDTLS_BIGNUM_C */ |
285 | | |
286 | | #if defined(MBEDTLS_BASE64_C) |
287 | | |
288 | | unsigned char mbedtls_ct_base64_enc_char(unsigned char value) |
289 | 0 | { |
290 | 0 | unsigned char digit = 0; |
291 | | /* For each range of values, if value is in that range, mask digit with |
292 | | * the corresponding value. Since value can only be in a single range, |
293 | | * only at most one masking will change digit. */ |
294 | 0 | digit |= mbedtls_ct_uchar_mask_of_range(0, 25, value) & ('A' + value); |
295 | 0 | digit |= mbedtls_ct_uchar_mask_of_range(26, 51, value) & ('a' + value - 26); |
296 | 0 | digit |= mbedtls_ct_uchar_mask_of_range(52, 61, value) & ('0' + value - 52); |
297 | 0 | digit |= mbedtls_ct_uchar_mask_of_range(62, 62, value) & '+'; |
298 | 0 | digit |= mbedtls_ct_uchar_mask_of_range(63, 63, value) & '/'; |
299 | 0 | return digit; |
300 | 0 | } |
301 | | |
302 | | signed char mbedtls_ct_base64_dec_value(unsigned char c) |
303 | 0 | { |
304 | 0 | unsigned char val = 0; |
305 | | /* For each range of digits, if c is in that range, mask val with |
306 | | * the corresponding value. Since c can only be in a single range, |
307 | | * only at most one masking will change val. Set val to one plus |
308 | | * the desired value so that it stays 0 if c is in none of the ranges. */ |
309 | 0 | val |= mbedtls_ct_uchar_mask_of_range('A', 'Z', c) & (c - 'A' + 0 + 1); |
310 | 0 | val |= mbedtls_ct_uchar_mask_of_range('a', 'z', c) & (c - 'a' + 26 + 1); |
311 | 0 | val |= mbedtls_ct_uchar_mask_of_range('0', '9', c) & (c - '0' + 52 + 1); |
312 | 0 | val |= mbedtls_ct_uchar_mask_of_range('+', '+', c) & (c - '+' + 62 + 1); |
313 | 0 | val |= mbedtls_ct_uchar_mask_of_range('/', '/', c) & (c - '/' + 63 + 1); |
314 | | /* At this point, val is 0 if c is an invalid digit and v+1 if c is |
315 | | * a digit with the value v. */ |
316 | 0 | return val - 1; |
317 | 0 | } |
318 | | |
319 | | #endif /* MBEDTLS_BASE64_C */ |
320 | | |
321 | | #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) |
322 | | |
323 | | /** Shift some data towards the left inside a buffer. |
324 | | * |
325 | | * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally |
326 | | * equivalent to |
327 | | * ``` |
328 | | * memmove(start, start + offset, total - offset); |
329 | | * memset(start + offset, 0, total - offset); |
330 | | * ``` |
331 | | * but it strives to use a memory access pattern (and thus total timing) |
332 | | * that does not depend on \p offset. This timing independence comes at |
333 | | * the expense of performance. |
334 | | * |
335 | | * \param start Pointer to the start of the buffer. |
336 | | * \param total Total size of the buffer. |
337 | | * \param offset Offset from which to copy \p total - \p offset bytes. |
338 | | */ |
339 | | static void mbedtls_ct_mem_move_to_left(void *start, |
340 | | size_t total, |
341 | | size_t offset) |
342 | 0 | { |
343 | 0 | volatile unsigned char *buf = start; |
344 | 0 | size_t i, n; |
345 | 0 | if (total == 0) { |
346 | 0 | return; |
347 | 0 | } |
348 | 0 | for (i = 0; i < total; i++) { |
349 | 0 | unsigned no_op = mbedtls_ct_size_gt(total - offset, i); |
350 | | /* The first `total - offset` passes are a no-op. The last |
351 | | * `offset` passes shift the data one byte to the left and |
352 | | * zero out the last byte. */ |
353 | 0 | for (n = 0; n < total - 1; n++) { |
354 | 0 | unsigned char current = buf[n]; |
355 | 0 | unsigned char next = buf[n+1]; |
356 | 0 | buf[n] = mbedtls_ct_uint_if(no_op, current, next); |
357 | 0 | } |
358 | 0 | buf[total-1] = mbedtls_ct_uint_if(no_op, buf[total-1], 0); |
359 | 0 | } |
360 | 0 | } |
361 | | |
362 | | #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ |
363 | | |
364 | | #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) |
365 | | void mbedtls_ct_memcpy_if_eq(unsigned char *dest, |
366 | | const unsigned char *src, |
367 | | size_t len, |
368 | | size_t c1, |
369 | | size_t c2) |
370 | 0 | { |
371 | | /* mask = c1 == c2 ? 0xff : 0x00 */ |
372 | 0 | const size_t equal = mbedtls_ct_size_bool_eq(c1, c2); |
373 | 0 | const unsigned char mask = (unsigned char) mbedtls_ct_size_mask(equal); |
374 | | |
375 | | /* dest[i] = c1 == c2 ? src[i] : dest[i] */ |
376 | 0 | for (size_t i = 0; i < len; i++) { |
377 | 0 | dest[i] = (src[i] & mask) | (dest[i] & ~mask); |
378 | 0 | } |
379 | 0 | } |
380 | | |
381 | | void mbedtls_ct_memcpy_offset(unsigned char *dest, |
382 | | const unsigned char *src, |
383 | | size_t offset, |
384 | | size_t offset_min, |
385 | | size_t offset_max, |
386 | | size_t len) |
387 | 0 | { |
388 | 0 | size_t offsetval; |
389 | |
|
390 | 0 | for (offsetval = offset_min; offsetval <= offset_max; offsetval++) { |
391 | 0 | mbedtls_ct_memcpy_if_eq(dest, src + offsetval, len, |
392 | 0 | offsetval, offset); |
393 | 0 | } |
394 | 0 | } |
395 | | |
396 | | int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, |
397 | | const unsigned char *add_data, |
398 | | size_t add_data_len, |
399 | | const unsigned char *data, |
400 | | size_t data_len_secret, |
401 | | size_t min_data_len, |
402 | | size_t max_data_len, |
403 | | unsigned char *output) |
404 | 0 | { |
405 | | /* |
406 | | * This function breaks the HMAC abstraction and uses the md_clone() |
407 | | * extension to the MD API in order to get constant-flow behaviour. |
408 | | * |
409 | | * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means |
410 | | * concatenation, and okey/ikey are the XOR of the key with some fixed bit |
411 | | * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. |
412 | | * |
413 | | * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to |
414 | | * minlen, then cloning the context, and for each byte up to maxlen |
415 | | * finishing up the hash computation, keeping only the correct result. |
416 | | * |
417 | | * Then we only need to compute HASH(okey + inner_hash) and we're done. |
418 | | */ |
419 | 0 | const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info); |
420 | | /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5, |
421 | | * all of which have the same block size except SHA-384. */ |
422 | 0 | const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; |
423 | 0 | const unsigned char * const ikey = ctx->hmac_ctx; |
424 | 0 | const unsigned char * const okey = ikey + block_size; |
425 | 0 | const size_t hash_size = mbedtls_md_get_size(ctx->md_info); |
426 | |
|
427 | 0 | unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; |
428 | 0 | mbedtls_md_context_t aux; |
429 | 0 | size_t offset; |
430 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
431 | |
|
432 | 0 | mbedtls_md_init(&aux); |
433 | |
|
434 | 0 | #define MD_CHK(func_call) \ |
435 | 0 | do { \ |
436 | 0 | ret = (func_call); \ |
437 | 0 | if (ret != 0) \ |
438 | 0 | goto cleanup; \ |
439 | 0 | } while (0) |
440 | |
|
441 | 0 | MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0)); |
442 | | |
443 | | /* After hmac_start() of hmac_reset(), ikey has already been hashed, |
444 | | * so we can start directly with the message */ |
445 | 0 | MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len)); |
446 | 0 | MD_CHK(mbedtls_md_update(ctx, data, min_data_len)); |
447 | | |
448 | | /* Fill the hash buffer in advance with something that is |
449 | | * not a valid hash (barring an attack on the hash and |
450 | | * deliberately-crafted input), in case the caller doesn't |
451 | | * check the return status properly. */ |
452 | 0 | memset(output, '!', hash_size); |
453 | | |
454 | | /* For each possible length, compute the hash up to that point */ |
455 | 0 | for (offset = min_data_len; offset <= max_data_len; offset++) { |
456 | 0 | MD_CHK(mbedtls_md_clone(&aux, ctx)); |
457 | 0 | MD_CHK(mbedtls_md_finish(&aux, aux_out)); |
458 | | /* Keep only the correct inner_hash in the output buffer */ |
459 | 0 | mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size, |
460 | 0 | offset, data_len_secret); |
461 | |
|
462 | 0 | if (offset < max_data_len) { |
463 | 0 | MD_CHK(mbedtls_md_update(ctx, data + offset, 1)); |
464 | 0 | } |
465 | 0 | } |
466 | | |
467 | | /* The context needs to finish() before it starts() again */ |
468 | 0 | MD_CHK(mbedtls_md_finish(ctx, aux_out)); |
469 | | |
470 | | /* Now compute HASH(okey + inner_hash) */ |
471 | 0 | MD_CHK(mbedtls_md_starts(ctx)); |
472 | 0 | MD_CHK(mbedtls_md_update(ctx, okey, block_size)); |
473 | 0 | MD_CHK(mbedtls_md_update(ctx, output, hash_size)); |
474 | 0 | MD_CHK(mbedtls_md_finish(ctx, output)); |
475 | | |
476 | | /* Done, get ready for next time */ |
477 | 0 | MD_CHK(mbedtls_md_hmac_reset(ctx)); |
478 | | |
479 | 0 | #undef MD_CHK |
480 | | |
481 | 0 | cleanup: |
482 | 0 | mbedtls_md_free(&aux); |
483 | 0 | return ret; |
484 | 0 | } |
485 | | |
486 | | #endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ |
487 | | |
488 | | #if defined(MBEDTLS_BIGNUM_C) |
489 | | |
490 | | #define MPI_VALIDATE_RET(cond) \ |
491 | 0 | MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA) |
492 | | |
493 | | /* |
494 | | * Conditionally assign X = Y, without leaking information |
495 | | * about whether the assignment was made or not. |
496 | | * (Leaking information about the respective sizes of X and Y is ok however.) |
497 | | */ |
498 | | #if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103) |
499 | | /* |
500 | | * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: |
501 | | * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 |
502 | | */ |
503 | | __declspec(noinline) |
504 | | #endif |
505 | | int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, |
506 | | const mbedtls_mpi *Y, |
507 | | unsigned char assign) |
508 | 0 | { |
509 | 0 | int ret = 0; |
510 | 0 | size_t i; |
511 | 0 | mbedtls_mpi_uint limb_mask; |
512 | 0 | MPI_VALIDATE_RET(X != NULL); |
513 | 0 | MPI_VALIDATE_RET(Y != NULL); |
514 | | |
515 | | /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */ |
516 | 0 | limb_mask = mbedtls_ct_mpi_uint_mask(assign);; |
517 | |
|
518 | 0 | MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); |
519 | | |
520 | 0 | X->s = (int) mbedtls_ct_uint_if(assign, Y->s, X->s); |
521 | |
|
522 | 0 | mbedtls_ct_mpi_uint_cond_assign(Y->n, X->p, Y->p, assign); |
523 | |
|
524 | 0 | for (i = Y->n; i < X->n; i++) { |
525 | 0 | X->p[i] &= ~limb_mask; |
526 | 0 | } |
527 | |
|
528 | 0 | cleanup: |
529 | 0 | return ret; |
530 | 0 | } |
531 | | |
532 | | /* |
533 | | * Conditionally swap X and Y, without leaking information |
534 | | * about whether the swap was made or not. |
535 | | * Here it is not ok to simply swap the pointers, which would lead to |
536 | | * different memory access patterns when X and Y are used afterwards. |
537 | | */ |
538 | | int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, |
539 | | mbedtls_mpi *Y, |
540 | | unsigned char swap) |
541 | 0 | { |
542 | 0 | int ret, s; |
543 | 0 | size_t i; |
544 | 0 | mbedtls_mpi_uint limb_mask; |
545 | 0 | mbedtls_mpi_uint tmp; |
546 | 0 | MPI_VALIDATE_RET(X != NULL); |
547 | 0 | MPI_VALIDATE_RET(Y != NULL); |
548 | |
|
549 | 0 | if (X == Y) { |
550 | 0 | return 0; |
551 | 0 | } |
552 | | |
553 | | /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */ |
554 | 0 | limb_mask = mbedtls_ct_mpi_uint_mask(swap); |
555 | |
|
556 | 0 | MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); |
557 | 0 | MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n)); |
558 | | |
559 | 0 | s = X->s; |
560 | 0 | X->s = (int) mbedtls_ct_uint_if(swap, Y->s, X->s); |
561 | 0 | Y->s = (int) mbedtls_ct_uint_if(swap, s, Y->s); |
562 | | |
563 | |
|
564 | 0 | for (i = 0; i < X->n; i++) { |
565 | 0 | tmp = X->p[i]; |
566 | 0 | X->p[i] = (X->p[i] & ~limb_mask) | (Y->p[i] & limb_mask); |
567 | 0 | Y->p[i] = (Y->p[i] & ~limb_mask) | (tmp & limb_mask); |
568 | 0 | } |
569 | |
|
570 | 0 | cleanup: |
571 | 0 | return ret; |
572 | 0 | } |
573 | | |
574 | | /* |
575 | | * Compare signed values in constant time |
576 | | */ |
577 | | int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, |
578 | | const mbedtls_mpi *Y, |
579 | | unsigned *ret) |
580 | 0 | { |
581 | 0 | size_t i; |
582 | | /* The value of any of these variables is either 0 or 1 at all times. */ |
583 | 0 | unsigned cond, done, X_is_negative, Y_is_negative; |
584 | |
|
585 | 0 | MPI_VALIDATE_RET(X != NULL); |
586 | 0 | MPI_VALIDATE_RET(Y != NULL); |
587 | 0 | MPI_VALIDATE_RET(ret != NULL); |
588 | |
|
589 | 0 | if (X->n != Y->n) { |
590 | 0 | return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; |
591 | 0 | } |
592 | | |
593 | | /* |
594 | | * Set sign_N to 1 if N >= 0, 0 if N < 0. |
595 | | * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. |
596 | | */ |
597 | 0 | X_is_negative = (X->s & 2) >> 1; |
598 | 0 | Y_is_negative = (Y->s & 2) >> 1; |
599 | | |
600 | | /* |
601 | | * If the signs are different, then the positive operand is the bigger. |
602 | | * That is if X is negative (X_is_negative == 1), then X < Y is true and it |
603 | | * is false if X is positive (X_is_negative == 0). |
604 | | */ |
605 | 0 | cond = (X_is_negative ^ Y_is_negative); |
606 | 0 | *ret = cond & X_is_negative; |
607 | | |
608 | | /* |
609 | | * This is a constant-time function. We might have the result, but we still |
610 | | * need to go through the loop. Record if we have the result already. |
611 | | */ |
612 | 0 | done = cond; |
613 | |
|
614 | 0 | for (i = X->n; i > 0; i--) { |
615 | | /* |
616 | | * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both |
617 | | * X and Y are negative. |
618 | | * |
619 | | * Again even if we can make a decision, we just mark the result and |
620 | | * the fact that we are done and continue looping. |
621 | | */ |
622 | 0 | cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]); |
623 | 0 | *ret |= cond & (1 - done) & X_is_negative; |
624 | 0 | done |= cond; |
625 | | |
626 | | /* |
627 | | * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both |
628 | | * X and Y are positive. |
629 | | * |
630 | | * Again even if we can make a decision, we just mark the result and |
631 | | * the fact that we are done and continue looping. |
632 | | */ |
633 | 0 | cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]); |
634 | 0 | *ret |= cond & (1 - done) & (1 - X_is_negative); |
635 | 0 | done |= cond; |
636 | 0 | } |
637 | |
|
638 | 0 | return 0; |
639 | 0 | } |
640 | | |
641 | | #endif /* MBEDTLS_BIGNUM_C */ |
642 | | |
643 | | #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) |
644 | | |
645 | | int mbedtls_ct_rsaes_pkcs1_v15_unpadding(int mode, |
646 | | unsigned char *input, |
647 | | size_t ilen, |
648 | | unsigned char *output, |
649 | | size_t output_max_len, |
650 | | size_t *olen) |
651 | 0 | { |
652 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
653 | 0 | size_t i, plaintext_max_size; |
654 | | |
655 | | /* The following variables take sensitive values: their value must |
656 | | * not leak into the observable behavior of the function other than |
657 | | * the designated outputs (output, olen, return value). Otherwise |
658 | | * this would open the execution of the function to |
659 | | * side-channel-based variants of the Bleichenbacher padding oracle |
660 | | * attack. Potential side channels include overall timing, memory |
661 | | * access patterns (especially visible to an adversary who has access |
662 | | * to a shared memory cache), and branches (especially visible to |
663 | | * an adversary who has access to a shared code cache or to a shared |
664 | | * branch predictor). */ |
665 | 0 | size_t pad_count = 0; |
666 | 0 | unsigned bad = 0; |
667 | 0 | unsigned char pad_done = 0; |
668 | 0 | size_t plaintext_size = 0; |
669 | 0 | unsigned output_too_large; |
670 | |
|
671 | 0 | plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11 |
672 | 0 | : output_max_len; |
673 | | |
674 | | /* Check and get padding length in constant time and constant |
675 | | * memory trace. The first byte must be 0. */ |
676 | 0 | bad |= input[0]; |
677 | |
|
678 | 0 | if (mode == MBEDTLS_RSA_PRIVATE) { |
679 | | /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 |
680 | | * where PS must be at least 8 nonzero bytes. */ |
681 | 0 | bad |= input[1] ^ MBEDTLS_RSA_CRYPT; |
682 | | |
683 | | /* Read the whole buffer. Set pad_done to nonzero if we find |
684 | | * the 0x00 byte and remember the padding length in pad_count. */ |
685 | 0 | for (i = 2; i < ilen; i++) { |
686 | 0 | pad_done |= ((input[i] | (unsigned char) -input[i]) >> 7) ^ 1; |
687 | 0 | pad_count += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1; |
688 | 0 | } |
689 | 0 | } else { |
690 | | /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 |
691 | | * where PS must be at least 8 bytes with the value 0xFF. */ |
692 | 0 | bad |= input[1] ^ MBEDTLS_RSA_SIGN; |
693 | | |
694 | | /* Read the whole buffer. Set pad_done to nonzero if we find |
695 | | * the 0x00 byte and remember the padding length in pad_count. |
696 | | * If there's a non-0xff byte in the padding, the padding is bad. */ |
697 | 0 | for (i = 2; i < ilen; i++) { |
698 | 0 | pad_done |= mbedtls_ct_uint_if(input[i], 0, 1); |
699 | 0 | pad_count += mbedtls_ct_uint_if(pad_done, 0, 1); |
700 | 0 | bad |= mbedtls_ct_uint_if(pad_done, 0, input[i] ^ 0xFF); |
701 | 0 | } |
702 | 0 | } |
703 | | |
704 | | /* If pad_done is still zero, there's no data, only unfinished padding. */ |
705 | 0 | bad |= mbedtls_ct_uint_if(pad_done, 0, 1); |
706 | | |
707 | | /* There must be at least 8 bytes of padding. */ |
708 | 0 | bad |= mbedtls_ct_size_gt(8, pad_count); |
709 | | |
710 | | /* If the padding is valid, set plaintext_size to the number of |
711 | | * remaining bytes after stripping the padding. If the padding |
712 | | * is invalid, avoid leaking this fact through the size of the |
713 | | * output: use the maximum message size that fits in the output |
714 | | * buffer. Do it without branches to avoid leaking the padding |
715 | | * validity through timing. RSA keys are small enough that all the |
716 | | * size_t values involved fit in unsigned int. */ |
717 | 0 | plaintext_size = mbedtls_ct_uint_if( |
718 | 0 | bad, (unsigned) plaintext_max_size, |
719 | 0 | (unsigned) (ilen - pad_count - 3)); |
720 | | |
721 | | /* Set output_too_large to 0 if the plaintext fits in the output |
722 | | * buffer and to 1 otherwise. */ |
723 | 0 | output_too_large = mbedtls_ct_size_gt(plaintext_size, |
724 | 0 | plaintext_max_size); |
725 | | |
726 | | /* Set ret without branches to avoid timing attacks. Return: |
727 | | * - INVALID_PADDING if the padding is bad (bad != 0). |
728 | | * - OUTPUT_TOO_LARGE if the padding is good but the decrypted |
729 | | * plaintext does not fit in the output buffer. |
730 | | * - 0 if the padding is correct. */ |
731 | 0 | ret = -(int) mbedtls_ct_uint_if( |
732 | 0 | bad, -MBEDTLS_ERR_RSA_INVALID_PADDING, |
733 | 0 | mbedtls_ct_uint_if(output_too_large, |
734 | 0 | -MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, |
735 | 0 | 0)); |
736 | | |
737 | | /* If the padding is bad or the plaintext is too large, zero the |
738 | | * data that we're about to copy to the output buffer. |
739 | | * We need to copy the same amount of data |
740 | | * from the same buffer whether the padding is good or not to |
741 | | * avoid leaking the padding validity through overall timing or |
742 | | * through memory or cache access patterns. */ |
743 | 0 | bad = mbedtls_ct_uint_mask(bad | output_too_large); |
744 | 0 | for (i = 11; i < ilen; i++) { |
745 | 0 | input[i] &= ~bad; |
746 | 0 | } |
747 | | |
748 | | /* If the plaintext is too large, truncate it to the buffer size. |
749 | | * Copy anyway to avoid revealing the length through timing, because |
750 | | * revealing the length is as bad as revealing the padding validity |
751 | | * for a Bleichenbacher attack. */ |
752 | 0 | plaintext_size = mbedtls_ct_uint_if(output_too_large, |
753 | 0 | (unsigned) plaintext_max_size, |
754 | 0 | (unsigned) plaintext_size); |
755 | | |
756 | | /* Move the plaintext to the leftmost position where it can start in |
757 | | * the working buffer, i.e. make it start plaintext_max_size from |
758 | | * the end of the buffer. Do this with a memory access trace that |
759 | | * does not depend on the plaintext size. After this move, the |
760 | | * starting location of the plaintext is no longer sensitive |
761 | | * information. */ |
762 | 0 | mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size, |
763 | 0 | plaintext_max_size, |
764 | 0 | plaintext_max_size - plaintext_size); |
765 | | |
766 | | /* Finally copy the decrypted plaintext plus trailing zeros into the output |
767 | | * buffer. If output_max_len is 0, then output may be an invalid pointer |
768 | | * and the result of memcpy() would be undefined; prevent undefined |
769 | | * behavior making sure to depend only on output_max_len (the size of the |
770 | | * user-provided output buffer), which is independent from plaintext |
771 | | * length, validity of padding, success of the decryption, and other |
772 | | * secrets. */ |
773 | 0 | if (output_max_len != 0) { |
774 | 0 | memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size); |
775 | 0 | } |
776 | | |
777 | | /* Report the amount of data we copied to the output buffer. In case |
778 | | * of errors (bad padding or output too large), the value of *olen |
779 | | * when this function returns is not specified. Making it equivalent |
780 | | * to the good case limits the risks of leaking the padding validity. */ |
781 | 0 | *olen = plaintext_size; |
782 | |
|
783 | 0 | return ret; |
784 | 0 | } |
785 | | |
786 | | #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ |