blob: 2307ed53b50ec049726b1da779f3d84e571cb2d0 [file] [log] [blame]
gabor-mezei-arm90559722021-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 Peskine1b6c09a2023-01-11 14:52:35 +010020/*
Gabor Mezeidbe0f892021-11-03 16:13:32 +010021 * The following functions are implemented without using comparison operators, as those
Gabor Mezei3c38b6e2021-10-18 16:09:41 +020022 * might be translated to branches by some compilers on some platforms.
23 */
24
gabor-mezei-arm90559722021-07-12 16:31:22 +020025#include "common.h"
Gabor Mezeic0ae1cf2021-10-20 12:09:35 +020026#include "constant_time_internal.h"
Gabor Mezeie24dea82021-10-19 12:22:25 +020027#include "mbedtls/constant_time.h"
gabor-mezei-armcb4317b2021-09-27 14:28:31 +020028#include "mbedtls/error.h"
gabor-mezei-armd5a392a2021-09-29 10:50:31 +020029#include "mbedtls/platform_util.h"
gabor-mezei-arm944c1072021-09-27 11:28:54 +020030
gabor-mezei-arm097d4f52021-09-27 12:55:33 +020031#if defined(MBEDTLS_BIGNUM_C)
32#include "mbedtls/bignum.h"
33#endif
34
gabor-mezei-armcb4317b2021-09-27 14:28:31 +020035#if defined(MBEDTLS_SSL_TLS_C)
36#include "mbedtls/ssl_internal.h"
37#endif
38
gabor-mezei-armd5a392a2021-09-29 10:50:31 +020039#if defined(MBEDTLS_RSA_C)
40#include "mbedtls/rsa.h"
41#endif
42
Gabor Mezei46f79c32021-11-15 16:13:01 +010043#if defined(MBEDTLS_BASE64_C)
44#include "constant_time_invasive.h"
45#endif
46
gabor-mezei-armf52941e2021-09-27 16:11:12 +020047#include <string.h>
gabor-mezei-arm097d4f52021-09-27 12:55:33 +020048
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010049int mbedtls_ct_memcmp(const void *a,
50 const void *b,
51 size_t n)
gabor-mezei-arm944c1072021-09-27 11:28:54 +020052{
53 size_t i;
54 volatile const unsigned char *A = (volatile const unsigned char *) a;
55 volatile const unsigned char *B = (volatile const unsigned char *) b;
56 volatile unsigned char diff = 0;
57
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010058 for (i = 0; i < n; i++) {
gabor-mezei-arm944c1072021-09-27 11:28:54 +020059 /* Read volatile data in order before computing diff.
60 * This avoids IAR compiler warning:
61 * 'the order of volatile accesses is undefined ..' */
62 unsigned char x = A[i], y = B[i];
63 diff |= x ^ y;
64 }
65
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010066 return (int) diff;
gabor-mezei-arm944c1072021-09-27 11:28:54 +020067}
68
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010069unsigned mbedtls_ct_uint_mask(unsigned value)
gabor-mezei-armc11cac92021-09-27 11:40:03 +020070{
71 /* MSVC has a warning about unary minus on unsigned, but this is
72 * well-defined and precisely what we want to do here */
73#if defined(_MSC_VER)
74#pragma warning( push )
75#pragma warning( disable : 4146 )
76#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010077 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-armc11cac92021-09-27 11:40:03 +020078#if defined(_MSC_VER)
79#pragma warning( pop )
80#endif
81}
gabor-mezei-armd361ccd2021-09-27 11:49:42 +020082
Dave Rodgman1924adb2023-09-20 17:22:00 +010083#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || \
84 defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC)
Gabor Mezei61bf64f2021-10-20 11:17:43 +020085
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010086size_t mbedtls_ct_size_mask(size_t value)
gabor-mezei-armd361ccd2021-09-27 11:49:42 +020087{
88 /* MSVC has a warning about unary minus on unsigned integer types,
89 * but this is well-defined and precisely what we want to do here. */
90#if defined(_MSC_VER)
91#pragma warning( push )
92#pragma warning( disable : 4146 )
93#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010094 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-armd361ccd2021-09-27 11:49:42 +020095#if defined(_MSC_VER)
96#pragma warning( pop )
97#endif
98}
gabor-mezei-arm4d6b1462021-09-27 11:53:54 +020099
Dave Rodgman1924adb2023-09-20 17:22:00 +0100100#endif /* defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) ||
101 defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) */
Gabor Mezei61bf64f2021-10-20 11:17:43 +0200102
gabor-mezei-arm60febd52021-08-11 15:07:02 +0200103#if defined(MBEDTLS_BIGNUM_C)
104
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100105mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value)
gabor-mezei-arm60febd52021-08-11 15:07:02 +0200106{
107 /* MSVC has a warning about unary minus on unsigned, but this is
108 * well-defined and precisely what we want to do here */
109#if defined(_MSC_VER)
110#pragma warning( push )
111#pragma warning( disable : 4146 )
112#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100113 return -((value | -value) >> (sizeof(value) * 8 - 1));
gabor-mezei-arm60febd52021-08-11 15:07:02 +0200114#if defined(_MSC_VER)
115#pragma warning( pop )
116#endif
117}
118
119#endif /* MBEDTLS_BIGNUM_C */
120
Dave Rodgman1d523682023-09-20 16:26:49 +0100121#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || \
Dave Rodgman1924adb2023-09-20 17:22:00 +0100122 defined(MBEDTLS_CIPHER_MODE_CBC)
Gabor Mezei2b358802021-10-18 17:05:06 +0200123
Gabor Mezei2c5ed222021-10-18 16:05:50 +0200124/** Constant-flow mask generation for "less than" comparison:
125 * - if \p x < \p y, return all-bits 1, that is (size_t) -1
126 * - otherwise, return all bits 0, that is 0
127 *
128 * This function can be used to write constant-time code by replacing branches
129 * with bit operations using masks.
130 *
131 * \param x The first value to analyze.
132 * \param y The second value to analyze.
133 *
134 * \return All-bits-one if \p x is less than \p y, otherwise zero.
135 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100136static size_t mbedtls_ct_size_mask_lt(size_t x,
137 size_t y)
gabor-mezei-arm4d6b1462021-09-27 11:53:54 +0200138{
139 /* This has the most significant bit set if and only if x < y */
140 const size_t sub = x - y;
141
142 /* sub1 = (x < y) ? 1 : 0 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100143 const size_t sub1 = sub >> (sizeof(sub) * 8 - 1);
gabor-mezei-arm4d6b1462021-09-27 11:53:54 +0200144
145 /* mask = (x < y) ? 0xff... : 0x00... */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100146 const size_t mask = mbedtls_ct_size_mask(sub1);
gabor-mezei-arm4d6b1462021-09-27 11:53:54 +0200147
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100148 return mask;
gabor-mezei-arm4d6b1462021-09-27 11:53:54 +0200149}
gabor-mezei-arma2bcabc2021-09-27 11:58:31 +0200150
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151size_t mbedtls_ct_size_mask_ge(size_t x,
152 size_t y)
gabor-mezei-arma2bcabc2021-09-27 11:58:31 +0200153{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100154 return ~mbedtls_ct_size_mask_lt(x, y);
gabor-mezei-arma2bcabc2021-09-27 11:58:31 +0200155}
gabor-mezei-arm96584dd2021-09-27 12:15:19 +0200156
Dave Rodgman1d523682023-09-20 16:26:49 +0100157#endif /* defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) ||
Dave Rodgman1924adb2023-09-20 17:22:00 +0100158 defined(MBEDTLS_CIPHER_MODE_CBC) */
Gabor Mezei2b358802021-10-18 17:05:06 +0200159
Gabor Mezei46f79c32021-11-15 16:13:01 +0100160#if defined(MBEDTLS_BASE64_C)
161
162/* Return 0xff if low <= c <= high, 0 otherwise.
163 *
164 * Constant flow with respect to c.
165 */
Gabor Mezeidf293322021-11-26 17:20:36 +0100166MBEDTLS_STATIC_TESTABLE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100167unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low,
168 unsigned char high,
169 unsigned char c)
Gabor Mezei46f79c32021-11-15 16:13:01 +0100170{
171 /* low_mask is: 0 if low <= c, 0x...ff if low > c */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100172 unsigned low_mask = ((unsigned) c - low) >> 8;
Gabor Mezei46f79c32021-11-15 16:13:01 +0100173 /* high_mask is: 0 if c <= high, 0x...ff if c > high */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100174 unsigned high_mask = ((unsigned) high - c) >> 8;
175 return ~(low_mask | high_mask) & 0xff;
Gabor Mezei46f79c32021-11-15 16:13:01 +0100176}
177
178#endif /* MBEDTLS_BASE64_C */
179
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180unsigned mbedtls_ct_size_bool_eq(size_t x,
181 size_t y)
gabor-mezei-arm96584dd2021-09-27 12:15:19 +0200182{
183 /* diff = 0 if x == y, non-zero otherwise */
184 const size_t diff = x ^ y;
185
186 /* MSVC has a warning about unary minus on unsigned integer types,
187 * but this is well-defined and precisely what we want to do here. */
188#if defined(_MSC_VER)
189#pragma warning( push )
190#pragma warning( disable : 4146 )
191#endif
192
193 /* diff_msb's most significant bit is equal to x != y */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194 const size_t diff_msb = (diff | (size_t) -diff);
gabor-mezei-arm96584dd2021-09-27 12:15:19 +0200195
196#if defined(_MSC_VER)
197#pragma warning( pop )
198#endif
199
200 /* diff1 = (x != y) ? 1 : 0 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100201 const unsigned diff1 = diff_msb >> (sizeof(diff_msb) * 8 - 1);
gabor-mezei-arm96584dd2021-09-27 12:15:19 +0200202
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 return 1 ^ diff1;
gabor-mezei-arm96584dd2021-09-27 12:15:19 +0200204}
gabor-mezei-arm9d7bf092021-09-27 12:25:07 +0200205
Gabor Mezei2b358802021-10-18 17:05:06 +0200206#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
207
Gabor Mezeifd8a42d2021-10-18 16:35:23 +0200208/** Constant-flow "greater than" comparison:
209 * return x > y
210 *
211 * This is equivalent to \p x > \p y, but is likely to be compiled
212 * to code using bitwise operation rather than a branch.
213 *
214 * \param x The first value to analyze.
215 * \param y The second value to analyze.
216 *
217 * \return 1 if \p x greater than \p y, otherwise 0.
218 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219static unsigned mbedtls_ct_size_gt(size_t x,
220 size_t y)
gabor-mezei-arm9d7bf092021-09-27 12:25:07 +0200221{
gabor-mezei-arm5e488242021-08-10 20:36:09 +0200222 /* Return the sign bit (1 for negative) of (y - x). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100223 return (y - x) >> (sizeof(size_t) * 8 - 1);
gabor-mezei-arm9d7bf092021-09-27 12:25:07 +0200224}
gabor-mezei-arm097d4f52021-09-27 12:55:33 +0200225
Gabor Mezei2b358802021-10-18 17:05:06 +0200226#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
227
gabor-mezei-arm097d4f52021-09-27 12:55:33 +0200228#if defined(MBEDTLS_BIGNUM_C)
229
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x,
231 const mbedtls_mpi_uint y)
gabor-mezei-arm097d4f52021-09-27 12:55:33 +0200232{
233 mbedtls_mpi_uint ret;
234 mbedtls_mpi_uint cond;
235
236 /*
237 * Check if the most significant bits (MSB) of the operands are different.
238 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100239 cond = (x ^ y);
gabor-mezei-arm097d4f52021-09-27 12:55:33 +0200240 /*
241 * If the MSB are the same then the difference x-y will be negative (and
242 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
243 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100244 ret = (x - y) & ~cond;
gabor-mezei-arm097d4f52021-09-27 12:55:33 +0200245 /*
246 * If the MSB are different, then the operand with the MSB of 1 is the
247 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
248 * the MSB of y is 0.)
249 */
250 ret |= y & cond;
251
252
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100253 ret = ret >> (sizeof(mbedtls_mpi_uint) * 8 - 1);
gabor-mezei-arm097d4f52021-09-27 12:55:33 +0200254
255 return (unsigned) ret;
256}
257
258#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-arm75332532021-09-27 12:59:30 +0200259
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100260unsigned mbedtls_ct_uint_if(unsigned condition,
261 unsigned if1,
262 unsigned if0)
gabor-mezei-arm75332532021-09-27 12:59:30 +0200263{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100264 unsigned mask = mbedtls_ct_uint_mask(condition);
265 return (mask & if1) | (~mask & if0);
gabor-mezei-arm75332532021-09-27 12:59:30 +0200266}
gabor-mezei-arm5cec8b42021-09-27 13:03:57 +0200267
Gabor Mezei2b358802021-10-18 17:05:06 +0200268#if defined(MBEDTLS_BIGNUM_C)
gabor-mezei-armbc3a2882021-09-27 15:47:00 +0200269
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100270void mbedtls_ct_mpi_uint_cond_assign(size_t n,
271 mbedtls_mpi_uint *dest,
272 const mbedtls_mpi_uint *src,
273 unsigned char condition)
gabor-mezei-arm043192d2021-09-27 13:17:15 +0200274{
275 size_t i;
276
277 /* MSVC has a warning about unary minus on unsigned integer types,
278 * but this is well-defined and precisely what we want to do here. */
279#if defined(_MSC_VER)
280#pragma warning( push )
281#pragma warning( disable : 4146 )
282#endif
283
gabor-mezei-arm5e488242021-08-10 20:36:09 +0200284 /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */
285 const mbedtls_mpi_uint mask = -condition;
gabor-mezei-arm043192d2021-09-27 13:17:15 +0200286
287#if defined(_MSC_VER)
288#pragma warning( pop )
289#endif
290
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291 for (i = 0; i < n; i++) {
292 dest[i] = (src[i] & mask) | (dest[i] & ~mask);
293 }
gabor-mezei-arm043192d2021-09-27 13:17:15 +0200294}
295
296#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-arm7b23c0b2021-09-27 13:31:06 +0200297
Gabor Mezei200708d2021-11-15 16:18:54 +0100298#if defined(MBEDTLS_BASE64_C)
299
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100300unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
Gabor Mezei200708d2021-11-15 16:18:54 +0100301{
302 unsigned char digit = 0;
Gabor Mezei46ca2f72021-11-24 15:51:39 +0100303 /* For each range of values, if value is in that range, mask digit with
304 * the corresponding value. Since value can only be in a single range,
Gabor Mezei200708d2021-11-15 16:18:54 +0100305 * only at most one masking will change digit. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306 digit |= mbedtls_ct_uchar_mask_of_range(0, 25, value) & ('A' + value);
307 digit |= mbedtls_ct_uchar_mask_of_range(26, 51, value) & ('a' + value - 26);
308 digit |= mbedtls_ct_uchar_mask_of_range(52, 61, value) & ('0' + value - 52);
309 digit |= mbedtls_ct_uchar_mask_of_range(62, 62, value) & '+';
310 digit |= mbedtls_ct_uchar_mask_of_range(63, 63, value) & '/';
311 return digit;
Gabor Mezei200708d2021-11-15 16:18:54 +0100312}
313
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100314signed char mbedtls_ct_base64_dec_value(unsigned char c)
Gabor Mezei3d4dba82021-11-15 16:22:37 +0100315{
316 unsigned char val = 0;
317 /* For each range of digits, if c is in that range, mask val with
318 * the corresponding value. Since c can only be in a single range,
319 * only at most one masking will change val. Set val to one plus
320 * the desired value so that it stays 0 if c is in none of the ranges. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100321 val |= mbedtls_ct_uchar_mask_of_range('A', 'Z', c) & (c - 'A' + 0 + 1);
322 val |= mbedtls_ct_uchar_mask_of_range('a', 'z', c) & (c - 'a' + 26 + 1);
323 val |= mbedtls_ct_uchar_mask_of_range('0', '9', c) & (c - '0' + 52 + 1);
324 val |= mbedtls_ct_uchar_mask_of_range('+', '+', c) & (c - '+' + 62 + 1);
325 val |= mbedtls_ct_uchar_mask_of_range('/', '/', c) & (c - '/' + 63 + 1);
Gabor Mezei3d4dba82021-11-15 16:22:37 +0100326 /* At this point, val is 0 if c is an invalid digit and v+1 if c is
327 * a digit with the value v. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100328 return val - 1;
Gabor Mezei3d4dba82021-11-15 16:22:37 +0100329}
330
Gabor Mezei200708d2021-11-15 16:18:54 +0100331#endif /* MBEDTLS_BASE64_C */
332
Gabor Mezei2b358802021-10-18 17:05:06 +0200333#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
334
Gabor Mezeifd8a42d2021-10-18 16:35:23 +0200335/** Shift some data towards the left inside a buffer.
336 *
Gabor Mezei18a44942021-10-20 11:59:27 +0200337 * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally
Gabor Mezeifd8a42d2021-10-18 16:35:23 +0200338 * equivalent to
339 * ```
340 * memmove(start, start + offset, total - offset);
341 * memset(start + offset, 0, total - offset);
342 * ```
343 * but it strives to use a memory access pattern (and thus total timing)
344 * that does not depend on \p offset. This timing independence comes at
345 * the expense of performance.
346 *
347 * \param start Pointer to the start of the buffer.
348 * \param total Total size of the buffer.
349 * \param offset Offset from which to copy \p total - \p offset bytes.
350 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100351static void mbedtls_ct_mem_move_to_left(void *start,
352 size_t total,
353 size_t offset)
gabor-mezei-arm7b23c0b2021-09-27 13:31:06 +0200354{
355 volatile unsigned char *buf = start;
356 size_t i, n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100357 if (total == 0) {
gabor-mezei-arm7b23c0b2021-09-27 13:31:06 +0200358 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100359 }
360 for (i = 0; i < total; i++) {
361 unsigned no_op = mbedtls_ct_size_gt(total - offset, i);
gabor-mezei-arm7b23c0b2021-09-27 13:31:06 +0200362 /* The first `total - offset` passes are a no-op. The last
363 * `offset` passes shift the data one byte to the left and
364 * zero out the last byte. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100365 for (n = 0; n < total - 1; n++) {
gabor-mezei-arm7b23c0b2021-09-27 13:31:06 +0200366 unsigned char current = buf[n];
367 unsigned char next = buf[n+1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100368 buf[n] = mbedtls_ct_uint_if(no_op, current, next);
gabor-mezei-arm7b23c0b2021-09-27 13:31:06 +0200369 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100370 buf[total-1] = mbedtls_ct_uint_if(no_op, buf[total-1], 0);
gabor-mezei-arm7b23c0b2021-09-27 13:31:06 +0200371 }
372}
gabor-mezei-armee06feb2021-09-27 13:34:25 +0200373
Gabor Mezei2b358802021-10-18 17:05:06 +0200374#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
375
Przemek Stekiel169554c2022-10-06 10:53:20 +0200376#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100377void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
378 const unsigned char *src,
379 size_t len,
380 size_t c1,
381 size_t c2)
gabor-mezei-armee06feb2021-09-27 13:34:25 +0200382{
383 /* mask = c1 == c2 ? 0xff : 0x00 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100384 const size_t equal = mbedtls_ct_size_bool_eq(c1, c2);
385 const unsigned char mask = (unsigned char) mbedtls_ct_size_mask(equal);
gabor-mezei-armee06feb2021-09-27 13:34:25 +0200386
gabor-mezei-arm5e488242021-08-10 20:36:09 +0200387 /* dest[i] = c1 == c2 ? src[i] : dest[i] */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100388 for (size_t i = 0; i < len; i++) {
389 dest[i] = (src[i] & mask) | (dest[i] & ~mask);
gabor-mezei-arm0f7b9e42021-09-27 13:57:45 +0200390 }
391}
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200392
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100393void mbedtls_ct_memcpy_offset(unsigned char *dest,
394 const unsigned char *src,
395 size_t offset,
396 size_t offset_min,
397 size_t offset_max,
398 size_t len)
399{
400 size_t offsetval;
401
402 for (offsetval = offset_min; offsetval <= offset_max; offsetval++) {
403 mbedtls_ct_memcpy_if_eq(dest, src + offsetval, len,
404 offsetval, offset);
405 }
406}
407
408int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
409 const unsigned char *add_data,
410 size_t add_data_len,
411 const unsigned char *data,
412 size_t data_len_secret,
413 size_t min_data_len,
414 size_t max_data_len,
415 unsigned char *output)
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200416{
417 /*
418 * This function breaks the HMAC abstraction and uses the md_clone()
419 * extension to the MD API in order to get constant-flow behaviour.
420 *
421 * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
422 * concatenation, and okey/ikey are the XOR of the key with some fixed bit
423 * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx.
424 *
425 * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to
426 * minlen, then cloning the context, and for each byte up to maxlen
427 * finishing up the hash computation, keeping only the correct result.
428 *
429 * Then we only need to compute HASH(okey + inner_hash) and we're done.
430 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100431 const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info);
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200432 /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5,
433 * all of which have the same block size except SHA-384. */
434 const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;
435 const unsigned char * const ikey = ctx->hmac_ctx;
436 const unsigned char * const okey = ikey + block_size;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437 const size_t hash_size = mbedtls_md_get_size(ctx->md_info);
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200438
439 unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];
440 mbedtls_md_context_t aux;
441 size_t offset;
442 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
443
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100444 mbedtls_md_init(&aux);
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200445
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100446#define MD_CHK(func_call) \
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200447 do { \
448 ret = (func_call); \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100449 if (ret != 0) \
450 goto cleanup; \
451 } while (0)
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200452
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100453 MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0));
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200454
455 /* After hmac_start() of hmac_reset(), ikey has already been hashed,
456 * so we can start directly with the message */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100457 MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len));
458 MD_CHK(mbedtls_md_update(ctx, data, min_data_len));
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200459
Paul Elliottb8300282022-05-19 18:31:35 +0100460 /* Fill the hash buffer in advance with something that is
461 * not a valid hash (barring an attack on the hash and
462 * deliberately-crafted input), in case the caller doesn't
463 * check the return status properly. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100464 memset(output, '!', hash_size);
Paul Elliottb8300282022-05-19 18:31:35 +0100465
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200466 /* For each possible length, compute the hash up to that point */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100467 for (offset = min_data_len; offset <= max_data_len; offset++) {
468 MD_CHK(mbedtls_md_clone(&aux, ctx));
469 MD_CHK(mbedtls_md_finish(&aux, aux_out));
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200470 /* Keep only the correct inner_hash in the output buffer */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100471 mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
472 offset, data_len_secret);
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200473
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100474 if (offset < max_data_len) {
475 MD_CHK(mbedtls_md_update(ctx, data + offset, 1));
476 }
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200477 }
478
479 /* The context needs to finish() before it starts() again */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100480 MD_CHK(mbedtls_md_finish(ctx, aux_out));
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200481
482 /* Now compute HASH(okey + inner_hash) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100483 MD_CHK(mbedtls_md_starts(ctx));
484 MD_CHK(mbedtls_md_update(ctx, okey, block_size));
485 MD_CHK(mbedtls_md_update(ctx, output, hash_size));
486 MD_CHK(mbedtls_md_finish(ctx, output));
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200487
488 /* Done, get ready for next time */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100489 MD_CHK(mbedtls_md_hmac_reset(ctx));
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200490
491#undef MD_CHK
492
493cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100494 mbedtls_md_free(&aux);
495 return ret;
gabor-mezei-armcb4317b2021-09-27 14:28:31 +0200496}
497
Przemek Stekiel169554c2022-10-06 10:53:20 +0200498#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200499
500#if defined(MBEDTLS_BIGNUM_C)
501
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100502#define MPI_VALIDATE_RET(cond) \
503 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200504
505/*
506 * Conditionally assign X = Y, without leaking information
507 * about whether the assignment was made or not.
508 * (Leaking information about the respective sizes of X and Y is ok however.)
509 */
Tautvydas Žilys61156f82022-01-31 13:34:01 -0800510#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
Tautvydas Žilysea4af4d2022-01-26 15:33:27 -0800511/*
Tautvydas Žilys61156f82022-01-31 13:34:01 -0800512 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
Tautvydas Žilysea4af4d2022-01-26 15:33:27 -0800513 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
514 */
515__declspec(noinline)
516#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100517int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
518 const mbedtls_mpi *Y,
519 unsigned char assign)
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200520{
521 int ret = 0;
522 size_t i;
523 mbedtls_mpi_uint limb_mask;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100524 MPI_VALIDATE_RET(X != NULL);
525 MPI_VALIDATE_RET(Y != NULL);
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200526
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200527 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100528 limb_mask = mbedtls_ct_mpi_uint_mask(assign);;
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200529
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100530 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200531
Tom Cosgrove735d2c92023-05-03 09:50:10 +0100532 X->s = (int) mbedtls_ct_uint_if(assign, Y->s, X->s);
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200533
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100534 mbedtls_ct_mpi_uint_cond_assign(Y->n, X->p, Y->p, assign);
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200535
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100536 for (i = Y->n; i < X->n; i++) {
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200537 X->p[i] &= ~limb_mask;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100538 }
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200539
540cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100541 return ret;
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200542}
543
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200544/*
545 * Conditionally swap X and Y, without leaking information
546 * about whether the swap was made or not.
Shaun Case0e7791f2021-12-20 21:14:10 -0800547 * Here it is not ok to simply swap the pointers, which would lead to
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200548 * different memory access patterns when X and Y are used afterwards.
549 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100550int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
551 mbedtls_mpi *Y,
552 unsigned char swap)
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200553{
554 int ret, s;
555 size_t i;
556 mbedtls_mpi_uint limb_mask;
557 mbedtls_mpi_uint tmp;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100558 MPI_VALIDATE_RET(X != NULL);
559 MPI_VALIDATE_RET(Y != NULL);
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200560
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100561 if (X == Y) {
562 return 0;
563 }
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200564
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200565 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100566 limb_mask = mbedtls_ct_mpi_uint_mask(swap);
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200567
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100568 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
569 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200570
571 s = X->s;
Tom Cosgrove735d2c92023-05-03 09:50:10 +0100572 X->s = (int) mbedtls_ct_uint_if(swap, Y->s, X->s);
573 Y->s = (int) mbedtls_ct_uint_if(swap, s, Y->s);
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200574
575
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100576 for (i = 0; i < X->n; i++) {
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200577 tmp = X->p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100578 X->p[i] = (X->p[i] & ~limb_mask) | (Y->p[i] & limb_mask);
579 Y->p[i] = (Y->p[i] & ~limb_mask) | (tmp & limb_mask);
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200580 }
581
582cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100583 return ret;
gabor-mezei-arm58fc8a62021-09-27 15:37:50 +0200584}
585
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200586/*
587 * Compare signed values in constant time
588 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100589int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
590 const mbedtls_mpi *Y,
591 unsigned *ret)
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200592{
593 size_t i;
594 /* The value of any of these variables is either 0 or 1 at all times. */
595 unsigned cond, done, X_is_negative, Y_is_negative;
596
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100597 MPI_VALIDATE_RET(X != NULL);
598 MPI_VALIDATE_RET(Y != NULL);
599 MPI_VALIDATE_RET(ret != NULL);
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200600
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100601 if (X->n != Y->n) {
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200602 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100603 }
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200604
605 /*
606 * Set sign_N to 1 if N >= 0, 0 if N < 0.
607 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
608 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100609 X_is_negative = (X->s & 2) >> 1;
610 Y_is_negative = (Y->s & 2) >> 1;
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200611
612 /*
613 * If the signs are different, then the positive operand is the bigger.
614 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
615 * is false if X is positive (X_is_negative == 0).
616 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100617 cond = (X_is_negative ^ Y_is_negative);
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200618 *ret = cond & X_is_negative;
619
620 /*
621 * This is a constant-time function. We might have the result, but we still
622 * need to go through the loop. Record if we have the result already.
623 */
624 done = cond;
625
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100626 for (i = X->n; i > 0; i--) {
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200627 /*
628 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
629 * X and Y are negative.
630 *
631 * Again even if we can make a decision, we just mark the result and
632 * the fact that we are done and continue looping.
633 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100634 cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]);
635 *ret |= cond & (1 - done) & X_is_negative;
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200636 done |= cond;
637
638 /*
639 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
640 * X and Y are positive.
641 *
642 * Again even if we can make a decision, we just mark the result and
643 * the fact that we are done and continue looping.
644 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100645 cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]);
646 *ret |= cond & (1 - done) & (1 - X_is_negative);
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200647 done |= cond;
648 }
649
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100650 return 0;
gabor-mezei-armb10301d2021-09-27 15:41:30 +0200651}
652
gabor-mezei-armb8caeee2021-09-27 15:33:35 +0200653#endif /* MBEDTLS_BIGNUM_C */
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200654
655#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
656
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100657int mbedtls_ct_rsaes_pkcs1_v15_unpadding(int mode,
658 unsigned char *input,
659 size_t ilen,
660 unsigned char *output,
661 size_t output_max_len,
662 size_t *olen)
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200663{
664 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
665 size_t i, plaintext_max_size;
666
667 /* The following variables take sensitive values: their value must
668 * not leak into the observable behavior of the function other than
669 * the designated outputs (output, olen, return value). Otherwise
670 * this would open the execution of the function to
671 * side-channel-based variants of the Bleichenbacher padding oracle
672 * attack. Potential side channels include overall timing, memory
673 * access patterns (especially visible to an adversary who has access
674 * to a shared memory cache), and branches (especially visible to
675 * an adversary who has access to a shared code cache or to a shared
676 * branch predictor). */
677 size_t pad_count = 0;
678 unsigned bad = 0;
679 unsigned char pad_done = 0;
680 size_t plaintext_size = 0;
681 unsigned output_too_large;
682
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100683 plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11
Gabor Mezei150bdee2021-10-18 16:12:45 +0200684 : output_max_len;
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200685
686 /* Check and get padding length in constant time and constant
687 * memory trace. The first byte must be 0. */
Gabor Mezei91deea72021-10-18 16:17:57 +0200688 bad |= input[0];
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200689
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100690 if (mode == MBEDTLS_RSA_PRIVATE) {
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200691 /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
692 * where PS must be at least 8 nonzero bytes. */
Gabor Mezei91deea72021-10-18 16:17:57 +0200693 bad |= input[1] ^ MBEDTLS_RSA_CRYPT;
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200694
695 /* Read the whole buffer. Set pad_done to nonzero if we find
696 * the 0x00 byte and remember the padding length in pad_count. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100697 for (i = 2; i < ilen; i++) {
698 pad_done |= ((input[i] | (unsigned char) -input[i]) >> 7) ^ 1;
699 pad_count += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200700 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100701 } else {
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200702 /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
703 * where PS must be at least 8 bytes with the value 0xFF. */
Gabor Mezei91deea72021-10-18 16:17:57 +0200704 bad |= input[1] ^ MBEDTLS_RSA_SIGN;
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200705
706 /* Read the whole buffer. Set pad_done to nonzero if we find
707 * the 0x00 byte and remember the padding length in pad_count.
708 * If there's a non-0xff byte in the padding, the padding is bad. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100709 for (i = 2; i < ilen; i++) {
710 pad_done |= mbedtls_ct_uint_if(input[i], 0, 1);
711 pad_count += mbedtls_ct_uint_if(pad_done, 0, 1);
712 bad |= mbedtls_ct_uint_if(pad_done, 0, input[i] ^ 0xFF);
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200713 }
714 }
715
716 /* If pad_done is still zero, there's no data, only unfinished padding. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100717 bad |= mbedtls_ct_uint_if(pad_done, 0, 1);
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200718
719 /* There must be at least 8 bytes of padding. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100720 bad |= mbedtls_ct_size_gt(8, pad_count);
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200721
722 /* If the padding is valid, set plaintext_size to the number of
723 * remaining bytes after stripping the padding. If the padding
724 * is invalid, avoid leaking this fact through the size of the
725 * output: use the maximum message size that fits in the output
726 * buffer. Do it without branches to avoid leaking the padding
727 * validity through timing. RSA keys are small enough that all the
728 * size_t values involved fit in unsigned int. */
Gabor Mezei18a44942021-10-20 11:59:27 +0200729 plaintext_size = mbedtls_ct_uint_if(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100730 bad, (unsigned) plaintext_max_size,
731 (unsigned) (ilen - pad_count - 3));
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200732
733 /* Set output_too_large to 0 if the plaintext fits in the output
734 * buffer and to 1 otherwise. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100735 output_too_large = mbedtls_ct_size_gt(plaintext_size,
736 plaintext_max_size);
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200737
738 /* Set ret without branches to avoid timing attacks. Return:
739 * - INVALID_PADDING if the padding is bad (bad != 0).
740 * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
741 * plaintext does not fit in the output buffer.
742 * - 0 if the padding is correct. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100743 ret = -(int) mbedtls_ct_uint_if(
744 bad, -MBEDTLS_ERR_RSA_INVALID_PADDING,
745 mbedtls_ct_uint_if(output_too_large,
746 -MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
747 0));
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200748
749 /* If the padding is bad or the plaintext is too large, zero the
750 * data that we're about to copy to the output buffer.
751 * We need to copy the same amount of data
752 * from the same buffer whether the padding is good or not to
753 * avoid leaking the padding validity through overall timing or
754 * through memory or cache access patterns. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100755 bad = mbedtls_ct_uint_mask(bad | output_too_large);
756 for (i = 11; i < ilen; i++) {
Gabor Mezei91deea72021-10-18 16:17:57 +0200757 input[i] &= ~bad;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100758 }
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200759
760 /* If the plaintext is too large, truncate it to the buffer size.
761 * Copy anyway to avoid revealing the length through timing, because
762 * revealing the length is as bad as revealing the padding validity
763 * for a Bleichenbacher attack. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100764 plaintext_size = mbedtls_ct_uint_if(output_too_large,
765 (unsigned) plaintext_max_size,
766 (unsigned) plaintext_size);
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200767
768 /* Move the plaintext to the leftmost position where it can start in
769 * the working buffer, i.e. make it start plaintext_max_size from
770 * the end of the buffer. Do this with a memory access trace that
771 * does not depend on the plaintext size. After this move, the
772 * starting location of the plaintext is no longer sensitive
773 * information. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100774 mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size,
775 plaintext_max_size,
776 plaintext_max_size - plaintext_size);
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200777
778 /* Finally copy the decrypted plaintext plus trailing zeros into the output
779 * buffer. If output_max_len is 0, then output may be an invalid pointer
780 * and the result of memcpy() would be undefined; prevent undefined
781 * behavior making sure to depend only on output_max_len (the size of the
782 * user-provided output buffer), which is independent from plaintext
783 * length, validity of padding, success of the decryption, and other
784 * secrets. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100785 if (output_max_len != 0) {
786 memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);
787 }
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200788
789 /* Report the amount of data we copied to the output buffer. In case
790 * of errors (bad padding or output too large), the value of *olen
791 * when this function returns is not specified. Making it equivalent
792 * to the good case limits the risks of leaking the padding validity. */
793 *olen = plaintext_size;
794
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100795 return ret;
gabor-mezei-armf52941e2021-09-27 16:11:12 +0200796}
797
798#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */