blob: 5ed087c07adeec3fc6914b2d21d0824396dc307f [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)
Dave Rodgmanc54f25e2023-06-21 13:39:30 +010066#if ((defined(__arm__) || defined(__thumb__) || defined(__thumb2__)) && \
67 (UINTPTR_MAX == 0xfffffffful)) || \
68 (defined(__aarch64__) && ((UINTPTR_MAX == 0xffffffffull) || \
69 (UINTPTR_MAX == 0xffffffffffffffffull)))
Dave Rodgman63e89b42023-06-21 11:55:17 +010070/* We check pointer sizes to avoid issues with them not matching register size requirements */
Dave Rodgman051225d2022-12-30 21:25:35 +000071#define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS
72#endif
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000073#endif
74
Dave Rodgman051225d2022-12-30 21:25:35 +000075#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000076static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p)
77{
78 /* This is UB, even where it's safe:
79 * return *((volatile uint32_t*)p);
80 * so instead the same thing is expressed in assembly below.
81 */
82 uint32_t r;
83#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
Dave Rodgman4610d4b2023-01-30 09:26:48 +000084 asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :);
Dave Rodgman04cb9ac2023-06-21 07:32:22 +010085#elif defined(__aarch64__)
Dave Rodgman63e89b42023-06-21 11:55:17 +010086#if (UINTPTR_MAX == 0xfffffffful)
Dave Rodgmanb67db912023-06-21 09:15:27 +010087 /* ILP32: Specify the pointer operand slightly differently, as per #7787. */
Dave Rodgman04cb9ac2023-06-21 07:32:22 +010088 asm volatile ("ldr %w0, [%1]" : "=r" (r) : "p" (p) :);
Dave Rodgman63e89b42023-06-21 11:55:17 +010089#elif (UINTPTR_MAX == 0xffffffffffffffffull)
90 /* aarch64 with 64-bit pointers */
Dave Rodgmanb67db912023-06-21 09:15:27 +010091 asm volatile ("ldr %w0, [%1]" : "=r" (r) : "r" (p) :);
92#endif
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000093#endif
Dave Rodgman051225d2022-12-30 21:25:35 +000094 return r;
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000095}
Dave Rodgman051225d2022-12-30 21:25:35 +000096#endif /* MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS */
Dave Rodgman36dfc5a2022-12-22 15:04:43 +000097
Gilles Peskine449bd832023-01-11 14:50:10 +010098int mbedtls_ct_memcmp(const void *a,
99 const void *b,
100 size_t n)
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +0200101{
Dave Rodgman36dfc5a2022-12-22 15:04:43 +0000102 size_t i = 0;
Dave Rodgman7658b632023-01-11 17:39:33 +0000103 /*
104 * `A` and `B` are cast to volatile to ensure that the compiler
105 * generates code that always fully reads both buffers.
106 * Otherwise it could generate a test to exit early if `diff` has all
107 * bits set early in the loop.
108 */
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +0200109 volatile const unsigned char *A = (volatile const unsigned char *) a;
110 volatile const unsigned char *B = (volatile const unsigned char *) b;
Dave Rodgman7658b632023-01-11 17:39:33 +0000111 uint32_t diff = 0;
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +0200112
Dave Rodgman051225d2022-12-30 21:25:35 +0000113#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)
Dave Rodgman36dfc5a2022-12-22 15:04:43 +0000114 for (; (i + 4) <= n; i += 4) {
115 uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i);
116 uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i);
117 diff |= x ^ y;
118 }
119#endif
120
121 for (; i < n; i++) {
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +0200122 /* Read volatile data in order before computing diff.
123 * This avoids IAR compiler warning:
124 * 'the order of volatile accesses is undefined ..' */
125 unsigned char x = A[i], y = B[i];
126 diff |= x ^ y;
127 }
128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 return (int) diff;
gabor-mezei-armdb9a38c2021-09-27 11:28:54 +0200130}
131
Gilles Peskine449bd832023-01-11 14:50:10 +0100132unsigned mbedtls_ct_uint_mask(unsigned value)
gabor-mezei-arm340948e2021-09-27 11:40:03 +0200133{
134 /* MSVC has a warning about unary minus on unsigned, but this is
135 * well-defined and precisely what we want to do here */
136#if defined(_MSC_VER)
137#pragma warning( push )
138#pragma warning( disable : 4146 )
139#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-arm340948e2021-09-27 11:40:03 +0200141#if defined(_MSC_VER)
142#pragma warning( pop )
143#endif
144}
gabor-mezei-arm3733bf82021-09-27 11:49:42 +0200145
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200146#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
Gabor Mezei6a426c92021-10-20 11:17:43 +0200147
Gilles Peskine449bd832023-01-11 14:50:10 +0100148size_t mbedtls_ct_size_mask(size_t value)
gabor-mezei-arm3733bf82021-09-27 11:49:42 +0200149{
150 /* MSVC has a warning about unary minus on unsigned integer types,
151 * but this is well-defined and precisely what we want to do here. */
152#if defined(_MSC_VER)
153#pragma warning( push )
154#pragma warning( disable : 4146 )
155#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100156 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-arm3733bf82021-09-27 11:49:42 +0200157#if defined(_MSC_VER)
158#pragma warning( pop )
159#endif
160}
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200161
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200162#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
Gabor Mezei6a426c92021-10-20 11:17:43 +0200163
gabor-mezei-arm9cb55692021-08-11 15:07:02 +0200164#if defined(MBEDTLS_BIGNUM_C)
165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value)
gabor-mezei-arm9cb55692021-08-11 15:07:02 +0200167{
168 /* MSVC has a warning about unary minus on unsigned, but this is
169 * well-defined and precisely what we want to do here */
170#if defined(_MSC_VER)
171#pragma warning( push )
172#pragma warning( disable : 4146 )
173#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-arm9cb55692021-08-11 15:07:02 +0200175#if defined(_MSC_VER)
176#pragma warning( pop )
177#endif
178}
179
180#endif /* MBEDTLS_BIGNUM_C */
181
Gabor Mezeie2123792021-10-18 17:05:06 +0200182#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
183
Gabor Mezei1e642612021-10-18 16:05:50 +0200184/** Constant-flow mask generation for "less than" comparison:
185 * - if \p x < \p y, return all-bits 1, that is (size_t) -1
186 * - otherwise, return all bits 0, that is 0
187 *
188 * This function can be used to write constant-time code by replacing branches
189 * with bit operations using masks.
190 *
191 * \param x The first value to analyze.
192 * \param y The second value to analyze.
193 *
194 * \return All-bits-one if \p x is less than \p y, otherwise zero.
195 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100196static size_t mbedtls_ct_size_mask_lt(size_t x,
197 size_t y)
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200198{
199 /* This has the most significant bit set if and only if x < y */
200 const size_t sub = x - y;
201
202 /* sub1 = (x < y) ? 1 : 0 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 const size_t sub1 = sub >> (sizeof(sub) * 8 - 1);
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200204
205 /* mask = (x < y) ? 0xff... : 0x00... */
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 const size_t mask = mbedtls_ct_size_mask(sub1);
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200207
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 return mask;
gabor-mezei-armc76227d2021-09-27 11:53:54 +0200209}
gabor-mezei-arm16fc57b2021-09-27 11:58:31 +0200210
Gilles Peskine449bd832023-01-11 14:50:10 +0100211size_t mbedtls_ct_size_mask_ge(size_t x,
212 size_t y)
gabor-mezei-arm16fc57b2021-09-27 11:58:31 +0200213{
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 return ~mbedtls_ct_size_mask_lt(x, y);
gabor-mezei-arm16fc57b2021-09-27 11:58:31 +0200215}
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200216
Gabor Mezeie2123792021-10-18 17:05:06 +0200217#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
218
Gabor Mezei28d61152021-11-15 16:13:01 +0100219#if defined(MBEDTLS_BASE64_C)
220
221/* Return 0xff if low <= c <= high, 0 otherwise.
222 *
223 * Constant flow with respect to c.
224 */
Gabor Mezeic0d8dda2021-11-26 17:20:36 +0100225MBEDTLS_STATIC_TESTABLE
Gilles Peskine449bd832023-01-11 14:50:10 +0100226unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low,
227 unsigned char high,
228 unsigned char c)
Gabor Mezei28d61152021-11-15 16:13:01 +0100229{
230 /* low_mask is: 0 if low <= c, 0x...ff if low > c */
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 unsigned low_mask = ((unsigned) c - low) >> 8;
Gabor Mezei28d61152021-11-15 16:13:01 +0100232 /* high_mask is: 0 if c <= high, 0x...ff if c > high */
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 unsigned high_mask = ((unsigned) high - c) >> 8;
234 return ~(low_mask | high_mask) & 0xff;
Gabor Mezei28d61152021-11-15 16:13:01 +0100235}
236
237#endif /* MBEDTLS_BASE64_C */
238
Gilles Peskine449bd832023-01-11 14:50:10 +0100239unsigned mbedtls_ct_size_bool_eq(size_t x,
240 size_t y)
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200241{
242 /* diff = 0 if x == y, non-zero otherwise */
243 const size_t diff = x ^ y;
244
245 /* MSVC has a warning about unary minus on unsigned integer types,
246 * but this is well-defined and precisely what we want to do here. */
247#if defined(_MSC_VER)
248#pragma warning( push )
249#pragma warning( disable : 4146 )
250#endif
251
252 /* diff_msb's most significant bit is equal to x != y */
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 const size_t diff_msb = (diff | (size_t) -diff);
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200254
255#if defined(_MSC_VER)
256#pragma warning( pop )
257#endif
258
259 /* diff1 = (x != y) ? 1 : 0 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 const unsigned diff1 = diff_msb >> (sizeof(diff_msb) * 8 - 1);
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200261
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 return 1 ^ diff1;
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +0200263}
gabor-mezei-arm5a854422021-09-27 12:25:07 +0200264
Gabor Mezeie2123792021-10-18 17:05:06 +0200265#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
266
Gabor Mezeia2d0f902021-10-18 16:35:23 +0200267/** Constant-flow "greater than" comparison:
268 * return x > y
269 *
270 * This is equivalent to \p x > \p y, but is likely to be compiled
271 * to code using bitwise operation rather than a branch.
272 *
273 * \param x The first value to analyze.
274 * \param y The second value to analyze.
275 *
276 * \return 1 if \p x greater than \p y, otherwise 0.
277 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100278static unsigned mbedtls_ct_size_gt(size_t x,
279 size_t y)
gabor-mezei-arm5a854422021-09-27 12:25:07 +0200280{
gabor-mezei-arm87ac5be2021-08-10 20:36:09 +0200281 /* Return the sign bit (1 for negative) of (y - x). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 return (y - x) >> (sizeof(size_t) * 8 - 1);
gabor-mezei-arm5a854422021-09-27 12:25:07 +0200283}
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200284
Gabor Mezeie2123792021-10-18 17:05:06 +0200285#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
286
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200287#if defined(MBEDTLS_BIGNUM_C)
288
Gilles Peskine449bd832023-01-11 14:50:10 +0100289unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x,
290 const mbedtls_mpi_uint y)
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200291{
292 mbedtls_mpi_uint ret;
293 mbedtls_mpi_uint cond;
294
295 /*
296 * Check if the most significant bits (MSB) of the operands are different.
297 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 cond = (x ^ y);
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200299 /*
300 * If the MSB are the same then the difference x-y will be negative (and
301 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
302 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 ret = (x - y) & ~cond;
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200304 /*
305 * If the MSB are different, then the operand with the MSB of 1 is the
306 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
307 * the MSB of y is 0.)
308 */
309 ret |= y & cond;
310
311
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 ret = ret >> (sizeof(mbedtls_mpi_uint) * 8 - 1);
gabor-mezei-arm3f90fd52021-09-27 12:55:33 +0200313
314 return (unsigned) ret;
315}
316
317#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-armb2dbf2c2021-09-27 12:59:30 +0200318
Gilles Peskine449bd832023-01-11 14:50:10 +0100319unsigned mbedtls_ct_uint_if(unsigned condition,
320 unsigned if1,
321 unsigned if0)
gabor-mezei-armb2dbf2c2021-09-27 12:59:30 +0200322{
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 unsigned mask = mbedtls_ct_uint_mask(condition);
324 return (mask & if1) | (~mask & if0);
gabor-mezei-armb2dbf2c2021-09-27 12:59:30 +0200325}
gabor-mezei-armd3230d52021-09-27 13:03:57 +0200326
Gabor Mezeie2123792021-10-18 17:05:06 +0200327#if defined(MBEDTLS_BIGNUM_C)
gabor-mezei-arm65cefdb2021-09-27 15:47:00 +0200328
Gilles Peskine449bd832023-01-11 14:50:10 +0100329void mbedtls_ct_mpi_uint_cond_assign(size_t n,
330 mbedtls_mpi_uint *dest,
331 const mbedtls_mpi_uint *src,
332 unsigned char condition)
gabor-mezei-armbe8d98b2021-09-27 13:17:15 +0200333{
334 size_t i;
335
336 /* MSVC has a warning about unary minus on unsigned integer types,
337 * but this is well-defined and precisely what we want to do here. */
338#if defined(_MSC_VER)
339#pragma warning( push )
340#pragma warning( disable : 4146 )
341#endif
342
gabor-mezei-arm87ac5be2021-08-10 20:36:09 +0200343 /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */
344 const mbedtls_mpi_uint mask = -condition;
gabor-mezei-armbe8d98b2021-09-27 13:17:15 +0200345
346#if defined(_MSC_VER)
347#pragma warning( pop )
348#endif
349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 for (i = 0; i < n; i++) {
351 dest[i] = (src[i] & mask) | (dest[i] & ~mask);
352 }
gabor-mezei-armbe8d98b2021-09-27 13:17:15 +0200353}
354
355#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200356
Gabor Mezei9a4074a2021-11-15 16:18:54 +0100357#if defined(MBEDTLS_BASE64_C)
358
Gilles Peskine449bd832023-01-11 14:50:10 +0100359unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
Gabor Mezei9a4074a2021-11-15 16:18:54 +0100360{
361 unsigned char digit = 0;
Gabor Mezei14d5fac2021-11-24 15:51:39 +0100362 /* For each range of values, if value is in that range, mask digit with
363 * the corresponding value. Since value can only be in a single range,
Gabor Mezei9a4074a2021-11-15 16:18:54 +0100364 * only at most one masking will change digit. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 digit |= mbedtls_ct_uchar_mask_of_range(0, 25, value) & ('A' + value);
366 digit |= mbedtls_ct_uchar_mask_of_range(26, 51, value) & ('a' + value - 26);
367 digit |= mbedtls_ct_uchar_mask_of_range(52, 61, value) & ('0' + value - 52);
368 digit |= mbedtls_ct_uchar_mask_of_range(62, 62, value) & '+';
369 digit |= mbedtls_ct_uchar_mask_of_range(63, 63, value) & '/';
370 return digit;
Gabor Mezei9a4074a2021-11-15 16:18:54 +0100371}
372
Gilles Peskine449bd832023-01-11 14:50:10 +0100373signed char mbedtls_ct_base64_dec_value(unsigned char c)
Gabor Mezei358829a2021-11-15 16:22:37 +0100374{
375 unsigned char val = 0;
376 /* For each range of digits, if c is in that range, mask val with
377 * the corresponding value. Since c can only be in a single range,
378 * only at most one masking will change val. Set val to one plus
379 * the desired value so that it stays 0 if c is in none of the ranges. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 val |= mbedtls_ct_uchar_mask_of_range('A', 'Z', c) & (c - 'A' + 0 + 1);
381 val |= mbedtls_ct_uchar_mask_of_range('a', 'z', c) & (c - 'a' + 26 + 1);
382 val |= mbedtls_ct_uchar_mask_of_range('0', '9', c) & (c - '0' + 52 + 1);
383 val |= mbedtls_ct_uchar_mask_of_range('+', '+', c) & (c - '+' + 62 + 1);
384 val |= mbedtls_ct_uchar_mask_of_range('/', '/', c) & (c - '/' + 63 + 1);
Gabor Mezei358829a2021-11-15 16:22:37 +0100385 /* At this point, val is 0 if c is an invalid digit and v+1 if c is
386 * a digit with the value v. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 return val - 1;
Gabor Mezei358829a2021-11-15 16:22:37 +0100388}
389
Gabor Mezei9a4074a2021-11-15 16:18:54 +0100390#endif /* MBEDTLS_BASE64_C */
391
Gabor Mezeie2123792021-10-18 17:05:06 +0200392#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
393
Gabor Mezeia2d0f902021-10-18 16:35:23 +0200394/** Shift some data towards the left inside a buffer.
395 *
Gabor Mezei90437e32021-10-20 11:59:27 +0200396 * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally
Gabor Mezeia2d0f902021-10-18 16:35:23 +0200397 * equivalent to
398 * ```
399 * memmove(start, start + offset, total - offset);
400 * memset(start + offset, 0, total - offset);
401 * ```
402 * but it strives to use a memory access pattern (and thus total timing)
403 * that does not depend on \p offset. This timing independence comes at
404 * the expense of performance.
405 *
406 * \param start Pointer to the start of the buffer.
407 * \param total Total size of the buffer.
408 * \param offset Offset from which to copy \p total - \p offset bytes.
409 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100410static void mbedtls_ct_mem_move_to_left(void *start,
411 size_t total,
412 size_t offset)
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200413{
414 volatile unsigned char *buf = start;
415 size_t i, n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 if (total == 0) {
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200417 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 }
419 for (i = 0; i < total; i++) {
420 unsigned no_op = mbedtls_ct_size_gt(total - offset, i);
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200421 /* The first `total - offset` passes are a no-op. The last
422 * `offset` passes shift the data one byte to the left and
423 * zero out the last byte. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 for (n = 0; n < total - 1; n++) {
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200425 unsigned char current = buf[n];
426 unsigned char next = buf[n+1];
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 buf[n] = mbedtls_ct_uint_if(no_op, current, next);
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200428 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 buf[total-1] = mbedtls_ct_uint_if(no_op, buf[total-1], 0);
gabor-mezei-arm394aeaa2021-09-27 13:31:06 +0200430 }
431}
gabor-mezei-armdee0fd32021-09-27 13:34:25 +0200432
Gabor Mezeie2123792021-10-18 17:05:06 +0200433#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
434
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200435#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
Gabor Mezeie2123792021-10-18 17:05:06 +0200436
Gilles Peskine449bd832023-01-11 14:50:10 +0100437void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
438 const unsigned char *src,
439 size_t len,
440 size_t c1,
441 size_t c2)
gabor-mezei-armdee0fd32021-09-27 13:34:25 +0200442{
443 /* mask = c1 == c2 ? 0xff : 0x00 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 const size_t equal = mbedtls_ct_size_bool_eq(c1, c2);
gabor-mezei-armdee0fd32021-09-27 13:34:25 +0200445
gabor-mezei-arm87ac5be2021-08-10 20:36:09 +0200446 /* dest[i] = c1 == c2 ? src[i] : dest[i] */
Dave Rodgman36dfc5a2022-12-22 15:04:43 +0000447 size_t i = 0;
448#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
449 const uint32_t mask32 = (uint32_t) mbedtls_ct_size_mask(equal);
450 const unsigned char mask = (unsigned char) mask32 & 0xff;
451
452 for (; (i + 4) <= len; i += 4) {
453 uint32_t a = mbedtls_get_unaligned_uint32(src + i) & mask32;
454 uint32_t b = mbedtls_get_unaligned_uint32(dest + i) & ~mask32;
455 mbedtls_put_unaligned_uint32(dest + i, a | b);
456 }
457#else
458 const unsigned char mask = (unsigned char) mbedtls_ct_size_mask(equal);
459#endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */
460 for (; i < len; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 dest[i] = (src[i] & mask) | (dest[i] & ~mask);
462 }
gabor-mezei-armdee0fd32021-09-27 13:34:25 +0200463}
gabor-mezei-arm0e7f71e2021-09-27 13:57:45 +0200464
Gilles Peskine449bd832023-01-11 14:50:10 +0100465void mbedtls_ct_memcpy_offset(unsigned char *dest,
466 const unsigned char *src,
467 size_t offset,
468 size_t offset_min,
469 size_t offset_max,
470 size_t len)
gabor-mezei-arm0e7f71e2021-09-27 13:57:45 +0200471{
Gabor Mezei63bbba52021-10-18 16:17:57 +0200472 size_t offsetval;
gabor-mezei-arm0e7f71e2021-09-27 13:57:45 +0200473
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 for (offsetval = offset_min; offsetval <= offset_max; offsetval++) {
475 mbedtls_ct_memcpy_if_eq(dest, src + offsetval, len,
476 offsetval, offset);
gabor-mezei-arm0e7f71e2021-09-27 13:57:45 +0200477 }
478}
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200479
Neil Armstrong2968d302022-02-25 15:09:36 +0100480#if defined(MBEDTLS_USE_PSA_CRYPTO)
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100481
482#if defined(PSA_WANT_ALG_SHA_384)
Gilles Peskine449bd832023-01-11 14:50:10 +0100483#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384)
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100484#elif defined(PSA_WANT_ALG_SHA_256)
Gilles Peskine449bd832023-01-11 14:50:10 +0100485#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256)
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100486#else /* See check_config.h */
Gilles Peskine449bd832023-01-11 14:50:10 +0100487#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1)
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100488#endif
489
Gilles Peskine449bd832023-01-11 14:50:10 +0100490int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
491 psa_algorithm_t mac_alg,
492 const unsigned char *add_data,
493 size_t add_data_len,
494 const unsigned char *data,
495 size_t data_len_secret,
496 size_t min_data_len,
497 size_t max_data_len,
498 unsigned char *output)
Neil Armstrong2968d302022-02-25 15:09:36 +0100499{
500 /*
Neil Armstrong28d9c632022-03-17 16:33:27 +0100501 * This function breaks the HMAC abstraction and uses psa_hash_clone()
502 * extension in order to get constant-flow behaviour.
Neil Armstrong2968d302022-02-25 15:09:36 +0100503 *
504 * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
505 * concatenation, and okey/ikey are the XOR of the key with some fixed bit
506 * patterns (see RFC 2104, sec. 2).
507 *
508 * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by
509 * hashing up to minlen, then cloning the context, and for each byte up
510 * to maxlen finishing up the hash computation, keeping only the
511 * correct result.
512 *
513 * Then we only need to compute HASH(okey + inner_hash) and we're done.
514 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg);
516 const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100517 unsigned char key_buf[MAX_HASH_BLOCK_LENGTH];
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 const size_t hash_size = PSA_HASH_LENGTH(hash_alg);
Neil Armstrong2968d302022-02-25 15:09:36 +0100519 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
520 size_t hash_length;
521
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100522 unsigned char aux_out[PSA_HASH_MAX_SIZE];
Neil Armstrong2968d302022-02-25 15:09:36 +0100523 psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT;
524 size_t offset;
525 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
526
Neil Armstrong2968d302022-02-25 15:09:36 +0100527 size_t mac_key_length;
528 size_t i;
529
Gilles Peskine449bd832023-01-11 14:50:10 +0100530#define PSA_CHK(func_call) \
Neil Armstrong2968d302022-02-25 15:09:36 +0100531 do { \
532 status = (func_call); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 if (status != PSA_SUCCESS) \
534 goto cleanup; \
535 } while (0)
Neil Armstrong2968d302022-02-25 15:09:36 +0100536
Neil Armstrong72c2f762022-03-17 16:39:10 +0100537 /* Export MAC key
538 * We assume key length is always exactly the output size
539 * which is never more than the block size, thus we use block_size
540 * as the key buffer size.
541 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length));
Neil Armstrong2968d302022-02-25 15:09:36 +0100543
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100544 /* Calculate ikey */
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 for (i = 0; i < mac_key_length; i++) {
546 key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36);
547 }
548 for (; i < block_size; ++i) {
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100549 key_buf[i] = 0x36;
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 }
Neil Armstrong2968d302022-02-25 15:09:36 +0100551
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 PSA_CHK(psa_hash_setup(&operation, hash_alg));
Neil Armstrong2968d302022-02-25 15:09:36 +0100553
554 /* Now compute inner_hash = HASH(ikey + msg) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
556 PSA_CHK(psa_hash_update(&operation, add_data, add_data_len));
557 PSA_CHK(psa_hash_update(&operation, data, min_data_len));
Neil Armstrong2968d302022-02-25 15:09:36 +0100558
Paul Elliott5260ce22022-05-09 18:15:54 +0100559 /* Fill the hash buffer in advance with something that is
560 * not a valid hash (barring an attack on the hash and
561 * deliberately-crafted input), in case the caller doesn't
562 * check the return status properly. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100563 memset(output, '!', hash_size);
Paul Elliott5260ce22022-05-09 18:15:54 +0100564
Neil Armstrong2968d302022-02-25 15:09:36 +0100565 /* For each possible length, compute the hash up to that point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100566 for (offset = min_data_len; offset <= max_data_len; offset++) {
567 PSA_CHK(psa_hash_clone(&operation, &aux_operation));
568 PSA_CHK(psa_hash_finish(&aux_operation, aux_out,
569 PSA_HASH_MAX_SIZE, &hash_length));
Neil Armstrong2968d302022-02-25 15:09:36 +0100570 /* Keep only the correct inner_hash in the output buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100571 mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
572 offset, data_len_secret);
Neil Armstrong2968d302022-02-25 15:09:36 +0100573
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 if (offset < max_data_len) {
575 PSA_CHK(psa_hash_update(&operation, data + offset, 1));
576 }
Neil Armstrong2968d302022-02-25 15:09:36 +0100577 }
578
Neil Armstrong28d9c632022-03-17 16:33:27 +0100579 /* Abort current operation to prepare for final operation */
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 PSA_CHK(psa_hash_abort(&operation));
Neil Armstrong2968d302022-02-25 15:09:36 +0100581
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100582 /* Calculate okey */
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 for (i = 0; i < mac_key_length; i++) {
584 key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C);
585 }
586 for (; i < block_size; ++i) {
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100587 key_buf[i] = 0x5C;
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 }
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100589
Neil Armstrong2968d302022-02-25 15:09:36 +0100590 /* Now compute HASH(okey + inner_hash) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 PSA_CHK(psa_hash_setup(&operation, hash_alg));
592 PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
593 PSA_CHK(psa_hash_update(&operation, output, hash_size));
594 PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length));
Neil Armstrong2968d302022-02-25 15:09:36 +0100595
596#undef PSA_CHK
597
598cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100599 mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH);
600 mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE);
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100601
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 psa_hash_abort(&operation);
603 psa_hash_abort(&aux_operation);
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500604 return PSA_TO_MBEDTLS_ERR(status);
Neil Armstrong2968d302022-02-25 15:09:36 +0100605}
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100606
607#undef MAX_HASH_BLOCK_LENGTH
608
Neil Armstrong2968d302022-02-25 15:09:36 +0100609#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100610int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
611 const unsigned char *add_data,
612 size_t add_data_len,
613 const unsigned char *data,
614 size_t data_len_secret,
615 size_t min_data_len,
616 size_t max_data_len,
617 unsigned char *output)
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200618{
619 /*
620 * This function breaks the HMAC abstraction and uses the md_clone()
621 * extension to the MD API in order to get constant-flow behaviour.
622 *
623 * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
624 * concatenation, and okey/ikey are the XOR of the key with some fixed bit
625 * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx.
626 *
627 * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to
628 * minlen, then cloning the context, and for each byte up to maxlen
629 * finishing up the hash computation, keeping only the correct result.
630 *
631 * Then we only need to compute HASH(okey + inner_hash) and we're done.
632 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info);
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200634 /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5,
635 * all of which have the same block size except SHA-384. */
636 const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;
637 const unsigned char * const ikey = ctx->hmac_ctx;
638 const unsigned char * const okey = ikey + block_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 const size_t hash_size = mbedtls_md_get_size(ctx->md_info);
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200640
641 unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];
642 mbedtls_md_context_t aux;
643 size_t offset;
644 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
645
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 mbedtls_md_init(&aux);
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200647
Gilles Peskine449bd832023-01-11 14:50:10 +0100648#define MD_CHK(func_call) \
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200649 do { \
650 ret = (func_call); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100651 if (ret != 0) \
652 goto cleanup; \
653 } while (0)
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200654
Gilles Peskine449bd832023-01-11 14:50:10 +0100655 MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200656
657 /* After hmac_start() of hmac_reset(), ikey has already been hashed,
658 * so we can start directly with the message */
Gilles Peskine449bd832023-01-11 14:50:10 +0100659 MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len));
660 MD_CHK(mbedtls_md_update(ctx, data, min_data_len));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200661
Paul Elliott5260ce22022-05-09 18:15:54 +0100662 /* Fill the hash buffer in advance with something that is
663 * not a valid hash (barring an attack on the hash and
664 * deliberately-crafted input), in case the caller doesn't
665 * check the return status properly. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 memset(output, '!', hash_size);
Paul Elliott5260ce22022-05-09 18:15:54 +0100667
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200668 /* For each possible length, compute the hash up to that point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100669 for (offset = min_data_len; offset <= max_data_len; offset++) {
670 MD_CHK(mbedtls_md_clone(&aux, ctx));
671 MD_CHK(mbedtls_md_finish(&aux, aux_out));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200672 /* Keep only the correct inner_hash in the output buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
674 offset, data_len_secret);
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200675
Gilles Peskine449bd832023-01-11 14:50:10 +0100676 if (offset < max_data_len) {
677 MD_CHK(mbedtls_md_update(ctx, data + offset, 1));
678 }
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200679 }
680
681 /* The context needs to finish() before it starts() again */
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 MD_CHK(mbedtls_md_finish(ctx, aux_out));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200683
684 /* Now compute HASH(okey + inner_hash) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100685 MD_CHK(mbedtls_md_starts(ctx));
686 MD_CHK(mbedtls_md_update(ctx, okey, block_size));
687 MD_CHK(mbedtls_md_update(ctx, output, hash_size));
688 MD_CHK(mbedtls_md_finish(ctx, output));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200689
690 /* Done, get ready for next time */
Gilles Peskine449bd832023-01-11 14:50:10 +0100691 MD_CHK(mbedtls_md_hmac_reset(ctx));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200692
693#undef MD_CHK
694
695cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100696 mbedtls_md_free(&aux);
697 return ret;
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200698}
Neil Armstrong2968d302022-02-25 15:09:36 +0100699#endif /* MBEDTLS_USE_PSA_CRYPTO */
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200700
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200701#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200702
703#if defined(MBEDTLS_BIGNUM_C)
704
Gilles Peskine449bd832023-01-11 14:50:10 +0100705#define MPI_VALIDATE_RET(cond) \
706 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200707
708/*
709 * Conditionally assign X = Y, without leaking information
710 * about whether the assignment was made or not.
711 * (Leaking information about the respective sizes of X and Y is ok however.)
712 */
Tautvydas Žilys40fc7da2022-01-31 13:34:01 -0800713#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
Tautvydas Žilys60165d72022-01-26 15:33:27 -0800714/*
Tautvydas Žilys40fc7da2022-01-31 13:34:01 -0800715 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
Tautvydas Žilys60165d72022-01-26 15:33:27 -0800716 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
717 */
718__declspec(noinline)
719#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100720int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
721 const mbedtls_mpi *Y,
722 unsigned char assign)
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200723{
724 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100725 MPI_VALIDATE_RET(X != NULL);
726 MPI_VALIDATE_RET(Y != NULL);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200727
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200728 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100729 mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(assign);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200730
Gilles Peskine449bd832023-01-11 14:50:10 +0100731 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200732
Tom Cosgrovee22413c2023-05-03 09:44:01 +0100733 X->s = (int) mbedtls_ct_uint_if(assign, Y->s, X->s);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200734
Gilles Peskine449bd832023-01-11 14:50:10 +0100735 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, assign);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200736
Gilles Peskine449bd832023-01-11 14:50:10 +0100737 for (size_t i = Y->n; i < X->n; i++) {
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200738 X->p[i] &= ~limb_mask;
Gilles Peskine449bd832023-01-11 14:50:10 +0100739 }
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200740
741cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100742 return ret;
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200743}
744
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200745/*
746 * Conditionally swap X and Y, without leaking information
747 * about whether the swap was made or not.
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800748 * Here it is not ok to simply swap the pointers, which would lead to
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200749 * different memory access patterns when X and Y are used afterwards.
750 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100751int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
752 mbedtls_mpi *Y,
753 unsigned char swap)
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200754{
Gabor Mezeid7edb1d2022-10-10 14:32:09 +0200755 int ret = 0;
756 int s;
Gilles Peskine449bd832023-01-11 14:50:10 +0100757 MPI_VALIDATE_RET(X != NULL);
758 MPI_VALIDATE_RET(Y != NULL);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200759
Gilles Peskine449bd832023-01-11 14:50:10 +0100760 if (X == Y) {
761 return 0;
762 }
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200763
Gilles Peskine449bd832023-01-11 14:50:10 +0100764 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
765 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200766
767 s = X->s;
Tom Cosgrovee22413c2023-05-03 09:44:01 +0100768 X->s = (int) mbedtls_ct_uint_if(swap, Y->s, X->s);
769 Y->s = (int) mbedtls_ct_uint_if(swap, s, Y->s);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200770
Gilles Peskine449bd832023-01-11 14:50:10 +0100771 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, swap);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200772
773cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100774 return ret;
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200775}
776
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200777/*
Janos Follath23bdeca2022-07-22 18:24:06 +0100778 * Compare unsigned values in constant time
779 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100780unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
781 const mbedtls_mpi_uint *B,
782 size_t limbs)
Janos Follath23bdeca2022-07-22 18:24:06 +0100783{
Janos Follath23bdeca2022-07-22 18:24:06 +0100784 unsigned ret, cond, done;
785
Janos Follath63184682022-08-11 17:42:59 +0100786 /* The value of any of these variables is either 0 or 1 for the rest of
787 * their scope. */
Janos Follath23bdeca2022-07-22 18:24:06 +0100788 ret = cond = done = 0;
789
Gilles Peskine449bd832023-01-11 14:50:10 +0100790 for (size_t i = limbs; i > 0; i--) {
Janos Follath23bdeca2022-07-22 18:24:06 +0100791 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100792 * If B[i - 1] < A[i - 1] then A < B is false and the result must
Janos Follath23bdeca2022-07-22 18:24:06 +0100793 * remain 0.
794 *
795 * Again even if we can make a decision, we just mark the result and
796 * the fact that we are done and continue looping.
797 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100798 cond = mbedtls_ct_mpi_uint_lt(B[i - 1], A[i - 1]);
Janos Follath23bdeca2022-07-22 18:24:06 +0100799 done |= cond;
800
801 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100802 * If A[i - 1] < B[i - 1] then A < B is true.
Janos Follath23bdeca2022-07-22 18:24:06 +0100803 *
804 * Again even if we can make a decision, we just mark the result and
805 * the fact that we are done and continue looping.
806 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100807 cond = mbedtls_ct_mpi_uint_lt(A[i - 1], B[i - 1]);
808 ret |= cond & (1 - done);
Janos Follath23bdeca2022-07-22 18:24:06 +0100809 done |= cond;
810 }
811
812 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100813 * If all the limbs were equal, then the numbers are equal, A < B is false
Janos Follath23bdeca2022-07-22 18:24:06 +0100814 * and leaving the result 0 is correct.
815 */
816
Gilles Peskine449bd832023-01-11 14:50:10 +0100817 return ret;
Janos Follath23bdeca2022-07-22 18:24:06 +0100818}
819
820/*
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200821 * Compare signed values in constant time
822 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100823int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
824 const mbedtls_mpi *Y,
825 unsigned *ret)
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200826{
827 size_t i;
828 /* The value of any of these variables is either 0 or 1 at all times. */
829 unsigned cond, done, X_is_negative, Y_is_negative;
830
Gilles Peskine449bd832023-01-11 14:50:10 +0100831 MPI_VALIDATE_RET(X != NULL);
832 MPI_VALIDATE_RET(Y != NULL);
833 MPI_VALIDATE_RET(ret != NULL);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200834
Gilles Peskine449bd832023-01-11 14:50:10 +0100835 if (X->n != Y->n) {
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200836 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100837 }
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200838
839 /*
840 * Set sign_N to 1 if N >= 0, 0 if N < 0.
841 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
842 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100843 X_is_negative = (X->s & 2) >> 1;
844 Y_is_negative = (Y->s & 2) >> 1;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200845
846 /*
847 * If the signs are different, then the positive operand is the bigger.
848 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
849 * is false if X is positive (X_is_negative == 0).
850 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100851 cond = (X_is_negative ^ Y_is_negative);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200852 *ret = cond & X_is_negative;
853
854 /*
855 * This is a constant-time function. We might have the result, but we still
856 * need to go through the loop. Record if we have the result already.
857 */
858 done = cond;
859
Gilles Peskine449bd832023-01-11 14:50:10 +0100860 for (i = X->n; i > 0; i--) {
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200861 /*
862 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
863 * X and Y are negative.
864 *
865 * Again even if we can make a decision, we just mark the result and
866 * the fact that we are done and continue looping.
867 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100868 cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]);
869 *ret |= cond & (1 - done) & X_is_negative;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200870 done |= cond;
871
872 /*
873 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
874 * X and Y are positive.
875 *
876 * Again even if we can make a decision, we just mark the result and
877 * the fact that we are done and continue looping.
878 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100879 cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]);
880 *ret |= cond & (1 - done) & (1 - X_is_negative);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200881 done |= cond;
882 }
883
Gilles Peskine449bd832023-01-11 14:50:10 +0100884 return 0;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200885}
886
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200887#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200888
889#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
890
Gilles Peskine449bd832023-01-11 14:50:10 +0100891int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
892 size_t ilen,
893 unsigned char *output,
894 size_t output_max_len,
895 size_t *olen)
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200896{
897 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
898 size_t i, plaintext_max_size;
899
900 /* The following variables take sensitive values: their value must
901 * not leak into the observable behavior of the function other than
902 * the designated outputs (output, olen, return value). Otherwise
903 * this would open the execution of the function to
904 * side-channel-based variants of the Bleichenbacher padding oracle
905 * attack. Potential side channels include overall timing, memory
906 * access patterns (especially visible to an adversary who has access
907 * to a shared memory cache), and branches (especially visible to
908 * an adversary who has access to a shared code cache or to a shared
909 * branch predictor). */
910 size_t pad_count = 0;
911 unsigned bad = 0;
912 unsigned char pad_done = 0;
913 size_t plaintext_size = 0;
914 unsigned output_too_large;
915
Gilles Peskine449bd832023-01-11 14:50:10 +0100916 plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11
Gabor Mezei7013f622021-10-18 16:12:45 +0200917 : output_max_len;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200918
919 /* Check and get padding length in constant time and constant
920 * memory trace. The first byte must be 0. */
Gabor Mezei63bbba52021-10-18 16:17:57 +0200921 bad |= input[0];
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200922
923
924 /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
Gabor Mezei63bbba52021-10-18 16:17:57 +0200925 * where PS must be at least 8 nonzero bytes. */
926 bad |= input[1] ^ MBEDTLS_RSA_CRYPT;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200927
928 /* Read the whole buffer. Set pad_done to nonzero if we find
Gabor Mezei63bbba52021-10-18 16:17:57 +0200929 * the 0x00 byte and remember the padding length in pad_count. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100930 for (i = 2; i < ilen; i++) {
931 pad_done |= ((input[i] | (unsigned char) -input[i]) >> 7) ^ 1;
932 pad_count += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200933 }
934
935
936 /* If pad_done is still zero, there's no data, only unfinished padding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100937 bad |= mbedtls_ct_uint_if(pad_done, 0, 1);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200938
939 /* There must be at least 8 bytes of padding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100940 bad |= mbedtls_ct_size_gt(8, pad_count);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200941
942 /* If the padding is valid, set plaintext_size to the number of
943 * remaining bytes after stripping the padding. If the padding
944 * is invalid, avoid leaking this fact through the size of the
945 * output: use the maximum message size that fits in the output
946 * buffer. Do it without branches to avoid leaking the padding
947 * validity through timing. RSA keys are small enough that all the
948 * size_t values involved fit in unsigned int. */
Gabor Mezei90437e32021-10-20 11:59:27 +0200949 plaintext_size = mbedtls_ct_uint_if(
Gilles Peskine449bd832023-01-11 14:50:10 +0100950 bad, (unsigned) plaintext_max_size,
951 (unsigned) (ilen - pad_count - 3));
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200952
953 /* Set output_too_large to 0 if the plaintext fits in the output
954 * buffer and to 1 otherwise. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100955 output_too_large = mbedtls_ct_size_gt(plaintext_size,
956 plaintext_max_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200957
958 /* Set ret without branches to avoid timing attacks. Return:
959 * - INVALID_PADDING if the padding is bad (bad != 0).
960 * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
961 * plaintext does not fit in the output buffer.
962 * - 0 if the padding is correct. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100963 ret = -(int) mbedtls_ct_uint_if(
964 bad, -MBEDTLS_ERR_RSA_INVALID_PADDING,
965 mbedtls_ct_uint_if(output_too_large,
966 -MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
967 0));
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200968
969 /* If the padding is bad or the plaintext is too large, zero the
970 * data that we're about to copy to the output buffer.
971 * We need to copy the same amount of data
972 * from the same buffer whether the padding is good or not to
973 * avoid leaking the padding validity through overall timing or
974 * through memory or cache access patterns. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100975 bad = mbedtls_ct_uint_mask(bad | output_too_large);
976 for (i = 11; i < ilen; i++) {
Gabor Mezei63bbba52021-10-18 16:17:57 +0200977 input[i] &= ~bad;
Gilles Peskine449bd832023-01-11 14:50:10 +0100978 }
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200979
980 /* If the plaintext is too large, truncate it to the buffer size.
981 * Copy anyway to avoid revealing the length through timing, because
982 * revealing the length is as bad as revealing the padding validity
983 * for a Bleichenbacher attack. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100984 plaintext_size = mbedtls_ct_uint_if(output_too_large,
985 (unsigned) plaintext_max_size,
986 (unsigned) plaintext_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200987
988 /* Move the plaintext to the leftmost position where it can start in
989 * the working buffer, i.e. make it start plaintext_max_size from
990 * the end of the buffer. Do this with a memory access trace that
991 * does not depend on the plaintext size. After this move, the
992 * starting location of the plaintext is no longer sensitive
993 * information. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100994 mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size,
995 plaintext_max_size,
996 plaintext_max_size - plaintext_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200997
998 /* Finally copy the decrypted plaintext plus trailing zeros into the output
999 * buffer. If output_max_len is 0, then output may be an invalid pointer
1000 * and the result of memcpy() would be undefined; prevent undefined
1001 * behavior making sure to depend only on output_max_len (the size of the
1002 * user-provided output buffer), which is independent from plaintext
1003 * length, validity of padding, success of the decryption, and other
1004 * secrets. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001005 if (output_max_len != 0) {
1006 memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);
1007 }
gabor-mezei-armfdb71182021-09-27 16:11:12 +02001008
1009 /* Report the amount of data we copied to the output buffer. In case
1010 * of errors (bad padding or output too large), the value of *olen
1011 * when this function returns is not specified. Making it equivalent
1012 * to the good case limits the risks of leaking the padding validity. */
1013 *olen = plaintext_size;
1014
Gilles Peskine449bd832023-01-11 14:50:10 +01001015 return ret;
gabor-mezei-armfdb71182021-09-27 16:11:12 +02001016}
1017
1018#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */