Coverage Report

Created: 2025-07-01 06:54

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