blob: 1f6c2ca020fc3f1649903477458a94fbbb3dc773 [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
Neil Armstrong2968d302022-02-25 15:09:36 +0100434#if defined(MBEDTLS_USE_PSA_CRYPTO)
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100435
436#if defined(PSA_WANT_ALG_SHA_384)
Gilles Peskine449bd832023-01-11 14:50:10 +0100437#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384)
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100438#elif defined(PSA_WANT_ALG_SHA_256)
Gilles Peskine449bd832023-01-11 14:50:10 +0100439#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256)
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100440#else /* See check_config.h */
Gilles Peskine449bd832023-01-11 14:50:10 +0100441#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1)
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100442#endif
443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
445 psa_algorithm_t mac_alg,
446 const unsigned char *add_data,
447 size_t add_data_len,
448 const unsigned char *data,
449 size_t data_len_secret,
450 size_t min_data_len,
451 size_t max_data_len,
452 unsigned char *output)
Neil Armstrong2968d302022-02-25 15:09:36 +0100453{
454 /*
Neil Armstrong28d9c632022-03-17 16:33:27 +0100455 * This function breaks the HMAC abstraction and uses psa_hash_clone()
456 * extension in order to get constant-flow behaviour.
Neil Armstrong2968d302022-02-25 15:09:36 +0100457 *
458 * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
459 * concatenation, and okey/ikey are the XOR of the key with some fixed bit
460 * patterns (see RFC 2104, sec. 2).
461 *
462 * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by
463 * hashing up to minlen, then cloning the context, and for each byte up
464 * to maxlen finishing up the hash computation, keeping only the
465 * correct result.
466 *
467 * Then we only need to compute HASH(okey + inner_hash) and we're done.
468 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg);
470 const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100471 unsigned char key_buf[MAX_HASH_BLOCK_LENGTH];
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 const size_t hash_size = PSA_HASH_LENGTH(hash_alg);
Neil Armstrong2968d302022-02-25 15:09:36 +0100473 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
474 size_t hash_length;
475
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100476 unsigned char aux_out[PSA_HASH_MAX_SIZE];
Neil Armstrong2968d302022-02-25 15:09:36 +0100477 psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT;
478 size_t offset;
479 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
480
Neil Armstrong2968d302022-02-25 15:09:36 +0100481 size_t mac_key_length;
482 size_t i;
483
Gilles Peskine449bd832023-01-11 14:50:10 +0100484#define PSA_CHK(func_call) \
Neil Armstrong2968d302022-02-25 15:09:36 +0100485 do { \
486 status = (func_call); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100487 if (status != PSA_SUCCESS) \
488 goto cleanup; \
489 } while (0)
Neil Armstrong2968d302022-02-25 15:09:36 +0100490
Neil Armstrong72c2f762022-03-17 16:39:10 +0100491 /* Export MAC key
492 * We assume key length is always exactly the output size
493 * which is never more than the block size, thus we use block_size
494 * as the key buffer size.
495 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length));
Neil Armstrong2968d302022-02-25 15:09:36 +0100497
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100498 /* Calculate ikey */
Gilles Peskine449bd832023-01-11 14:50:10 +0100499 for (i = 0; i < mac_key_length; i++) {
500 key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36);
501 }
502 for (; i < block_size; ++i) {
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100503 key_buf[i] = 0x36;
Gilles Peskine449bd832023-01-11 14:50:10 +0100504 }
Neil Armstrong2968d302022-02-25 15:09:36 +0100505
Gilles Peskine449bd832023-01-11 14:50:10 +0100506 PSA_CHK(psa_hash_setup(&operation, hash_alg));
Neil Armstrong2968d302022-02-25 15:09:36 +0100507
508 /* Now compute inner_hash = HASH(ikey + msg) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
510 PSA_CHK(psa_hash_update(&operation, add_data, add_data_len));
511 PSA_CHK(psa_hash_update(&operation, data, min_data_len));
Neil Armstrong2968d302022-02-25 15:09:36 +0100512
Paul Elliott5260ce22022-05-09 18:15:54 +0100513 /* Fill the hash buffer in advance with something that is
514 * not a valid hash (barring an attack on the hash and
515 * deliberately-crafted input), in case the caller doesn't
516 * check the return status properly. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 memset(output, '!', hash_size);
Paul Elliott5260ce22022-05-09 18:15:54 +0100518
Neil Armstrong2968d302022-02-25 15:09:36 +0100519 /* For each possible length, compute the hash up to that point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 for (offset = min_data_len; offset <= max_data_len; offset++) {
521 PSA_CHK(psa_hash_clone(&operation, &aux_operation));
522 PSA_CHK(psa_hash_finish(&aux_operation, aux_out,
523 PSA_HASH_MAX_SIZE, &hash_length));
Neil Armstrong2968d302022-02-25 15:09:36 +0100524 /* Keep only the correct inner_hash in the output buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
526 offset, data_len_secret);
Neil Armstrong2968d302022-02-25 15:09:36 +0100527
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 if (offset < max_data_len) {
529 PSA_CHK(psa_hash_update(&operation, data + offset, 1));
530 }
Neil Armstrong2968d302022-02-25 15:09:36 +0100531 }
532
Neil Armstrong28d9c632022-03-17 16:33:27 +0100533 /* Abort current operation to prepare for final operation */
Gilles Peskine449bd832023-01-11 14:50:10 +0100534 PSA_CHK(psa_hash_abort(&operation));
Neil Armstrong2968d302022-02-25 15:09:36 +0100535
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100536 /* Calculate okey */
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 for (i = 0; i < mac_key_length; i++) {
538 key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C);
539 }
540 for (; i < block_size; ++i) {
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100541 key_buf[i] = 0x5C;
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 }
Neil Armstrong9ebb9ff2022-03-17 17:04:37 +0100543
Neil Armstrong2968d302022-02-25 15:09:36 +0100544 /* Now compute HASH(okey + inner_hash) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 PSA_CHK(psa_hash_setup(&operation, hash_alg));
546 PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
547 PSA_CHK(psa_hash_update(&operation, output, hash_size));
548 PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length));
Neil Armstrong2968d302022-02-25 15:09:36 +0100549
550#undef PSA_CHK
551
552cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH);
554 mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE);
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100555
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 psa_hash_abort(&operation);
557 psa_hash_abort(&aux_operation);
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500558 return PSA_TO_MBEDTLS_ERR(status);
Neil Armstrong2968d302022-02-25 15:09:36 +0100559}
Neil Armstrong36cc13b2022-03-17 16:36:52 +0100560
561#undef MAX_HASH_BLOCK_LENGTH
562
Neil Armstrong2968d302022-02-25 15:09:36 +0100563#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100564int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
565 const unsigned char *add_data,
566 size_t add_data_len,
567 const unsigned char *data,
568 size_t data_len_secret,
569 size_t min_data_len,
570 size_t max_data_len,
571 unsigned char *output)
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200572{
573 /*
574 * This function breaks the HMAC abstraction and uses the md_clone()
575 * extension to the MD API in order to get constant-flow behaviour.
576 *
577 * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
578 * concatenation, and okey/ikey are the XOR of the key with some fixed bit
579 * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx.
580 *
581 * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to
582 * minlen, then cloning the context, and for each byte up to maxlen
583 * finishing up the hash computation, keeping only the correct result.
584 *
585 * Then we only need to compute HASH(okey + inner_hash) and we're done.
586 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100587 const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info);
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200588 /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5,
589 * all of which have the same block size except SHA-384. */
590 const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;
591 const unsigned char * const ikey = ctx->hmac_ctx;
592 const unsigned char * const okey = ikey + block_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 const size_t hash_size = mbedtls_md_get_size(ctx->md_info);
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200594
595 unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];
596 mbedtls_md_context_t aux;
597 size_t offset;
598 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
599
Gilles Peskine449bd832023-01-11 14:50:10 +0100600 mbedtls_md_init(&aux);
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200601
Gilles Peskine449bd832023-01-11 14:50:10 +0100602#define MD_CHK(func_call) \
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200603 do { \
604 ret = (func_call); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100605 if (ret != 0) \
606 goto cleanup; \
607 } while (0)
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200608
Gilles Peskine449bd832023-01-11 14:50:10 +0100609 MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200610
611 /* After hmac_start() of hmac_reset(), ikey has already been hashed,
612 * so we can start directly with the message */
Gilles Peskine449bd832023-01-11 14:50:10 +0100613 MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len));
614 MD_CHK(mbedtls_md_update(ctx, data, min_data_len));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200615
Paul Elliott5260ce22022-05-09 18:15:54 +0100616 /* Fill the hash buffer in advance with something that is
617 * not a valid hash (barring an attack on the hash and
618 * deliberately-crafted input), in case the caller doesn't
619 * check the return status properly. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100620 memset(output, '!', hash_size);
Paul Elliott5260ce22022-05-09 18:15:54 +0100621
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200622 /* For each possible length, compute the hash up to that point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 for (offset = min_data_len; offset <= max_data_len; offset++) {
624 MD_CHK(mbedtls_md_clone(&aux, ctx));
625 MD_CHK(mbedtls_md_finish(&aux, aux_out));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200626 /* Keep only the correct inner_hash in the output buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100627 mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
628 offset, data_len_secret);
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200629
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 if (offset < max_data_len) {
631 MD_CHK(mbedtls_md_update(ctx, data + offset, 1));
632 }
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200633 }
634
635 /* The context needs to finish() before it starts() again */
Gilles Peskine449bd832023-01-11 14:50:10 +0100636 MD_CHK(mbedtls_md_finish(ctx, aux_out));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200637
638 /* Now compute HASH(okey + inner_hash) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 MD_CHK(mbedtls_md_starts(ctx));
640 MD_CHK(mbedtls_md_update(ctx, okey, block_size));
641 MD_CHK(mbedtls_md_update(ctx, output, hash_size));
642 MD_CHK(mbedtls_md_finish(ctx, output));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200643
644 /* Done, get ready for next time */
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 MD_CHK(mbedtls_md_hmac_reset(ctx));
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200646
647#undef MD_CHK
648
649cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 mbedtls_md_free(&aux);
651 return ret;
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200652}
Neil Armstrong2968d302022-02-25 15:09:36 +0100653#endif /* MBEDTLS_USE_PSA_CRYPTO */
gabor-mezei-arm1349ffd2021-09-27 14:28:31 +0200654
Przemek Stekiel89ad6232022-09-27 13:36:12 +0200655#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200656
657#if defined(MBEDTLS_BIGNUM_C)
658
Gilles Peskine449bd832023-01-11 14:50:10 +0100659#define MPI_VALIDATE_RET(cond) \
660 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200661
662/*
663 * Conditionally assign X = Y, without leaking information
664 * about whether the assignment was made or not.
665 * (Leaking information about the respective sizes of X and Y is ok however.)
666 */
Tautvydas Žilys40fc7da2022-01-31 13:34:01 -0800667#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
Tautvydas Žilys60165d72022-01-26 15:33:27 -0800668/*
Tautvydas Žilys40fc7da2022-01-31 13:34:01 -0800669 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
Tautvydas Žilys60165d72022-01-26 15:33:27 -0800670 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
671 */
672__declspec(noinline)
673#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100674int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
675 const mbedtls_mpi *Y,
676 unsigned char assign)
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200677{
678 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 MPI_VALIDATE_RET(X != NULL);
680 MPI_VALIDATE_RET(Y != NULL);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200681
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200682 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(assign);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200684
Gilles Peskine449bd832023-01-11 14:50:10 +0100685 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200686
Tom Cosgrovee22413c2023-05-03 09:44:01 +0100687 X->s = (int) mbedtls_ct_uint_if(assign, Y->s, X->s);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200688
Gilles Peskine449bd832023-01-11 14:50:10 +0100689 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, assign);
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200690
Gilles Peskine449bd832023-01-11 14:50:10 +0100691 for (size_t i = Y->n; i < X->n; i++) {
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200692 X->p[i] &= ~limb_mask;
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 }
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200694
695cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100696 return ret;
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200697}
698
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200699/*
700 * Conditionally swap X and Y, without leaking information
701 * about whether the swap was made or not.
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800702 * Here it is not ok to simply swap the pointers, which would lead to
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200703 * different memory access patterns when X and Y are used afterwards.
704 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100705int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
706 mbedtls_mpi *Y,
707 unsigned char swap)
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200708{
Gabor Mezeid7edb1d2022-10-10 14:32:09 +0200709 int ret = 0;
710 int s;
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 MPI_VALIDATE_RET(X != NULL);
712 MPI_VALIDATE_RET(Y != NULL);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200713
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 if (X == Y) {
715 return 0;
716 }
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200717
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
719 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200720
721 s = X->s;
Tom Cosgrovee22413c2023-05-03 09:44:01 +0100722 X->s = (int) mbedtls_ct_uint_if(swap, Y->s, X->s);
723 Y->s = (int) mbedtls_ct_uint_if(swap, s, Y->s);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200724
Gilles Peskine449bd832023-01-11 14:50:10 +0100725 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, swap);
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200726
727cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 return ret;
gabor-mezei-arm5c976212021-09-27 15:37:50 +0200729}
730
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200731/*
Janos Follath23bdeca2022-07-22 18:24:06 +0100732 * Compare unsigned values in constant time
733 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100734unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
735 const mbedtls_mpi_uint *B,
736 size_t limbs)
Janos Follath23bdeca2022-07-22 18:24:06 +0100737{
Janos Follath23bdeca2022-07-22 18:24:06 +0100738 unsigned ret, cond, done;
739
Janos Follath63184682022-08-11 17:42:59 +0100740 /* The value of any of these variables is either 0 or 1 for the rest of
741 * their scope. */
Janos Follath23bdeca2022-07-22 18:24:06 +0100742 ret = cond = done = 0;
743
Gilles Peskine449bd832023-01-11 14:50:10 +0100744 for (size_t i = limbs; i > 0; i--) {
Janos Follath23bdeca2022-07-22 18:24:06 +0100745 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100746 * If B[i - 1] < A[i - 1] then A < B is false and the result must
Janos Follath23bdeca2022-07-22 18:24:06 +0100747 * remain 0.
748 *
749 * Again even if we can make a decision, we just mark the result and
750 * the fact that we are done and continue looping.
751 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100752 cond = mbedtls_ct_mpi_uint_lt(B[i - 1], A[i - 1]);
Janos Follath23bdeca2022-07-22 18:24:06 +0100753 done |= cond;
754
755 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100756 * If A[i - 1] < B[i - 1] then A < B is true.
Janos Follath23bdeca2022-07-22 18:24:06 +0100757 *
758 * Again even if we can make a decision, we just mark the result and
759 * the fact that we are done and continue looping.
760 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100761 cond = mbedtls_ct_mpi_uint_lt(A[i - 1], B[i - 1]);
762 ret |= cond & (1 - done);
Janos Follath23bdeca2022-07-22 18:24:06 +0100763 done |= cond;
764 }
765
766 /*
Janos Follathb7a88ec2022-08-19 12:24:40 +0100767 * If all the limbs were equal, then the numbers are equal, A < B is false
Janos Follath23bdeca2022-07-22 18:24:06 +0100768 * and leaving the result 0 is correct.
769 */
770
Gilles Peskine449bd832023-01-11 14:50:10 +0100771 return ret;
Janos Follath23bdeca2022-07-22 18:24:06 +0100772}
773
774/*
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200775 * Compare signed values in constant time
776 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100777int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
778 const mbedtls_mpi *Y,
779 unsigned *ret)
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200780{
781 size_t i;
782 /* The value of any of these variables is either 0 or 1 at all times. */
783 unsigned cond, done, X_is_negative, Y_is_negative;
784
Gilles Peskine449bd832023-01-11 14:50:10 +0100785 MPI_VALIDATE_RET(X != NULL);
786 MPI_VALIDATE_RET(Y != NULL);
787 MPI_VALIDATE_RET(ret != NULL);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200788
Gilles Peskine449bd832023-01-11 14:50:10 +0100789 if (X->n != Y->n) {
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200790 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100791 }
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200792
793 /*
794 * Set sign_N to 1 if N >= 0, 0 if N < 0.
795 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
796 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100797 X_is_negative = (X->s & 2) >> 1;
798 Y_is_negative = (Y->s & 2) >> 1;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200799
800 /*
801 * If the signs are different, then the positive operand is the bigger.
802 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
803 * is false if X is positive (X_is_negative == 0).
804 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100805 cond = (X_is_negative ^ Y_is_negative);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200806 *ret = cond & X_is_negative;
807
808 /*
809 * This is a constant-time function. We might have the result, but we still
810 * need to go through the loop. Record if we have the result already.
811 */
812 done = cond;
813
Gilles Peskine449bd832023-01-11 14:50:10 +0100814 for (i = X->n; i > 0; i--) {
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200815 /*
816 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
817 * X and Y are negative.
818 *
819 * Again even if we can make a decision, we just mark the result and
820 * the fact that we are done and continue looping.
821 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100822 cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]);
823 *ret |= cond & (1 - done) & X_is_negative;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200824 done |= cond;
825
826 /*
827 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
828 * X and Y are positive.
829 *
830 * Again even if we can make a decision, we just mark the result and
831 * the fact that we are done and continue looping.
832 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100833 cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]);
834 *ret |= cond & (1 - done) & (1 - X_is_negative);
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200835 done |= cond;
836 }
837
Gilles Peskine449bd832023-01-11 14:50:10 +0100838 return 0;
gabor-mezei-armc29a3da2021-09-27 15:41:30 +0200839}
840
gabor-mezei-arm40a49252021-09-27 15:33:35 +0200841#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200842
843#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
844
Gilles Peskine449bd832023-01-11 14:50:10 +0100845int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
846 size_t ilen,
847 unsigned char *output,
848 size_t output_max_len,
849 size_t *olen)
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200850{
851 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
852 size_t i, plaintext_max_size;
853
854 /* The following variables take sensitive values: their value must
855 * not leak into the observable behavior of the function other than
856 * the designated outputs (output, olen, return value). Otherwise
857 * this would open the execution of the function to
858 * side-channel-based variants of the Bleichenbacher padding oracle
859 * attack. Potential side channels include overall timing, memory
860 * access patterns (especially visible to an adversary who has access
861 * to a shared memory cache), and branches (especially visible to
862 * an adversary who has access to a shared code cache or to a shared
863 * branch predictor). */
864 size_t pad_count = 0;
865 unsigned bad = 0;
866 unsigned char pad_done = 0;
867 size_t plaintext_size = 0;
868 unsigned output_too_large;
869
Gilles Peskine449bd832023-01-11 14:50:10 +0100870 plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11
Gabor Mezei7013f622021-10-18 16:12:45 +0200871 : output_max_len;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200872
873 /* Check and get padding length in constant time and constant
874 * memory trace. The first byte must be 0. */
Gabor Mezei63bbba52021-10-18 16:17:57 +0200875 bad |= input[0];
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200876
877
878 /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
Gabor Mezei63bbba52021-10-18 16:17:57 +0200879 * where PS must be at least 8 nonzero bytes. */
880 bad |= input[1] ^ MBEDTLS_RSA_CRYPT;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200881
882 /* Read the whole buffer. Set pad_done to nonzero if we find
Gabor Mezei63bbba52021-10-18 16:17:57 +0200883 * the 0x00 byte and remember the padding length in pad_count. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100884 for (i = 2; i < ilen; i++) {
885 pad_done |= ((input[i] | (unsigned char) -input[i]) >> 7) ^ 1;
886 pad_count += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200887 }
888
889
890 /* If pad_done is still zero, there's no data, only unfinished padding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100891 bad |= mbedtls_ct_uint_if(pad_done, 0, 1);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200892
893 /* There must be at least 8 bytes of padding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100894 bad |= mbedtls_ct_size_gt(8, pad_count);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200895
896 /* If the padding is valid, set plaintext_size to the number of
897 * remaining bytes after stripping the padding. If the padding
898 * is invalid, avoid leaking this fact through the size of the
899 * output: use the maximum message size that fits in the output
900 * buffer. Do it without branches to avoid leaking the padding
901 * validity through timing. RSA keys are small enough that all the
902 * size_t values involved fit in unsigned int. */
Gabor Mezei90437e32021-10-20 11:59:27 +0200903 plaintext_size = mbedtls_ct_uint_if(
Gilles Peskine449bd832023-01-11 14:50:10 +0100904 bad, (unsigned) plaintext_max_size,
905 (unsigned) (ilen - pad_count - 3));
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200906
907 /* Set output_too_large to 0 if the plaintext fits in the output
908 * buffer and to 1 otherwise. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100909 output_too_large = mbedtls_ct_size_gt(plaintext_size,
910 plaintext_max_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200911
912 /* Set ret without branches to avoid timing attacks. Return:
913 * - INVALID_PADDING if the padding is bad (bad != 0).
914 * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
915 * plaintext does not fit in the output buffer.
916 * - 0 if the padding is correct. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100917 ret = -(int) mbedtls_ct_uint_if(
918 bad, -MBEDTLS_ERR_RSA_INVALID_PADDING,
919 mbedtls_ct_uint_if(output_too_large,
920 -MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
921 0));
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200922
923 /* If the padding is bad or the plaintext is too large, zero the
924 * data that we're about to copy to the output buffer.
925 * We need to copy the same amount of data
926 * from the same buffer whether the padding is good or not to
927 * avoid leaking the padding validity through overall timing or
928 * through memory or cache access patterns. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100929 bad = mbedtls_ct_uint_mask(bad | output_too_large);
930 for (i = 11; i < ilen; i++) {
Gabor Mezei63bbba52021-10-18 16:17:57 +0200931 input[i] &= ~bad;
Gilles Peskine449bd832023-01-11 14:50:10 +0100932 }
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200933
934 /* If the plaintext is too large, truncate it to the buffer size.
935 * Copy anyway to avoid revealing the length through timing, because
936 * revealing the length is as bad as revealing the padding validity
937 * for a Bleichenbacher attack. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100938 plaintext_size = mbedtls_ct_uint_if(output_too_large,
939 (unsigned) plaintext_max_size,
940 (unsigned) plaintext_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200941
942 /* Move the plaintext to the leftmost position where it can start in
943 * the working buffer, i.e. make it start plaintext_max_size from
944 * the end of the buffer. Do this with a memory access trace that
945 * does not depend on the plaintext size. After this move, the
946 * starting location of the plaintext is no longer sensitive
947 * information. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100948 mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size,
949 plaintext_max_size,
950 plaintext_max_size - plaintext_size);
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200951
952 /* Finally copy the decrypted plaintext plus trailing zeros into the output
953 * buffer. If output_max_len is 0, then output may be an invalid pointer
954 * and the result of memcpy() would be undefined; prevent undefined
955 * behavior making sure to depend only on output_max_len (the size of the
956 * user-provided output buffer), which is independent from plaintext
957 * length, validity of padding, success of the decryption, and other
958 * secrets. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100959 if (output_max_len != 0) {
960 memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);
961 }
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200962
963 /* Report the amount of data we copied to the output buffer. In case
964 * of errors (bad padding or output too large), the value of *olen
965 * when this function returns is not specified. Making it equivalent
966 * to the good case limits the risks of leaking the padding validity. */
967 *olen = plaintext_size;
968
Gilles Peskine449bd832023-01-11 14:50:10 +0100969 return ret;
gabor-mezei-armfdb71182021-09-27 16:11:12 +0200970}
971
972#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */