blob: a786d380bdc9c8c1ec4176492649c9da24b5cc12 [file] [log] [blame]
gabor-mezei-armd1125342021-07-12 16:31:22 +02001/**
2 * Constant-time functions
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
Gilles Peskine449bd832023-01-11 14:50:10 +010020/*
Gabor Mezei642eeb22021-11-03 16:13:32 +010021 * The following functions are implemented without using comparison operators, as those
Gabor Mezeieab90bc2021-10-18 16:09:41 +020022 * might be translated to branches by some compilers on some platforms.
23 */
24
gabor-mezei-armd1125342021-07-12 16:31:22 +020025#include "common.h"
Gabor Mezei22c9a6f2021-10-20 12:09:35 +020026#include "constant_time_internal.h"
Gabor Mezei765862c2021-10-19 12:22:25 +020027#include "mbedtls/constant_time.h"
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +020028#include "mbedtls/error.h"
gabor-mezei-arm5b3a32d2021-09-29 10:50:31 +020029#include "mbedtls/platform_util.h"
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +020030
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +020031#if defined(MBEDTLS_BIGNUM_C)
32#include "mbedtls/bignum.h"
Gabor Mezei87638a92022-09-15 20:02:36 +020033#include "bignum_core.h"
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +020034#endif
35
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +020036#if defined(MBEDTLS_SSL_TLS_C)
37#include "ssl_misc.h"
38#endif
39
gabor-mezei-arm5b3a32d2021-09-29 10:50:31 +020040#if defined(MBEDTLS_RSA_C)
41#include "mbedtls/rsa.h"
42#endif
43
Gabor Mezei28d61152021-11-15 16:13:01 +010044#if defined(MBEDTLS_BASE64_C)
45#include "constant_time_invasive.h"
46#endif
47
gabor-mezei-armfdb71182021-09-27 16:11:12 +020048#include <string.h>
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050049#if defined(MBEDTLS_USE_PSA_CRYPTO)
50#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
51 psa_to_ssl_errors, \
52 psa_generic_status_to_mbedtls)
53#endif
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +020054
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000055/*
Dave Rodgman051225d2022-12-30 21:25:35 +000056 * Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to
57 * perform fast unaligned access to volatile data.
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000058 *
59 * This is needed because mbedtls_get_unaligned_uintXX etc don't support volatile
60 * memory accesses.
61 *
Dave Rodgman051225d2022-12-30 21:25:35 +000062 * Some of these definitions could be moved into alignment.h but for now they are
63 * only used here.
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000064 */
Dave Rodgman051225d2022-12-30 21:25:35 +000065#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && defined(MBEDTLS_HAVE_ASM)
66#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__) || defined(__aarch64__)
67#define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS
68#endif
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000069#endif
70
Dave Rodgman051225d2022-12-30 21:25:35 +000071#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000072static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p)
73{
74 /* This is UB, even where it's safe:
75 * return *((volatile uint32_t*)p);
76 * so instead the same thing is expressed in assembly below.
77 */
78 uint32_t r;
79#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
Dave Rodgman4610d4b2023-01-30 09:26:48 +000080 asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :);
Dave Rodgman051225d2022-12-30 21:25:35 +000081#elif defined(__aarch64__)
Dave Rodgman4610d4b2023-01-30 09:26:48 +000082 asm volatile ("ldr %w0, [%1]" : "=r" (r) : "r" (p) :);
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000083#endif
Dave Rodgman051225d2022-12-30 21:25:35 +000084 return r;
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000085}
Dave Rodgman051225d2022-12-30 21:25:35 +000086#endif /* MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS */
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000087
Gilles Peskine449bd832023-01-11 14:50:10 +010088int mbedtls_ct_memcmp(const void *a,
89 const void *b,
90 size_t n)
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +020091{
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000092 size_t i = 0;
Dave Rodgman7658b632023-01-11 17:39:33 +000093 /*
94 * `A` and `B` are cast to volatile to ensure that the compiler
95 * generates code that always fully reads both buffers.
96 * Otherwise it could generate a test to exit early if `diff` has all
97 * bits set early in the loop.
98 */
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +020099 volatile const unsigned char *A = (volatile const unsigned char *) a;
100 volatile const unsigned char *B = (volatile const unsigned char *) b;
Dave Rodgman7658b632023-01-11 17:39:33 +0000101 uint32_t diff = 0;
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +0200102
Dave Rodgman051225d2022-12-30 21:25:35 +0000103#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)
Dave Rodgman36dfc5a2022-12-22 15:04:43 +0000104 for (; (i + 4) <= n; i += 4) {
105 uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i);
106 uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i);
107 diff |= x ^ y;
108 }
109#endif
110
111 for (; i < n; i++) {
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +0200112 /* Read volatile data in order before computing diff.
113 * This avoids IAR compiler warning:
114 * 'the order of volatile accesses is undefined ..' */
115 unsigned char x = A[i], y = B[i];
116 diff |= x ^ y;
117 }
118
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 return (int) diff;
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +0200120}
121
Gilles Peskine449bd832023-01-11 14:50:10 +0100122unsigned mbedtls_ct_uint_mask(unsigned value)
gabor-mezei-arm340948e2021-09-27 11:40:03 +0200123{
124 /* MSVC has a warning about unary minus on unsigned, but this is
125 * well-defined and precisely what we want to do here */
126#if defined(_MSC_VER)
127#pragma warning( push )
128#pragma warning( disable : 4146 )
129#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-arm340948e2021-09-27 11:40:03 +0200131#if defined(_MSC_VER)
132#pragma warning( pop )
133#endif
134}
gabor-mezei-arm3733bf82021-09-27 11:49:42 +0200135
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200136#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
Gabor Mezei6a426c92021-10-20 11:17:43 +0200137
Gilles Peskine449bd832023-01-11 14:50:10 +0100138size_t mbedtls_ct_size_mask(size_t value)
gabor-mezei-arm3733bf82021-09-27 11:49:42 +0200139{
140 /* MSVC has a warning about unary minus on unsigned integer types,
141 * but this is well-defined and precisely what we want to do here. */
142#if defined(_MSC_VER)
143#pragma warning( push )
144#pragma warning( disable : 4146 )
145#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-arm3733bf82021-09-27 11:49:42 +0200147#if defined(_MSC_VER)
148#pragma warning( pop )
149#endif
150}
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200151
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200152#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
Gabor Mezei6a426c92021-10-20 11:17:43 +0200153
gabor-mezei-arm9cb55692021-08-11 15:07:02 +0200154#if defined(MBEDTLS_BIGNUM_C)
155
Gilles Peskine449bd832023-01-11 14:50:10 +0100156mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value)
gabor-mezei-arm9cb55692021-08-11 15:07:02 +0200157{
158 /* MSVC has a warning about unary minus on unsigned, but this is
159 * well-defined and precisely what we want to do here */
160#if defined(_MSC_VER)
161#pragma warning( push )
162#pragma warning( disable : 4146 )
163#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-arm9cb55692021-08-11 15:07:02 +0200165#if defined(_MSC_VER)
166#pragma warning( pop )
167#endif
168}
169
170#endif /* MBEDTLS_BIGNUM_C */
171
Gabor Mezeie2123792021-10-18 17:05:06 +0200172#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
173
Gabor Mezei1e642612021-10-18 16:05:50 +0200174/** Constant-flow mask generation for "less than" comparison:
175 * - if \p x < \p y, return all-bits 1, that is (size_t) -1
176 * - otherwise, return all bits 0, that is 0
177 *
178 * This function can be used to write constant-time code by replacing branches
179 * with bit operations using masks.
180 *
181 * \param x The first value to analyze.
182 * \param y The second value to analyze.
183 *
184 * \return All-bits-one if \p x is less than \p y, otherwise zero.
185 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100186static size_t mbedtls_ct_size_mask_lt(size_t x,
187 size_t y)
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200188{
189 /* This has the most significant bit set if and only if x < y */
190 const size_t sub = x - y;
191
192 /* sub1 = (x < y) ? 1 : 0 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 const size_t sub1 = sub >> (sizeof(sub) * 8 - 1);
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200194
195 /* mask = (x < y) ? 0xff... : 0x00... */
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 const size_t mask = mbedtls_ct_size_mask(sub1);
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200197
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 return mask;
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200199}
gabor-mezei-arm16fc57b2021-09-27 11:58:31 +0200200
Gilles Peskine449bd832023-01-11 14:50:10 +0100201size_t mbedtls_ct_size_mask_ge(size_t x,
202 size_t y)
gabor-mezei-arm16fc57b2021-09-27 11:58:31 +0200203{
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 return ~mbedtls_ct_size_mask_lt(x, y);
gabor-mezei-arm16fc57b2021-09-27 11:58:31 +0200205}
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200206
Gabor Mezeie2123792021-10-18 17:05:06 +0200207#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
208
Gabor Mezei28d61152021-11-15 16:13:01 +0100209#if defined(MBEDTLS_BASE64_C)
210
211/* Return 0xff if low <= c <= high, 0 otherwise.
212 *
213 * Constant flow with respect to c.
214 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100215unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low,
216 unsigned char high,
217 unsigned char c)
Gabor Mezei28d61152021-11-15 16:13:01 +0100218{
219 /* low_mask is: 0 if low <= c, 0x...ff if low > c */
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 unsigned low_mask = ((unsigned) c - low) >> 8;
Gabor Mezei28d61152021-11-15 16:13:01 +0100221 /* high_mask is: 0 if c <= high, 0x...ff if c > high */
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 unsigned high_mask = ((unsigned) high - c) >> 8;
223 return ~(low_mask | high_mask) & 0xff;
Gabor Mezei28d61152021-11-15 16:13:01 +0100224}
225
226#endif /* MBEDTLS_BASE64_C */
227
Gilles Peskine449bd832023-01-11 14:50:10 +0100228unsigned mbedtls_ct_size_bool_eq(size_t x,
229 size_t y)
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200230{
231 /* diff = 0 if x == y, non-zero otherwise */
232 const size_t diff = x ^ y;
233
234 /* MSVC has a warning about unary minus on unsigned integer types,
235 * but this is well-defined and precisely what we want to do here. */
236#if defined(_MSC_VER)
237#pragma warning( push )
238#pragma warning( disable : 4146 )
239#endif
240
241 /* diff_msb's most significant bit is equal to x != y */
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 const size_t diff_msb = (diff | (size_t) -diff);
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200243
244#if defined(_MSC_VER)
245#pragma warning( pop )
246#endif
247
248 /* diff1 = (x != y) ? 1 : 0 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 const unsigned diff1 = diff_msb >> (sizeof(diff_msb) * 8 - 1);
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200250
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 return 1 ^ diff1;
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200252}
gabor-mezei-arm5a854422021-09-27 12:25:07 +0200253
Gabor Mezeie2123792021-10-18 17:05:06 +0200254#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
255
Gabor Mezeia2d0f902021-10-18 16:35:23 +0200256/** Constant-flow "greater than" comparison:
257 * return x > y
258 *
259 * This is equivalent to \p x > \p y, but is likely to be compiled
260 * to code using bitwise operation rather than a branch.
261 *
262 * \param x The first value to analyze.
263 * \param y The second value to analyze.
264 *
265 * \return 1 if \p x greater than \p y, otherwise 0.
266 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100267static unsigned mbedtls_ct_size_gt(size_t x,
268 size_t y)
gabor-mezei-arm5a854422021-09-27 12:25:07 +0200269{
gabor-mezei-arm87ac5be2021-08-10 20:36:09 +0200270 /* Return the sign bit (1 for negative) of (y - x). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 return (y - x) >> (sizeof(size_t) * 8 - 1);
gabor-mezei-arm5a854422021-09-27 12:25:07 +0200272}
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200273
Gabor Mezeie2123792021-10-18 17:05:06 +0200274#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
275
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200276#if defined(MBEDTLS_BIGNUM_C)
277
Gilles Peskine449bd832023-01-11 14:50:10 +0100278unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x,
279 const mbedtls_mpi_uint y)
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200280{
281 mbedtls_mpi_uint ret;
282 mbedtls_mpi_uint cond;
283
284 /*
285 * Check if the most significant bits (MSB) of the operands are different.
286 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 cond = (x ^ y);
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200288 /*
289 * If the MSB are the same then the difference x-y will be negative (and
290 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
291 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 ret = (x - y) & ~cond;
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200293 /*
294 * If the MSB are different, then the operand with the MSB of 1 is the
295 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
296 * the MSB of y is 0.)
297 */
298 ret |= y & cond;
299
300
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 ret = ret >> (sizeof(mbedtls_mpi_uint) * 8 - 1);
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200302
303 return (unsigned) ret;
304}
305
306#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-armb2dbf2c2021-09-27 12:59:30 +0200307
Gilles Peskine449bd832023-01-11 14:50:10 +0100308unsigned mbedtls_ct_uint_if(unsigned condition,
309 unsigned if1,
310 unsigned if0)
gabor-mezei-armb2dbf2c2021-09-27 12:59:30 +0200311{
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 unsigned mask = mbedtls_ct_uint_mask(condition);
313 return (mask & if1) | (~mask & if0);
gabor-mezei-armb2dbf2c2021-09-27 12:59:30 +0200314}
gabor-mezei-armd3230d52021-09-27 13:03:57 +0200315
Gabor Mezeie2123792021-10-18 17:05:06 +0200316#if defined(MBEDTLS_BIGNUM_C)
gabor-mezei-arm65cefdb2021-09-27 15:47:00 +0200317
Gilles Peskine449bd832023-01-11 14:50:10 +0100318void mbedtls_ct_mpi_uint_cond_assign(size_t n,
319 mbedtls_mpi_uint *dest,
320 const mbedtls_mpi_uint *src,
321 unsigned char condition)
gabor-mezei-armbe8d98b2021-09-27 13:17:15 +0200322{
323 size_t i;
324
325 /* MSVC has a warning about unary minus on unsigned integer types,
326 * but this is well-defined and precisely what we want to do here. */
327#if defined(_MSC_VER)
328#pragma warning( push )
329#pragma warning( disable : 4146 )
330#endif
331
gabor-mezei-arm87ac5be2021-08-10 20:36:09 +0200332 /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */
333 const mbedtls_mpi_uint mask = -condition;
gabor-mezei-armbe8d98b2021-09-27 13:17:15 +0200334
335#if defined(_MSC_VER)
336#pragma warning( pop )
337#endif
338
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 for (i = 0; i < n; i++) {
340 dest[i] = (src[i] & mask) | (dest[i] & ~mask);
341 }
gabor-mezei-armbe8d98b2021-09-27 13:17:15 +0200342}
343
344#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200345
Gabor Mezeie2123792021-10-18 17:05:06 +0200346#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
347
Gabor Mezeia2d0f902021-10-18 16:35:23 +0200348/** Shift some data towards the left inside a buffer.
349 *
Gabor Mezei90437e32021-10-20 11:59:27 +0200350 * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally
Gabor Mezeia2d0f902021-10-18 16:35:23 +0200351 * equivalent to
352 * ```
353 * memmove(start, start + offset, total - offset);
354 * memset(start + offset, 0, total - offset);
355 * ```
356 * but it strives to use a memory access pattern (and thus total timing)
357 * that does not depend on \p offset. This timing independence comes at
358 * the expense of performance.
359 *
360 * \param start Pointer to the start of the buffer.
361 * \param total Total size of the buffer.
362 * \param offset Offset from which to copy \p total - \p offset bytes.
363 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100364static void mbedtls_ct_mem_move_to_left(void *start,
365 size_t total,
366 size_t offset)
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200367{
368 volatile unsigned char *buf = start;
369 size_t i, n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 if (total == 0) {
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200371 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 }
373 for (i = 0; i < total; i++) {
374 unsigned no_op = mbedtls_ct_size_gt(total - offset, i);
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200375 /* The first `total - offset` passes are a no-op. The last
376 * `offset` passes shift the data one byte to the left and
377 * zero out the last byte. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 for (n = 0; n < total - 1; n++) {
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200379 unsigned char current = buf[n];
380 unsigned char next = buf[n+1];
Gilles Peskine449bd832023-01-11 14:50:10 +0100381 buf[n] = mbedtls_ct_uint_if(no_op, current, next);
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200382 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 buf[total-1] = mbedtls_ct_uint_if(no_op, buf[total-1], 0);
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200384 }
385}
gabor-mezei-armdee0fd32021-09-27 13:34:25 +0200386
Gabor Mezeie2123792021-10-18 17:05:06 +0200387#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
388
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200389#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
Gabor Mezeie2123792021-10-18 17:05:06 +0200390
Gilles Peskine449bd832023-01-11 14:50:10 +0100391void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
392 const unsigned char *src,
393 size_t len,
394 size_t c1,
395 size_t c2)
gabor-mezei-armdee0fd32021-09-27 13:34:25 +0200396{
397 /* mask = c1 == c2 ? 0xff : 0x00 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 const size_t equal = mbedtls_ct_size_bool_eq(c1, c2);
gabor-mezei-armdee0fd32021-09-27 13:34:25 +0200399
gabor-mezei-arm87ac5be2021-08-10 20:36:09 +0200400 /* dest[i] = c1 == c2 ? src[i] : dest[i] */
Dave Rodgman36dfc5a2022-12-22 15:04:43 +0000401 size_t i = 0;
402#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
403 const uint32_t mask32 = (uint32_t) mbedtls_ct_size_mask(equal);
404 const unsigned char mask = (unsigned char) mask32 & 0xff;
405
406 for (; (i + 4) <= len; i += 4) {
407 uint32_t a = mbedtls_get_unaligned_uint32(src + i) & mask32;
408 uint32_t b = mbedtls_get_unaligned_uint32(dest + i) & ~mask32;
409 mbedtls_put_unaligned_uint32(dest + i, a | b);
410 }
411#else
412 const unsigned char mask = (unsigned char) mbedtls_ct_size_mask(equal);
413#endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */
414 for (; i < len; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 dest[i] = (src[i] & mask) | (dest[i] & ~mask);
416 }
gabor-mezei-armdee0fd32021-09-27 13:34:25 +0200417}
gabor-mezei-arm0e7f71e2021-09-27 13:57:45 +0200418
Gilles Peskine449bd832023-01-11 14:50:10 +0100419void mbedtls_ct_memcpy_offset(unsigned char *dest,
420 const unsigned char *src,
421 size_t offset,
422 size_t offset_min,
423 size_t offset_max,
424 size_t len)
gabor-mezei-arm0e7f71e2021-09-27 13:57:45 +0200425{
Gabor Mezei63bbba52021-10-18 16:17:57 +0200426 size_t offsetval;
gabor-mezei-arm0e7f71e2021-09-27 13:57:45 +0200427
Gilles Peskine449bd832023-01-11 14:50:10 +0100428 for (offsetval = offset_min; offsetval <= offset_max; offsetval++) {
429 mbedtls_ct_memcpy_if_eq(dest, src + offsetval, len,
430 offsetval, offset);
gabor-mezei-arm0e7f71e2021-09-27 13:57:45 +0200431 }
432}
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200433
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200434#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200435
436#if defined(MBEDTLS_BIGNUM_C)
437
Gilles Peskine449bd832023-01-11 14:50:10 +0100438#define MPI_VALIDATE_RET(cond) \
439 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200440
441/*
442 * Conditionally assign X = Y, without leaking information
443 * about whether the assignment was made or not.
444 * (Leaking information about the respective sizes of X and Y is ok however.)
445 */
Tautvydas Žilys40fc7da2022-01-31 13:34:01 -0800446#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
Tautvydas Žilys60165d72022-01-26 15:33:27 -0800447/*
Tautvydas Žilys40fc7da2022-01-31 13:34:01 -0800448 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
Tautvydas Žilys60165d72022-01-26 15:33:27 -0800449 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
450 */
451__declspec(noinline)
452#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100453int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
454 const mbedtls_mpi *Y,
455 unsigned char assign)
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200456{
457 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 MPI_VALIDATE_RET(X != NULL);
459 MPI_VALIDATE_RET(Y != NULL);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200460
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200461 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(assign);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200463
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200465
Tom Cosgrovee22413c2023-05-03 09:44:01 +0100466 X->s = (int) mbedtls_ct_uint_if(assign, Y->s, X->s);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200467
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, assign);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200469
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 for (size_t i = Y->n; i < X->n; i++) {
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200471 X->p[i] &= ~limb_mask;
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 }
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200473
474cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 return ret;
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200476}
477
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200478/*
479 * Conditionally swap X and Y, without leaking information
480 * about whether the swap was made or not.
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800481 * Here it is not ok to simply swap the pointers, which would lead to
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200482 * different memory access patterns when X and Y are used afterwards.
483 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100484int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
485 mbedtls_mpi *Y,
486 unsigned char swap)
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200487{
Gabor Mezeid7edb1d2022-10-10 14:32:09 +0200488 int ret = 0;
489 int s;
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 MPI_VALIDATE_RET(X != NULL);
491 MPI_VALIDATE_RET(Y != NULL);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200492
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 if (X == Y) {
494 return 0;
495 }
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200496
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
498 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200499
500 s = X->s;
Tom Cosgrovee22413c2023-05-03 09:44:01 +0100501 X->s = (int) mbedtls_ct_uint_if(swap, Y->s, X->s);
502 Y->s = (int) mbedtls_ct_uint_if(swap, s, Y->s);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200503
Gilles Peskine449bd832023-01-11 14:50:10 +0100504 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, swap);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200505
506cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 return ret;
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200508}
509
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200510/*
Janos Follath23bdeca2022-07-22 18:24:06 +0100511 * Compare unsigned values in constant time
512 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100513unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
514 const mbedtls_mpi_uint *B,
515 size_t limbs)
Janos Follath23bdeca2022-07-22 18:24:06 +0100516{
Janos Follath23bdeca2022-07-22 18:24:06 +0100517 unsigned ret, cond, done;
518
Janos Follath63184682022-08-11 17:42:59 +0100519 /* The value of any of these variables is either 0 or 1 for the rest of
520 * their scope. */
Janos Follath23bdeca2022-07-22 18:24:06 +0100521 ret = cond = done = 0;
522
Gilles Peskine449bd832023-01-11 14:50:10 +0100523 for (size_t i = limbs; i > 0; i--) {
Janos Follath23bdeca2022-07-22 18:24:06 +0100524 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100525 * If B[i - 1] < A[i - 1] then A < B is false and the result must
Janos Follath23bdeca2022-07-22 18:24:06 +0100526 * remain 0.
527 *
528 * Again even if we can make a decision, we just mark the result and
529 * the fact that we are done and continue looping.
530 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100531 cond = mbedtls_ct_mpi_uint_lt(B[i - 1], A[i - 1]);
Janos Follath23bdeca2022-07-22 18:24:06 +0100532 done |= cond;
533
534 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100535 * If A[i - 1] < B[i - 1] then A < B is true.
Janos Follath23bdeca2022-07-22 18:24:06 +0100536 *
537 * Again even if we can make a decision, we just mark the result and
538 * the fact that we are done and continue looping.
539 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 cond = mbedtls_ct_mpi_uint_lt(A[i - 1], B[i - 1]);
541 ret |= cond & (1 - done);
Janos Follath23bdeca2022-07-22 18:24:06 +0100542 done |= cond;
543 }
544
545 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100546 * If all the limbs were equal, then the numbers are equal, A < B is false
Janos Follath23bdeca2022-07-22 18:24:06 +0100547 * and leaving the result 0 is correct.
548 */
549
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 return ret;
Janos Follath23bdeca2022-07-22 18:24:06 +0100551}
552
553/*
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200554 * Compare signed values in constant time
555 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100556int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
557 const mbedtls_mpi *Y,
558 unsigned *ret)
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200559{
560 size_t i;
561 /* The value of any of these variables is either 0 or 1 at all times. */
562 unsigned cond, done, X_is_negative, Y_is_negative;
563
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 MPI_VALIDATE_RET(X != NULL);
565 MPI_VALIDATE_RET(Y != NULL);
566 MPI_VALIDATE_RET(ret != NULL);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200567
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 if (X->n != Y->n) {
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200569 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 }
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200571
572 /*
573 * Set sign_N to 1 if N >= 0, 0 if N < 0.
574 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
575 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100576 X_is_negative = (X->s & 2) >> 1;
577 Y_is_negative = (Y->s & 2) >> 1;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200578
579 /*
580 * If the signs are different, then the positive operand is the bigger.
581 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
582 * is false if X is positive (X_is_negative == 0).
583 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 cond = (X_is_negative ^ Y_is_negative);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200585 *ret = cond & X_is_negative;
586
587 /*
588 * This is a constant-time function. We might have the result, but we still
589 * need to go through the loop. Record if we have the result already.
590 */
591 done = cond;
592
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 for (i = X->n; i > 0; i--) {
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200594 /*
595 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
596 * X and Y are negative.
597 *
598 * Again even if we can make a decision, we just mark the result and
599 * the fact that we are done and continue looping.
600 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]);
602 *ret |= cond & (1 - done) & X_is_negative;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200603 done |= cond;
604
605 /*
606 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
607 * X and Y are positive.
608 *
609 * Again even if we can make a decision, we just mark the result and
610 * the fact that we are done and continue looping.
611 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]);
613 *ret |= cond & (1 - done) & (1 - X_is_negative);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200614 done |= cond;
615 }
616
Gilles Peskine449bd832023-01-11 14:50:10 +0100617 return 0;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200618}
619
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200620#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200621
622#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
623
Gilles Peskine449bd832023-01-11 14:50:10 +0100624int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
625 size_t ilen,
626 unsigned char *output,
627 size_t output_max_len,
628 size_t *olen)
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200629{
630 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
631 size_t i, plaintext_max_size;
632
633 /* The following variables take sensitive values: their value must
634 * not leak into the observable behavior of the function other than
635 * the designated outputs (output, olen, return value). Otherwise
636 * this would open the execution of the function to
637 * side-channel-based variants of the Bleichenbacher padding oracle
638 * attack. Potential side channels include overall timing, memory
639 * access patterns (especially visible to an adversary who has access
640 * to a shared memory cache), and branches (especially visible to
641 * an adversary who has access to a shared code cache or to a shared
642 * branch predictor). */
643 size_t pad_count = 0;
644 unsigned bad = 0;
645 unsigned char pad_done = 0;
646 size_t plaintext_size = 0;
647 unsigned output_too_large;
648
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11
Gabor Mezei7013f622021-10-18 16:12:45 +0200650 : output_max_len;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200651
652 /* Check and get padding length in constant time and constant
653 * memory trace. The first byte must be 0. */
Gabor Mezei63bbba52021-10-18 16:17:57 +0200654 bad |= input[0];
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200655
656
657 /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
Gabor Mezei63bbba52021-10-18 16:17:57 +0200658 * where PS must be at least 8 nonzero bytes. */
659 bad |= input[1] ^ MBEDTLS_RSA_CRYPT;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200660
661 /* Read the whole buffer. Set pad_done to nonzero if we find
Gabor Mezei63bbba52021-10-18 16:17:57 +0200662 * the 0x00 byte and remember the padding length in pad_count. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100663 for (i = 2; i < ilen; i++) {
664 pad_done |= ((input[i] | (unsigned char) -input[i]) >> 7) ^ 1;
665 pad_count += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200666 }
667
668
669 /* If pad_done is still zero, there's no data, only unfinished padding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100670 bad |= mbedtls_ct_uint_if(pad_done, 0, 1);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200671
672 /* There must be at least 8 bytes of padding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 bad |= mbedtls_ct_size_gt(8, pad_count);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200674
675 /* If the padding is valid, set plaintext_size to the number of
676 * remaining bytes after stripping the padding. If the padding
677 * is invalid, avoid leaking this fact through the size of the
678 * output: use the maximum message size that fits in the output
679 * buffer. Do it without branches to avoid leaking the padding
680 * validity through timing. RSA keys are small enough that all the
681 * size_t values involved fit in unsigned int. */
Gabor Mezei90437e32021-10-20 11:59:27 +0200682 plaintext_size = mbedtls_ct_uint_if(
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 bad, (unsigned) plaintext_max_size,
684 (unsigned) (ilen - pad_count - 3));
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200685
686 /* Set output_too_large to 0 if the plaintext fits in the output
687 * buffer and to 1 otherwise. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 output_too_large = mbedtls_ct_size_gt(plaintext_size,
689 plaintext_max_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200690
691 /* Set ret without branches to avoid timing attacks. Return:
692 * - INVALID_PADDING if the padding is bad (bad != 0).
693 * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
694 * plaintext does not fit in the output buffer.
695 * - 0 if the padding is correct. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100696 ret = -(int) mbedtls_ct_uint_if(
697 bad, -MBEDTLS_ERR_RSA_INVALID_PADDING,
698 mbedtls_ct_uint_if(output_too_large,
699 -MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
700 0));
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200701
702 /* If the padding is bad or the plaintext is too large, zero the
703 * data that we're about to copy to the output buffer.
704 * We need to copy the same amount of data
705 * from the same buffer whether the padding is good or not to
706 * avoid leaking the padding validity through overall timing or
707 * through memory or cache access patterns. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 bad = mbedtls_ct_uint_mask(bad | output_too_large);
709 for (i = 11; i < ilen; i++) {
Gabor Mezei63bbba52021-10-18 16:17:57 +0200710 input[i] &= ~bad;
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 }
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200712
713 /* If the plaintext is too large, truncate it to the buffer size.
714 * Copy anyway to avoid revealing the length through timing, because
715 * revealing the length is as bad as revealing the padding validity
716 * for a Bleichenbacher attack. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100717 plaintext_size = mbedtls_ct_uint_if(output_too_large,
718 (unsigned) plaintext_max_size,
719 (unsigned) plaintext_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200720
721 /* Move the plaintext to the leftmost position where it can start in
722 * the working buffer, i.e. make it start plaintext_max_size from
723 * the end of the buffer. Do this with a memory access trace that
724 * does not depend on the plaintext size. After this move, the
725 * starting location of the plaintext is no longer sensitive
726 * information. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100727 mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size,
728 plaintext_max_size,
729 plaintext_max_size - plaintext_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200730
731 /* Finally copy the decrypted plaintext plus trailing zeros into the output
732 * buffer. If output_max_len is 0, then output may be an invalid pointer
733 * and the result of memcpy() would be undefined; prevent undefined
734 * behavior making sure to depend only on output_max_len (the size of the
735 * user-provided output buffer), which is independent from plaintext
736 * length, validity of padding, success of the decryption, and other
737 * secrets. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100738 if (output_max_len != 0) {
739 memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);
740 }
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200741
742 /* Report the amount of data we copied to the output buffer. In case
743 * of errors (bad padding or output too large), the value of *olen
744 * when this function returns is not specified. Making it equivalent
745 * to the good case limits the risks of leaking the padding validity. */
746 *olen = plaintext_size;
747
Gilles Peskine449bd832023-01-11 14:50:10 +0100748 return ret;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200749}
750
751#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */