Merge pull request #7578 from daverodgman/safer-ct5
Improve constant-time interface
This commit is contained in:
commit
54da1a69a2
24 changed files with 2412 additions and 1369 deletions
|
@ -23,20 +23,22 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
/** Constant-time buffer comparison without branches.
|
||||
*
|
||||
* This is equivalent to the standard memcmp function, but is likely to be
|
||||
* compiled to code using bitwise operation rather than a branch.
|
||||
* compiled to code using bitwise operations rather than a branch, such that
|
||||
* the time taken is constant w.r.t. the data pointed to by \p a and \p b,
|
||||
* and w.r.t. whether \p a and \p b are equal or not. It is not constant-time
|
||||
* w.r.t. \p n .
|
||||
*
|
||||
* This function can be used to write constant-time code by replacing branches
|
||||
* with bit operations using masks.
|
||||
*
|
||||
* \param a Pointer to the first buffer.
|
||||
* \param b Pointer to the second buffer.
|
||||
* \param n The number of bytes to compare in the buffer.
|
||||
* \param a Pointer to the first buffer, containing at least \p n bytes. May not be NULL.
|
||||
* \param b Pointer to the second buffer, containing at least \p n bytes. May not be NULL.
|
||||
* \param n The number of bytes to compare.
|
||||
*
|
||||
* \return Zero if the content of the two buffer is the same,
|
||||
* \return Zero if the contents of the two buffers are the same,
|
||||
* otherwise non-zero.
|
||||
*/
|
||||
int mbedtls_ct_memcmp(const void *a,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#if defined(MBEDTLS_BASE64_C)
|
||||
|
||||
#include "mbedtls/base64.h"
|
||||
#include "base64_internal.h"
|
||||
#include "constant_time_internal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
@ -33,6 +34,39 @@
|
|||
#include "mbedtls/platform.h"
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
MBEDTLS_STATIC_TESTABLE
|
||||
unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
|
||||
{
|
||||
unsigned char digit = 0;
|
||||
/* For each range of values, if value is in that range, mask digit with
|
||||
* the corresponding value. Since value can only be in a single range,
|
||||
* only at most one masking will change digit. */
|
||||
digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value);
|
||||
digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26);
|
||||
digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52);
|
||||
digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+');
|
||||
digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/');
|
||||
return digit;
|
||||
}
|
||||
|
||||
MBEDTLS_STATIC_TESTABLE
|
||||
signed char mbedtls_ct_base64_dec_value(unsigned char c)
|
||||
{
|
||||
unsigned char val = 0;
|
||||
/* For each range of digits, if c is in that range, mask val with
|
||||
* the corresponding value. Since c can only be in a single range,
|
||||
* only at most one masking will change val. Set val to one plus
|
||||
* the desired value so that it stays 0 if c is in none of the ranges. */
|
||||
val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' + 0 + 1);
|
||||
val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1);
|
||||
val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1);
|
||||
val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1);
|
||||
val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1);
|
||||
/* At this point, val is 0 if c is an invalid digit and v+1 if c is
|
||||
* a digit with the value v. */
|
||||
return val - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a buffer into base64 format
|
||||
*/
|
||||
|
|
57
library/base64_internal.h
Normal file
57
library/base64_internal.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* \file base64_internal.h
|
||||
*
|
||||
* \brief RFC 1521 base64 encoding/decoding: interfaces for invasive testing
|
||||
*/
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_BASE64_INTERNAL
|
||||
#define MBEDTLS_BASE64_INTERNAL
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS)
|
||||
|
||||
/** Given a value in the range 0..63, return the corresponding Base64 digit.
|
||||
*
|
||||
* The implementation assumes that letters are consecutive (e.g. ASCII
|
||||
* but not EBCDIC).
|
||||
*
|
||||
* \param value A value in the range 0..63.
|
||||
*
|
||||
* \return A base64 digit converted from \p value.
|
||||
*/
|
||||
unsigned char mbedtls_ct_base64_enc_char(unsigned char value);
|
||||
|
||||
/** Given a Base64 digit, return its value.
|
||||
*
|
||||
* If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
|
||||
* return -1.
|
||||
*
|
||||
* The implementation assumes that letters are consecutive (e.g. ASCII
|
||||
* but not EBCDIC).
|
||||
*
|
||||
* \param c A base64 digit.
|
||||
*
|
||||
* \return The value of the base64 digit \p c.
|
||||
*/
|
||||
signed char mbedtls_ct_base64_dec_value(unsigned char c);
|
||||
|
||||
#endif /* MBEDTLS_TEST_HOOKS */
|
||||
|
||||
#endif /* MBEDTLS_BASE64_INTERNAL */
|
130
library/bignum.c
130
library/bignum.c
|
@ -54,6 +54,132 @@
|
|||
#define MPI_VALIDATE(cond) \
|
||||
MBEDTLS_INTERNAL_VALIDATE(cond)
|
||||
|
||||
/*
|
||||
* Compare signed values in constant time
|
||||
*/
|
||||
int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
|
||||
const mbedtls_mpi *Y,
|
||||
unsigned *ret)
|
||||
{
|
||||
mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
|
||||
|
||||
MPI_VALIDATE_RET(X != NULL);
|
||||
MPI_VALIDATE_RET(Y != NULL);
|
||||
MPI_VALIDATE_RET(ret != NULL);
|
||||
|
||||
if (X->n != Y->n) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set sign_N to 1 if N >= 0, 0 if N < 0.
|
||||
* We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
|
||||
*/
|
||||
X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
|
||||
Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
|
||||
|
||||
/*
|
||||
* If the signs are different, then the positive operand is the bigger.
|
||||
* That is if X is negative (X_is_negative == 1), then X < Y is true and it
|
||||
* is false if X is positive (X_is_negative == 0).
|
||||
*/
|
||||
different_sign = mbedtls_ct_bool_xor(X_is_negative, Y_is_negative); // non-zero if different sign
|
||||
result = mbedtls_ct_bool_and(different_sign, X_is_negative);
|
||||
|
||||
/*
|
||||
* Assuming signs are the same, compare X and Y. We switch the comparison
|
||||
* order if they are negative so that we get the right result, regardles of
|
||||
* sign.
|
||||
*/
|
||||
|
||||
/* This array is used to conditionally swap the pointers in const time */
|
||||
void * const p[2] = { X->p, Y->p };
|
||||
size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
|
||||
mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
|
||||
|
||||
/*
|
||||
* Store in result iff the signs are the same (i.e., iff different_sign == false). If
|
||||
* the signs differ, result has already been set, so we don't change it.
|
||||
*/
|
||||
result = mbedtls_ct_bool_or(result,
|
||||
mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
|
||||
|
||||
*ret = mbedtls_ct_uint_if_else_0(result, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Conditionally assign X = Y, without leaking information
|
||||
* about whether the assignment was made or not.
|
||||
* (Leaking information about the respective sizes of X and Y is ok however.)
|
||||
*/
|
||||
#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
|
||||
/*
|
||||
* MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
|
||||
* https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
|
||||
*/
|
||||
__declspec(noinline)
|
||||
#endif
|
||||
int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
|
||||
const mbedtls_mpi *Y,
|
||||
unsigned char assign)
|
||||
{
|
||||
int ret = 0;
|
||||
MPI_VALIDATE_RET(X != NULL);
|
||||
MPI_VALIDATE_RET(Y != NULL);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
|
||||
|
||||
mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
|
||||
|
||||
X->s = (int) mbedtls_ct_uint_if(do_assign, Y->s, X->s);
|
||||
|
||||
mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
|
||||
|
||||
mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
|
||||
for (size_t i = Y->n; i < X->n; i++) {
|
||||
X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Conditionally swap X and Y, without leaking information
|
||||
* about whether the swap was made or not.
|
||||
* Here it is not ok to simply swap the pointers, which would lead to
|
||||
* different memory access patterns when X and Y are used afterwards.
|
||||
*/
|
||||
int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
|
||||
mbedtls_mpi *Y,
|
||||
unsigned char swap)
|
||||
{
|
||||
int ret = 0;
|
||||
int s;
|
||||
MPI_VALIDATE_RET(X != NULL);
|
||||
MPI_VALIDATE_RET(Y != NULL);
|
||||
|
||||
if (X == Y) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
|
||||
|
||||
s = X->s;
|
||||
X->s = (int) mbedtls_ct_uint_if(do_swap, Y->s, X->s);
|
||||
Y->s = (int) mbedtls_ct_uint_if(do_swap, s, Y->s);
|
||||
|
||||
mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Implementation that should never be optimized out by the compiler */
|
||||
#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
|
||||
|
||||
|
@ -1624,10 +1750,8 @@ static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_
|
|||
|
||||
for (size_t i = 0; i < T_size; i++) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
|
||||
(unsigned char) mbedtls_ct_size_bool_eq(i,
|
||||
idx)));
|
||||
(unsigned char) mbedtls_ct_uint_eq(i, idx)));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -144,54 +144,92 @@ void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,
|
|||
|
||||
/* Whether min <= A, in constant time.
|
||||
* A_limbs must be at least 1. */
|
||||
unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
|
||||
mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
|
||||
const mbedtls_mpi_uint *A,
|
||||
size_t A_limbs)
|
||||
{
|
||||
/* min <= least significant limb? */
|
||||
unsigned min_le_lsl = 1 ^ mbedtls_ct_mpi_uint_lt(A[0], min);
|
||||
mbedtls_ct_condition_t min_le_lsl = mbedtls_ct_uint_ge(A[0], min);
|
||||
|
||||
/* limbs other than the least significant one are all zero? */
|
||||
mbedtls_mpi_uint msll_mask = 0;
|
||||
mbedtls_ct_condition_t msll_mask = MBEDTLS_CT_FALSE;
|
||||
for (size_t i = 1; i < A_limbs; i++) {
|
||||
msll_mask |= A[i];
|
||||
msll_mask = mbedtls_ct_bool_or(msll_mask, mbedtls_ct_bool(A[i]));
|
||||
}
|
||||
/* The most significant limbs of A are not all zero iff msll_mask != 0. */
|
||||
unsigned msll_nonzero = mbedtls_ct_mpi_uint_mask(msll_mask) & 1;
|
||||
|
||||
/* min <= A iff the lowest limb of A is >= min or the other limbs
|
||||
* are not all zero. */
|
||||
return min_le_lsl | msll_nonzero;
|
||||
return mbedtls_ct_bool_or(msll_mask, min_le_lsl);
|
||||
}
|
||||
|
||||
mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
|
||||
const mbedtls_mpi_uint *B,
|
||||
size_t limbs)
|
||||
{
|
||||
mbedtls_ct_condition_t ret = MBEDTLS_CT_FALSE, cond = MBEDTLS_CT_FALSE, done = MBEDTLS_CT_FALSE;
|
||||
|
||||
for (size_t i = limbs; i > 0; i--) {
|
||||
/*
|
||||
* If B[i - 1] < A[i - 1] then A < B is false and the result must
|
||||
* remain 0.
|
||||
*
|
||||
* Again even if we can make a decision, we just mark the result and
|
||||
* the fact that we are done and continue looping.
|
||||
*/
|
||||
cond = mbedtls_ct_uint_lt(B[i - 1], A[i - 1]);
|
||||
done = mbedtls_ct_bool_or(done, cond);
|
||||
|
||||
/*
|
||||
* If A[i - 1] < B[i - 1] then A < B is true.
|
||||
*
|
||||
* Again even if we can make a decision, we just mark the result and
|
||||
* the fact that we are done and continue looping.
|
||||
*/
|
||||
cond = mbedtls_ct_uint_lt(A[i - 1], B[i - 1]);
|
||||
ret = mbedtls_ct_bool_or(ret, mbedtls_ct_bool_and(cond, mbedtls_ct_bool_not(done)));
|
||||
done = mbedtls_ct_bool_or(done, cond);
|
||||
}
|
||||
|
||||
/*
|
||||
* If all the limbs were equal, then the numbers are equal, A < B is false
|
||||
* and leaving the result 0 is correct.
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
|
||||
const mbedtls_mpi_uint *A,
|
||||
size_t limbs,
|
||||
unsigned char assign)
|
||||
mbedtls_ct_condition_t assign)
|
||||
{
|
||||
if (X == A) {
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_ct_mpi_uint_cond_assign(limbs, X, A, assign);
|
||||
/* This function is very performance-sensitive for RSA. For this reason
|
||||
* we have the loop below, instead of calling mbedtls_ct_memcpy_if
|
||||
* (this is more optimal since here we don't have to handle the case where
|
||||
* we copy awkwardly sized data).
|
||||
*/
|
||||
for (size_t i = 0; i < limbs; i++) {
|
||||
X[i] = mbedtls_ct_mpi_uint_if(assign, A[i], X[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
|
||||
mbedtls_mpi_uint *Y,
|
||||
size_t limbs,
|
||||
unsigned char swap)
|
||||
mbedtls_ct_condition_t swap)
|
||||
{
|
||||
if (X == Y) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
|
||||
mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(swap);
|
||||
|
||||
for (size_t i = 0; i < limbs; i++) {
|
||||
mbedtls_mpi_uint tmp = X[i];
|
||||
X[i] = (X[i] & ~limb_mask) | (Y[i] & limb_mask);
|
||||
Y[i] = (Y[i] & ~limb_mask) | (tmp & limb_mask);
|
||||
X[i] = mbedtls_ct_mpi_uint_if(swap, Y[i], X[i]);
|
||||
Y[i] = mbedtls_ct_mpi_uint_if(swap, tmp, Y[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,11 +460,10 @@ mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X,
|
|||
{
|
||||
mbedtls_mpi_uint c = 0;
|
||||
|
||||
/* all-bits 0 if cond is 0, all-bits 1 if cond is non-0 */
|
||||
const mbedtls_mpi_uint mask = mbedtls_ct_mpi_uint_mask(cond);
|
||||
mbedtls_ct_condition_t do_add = mbedtls_ct_bool(cond);
|
||||
|
||||
for (size_t i = 0; i < limbs; i++) {
|
||||
mbedtls_mpi_uint add = mask & A[i];
|
||||
mbedtls_mpi_uint add = mbedtls_ct_mpi_uint_if_else_0(do_add, A[i]);
|
||||
mbedtls_mpi_uint t = c + X[i];
|
||||
c = (t < X[i]);
|
||||
t += add;
|
||||
|
@ -568,7 +605,11 @@ void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X,
|
|||
* So the correct return value is already in X if (carry ^ borrow) = 0,
|
||||
* but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1.
|
||||
*/
|
||||
mbedtls_ct_mpi_uint_cond_assign(AN_limbs, X, T, (unsigned char) (carry ^ borrow));
|
||||
mbedtls_ct_memcpy_if(mbedtls_ct_bool(carry ^ borrow),
|
||||
(unsigned char *) X,
|
||||
(unsigned char *) T,
|
||||
NULL,
|
||||
AN_limbs * sizeof(mbedtls_mpi_uint));
|
||||
}
|
||||
|
||||
int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X,
|
||||
|
@ -593,7 +634,7 @@ void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest,
|
|||
size_t index)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++, table += limbs) {
|
||||
unsigned char assign = mbedtls_ct_size_bool_eq(i, index);
|
||||
mbedtls_ct_condition_t assign = mbedtls_ct_uint_eq(i, index);
|
||||
mbedtls_mpi_core_cond_assign(dest, table, limbs, assign);
|
||||
}
|
||||
}
|
||||
|
@ -633,7 +674,7 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
|
|||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng)
|
||||
{
|
||||
unsigned ge_lower = 1, lt_upper = 0;
|
||||
mbedtls_ct_condition_t ge_lower = MBEDTLS_CT_TRUE, lt_upper = MBEDTLS_CT_FALSE;
|
||||
size_t n_bits = mbedtls_mpi_core_bitlen(N, limbs);
|
||||
size_t n_bytes = (n_bits + 7) / 8;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
@ -678,7 +719,7 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
|
|||
|
||||
ge_lower = mbedtls_mpi_core_uint_le_mpi(min, X, limbs);
|
||||
lt_upper = mbedtls_mpi_core_lt_ct(X, N, limbs);
|
||||
} while (ge_lower == 0 || lt_upper == 0);
|
||||
} while (mbedtls_ct_bool_and(ge_lower, lt_upper) == MBEDTLS_CT_FALSE);
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
|
|
|
@ -86,6 +86,8 @@
|
|||
#include "mbedtls/bignum.h"
|
||||
#endif
|
||||
|
||||
#include "constant_time_internal.h"
|
||||
|
||||
#define ciL (sizeof(mbedtls_mpi_uint)) /** chars in limb */
|
||||
#define biL (ciL << 3) /** bits in limb */
|
||||
#define biH (ciL << 2) /** half limb size */
|
||||
|
@ -142,12 +144,30 @@ void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,
|
|||
* \param A_limbs The number of limbs of \p A.
|
||||
* This must be at least 1.
|
||||
*
|
||||
* \return 1 if \p min is less than or equal to \p A, otherwise 0.
|
||||
* \return MBEDTLS_CT_TRUE if \p min is less than or equal to \p A, otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
|
||||
mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
|
||||
const mbedtls_mpi_uint *A,
|
||||
size_t A_limbs);
|
||||
|
||||
/**
|
||||
* \brief Check if one unsigned MPI is less than another in constant
|
||||
* time.
|
||||
*
|
||||
* \param A The left-hand MPI. This must point to an array of limbs
|
||||
* with the same allocated length as \p B.
|
||||
* \param B The right-hand MPI. This must point to an array of limbs
|
||||
* with the same allocated length as \p A.
|
||||
* \param limbs The number of limbs in \p A and \p B.
|
||||
* This must not be 0.
|
||||
*
|
||||
* \return MBEDTLS_CT_TRUE if \p A is less than \p B.
|
||||
* MBEDTLS_CT_FALSE if \p A is greater than or equal to \p B.
|
||||
*/
|
||||
mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
|
||||
const mbedtls_mpi_uint *B,
|
||||
size_t limbs);
|
||||
|
||||
/**
|
||||
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
|
||||
* whether assignment was done or not.
|
||||
|
@ -158,21 +178,17 @@ unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
|
|||
* \param[in] A The address of the source MPI. This must be initialized.
|
||||
* \param limbs The number of limbs of \p A.
|
||||
* \param assign The condition deciding whether to perform the
|
||||
* assignment or not. Must be either 0 or 1:
|
||||
* * \c 1: Perform the assignment `X = A`.
|
||||
* * \c 0: Keep the original value of \p X.
|
||||
* assignment or not. Callers will need to use
|
||||
* the constant time interface (e.g. `mbedtls_ct_bool()`)
|
||||
* to construct this argument.
|
||||
*
|
||||
* \note This function avoids leaking any information about whether
|
||||
* the assignment was done or not.
|
||||
*
|
||||
* \warning If \p assign is neither 0 nor 1, the result of this function
|
||||
* is indeterminate, and the resulting value in \p X might be
|
||||
* neither its original value nor the value in \p A.
|
||||
*/
|
||||
void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
|
||||
const mbedtls_mpi_uint *A,
|
||||
size_t limbs,
|
||||
unsigned char assign);
|
||||
mbedtls_ct_condition_t assign);
|
||||
|
||||
/**
|
||||
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
|
||||
|
@ -184,21 +200,15 @@ void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
|
|||
* This must be initialized.
|
||||
* \param limbs The number of limbs of \p X and \p Y.
|
||||
* \param swap The condition deciding whether to perform
|
||||
* the swap or not. Must be either 0 or 1:
|
||||
* * \c 1: Swap the values of \p X and \p Y.
|
||||
* * \c 0: Keep the original values of \p X and \p Y.
|
||||
* the swap or not.
|
||||
*
|
||||
* \note This function avoids leaking any information about whether
|
||||
* the swap was done or not.
|
||||
*
|
||||
* \warning If \p swap is neither 0 nor 1, the result of this function
|
||||
* is indeterminate, and both \p X and \p Y might end up with
|
||||
* values different to either of the original ones.
|
||||
*/
|
||||
void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
|
||||
mbedtls_mpi_uint *Y,
|
||||
size_t limbs,
|
||||
unsigned char swap);
|
||||
mbedtls_ct_condition_t swap);
|
||||
|
||||
/** Import X from unsigned binary data, little-endian.
|
||||
*
|
||||
|
|
|
@ -40,7 +40,7 @@ void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
|
|||
const mbedtls_mpi_mod_modulus *N,
|
||||
unsigned char assign)
|
||||
{
|
||||
mbedtls_mpi_core_cond_assign(X, A, N->limbs, assign);
|
||||
mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));
|
||||
}
|
||||
|
||||
void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
|
||||
|
@ -48,7 +48,7 @@ void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
|
|||
const mbedtls_mpi_mod_modulus *N,
|
||||
unsigned char swap)
|
||||
{
|
||||
mbedtls_mpi_core_cond_swap(X, Y, N->limbs, swap);
|
||||
mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
|
||||
|
|
File diff suppressed because it is too large
Load diff
306
library/constant_time_impl.h
Normal file
306
library/constant_time_impl.h
Normal file
|
@ -0,0 +1,306 @@
|
|||
/**
|
||||
* Constant-time functions
|
||||
*
|
||||
* For readability, the static inline definitions are here, and
|
||||
* constant_time_internal.h has only the declarations.
|
||||
*
|
||||
* This results in duplicate declarations of the form:
|
||||
* static inline void f() { ... }
|
||||
* static inline void f();
|
||||
* when constant_time_internal.h is included. This appears to behave
|
||||
* exactly as if the declaration-without-definition was not present.
|
||||
*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CONSTANT_TIME_IMPL_H
|
||||
#define MBEDTLS_CONSTANT_TIME_IMPL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
#include "mbedtls/bignum.h"
|
||||
#endif
|
||||
|
||||
/* constant_time_impl.h contains all the static inline implementations,
|
||||
* so that constant_time_internal.h is more readable.
|
||||
*
|
||||
* gcc generates warnings about duplicate declarations, so disable this
|
||||
* warning.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
#endif
|
||||
|
||||
/* Disable asm under Memsan because it confuses Memsan and generates false errors */
|
||||
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
|
||||
#define MBEDTLS_CT_NO_ASM
|
||||
#elif defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#define MBEDTLS_CT_NO_ASM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
|
||||
#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && (!defined(__ARMCC_VERSION) || \
|
||||
__ARMCC_VERSION >= 6000000) && !defined(MBEDTLS_CT_NO_ASM)
|
||||
#define MBEDTLS_CT_ASM
|
||||
#if (defined(__arm__) || defined(__thumb__) || defined(__thumb2__))
|
||||
#define MBEDTLS_CT_ARM_ASM
|
||||
#elif defined(__aarch64__)
|
||||
#define MBEDTLS_CT_AARCH64_ASM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_CT_SIZE (sizeof(mbedtls_ct_uint_t) * 8)
|
||||
|
||||
|
||||
/* ============================================================================
|
||||
* Core const-time primitives
|
||||
*/
|
||||
|
||||
/* Ensure that the compiler cannot know the value of x (i.e., cannot optimise
|
||||
* based on its value) after this function is called.
|
||||
*
|
||||
* If we are not using assembly, this will be fairly inefficient, so its use
|
||||
* should be minimised.
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CT_ASM)
|
||||
extern volatile mbedtls_ct_uint_t mbedtls_ct_zero;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Ensure that a value cannot be known at compile time.
|
||||
*
|
||||
* \param x The value to hide from the compiler.
|
||||
* \return The same value that was passed in, such that the compiler
|
||||
* cannot prove its value (even for calls of the form
|
||||
* x = mbedtls_ct_compiler_opaque(1), x will be unknown).
|
||||
*
|
||||
* \note This is mainly used in constructing mbedtls_ct_condition_t
|
||||
* values and performing operations over them, to ensure that
|
||||
* there is no way for the compiler to ever know anything about
|
||||
* the value of an mbedtls_ct_condition_t.
|
||||
*/
|
||||
static inline mbedtls_ct_uint_t mbedtls_ct_compiler_opaque(mbedtls_ct_uint_t x)
|
||||
{
|
||||
#if defined(MBEDTLS_CT_ASM)
|
||||
asm volatile ("" : [x] "+r" (x) :);
|
||||
return x;
|
||||
#else
|
||||
return x ^ mbedtls_ct_zero;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert a number into a condition in constant time. */
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x)
|
||||
{
|
||||
/*
|
||||
* Define mask-generation code that, as far as possible, will not use branches or conditional instructions.
|
||||
*
|
||||
* For some platforms / type sizes, we define assembly to assure this.
|
||||
*
|
||||
* Otherwise, we define a plain C fallback which (in May 2023) does not get optimised into
|
||||
* conditional instructions or branches by trunk clang, gcc, or MSVC v19.
|
||||
*/
|
||||
const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);
|
||||
#if defined(_MSC_VER)
|
||||
/* MSVC has a warning about unary minus on unsigned, but this is
|
||||
* well-defined and precisely what we want to do here */
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4146 )
|
||||
#endif
|
||||
return (mbedtls_ct_condition_t) (((mbedtls_ct_int_t) ((-xo) | -(xo >> 1))) >>
|
||||
(MBEDTLS_CT_SIZE - 1));
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_uint_t mbedtls_ct_if(mbedtls_ct_condition_t condition,
|
||||
mbedtls_ct_uint_t if1,
|
||||
mbedtls_ct_uint_t if0)
|
||||
{
|
||||
mbedtls_ct_condition_t not_cond =
|
||||
(mbedtls_ct_condition_t) (~mbedtls_ct_compiler_opaque(condition));
|
||||
return (mbedtls_ct_uint_t) ((condition & if1) | (not_cond & if0));
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y)
|
||||
{
|
||||
/* Ensure that the compiler cannot optimise the following operations over x and y,
|
||||
* even if it knows the value of x and y.
|
||||
*/
|
||||
const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);
|
||||
const mbedtls_ct_uint_t yo = mbedtls_ct_compiler_opaque(y);
|
||||
/*
|
||||
* Check if the most significant bits (MSB) of the operands are different.
|
||||
* cond is true iff the MSBs differ.
|
||||
*/
|
||||
mbedtls_ct_condition_t cond = mbedtls_ct_bool((xo ^ yo) >> (MBEDTLS_CT_SIZE - 1));
|
||||
|
||||
/*
|
||||
* If the MSB are the same then the difference x-y will be negative (and
|
||||
* have its MSB set to 1 during conversion to unsigned) if and only if x<y.
|
||||
*
|
||||
* If the MSB are different, then the operand with the MSB of 1 is the
|
||||
* bigger. (That is if y has MSB of 1, then x<y is true and it is false if
|
||||
* the MSB of y is 0.)
|
||||
*/
|
||||
|
||||
// Select either y, or x - y
|
||||
mbedtls_ct_uint_t ret = mbedtls_ct_if(cond, yo, (mbedtls_ct_uint_t) (xo - yo));
|
||||
|
||||
// Extract only the MSB of ret
|
||||
ret = ret >> (MBEDTLS_CT_SIZE - 1);
|
||||
|
||||
// Convert to a condition (i.e., all bits set iff non-zero)
|
||||
return mbedtls_ct_bool(ret);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y)
|
||||
{
|
||||
/* diff = 0 if x == y, non-zero otherwise */
|
||||
const mbedtls_ct_uint_t diff = mbedtls_ct_compiler_opaque(x) ^ mbedtls_ct_compiler_opaque(y);
|
||||
|
||||
/* all ones if x != y, 0 otherwise */
|
||||
return mbedtls_ct_bool(diff);
|
||||
}
|
||||
|
||||
static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
|
||||
unsigned char high,
|
||||
unsigned char c,
|
||||
unsigned char t)
|
||||
{
|
||||
const unsigned char co = (const unsigned char) mbedtls_ct_compiler_opaque(c);
|
||||
const unsigned char to = (const unsigned char) mbedtls_ct_compiler_opaque(t);
|
||||
|
||||
/* low_mask is: 0 if low <= c, 0x...ff if low > c */
|
||||
unsigned low_mask = ((unsigned) co - low) >> 8;
|
||||
/* high_mask is: 0 if c <= high, 0x...ff if c > high */
|
||||
unsigned high_mask = ((unsigned) high - co) >> 8;
|
||||
|
||||
return (unsigned char) (~(low_mask | high_mask)) & to;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================================
|
||||
* Everything below here is trivial wrapper functions
|
||||
*/
|
||||
|
||||
static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,
|
||||
size_t if1,
|
||||
size_t if0)
|
||||
{
|
||||
return (size_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0);
|
||||
}
|
||||
|
||||
static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,
|
||||
unsigned if1,
|
||||
unsigned if0)
|
||||
{
|
||||
return (unsigned) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
|
||||
static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition,
|
||||
mbedtls_mpi_uint if1,
|
||||
mbedtls_mpi_uint if0)
|
||||
{
|
||||
return (mbedtls_mpi_uint) mbedtls_ct_if(condition,
|
||||
(mbedtls_ct_uint_t) if1,
|
||||
(mbedtls_ct_uint_t) if0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1)
|
||||
{
|
||||
return (size_t) (condition & if1);
|
||||
}
|
||||
|
||||
static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1)
|
||||
{
|
||||
return (unsigned) (condition & if1);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
|
||||
static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,
|
||||
mbedtls_mpi_uint if1)
|
||||
{
|
||||
return (mbedtls_mpi_uint) (condition & if1);
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_BIGNUM_C */
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y)
|
||||
{
|
||||
return ~mbedtls_ct_uint_ne(x, y);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y)
|
||||
{
|
||||
return mbedtls_ct_uint_lt(y, x);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y)
|
||||
{
|
||||
return ~mbedtls_ct_uint_lt(x, y);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y)
|
||||
{
|
||||
return ~mbedtls_ct_uint_gt(x, y);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_xor(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t y)
|
||||
{
|
||||
return (mbedtls_ct_condition_t) (x ^ y);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t y)
|
||||
{
|
||||
return (mbedtls_ct_condition_t) (x & y);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t y)
|
||||
{
|
||||
return (mbedtls_ct_condition_t) (x | y);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x)
|
||||
{
|
||||
return (mbedtls_ct_condition_t) (~x);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_CONSTANT_TIME_IMPL_H */
|
|
@ -20,224 +20,442 @@
|
|||
#ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H
|
||||
#define MBEDTLS_CONSTANT_TIME_INTERNAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
#include "mbedtls/bignum.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
#include "ssl_misc.h"
|
||||
/* The constant-time interface provides various operations that are likely
|
||||
* to result in constant-time code that does not branch or use conditional
|
||||
* instructions for secret data (for secret pointers, this also applies to
|
||||
* the data pointed to).
|
||||
*
|
||||
* It has three main parts:
|
||||
*
|
||||
* - boolean operations
|
||||
* These are all named mbedtls_ct_<type>_<operation>.
|
||||
* They operate over <type> and return mbedtls_ct_condition_t.
|
||||
* All arguments are considered secret.
|
||||
* example: bool x = y | z => x = mbedtls_ct_bool_or(y, z)
|
||||
* example: bool x = y == z => x = mbedtls_ct_uint_eq(y, z)
|
||||
*
|
||||
* - conditional data selection
|
||||
* These are all named mbedtls_ct_<type>_if and mbedtls_ct_<type>_if_else_0
|
||||
* All arguments are considered secret.
|
||||
* example: size_t a = x ? b : c => a = mbedtls_ct_size_if(x, b, c)
|
||||
* example: unsigned a = x ? b : 0 => a = mbedtls_ct_uint__if_else_0(x, b)
|
||||
*
|
||||
* - block memory operations
|
||||
* Only some arguments are considered secret, as documented for each
|
||||
* function.
|
||||
* example: if (x) memcpy(...) => mbedtls_ct_memcpy_if(x, ...)
|
||||
*
|
||||
* mbedtls_ct_condition_t must be treated as opaque and only created and
|
||||
* manipulated via the functions in this header. The compiler should never
|
||||
* be able to prove anything about its value at compile-time.
|
||||
*
|
||||
* mbedtls_ct_uint_t is an unsigned integer type over which constant time
|
||||
* operations may be performed via the functions in this header. It is as big
|
||||
* as the larger of size_t and mbedtls_mpi_uint, i.e. it is safe to cast
|
||||
* to/from "unsigned int", "size_t", and "mbedtls_mpi_uint" (and any other
|
||||
* not-larger integer types).
|
||||
*
|
||||
* For Arm (32-bit, 64-bit and Thumb), x86 and x86-64, assembly implementations
|
||||
* are used to ensure that the generated code is constant time. For other
|
||||
* architectures, it uses a plain C fallback designed to yield constant-time code
|
||||
* (this has been observed to be constant-time on latest gcc, clang and MSVC
|
||||
* as of May 2023).
|
||||
*
|
||||
* For readability, the static inline definitions are separated out into
|
||||
* constant_time_impl.h.
|
||||
*/
|
||||
|
||||
#if (SIZE_MAX > 0xffffffffffffffffULL)
|
||||
/* Pointer size > 64-bit */
|
||||
typedef size_t mbedtls_ct_condition_t;
|
||||
typedef size_t mbedtls_ct_uint_t;
|
||||
typedef ptrdiff_t mbedtls_ct_int_t;
|
||||
#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(SIZE_MAX))
|
||||
#elif (SIZE_MAX > 0xffffffff) || defined(MBEDTLS_HAVE_INT64)
|
||||
/* 32-bit < pointer size <= 64-bit, or 64-bit MPI */
|
||||
typedef uint64_t mbedtls_ct_condition_t;
|
||||
typedef uint64_t mbedtls_ct_uint_t;
|
||||
typedef int64_t mbedtls_ct_int_t;
|
||||
#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT64_MAX))
|
||||
#else
|
||||
/* Pointer size <= 32-bit, and no 64-bit MPIs */
|
||||
typedef uint32_t mbedtls_ct_condition_t;
|
||||
typedef uint32_t mbedtls_ct_uint_t;
|
||||
typedef int32_t mbedtls_ct_int_t;
|
||||
#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT32_MAX))
|
||||
#endif
|
||||
#define MBEDTLS_CT_FALSE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(0))
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
/** Turn a value into a mask:
|
||||
* - if \p value == 0, return the all-bits 0 mask, aka 0
|
||||
* - otherwise, return the all-bits 1 mask, aka (unsigned) -1
|
||||
*
|
||||
* This function can be used to write constant-time code by replacing branches
|
||||
* with bit operations using masks.
|
||||
*
|
||||
* \param value The value to analyze.
|
||||
*
|
||||
* \return Zero if \p value is zero, otherwise all-bits-one.
|
||||
/* ============================================================================
|
||||
* Boolean operations
|
||||
*/
|
||||
unsigned mbedtls_ct_uint_mask(unsigned value);
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
|
||||
/** Turn a value into a mask:
|
||||
* - if \p value == 0, return the all-bits 0 mask, aka 0
|
||||
* - otherwise, return the all-bits 1 mask, aka (size_t) -1
|
||||
/** Convert a number into a mbedtls_ct_condition_t.
|
||||
*
|
||||
* This function can be used to write constant-time code by replacing branches
|
||||
* with bit operations using masks.
|
||||
* \param x Number to convert.
|
||||
*
|
||||
* \param value The value to analyze.
|
||||
* \return MBEDTLS_CT_TRUE if \p x != 0, or MBEDTLS_CT_FALSE if \p x == 0
|
||||
*
|
||||
* \return Zero if \p value is zero, otherwise all-bits-one.
|
||||
*/
|
||||
size_t mbedtls_ct_size_mask(size_t value);
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x);
|
||||
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
|
||||
/** Turn a value into a mask:
|
||||
* - if \p value == 0, return the all-bits 0 mask, aka 0
|
||||
* - otherwise, return the all-bits 1 mask, aka (mbedtls_mpi_uint) -1
|
||||
/** Boolean "not equal" operation.
|
||||
*
|
||||
* This function can be used to write constant-time code by replacing branches
|
||||
* with bit operations using masks.
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \param value The value to analyze.
|
||||
*
|
||||
* \return Zero if \p value is zero, otherwise all-bits-one.
|
||||
*/
|
||||
mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value);
|
||||
|
||||
#endif /* MBEDTLS_BIGNUM_C */
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
|
||||
|
||||
/** Constant-flow mask generation for "greater or equal" comparison:
|
||||
* - if \p x >= \p y, return all-bits 1, that is (size_t) -1
|
||||
* - otherwise, return all bits 0, that is 0
|
||||
*
|
||||
* This function can be used to write constant-time code by replacing branches
|
||||
* with bit operations using masks.
|
||||
* \p x != \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \return All-bits-one if \p x is greater or equal than \p y,
|
||||
* otherwise zero.
|
||||
* \return MBEDTLS_CT_TRUE if \p x != \p y, otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
size_t mbedtls_ct_size_mask_ge(size_t x,
|
||||
size_t y);
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);
|
||||
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
|
||||
|
||||
/** Constant-flow boolean "equal" comparison:
|
||||
* return x == y
|
||||
/** Boolean "equals" operation.
|
||||
*
|
||||
* This is equivalent to \p x == \p y, but is likely to be compiled
|
||||
* to code using bitwise operation rather than a branch.
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \p x == \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \return 1 if \p x equals to \p y, otherwise 0.
|
||||
* \return MBEDTLS_CT_TRUE if \p x == \p y, otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
unsigned mbedtls_ct_size_bool_eq(size_t x,
|
||||
size_t y);
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y);
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
|
||||
/** Decide if an integer is less than the other, without branches.
|
||||
/** Boolean "less than" operation.
|
||||
*
|
||||
* This is equivalent to \p x < \p y, but is likely to be compiled
|
||||
* to code using bitwise operation rather than a branch.
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \p x < \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \return 1 if \p x is less than \p y, otherwise 0.
|
||||
* \return MBEDTLS_CT_TRUE if \p x < \p y, otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x,
|
||||
const mbedtls_mpi_uint y);
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);
|
||||
|
||||
/**
|
||||
* \brief Check if one unsigned MPI is less than another in constant
|
||||
* time.
|
||||
/** Boolean "greater than" operation.
|
||||
*
|
||||
* \param A The left-hand MPI. This must point to an array of limbs
|
||||
* with the same allocated length as \p B.
|
||||
* \param B The right-hand MPI. This must point to an array of limbs
|
||||
* with the same allocated length as \p A.
|
||||
* \param limbs The number of limbs in \p A and \p B.
|
||||
* This must not be 0.
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \return The result of the comparison:
|
||||
* \c 1 if \p A is less than \p B.
|
||||
* \c 0 if \p A is greater than or equal to \p B.
|
||||
* \p x > \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \return MBEDTLS_CT_TRUE if \p x > \p y, otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
|
||||
const mbedtls_mpi_uint *B,
|
||||
size_t limbs);
|
||||
#endif /* MBEDTLS_BIGNUM_C */
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y);
|
||||
|
||||
/** Choose between two integer values without branches.
|
||||
/** Boolean "greater or equal" operation.
|
||||
*
|
||||
* This is equivalent to `condition ? if1 : if0`, but is likely to be compiled
|
||||
* to code using bitwise operation rather than a branch.
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \p x >= \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \return MBEDTLS_CT_TRUE if \p x >= \p y,
|
||||
* otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y);
|
||||
|
||||
/** Boolean "less than or equal" operation.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \p x <= \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \return MBEDTLS_CT_TRUE if \p x <= \p y,
|
||||
* otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y);
|
||||
|
||||
/** Boolean "xor" operation.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \p x ^ \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \note This is more efficient than mbedtls_ct_uint_ne if both arguments are
|
||||
* mbedtls_ct_condition_t.
|
||||
*
|
||||
* \return MBEDTLS_CT_TRUE if \p x ^ \p y,
|
||||
* otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_xor(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t y);
|
||||
|
||||
/** Boolean "and" operation.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \p x && \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \return MBEDTLS_CT_TRUE if \p x && \p y,
|
||||
* otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t y);
|
||||
|
||||
/** Boolean "or" operation.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \p x || \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
*
|
||||
* \return MBEDTLS_CT_TRUE if \p x || \p y,
|
||||
* otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t y);
|
||||
|
||||
/** Boolean "not" operation.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* ! \p x
|
||||
*
|
||||
* \param x The value to invert
|
||||
*
|
||||
* \return MBEDTLS_CT_FALSE if \p x, otherwise MBEDTLS_CT_TRUE.
|
||||
*/
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x);
|
||||
|
||||
|
||||
/* ============================================================================
|
||||
* Data selection operations
|
||||
*/
|
||||
|
||||
/** Choose between two size_t values.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* condition ? if1 : if0.
|
||||
*
|
||||
* \param condition Condition to test.
|
||||
* \param if1 Value to use if \p condition is nonzero.
|
||||
* \param if0 Value to use if \p condition is zero.
|
||||
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
|
||||
* \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
|
||||
*
|
||||
* \return \c if1 if \p condition is nonzero, otherwise \c if0.
|
||||
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
|
||||
*/
|
||||
unsigned mbedtls_ct_uint_if(unsigned condition,
|
||||
static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,
|
||||
size_t if1,
|
||||
size_t if0);
|
||||
|
||||
/** Choose between two unsigned values.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* condition ? if1 : if0.
|
||||
*
|
||||
* \param condition Condition to test.
|
||||
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
|
||||
* \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
|
||||
*
|
||||
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
|
||||
*/
|
||||
static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,
|
||||
unsigned if1,
|
||||
unsigned if0);
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
|
||||
/** Conditionally assign a value without branches.
|
||||
/** Choose between two mbedtls_mpi_uint values.
|
||||
*
|
||||
* This is equivalent to `if ( condition ) dest = src`, but is likely
|
||||
* to be compiled to code using bitwise operation rather than a branch.
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \param n \p dest and \p src must be arrays of limbs of size n.
|
||||
* \param dest The MPI to conditionally assign to. This must point
|
||||
* to an initialized MPI.
|
||||
* \param src The MPI to be assigned from. This must point to an
|
||||
* initialized MPI.
|
||||
* \param condition Condition to test, must be 0 or 1.
|
||||
* condition ? if1 : if0.
|
||||
*
|
||||
* \param condition Condition to test.
|
||||
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
|
||||
* \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
|
||||
*
|
||||
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
|
||||
*/
|
||||
void mbedtls_ct_mpi_uint_cond_assign(size_t n,
|
||||
mbedtls_mpi_uint *dest,
|
||||
const mbedtls_mpi_uint *src,
|
||||
unsigned char condition);
|
||||
static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, \
|
||||
mbedtls_mpi_uint if1, \
|
||||
mbedtls_mpi_uint if0);
|
||||
|
||||
#endif /* MBEDTLS_BIGNUM_C */
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_BASE64_C)
|
||||
|
||||
/** Given a value in the range 0..63, return the corresponding Base64 digit.
|
||||
/** Choose between an unsigned value and 0.
|
||||
*
|
||||
* The implementation assumes that letters are consecutive (e.g. ASCII
|
||||
* but not EBCDIC).
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \param value A value in the range 0..63.
|
||||
* condition ? if1 : 0.
|
||||
*
|
||||
* \return A base64 digit converted from \p value.
|
||||
* Functionally equivalent to mbedtls_ct_uint_if(condition, if1, 0) but
|
||||
* results in smaller code size.
|
||||
*
|
||||
* \param condition Condition to test.
|
||||
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
|
||||
*
|
||||
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
|
||||
*/
|
||||
unsigned char mbedtls_ct_base64_enc_char(unsigned char value);
|
||||
static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1);
|
||||
|
||||
/** Given a Base64 digit, return its value.
|
||||
/** Choose between a size_t value and 0.
|
||||
*
|
||||
* If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
|
||||
* return -1.
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* The implementation assumes that letters are consecutive (e.g. ASCII
|
||||
* but not EBCDIC).
|
||||
* condition ? if1 : 0.
|
||||
*
|
||||
* \param c A base64 digit.
|
||||
* Functionally equivalent to mbedtls_ct_size_if(condition, if1, 0) but
|
||||
* results in smaller code size.
|
||||
*
|
||||
* \return The value of the base64 digit \p c.
|
||||
* \param condition Condition to test.
|
||||
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
|
||||
*
|
||||
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
|
||||
*/
|
||||
signed char mbedtls_ct_base64_dec_value(unsigned char c);
|
||||
static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1);
|
||||
|
||||
#endif /* MBEDTLS_BASE64_C */
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
|
||||
/** Conditional memcpy without branches.
|
||||
/** Choose between an mbedtls_mpi_uint value and 0.
|
||||
*
|
||||
* This is equivalent to `if ( c1 == c2 ) memcpy(dest, src, len)`, but is likely
|
||||
* to be compiled to code using bitwise operation rather than a branch.
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \param dest The pointer to conditionally copy to.
|
||||
* \param src The pointer to copy from. Shouldn't overlap with \p dest.
|
||||
* \param len The number of bytes to copy.
|
||||
* \param c1 The first value to analyze in the condition.
|
||||
* \param c2 The second value to analyze in the condition.
|
||||
* condition ? if1 : 0.
|
||||
*
|
||||
* Functionally equivalent to mbedtls_ct_mpi_uint_if(condition, if1, 0) but
|
||||
* results in smaller code size.
|
||||
*
|
||||
* \param condition Condition to test.
|
||||
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
|
||||
*
|
||||
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
|
||||
*/
|
||||
void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
|
||||
const unsigned char *src,
|
||||
size_t len,
|
||||
size_t c1, size_t c2);
|
||||
static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,
|
||||
mbedtls_mpi_uint if1);
|
||||
|
||||
/** Copy data from a secret position with constant flow.
|
||||
#endif
|
||||
|
||||
/** Constant-flow char selection
|
||||
*
|
||||
* This function copies \p len bytes from \p src_base + \p offset_secret to \p
|
||||
* dst, with a code flow and memory access pattern that does not depend on \p
|
||||
* offset_secret, but only on \p offset_min, \p offset_max and \p len.
|
||||
* Functionally equivalent to `memcpy(dst, src + offset_secret, len)`.
|
||||
* \param low Secret. Bottom of range
|
||||
* \param high Secret. Top of range
|
||||
* \param c Secret. Value to compare to range
|
||||
* \param t Secret. Value to return, if in range
|
||||
*
|
||||
* \return \p t if \p low <= \p c <= \p high, 0 otherwise.
|
||||
*/
|
||||
static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
|
||||
unsigned char high,
|
||||
unsigned char c,
|
||||
unsigned char t);
|
||||
|
||||
|
||||
/* ============================================================================
|
||||
* Block memory operations
|
||||
*/
|
||||
|
||||
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
|
||||
|
||||
/** Conditionally set a block of memory to zero.
|
||||
*
|
||||
* Regardless of the condition, every byte will be read once and written to
|
||||
* once.
|
||||
*
|
||||
* \param condition Secret. Condition to test.
|
||||
* \param buf Secret. Pointer to the start of the buffer.
|
||||
* \param len Number of bytes to set to zero.
|
||||
*
|
||||
* \warning Unlike mbedtls_platform_zeroize, this does not have the same guarantees
|
||||
* about not being optimised away if the memory is never read again.
|
||||
*/
|
||||
void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len);
|
||||
|
||||
/** Shift some data towards the left inside a buffer.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* memmove(start, start + offset, total - offset);
|
||||
* memset(start + (total - offset), 0, offset);
|
||||
*
|
||||
* Timing independence comes at the expense of performance.
|
||||
*
|
||||
* \param start Secret. Pointer to the start of the buffer.
|
||||
* \param total Total size of the buffer.
|
||||
* \param offset Secret. Offset from which to copy \p total - \p offset bytes.
|
||||
*/
|
||||
void mbedtls_ct_memmove_left(void *start,
|
||||
size_t total,
|
||||
size_t offset);
|
||||
|
||||
#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */
|
||||
|
||||
/** Conditional memcpy.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* if (condition) {
|
||||
* memcpy(dest, src1, len);
|
||||
* } else {
|
||||
* if (src2 != NULL)
|
||||
* memcpy(dest, src2, len);
|
||||
* }
|
||||
*
|
||||
* It will always read len bytes from src1.
|
||||
* If src2 != NULL, it will always read len bytes from src2.
|
||||
* If src2 == NULL, it will instead read len bytes from dest (as if src2 == dest).
|
||||
*
|
||||
* \param condition The condition
|
||||
* \param dest Secret. Destination pointer.
|
||||
* \param src1 Secret. Pointer to copy from (if \p condition == MBEDTLS_CT_TRUE).
|
||||
* This may be equal to \p dest, but may not overlap in other ways.
|
||||
* \param src2 Secret (contents only - may branch to determine if this parameter is NULL).
|
||||
* Pointer to copy from (if \p condition == MBEDTLS_CT_FALSE and \p src2 is not NULL). May be NULL.
|
||||
* This may be equal to \p dest, but may not overlap it in other ways. It may overlap with \p src1.
|
||||
* \param len Number of bytes to copy.
|
||||
*/
|
||||
void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition,
|
||||
unsigned char *dest,
|
||||
const unsigned char *src1,
|
||||
const unsigned char *src2,
|
||||
size_t len
|
||||
);
|
||||
|
||||
/** Copy data from a secret position.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* memcpy(dst, src + offset, len)
|
||||
*
|
||||
* This function copies \p len bytes from \p src_base + \p offset to \p
|
||||
* dst, with a code flow and memory access pattern that does not depend on
|
||||
* \p offset, but only on \p offset_min, \p offset_max and \p len.
|
||||
*
|
||||
* \note This function reads from \p dest, but the value that
|
||||
* is read does not influence the result and this
|
||||
|
@ -246,12 +464,12 @@ void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
|
|||
* positives from static or dynamic analyzers, especially
|
||||
* if \p dest is not initialized.
|
||||
*
|
||||
* \param dest The destination buffer. This must point to a writable
|
||||
* \param dest Secret. The destination buffer. This must point to a writable
|
||||
* buffer of at least \p len bytes.
|
||||
* \param src The base of the source buffer. This must point to a
|
||||
* \param src Secret. The base of the source buffer. This must point to a
|
||||
* readable buffer of at least \p offset_max + \p len
|
||||
* bytes. Shouldn't overlap with \p dest.
|
||||
* \param offset The offset in the source buffer from which to copy.
|
||||
* bytes. Shouldn't overlap with \p dest
|
||||
* \param offset Secret. The offset in the source buffer from which to copy.
|
||||
* This must be no less than \p offset_min and no greater
|
||||
* than \p offset_max.
|
||||
* \param offset_min The minimal value of \p offset.
|
||||
|
@ -265,99 +483,14 @@ void mbedtls_ct_memcpy_offset(unsigned char *dest,
|
|||
size_t offset_max,
|
||||
size_t len);
|
||||
|
||||
/** Compute the HMAC of variable-length data with constant flow.
|
||||
*
|
||||
* This function computes the HMAC of the concatenation of \p add_data and \p
|
||||
* data, and does with a code flow and memory access pattern that does not
|
||||
* depend on \p data_len_secret, but only on \p min_data_len and \p
|
||||
* max_data_len. In particular, this function always reads exactly \p
|
||||
* max_data_len bytes from \p data.
|
||||
*
|
||||
* \param ctx The HMAC context. It must have keys configured
|
||||
* with mbedtls_md_hmac_starts() and use one of the
|
||||
* following hashes: SHA-384, SHA-256, SHA-1 or MD-5.
|
||||
* It is reset using mbedtls_md_hmac_reset() after
|
||||
* the computation is complete to prepare for the
|
||||
* next computation.
|
||||
* \param add_data The first part of the message whose HMAC is being
|
||||
* calculated. This must point to a readable buffer
|
||||
* of \p add_data_len bytes.
|
||||
* \param add_data_len The length of \p add_data in bytes.
|
||||
* \param data The buffer containing the second part of the
|
||||
* message. This must point to a readable buffer
|
||||
* of \p max_data_len bytes.
|
||||
* \param data_len_secret The length of the data to process in \p data.
|
||||
* This must be no less than \p min_data_len and no
|
||||
* greater than \p max_data_len.
|
||||
* \param min_data_len The minimal length of the second part of the
|
||||
* message, read from \p data.
|
||||
* \param max_data_len The maximal length of the second part of the
|
||||
* message, read from \p data.
|
||||
* \param output The HMAC will be written here. This must point to
|
||||
* a writable buffer of sufficient size to hold the
|
||||
* HMAC value.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED
|
||||
* The hardware accelerator failed.
|
||||
/* Documented in include/mbedtls/constant_time.h. a and b are secret.
|
||||
|
||||
int mbedtls_ct_memcmp(const void *a,
|
||||
const void *b,
|
||||
size_t n);
|
||||
*/
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const unsigned char *add_data,
|
||||
size_t add_data_len,
|
||||
const unsigned char *data,
|
||||
size_t data_len_secret,
|
||||
size_t min_data_len,
|
||||
size_t max_data_len,
|
||||
unsigned char *output);
|
||||
#else
|
||||
int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
|
||||
const unsigned char *add_data,
|
||||
size_t add_data_len,
|
||||
const unsigned char *data,
|
||||
size_t data_len_secret,
|
||||
size_t min_data_len,
|
||||
size_t max_data_len,
|
||||
unsigned char *output);
|
||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
||||
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
|
||||
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
|
||||
|
||||
/** This function performs the unpadding part of a PKCS#1 v1.5 decryption
|
||||
* operation (EME-PKCS1-v1_5 decoding).
|
||||
*
|
||||
* \note The return value from this function is a sensitive value
|
||||
* (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen
|
||||
* in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING
|
||||
* is often a situation that an attacker can provoke and leaking which
|
||||
* one is the result is precisely the information the attacker wants.
|
||||
*
|
||||
* \param input The input buffer which is the payload inside PKCS#1v1.5
|
||||
* encryption padding, called the "encoded message EM"
|
||||
* by the terminology.
|
||||
* \param ilen The length of the payload in the \p input buffer.
|
||||
* \param output The buffer for the payload, called "message M" by the
|
||||
* PKCS#1 terminology. This must be a writable buffer of
|
||||
* length \p output_max_len bytes.
|
||||
* \param olen The address at which to store the length of
|
||||
* the payload. This must not be \c NULL.
|
||||
* \param output_max_len The length in bytes of the output buffer \p output.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
|
||||
* The output buffer is too small for the unpadded payload.
|
||||
* \return #MBEDTLS_ERR_RSA_INVALID_PADDING
|
||||
* The input doesn't contain properly formatted padding.
|
||||
*/
|
||||
int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
|
||||
size_t ilen,
|
||||
unsigned char *output,
|
||||
size_t output_max_len,
|
||||
size_t *olen);
|
||||
|
||||
#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
|
||||
/* Include the implementation of static inline functions above. */
|
||||
#include "constant_time_impl.h"
|
||||
|
||||
#endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
* \file constant_time_invasive.h
|
||||
*
|
||||
* \brief Constant-time module: interfaces for invasive testing only.
|
||||
*
|
||||
* The interfaces in this file are intended for testing purposes only.
|
||||
* They SHOULD NOT be made available in library integrations except when
|
||||
* building the library for testing.
|
||||
*/
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CONSTANT_TIME_INVASIVE_H
|
||||
#define MBEDTLS_CONSTANT_TIME_INVASIVE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS)
|
||||
|
||||
/** Turn a value into a mask:
|
||||
* - if \p low <= \p c <= \p high,
|
||||
* return the all-bits 1 mask, aka (unsigned) -1
|
||||
* - otherwise, return the all-bits 0 mask, aka 0
|
||||
*
|
||||
* \param low The value to analyze.
|
||||
* \param high The value to analyze.
|
||||
* \param c The value to analyze.
|
||||
*
|
||||
* \return All-bits-one if \p low <= \p c <= \p high, otherwise zero.
|
||||
*/
|
||||
unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low,
|
||||
unsigned char high,
|
||||
unsigned char c);
|
||||
|
||||
#endif /* MBEDTLS_TEST_HOOKS */
|
||||
|
||||
#endif /* MBEDTLS_CONSTANT_TIME_INVASIVE_H */
|
158
library/rsa.c
158
library/rsa.c
|
@ -56,6 +56,164 @@
|
|||
|
||||
#include "mbedtls/platform.h"
|
||||
|
||||
|
||||
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
|
||||
|
||||
/** This function performs the unpadding part of a PKCS#1 v1.5 decryption
|
||||
* operation (EME-PKCS1-v1_5 decoding).
|
||||
*
|
||||
* \note The return value from this function is a sensitive value
|
||||
* (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen
|
||||
* in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING
|
||||
* is often a situation that an attacker can provoke and leaking which
|
||||
* one is the result is precisely the information the attacker wants.
|
||||
*
|
||||
* \param input The input buffer which is the payload inside PKCS#1v1.5
|
||||
* encryption padding, called the "encoded message EM"
|
||||
* by the terminology.
|
||||
* \param ilen The length of the payload in the \p input buffer.
|
||||
* \param output The buffer for the payload, called "message M" by the
|
||||
* PKCS#1 terminology. This must be a writable buffer of
|
||||
* length \p output_max_len bytes.
|
||||
* \param olen The address at which to store the length of
|
||||
* the payload. This must not be \c NULL.
|
||||
* \param output_max_len The length in bytes of the output buffer \p output.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
|
||||
* The output buffer is too small for the unpadded payload.
|
||||
* \return #MBEDTLS_ERR_RSA_INVALID_PADDING
|
||||
* The input doesn't contain properly formatted padding.
|
||||
*/
|
||||
static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
|
||||
size_t ilen,
|
||||
unsigned char *output,
|
||||
size_t output_max_len,
|
||||
size_t *olen)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t i, plaintext_max_size;
|
||||
|
||||
/* The following variables take sensitive values: their value must
|
||||
* not leak into the observable behavior of the function other than
|
||||
* the designated outputs (output, olen, return value). Otherwise
|
||||
* this would open the execution of the function to
|
||||
* side-channel-based variants of the Bleichenbacher padding oracle
|
||||
* attack. Potential side channels include overall timing, memory
|
||||
* access patterns (especially visible to an adversary who has access
|
||||
* to a shared memory cache), and branches (especially visible to
|
||||
* an adversary who has access to a shared code cache or to a shared
|
||||
* branch predictor). */
|
||||
size_t pad_count = 0;
|
||||
mbedtls_ct_condition_t bad;
|
||||
mbedtls_ct_condition_t pad_done;
|
||||
size_t plaintext_size = 0;
|
||||
mbedtls_ct_condition_t output_too_large;
|
||||
|
||||
plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11
|
||||
: output_max_len;
|
||||
|
||||
/* Check and get padding length in constant time and constant
|
||||
* memory trace. The first byte must be 0. */
|
||||
bad = mbedtls_ct_bool(input[0]);
|
||||
|
||||
|
||||
/* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
|
||||
* where PS must be at least 8 nonzero bytes. */
|
||||
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(input[1], MBEDTLS_RSA_CRYPT));
|
||||
|
||||
/* Read the whole buffer. Set pad_done to nonzero if we find
|
||||
* the 0x00 byte and remember the padding length in pad_count. */
|
||||
pad_done = MBEDTLS_CT_FALSE;
|
||||
for (i = 2; i < ilen; i++) {
|
||||
mbedtls_ct_condition_t found = mbedtls_ct_uint_eq(input[i], 0);
|
||||
pad_done = mbedtls_ct_bool_or(pad_done, found);
|
||||
pad_count += mbedtls_ct_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1);
|
||||
}
|
||||
|
||||
/* If pad_done is still zero, there's no data, only unfinished padding. */
|
||||
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_not(pad_done));
|
||||
|
||||
/* There must be at least 8 bytes of padding. */
|
||||
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_gt(8, pad_count));
|
||||
|
||||
/* If the padding is valid, set plaintext_size to the number of
|
||||
* remaining bytes after stripping the padding. If the padding
|
||||
* is invalid, avoid leaking this fact through the size of the
|
||||
* output: use the maximum message size that fits in the output
|
||||
* buffer. Do it without branches to avoid leaking the padding
|
||||
* validity through timing. RSA keys are small enough that all the
|
||||
* size_t values involved fit in unsigned int. */
|
||||
plaintext_size = mbedtls_ct_uint_if(
|
||||
bad, (unsigned) plaintext_max_size,
|
||||
(unsigned) (ilen - pad_count - 3));
|
||||
|
||||
/* Set output_too_large to 0 if the plaintext fits in the output
|
||||
* buffer and to 1 otherwise. */
|
||||
output_too_large = mbedtls_ct_uint_gt(plaintext_size,
|
||||
plaintext_max_size);
|
||||
|
||||
/* Set ret without branches to avoid timing attacks. Return:
|
||||
* - INVALID_PADDING if the padding is bad (bad != 0).
|
||||
* - OUTPUT_TOO_LARGE if the padding is good but the decrypted
|
||||
* plaintext does not fit in the output buffer.
|
||||
* - 0 if the padding is correct. */
|
||||
ret = -(int) mbedtls_ct_uint_if(
|
||||
bad,
|
||||
(unsigned) (-(MBEDTLS_ERR_RSA_INVALID_PADDING)),
|
||||
mbedtls_ct_uint_if_else_0(
|
||||
output_too_large,
|
||||
(unsigned) (-(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE)))
|
||||
);
|
||||
|
||||
/* If the padding is bad or the plaintext is too large, zero the
|
||||
* data that we're about to copy to the output buffer.
|
||||
* We need to copy the same amount of data
|
||||
* from the same buffer whether the padding is good or not to
|
||||
* avoid leaking the padding validity through overall timing or
|
||||
* through memory or cache access patterns. */
|
||||
mbedtls_ct_zeroize_if(mbedtls_ct_bool_or(bad, output_too_large), input + 11, ilen - 11);
|
||||
|
||||
/* If the plaintext is too large, truncate it to the buffer size.
|
||||
* Copy anyway to avoid revealing the length through timing, because
|
||||
* revealing the length is as bad as revealing the padding validity
|
||||
* for a Bleichenbacher attack. */
|
||||
plaintext_size = mbedtls_ct_uint_if(output_too_large,
|
||||
(unsigned) plaintext_max_size,
|
||||
(unsigned) plaintext_size);
|
||||
|
||||
/* Move the plaintext to the leftmost position where it can start in
|
||||
* the working buffer, i.e. make it start plaintext_max_size from
|
||||
* the end of the buffer. Do this with a memory access trace that
|
||||
* does not depend on the plaintext size. After this move, the
|
||||
* starting location of the plaintext is no longer sensitive
|
||||
* information. */
|
||||
mbedtls_ct_memmove_left(input + ilen - plaintext_max_size,
|
||||
plaintext_max_size,
|
||||
plaintext_max_size - plaintext_size);
|
||||
|
||||
/* Finally copy the decrypted plaintext plus trailing zeros into the output
|
||||
* buffer. If output_max_len is 0, then output may be an invalid pointer
|
||||
* and the result of memcpy() would be undefined; prevent undefined
|
||||
* behavior making sure to depend only on output_max_len (the size of the
|
||||
* user-provided output buffer), which is independent from plaintext
|
||||
* length, validity of padding, success of the decryption, and other
|
||||
* secrets. */
|
||||
if (output_max_len != 0) {
|
||||
memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);
|
||||
}
|
||||
|
||||
/* Report the amount of data we copied to the output buffer. In case
|
||||
* of errors (bad padding or output too large), the value of *olen
|
||||
* when this function returns is not specified. Making it equivalent
|
||||
* to the good case limits the risks of leaking the padding validity. */
|
||||
*olen = plaintext_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
|
||||
|
||||
#if !defined(MBEDTLS_RSA_ALT)
|
||||
|
||||
int mbedtls_rsa_import(mbedtls_rsa_context *ctx,
|
||||
|
|
|
@ -2796,4 +2796,64 @@ static inline void mbedtls_ssl_session_clear_ticket_flags(
|
|||
int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl);
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
|
||||
/** Compute the HMAC of variable-length data with constant flow.
|
||||
*
|
||||
* This function computes the HMAC of the concatenation of \p add_data and \p
|
||||
* data, and does with a code flow and memory access pattern that does not
|
||||
* depend on \p data_len_secret, but only on \p min_data_len and \p
|
||||
* max_data_len. In particular, this function always reads exactly \p
|
||||
* max_data_len bytes from \p data.
|
||||
*
|
||||
* \param ctx The HMAC context. It must have keys configured
|
||||
* with mbedtls_md_hmac_starts() and use one of the
|
||||
* following hashes: SHA-384, SHA-256, SHA-1 or MD-5.
|
||||
* It is reset using mbedtls_md_hmac_reset() after
|
||||
* the computation is complete to prepare for the
|
||||
* next computation.
|
||||
* \param add_data The first part of the message whose HMAC is being
|
||||
* calculated. This must point to a readable buffer
|
||||
* of \p add_data_len bytes.
|
||||
* \param add_data_len The length of \p add_data in bytes.
|
||||
* \param data The buffer containing the second part of the
|
||||
* message. This must point to a readable buffer
|
||||
* of \p max_data_len bytes.
|
||||
* \param data_len_secret The length of the data to process in \p data.
|
||||
* This must be no less than \p min_data_len and no
|
||||
* greater than \p max_data_len.
|
||||
* \param min_data_len The minimal length of the second part of the
|
||||
* message, read from \p data.
|
||||
* \param max_data_len The maximal length of the second part of the
|
||||
* message, read from \p data.
|
||||
* \param output The HMAC will be written here. This must point to
|
||||
* a writable buffer of sufficient size to hold the
|
||||
* HMAC value.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED
|
||||
* The hardware accelerator failed.
|
||||
*/
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t mac_alg,
|
||||
const unsigned char *add_data,
|
||||
size_t add_data_len,
|
||||
const unsigned char *data,
|
||||
size_t data_len_secret,
|
||||
size_t min_data_len,
|
||||
size_t max_data_len,
|
||||
unsigned char *output);
|
||||
#else
|
||||
int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
|
||||
const unsigned char *add_data,
|
||||
size_t add_data_len,
|
||||
const unsigned char *data,
|
||||
size_t data_len_secret,
|
||||
size_t min_data_len,
|
||||
size_t max_data_len,
|
||||
unsigned char *output);
|
||||
#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */
|
||||
#endif /* MBEDTLS_TEST_HOOKS && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) */
|
||||
|
||||
#endif /* ssl_misc.h */
|
||||
|
|
|
@ -60,6 +60,234 @@ static int local_err_translation(psa_status_t status)
|
|||
#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
|
||||
#if defined(PSA_WANT_ALG_SHA_384)
|
||||
#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384)
|
||||
#elif defined(PSA_WANT_ALG_SHA_256)
|
||||
#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256)
|
||||
#else /* See check_config.h */
|
||||
#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1)
|
||||
#endif
|
||||
|
||||
MBEDTLS_STATIC_TESTABLE
|
||||
int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t mac_alg,
|
||||
const unsigned char *add_data,
|
||||
size_t add_data_len,
|
||||
const unsigned char *data,
|
||||
size_t data_len_secret,
|
||||
size_t min_data_len,
|
||||
size_t max_data_len,
|
||||
unsigned char *output)
|
||||
{
|
||||
/*
|
||||
* This function breaks the HMAC abstraction and uses psa_hash_clone()
|
||||
* extension in order to get constant-flow behaviour.
|
||||
*
|
||||
* HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
|
||||
* concatenation, and okey/ikey are the XOR of the key with some fixed bit
|
||||
* patterns (see RFC 2104, sec. 2).
|
||||
*
|
||||
* We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by
|
||||
* hashing up to minlen, then cloning the context, and for each byte up
|
||||
* to maxlen finishing up the hash computation, keeping only the
|
||||
* correct result.
|
||||
*
|
||||
* Then we only need to compute HASH(okey + inner_hash) and we're done.
|
||||
*/
|
||||
psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg);
|
||||
const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
|
||||
unsigned char key_buf[MAX_HASH_BLOCK_LENGTH];
|
||||
const size_t hash_size = PSA_HASH_LENGTH(hash_alg);
|
||||
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
|
||||
size_t hash_length;
|
||||
|
||||
unsigned char aux_out[PSA_HASH_MAX_SIZE];
|
||||
psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT;
|
||||
size_t offset;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t mac_key_length;
|
||||
size_t i;
|
||||
|
||||
#define PSA_CHK(func_call) \
|
||||
do { \
|
||||
status = (func_call); \
|
||||
if (status != PSA_SUCCESS) \
|
||||
goto cleanup; \
|
||||
} while (0)
|
||||
|
||||
/* Export MAC key
|
||||
* We assume key length is always exactly the output size
|
||||
* which is never more than the block size, thus we use block_size
|
||||
* as the key buffer size.
|
||||
*/
|
||||
PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length));
|
||||
|
||||
/* Calculate ikey */
|
||||
for (i = 0; i < mac_key_length; i++) {
|
||||
key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36);
|
||||
}
|
||||
for (; i < block_size; ++i) {
|
||||
key_buf[i] = 0x36;
|
||||
}
|
||||
|
||||
PSA_CHK(psa_hash_setup(&operation, hash_alg));
|
||||
|
||||
/* Now compute inner_hash = HASH(ikey + msg) */
|
||||
PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
|
||||
PSA_CHK(psa_hash_update(&operation, add_data, add_data_len));
|
||||
PSA_CHK(psa_hash_update(&operation, data, min_data_len));
|
||||
|
||||
/* Fill the hash buffer in advance with something that is
|
||||
* not a valid hash (barring an attack on the hash and
|
||||
* deliberately-crafted input), in case the caller doesn't
|
||||
* check the return status properly. */
|
||||
memset(output, '!', hash_size);
|
||||
|
||||
/* For each possible length, compute the hash up to that point */
|
||||
for (offset = min_data_len; offset <= max_data_len; offset++) {
|
||||
PSA_CHK(psa_hash_clone(&operation, &aux_operation));
|
||||
PSA_CHK(psa_hash_finish(&aux_operation, aux_out,
|
||||
PSA_HASH_MAX_SIZE, &hash_length));
|
||||
/* Keep only the correct inner_hash in the output buffer */
|
||||
mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret),
|
||||
output, aux_out, NULL, hash_size);
|
||||
|
||||
if (offset < max_data_len) {
|
||||
PSA_CHK(psa_hash_update(&operation, data + offset, 1));
|
||||
}
|
||||
}
|
||||
|
||||
/* Abort current operation to prepare for final operation */
|
||||
PSA_CHK(psa_hash_abort(&operation));
|
||||
|
||||
/* Calculate okey */
|
||||
for (i = 0; i < mac_key_length; i++) {
|
||||
key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C);
|
||||
}
|
||||
for (; i < block_size; ++i) {
|
||||
key_buf[i] = 0x5C;
|
||||
}
|
||||
|
||||
/* Now compute HASH(okey + inner_hash) */
|
||||
PSA_CHK(psa_hash_setup(&operation, hash_alg));
|
||||
PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
|
||||
PSA_CHK(psa_hash_update(&operation, output, hash_size));
|
||||
PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length));
|
||||
|
||||
#undef PSA_CHK
|
||||
|
||||
cleanup:
|
||||
mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH);
|
||||
mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE);
|
||||
|
||||
psa_hash_abort(&operation);
|
||||
psa_hash_abort(&aux_operation);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
#undef MAX_HASH_BLOCK_LENGTH
|
||||
|
||||
#else
|
||||
MBEDTLS_STATIC_TESTABLE
|
||||
int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
|
||||
const unsigned char *add_data,
|
||||
size_t add_data_len,
|
||||
const unsigned char *data,
|
||||
size_t data_len_secret,
|
||||
size_t min_data_len,
|
||||
size_t max_data_len,
|
||||
unsigned char *output)
|
||||
{
|
||||
/*
|
||||
* This function breaks the HMAC abstraction and uses the md_clone()
|
||||
* extension to the MD API in order to get constant-flow behaviour.
|
||||
*
|
||||
* HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
|
||||
* concatenation, and okey/ikey are the XOR of the key with some fixed bit
|
||||
* patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx.
|
||||
*
|
||||
* We'll first compute inner_hash = HASH(ikey + msg) by hashing up to
|
||||
* minlen, then cloning the context, and for each byte up to maxlen
|
||||
* finishing up the hash computation, keeping only the correct result.
|
||||
*
|
||||
* Then we only need to compute HASH(okey + inner_hash) and we're done.
|
||||
*/
|
||||
const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info);
|
||||
/* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5,
|
||||
* all of which have the same block size except SHA-384. */
|
||||
const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;
|
||||
const unsigned char * const ikey = ctx->hmac_ctx;
|
||||
const unsigned char * const okey = ikey + block_size;
|
||||
const size_t hash_size = mbedtls_md_get_size(ctx->md_info);
|
||||
|
||||
unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];
|
||||
mbedtls_md_context_t aux;
|
||||
size_t offset;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
mbedtls_md_init(&aux);
|
||||
|
||||
#define MD_CHK(func_call) \
|
||||
do { \
|
||||
ret = (func_call); \
|
||||
if (ret != 0) \
|
||||
goto cleanup; \
|
||||
} while (0)
|
||||
|
||||
MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0));
|
||||
|
||||
/* After hmac_start() of hmac_reset(), ikey has already been hashed,
|
||||
* so we can start directly with the message */
|
||||
MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len));
|
||||
MD_CHK(mbedtls_md_update(ctx, data, min_data_len));
|
||||
|
||||
/* Fill the hash buffer in advance with something that is
|
||||
* not a valid hash (barring an attack on the hash and
|
||||
* deliberately-crafted input), in case the caller doesn't
|
||||
* check the return status properly. */
|
||||
memset(output, '!', hash_size);
|
||||
|
||||
/* For each possible length, compute the hash up to that point */
|
||||
for (offset = min_data_len; offset <= max_data_len; offset++) {
|
||||
MD_CHK(mbedtls_md_clone(&aux, ctx));
|
||||
MD_CHK(mbedtls_md_finish(&aux, aux_out));
|
||||
/* Keep only the correct inner_hash in the output buffer */
|
||||
mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret),
|
||||
output, aux_out, NULL, hash_size);
|
||||
|
||||
if (offset < max_data_len) {
|
||||
MD_CHK(mbedtls_md_update(ctx, data + offset, 1));
|
||||
}
|
||||
}
|
||||
|
||||
/* The context needs to finish() before it starts() again */
|
||||
MD_CHK(mbedtls_md_finish(ctx, aux_out));
|
||||
|
||||
/* Now compute HASH(okey + inner_hash) */
|
||||
MD_CHK(mbedtls_md_starts(ctx));
|
||||
MD_CHK(mbedtls_md_update(ctx, okey, block_size));
|
||||
MD_CHK(mbedtls_md_update(ctx, output, hash_size));
|
||||
MD_CHK(mbedtls_md_finish(ctx, output));
|
||||
|
||||
/* Done, get ready for next time */
|
||||
MD_CHK(mbedtls_md_hmac_reset(ctx));
|
||||
|
||||
#undef MD_CHK
|
||||
|
||||
cleanup:
|
||||
mbedtls_md_free(&aux);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
||||
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
|
||||
static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl);
|
||||
|
||||
/*
|
||||
|
@ -1690,11 +1918,11 @@ hmac_failed_etm_enabled:
|
|||
padlen = data[rec->data_len - 1];
|
||||
|
||||
if (auth_done == 1) {
|
||||
const size_t mask = mbedtls_ct_size_mask_ge(
|
||||
const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge(
|
||||
rec->data_len,
|
||||
padlen + 1);
|
||||
correct &= mask;
|
||||
padlen &= mask;
|
||||
correct = mbedtls_ct_size_if_else_0(ge, correct);
|
||||
padlen = mbedtls_ct_size_if_else_0(ge, padlen);
|
||||
} else {
|
||||
#if defined(MBEDTLS_SSL_DEBUG_ALL)
|
||||
if (rec->data_len < transform->maclen + padlen + 1) {
|
||||
|
@ -1706,12 +1934,11 @@ hmac_failed_etm_enabled:
|
|||
padlen + 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
const size_t mask = mbedtls_ct_size_mask_ge(
|
||||
const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge(
|
||||
rec->data_len,
|
||||
transform->maclen + padlen + 1);
|
||||
correct &= mask;
|
||||
padlen &= mask;
|
||||
correct = mbedtls_ct_size_if_else_0(ge, correct);
|
||||
padlen = mbedtls_ct_size_if_else_0(ge, padlen);
|
||||
}
|
||||
|
||||
padlen++;
|
||||
|
@ -1740,19 +1967,20 @@ hmac_failed_etm_enabled:
|
|||
/* pad_count += (idx >= padding_idx) &&
|
||||
* (check[idx] == padlen - 1);
|
||||
*/
|
||||
const size_t mask = mbedtls_ct_size_mask_ge(idx, padding_idx);
|
||||
const size_t equal = mbedtls_ct_size_bool_eq(check[idx],
|
||||
padlen - 1);
|
||||
pad_count += mask & equal;
|
||||
const mbedtls_ct_condition_t a = mbedtls_ct_uint_ge(idx, padding_idx);
|
||||
size_t increment = mbedtls_ct_size_if_else_0(a, 1);
|
||||
const mbedtls_ct_condition_t b = mbedtls_ct_uint_eq(check[idx], padlen - 1);
|
||||
increment = mbedtls_ct_size_if_else_0(b, increment);
|
||||
pad_count += increment;
|
||||
}
|
||||
correct &= mbedtls_ct_size_bool_eq(pad_count, padlen);
|
||||
correct = mbedtls_ct_size_if_else_0(mbedtls_ct_uint_eq(pad_count, padlen), padlen);
|
||||
|
||||
#if defined(MBEDTLS_SSL_DEBUG_ALL)
|
||||
if (padlen > 0 && correct == 0) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("bad padding byte detected"));
|
||||
}
|
||||
#endif
|
||||
padlen &= mbedtls_ct_size_mask(correct);
|
||||
padlen = mbedtls_ct_size_if_else_0(mbedtls_ct_bool(correct), padlen);
|
||||
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
|
||||
|
||||
|
|
|
@ -3506,9 +3506,8 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
|
|||
unsigned char *pms = ssl->handshake->premaster + pms_offset;
|
||||
unsigned char ver[2];
|
||||
unsigned char fake_pms[48], peer_pms[48];
|
||||
unsigned char mask;
|
||||
size_t i, peer_pmslen;
|
||||
unsigned int diff;
|
||||
size_t peer_pmslen;
|
||||
mbedtls_ct_condition_t diff;
|
||||
|
||||
/* In case of a failure in decryption, the decryption may write less than
|
||||
* 2 bytes of output, but we always read the first two bytes. It doesn't
|
||||
|
@ -3537,13 +3536,10 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
|
|||
/* Avoid data-dependent branches while checking for invalid
|
||||
* padding, to protect against timing-based Bleichenbacher-type
|
||||
* attacks. */
|
||||
diff = (unsigned int) ret;
|
||||
diff |= peer_pmslen ^ 48;
|
||||
diff |= peer_pms[0] ^ ver[0];
|
||||
diff |= peer_pms[1] ^ ver[1];
|
||||
|
||||
/* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
|
||||
mask = mbedtls_ct_uint_mask(diff);
|
||||
diff = mbedtls_ct_bool(ret);
|
||||
diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pmslen, 48));
|
||||
diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[0], ver[0]));
|
||||
diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[1], ver[1]));
|
||||
|
||||
/*
|
||||
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
|
||||
|
@ -3562,7 +3558,7 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
|
|||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_DEBUG_ALL)
|
||||
if (diff != 0) {
|
||||
if (diff != MBEDTLS_CT_FALSE) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
|
||||
}
|
||||
#endif
|
||||
|
@ -3576,9 +3572,7 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
|
|||
|
||||
/* Set pms to either the true or the fake PMS, without
|
||||
* data-dependent branches. */
|
||||
for (i = 0; i < ssl->handshake->pmslen; i++) {
|
||||
pms[i] = (mask & fake_pms[i]) | ((~mask) & peer_pms[i]);
|
||||
}
|
||||
mbedtls_ct_memcpy_if(diff, pms, fake_pms, peer_pms, ssl->handshake->pmslen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,27 +1,3 @@
|
|||
mask_of_range empty (1..0)
|
||||
mask_of_range:1:0
|
||||
|
||||
mask_of_range empty (255..0)
|
||||
mask_of_range:255:0
|
||||
|
||||
mask_of_range empty (42..7)
|
||||
mask_of_range:42:7
|
||||
|
||||
mask_of_range 0..0
|
||||
mask_of_range:0:0
|
||||
|
||||
mask_of_range 42..42
|
||||
mask_of_range:42:42
|
||||
|
||||
mask_of_range 255..255
|
||||
mask_of_range:255:255
|
||||
|
||||
mask_of_range 0..255
|
||||
mask_of_range:0:255
|
||||
|
||||
mask_of_range 'A'..'Z'
|
||||
mask_of_range:65:90
|
||||
|
||||
enc_char (all digits)
|
||||
enc_chars:
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* BEGIN_HEADER */
|
||||
#include "mbedtls/base64.h"
|
||||
#include "base64_internal.h"
|
||||
#include "constant_time_internal.h"
|
||||
#include "constant_time_invasive.h"
|
||||
#include <test/constant_flow.h>
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS)
|
||||
|
@ -16,26 +16,6 @@ static const char base64_digits[] =
|
|||
* END_DEPENDENCIES
|
||||
*/
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
|
||||
void mask_of_range(int low_arg, int high_arg)
|
||||
{
|
||||
unsigned char low = low_arg, high = high_arg;
|
||||
unsigned c;
|
||||
for (c = 0; c <= 0xff; c++) {
|
||||
mbedtls_test_set_step(c);
|
||||
TEST_CF_SECRET(&c, sizeof(c));
|
||||
unsigned char m = mbedtls_ct_uchar_mask_of_range(low, high, c);
|
||||
TEST_CF_PUBLIC(&c, sizeof(c));
|
||||
TEST_CF_PUBLIC(&m, sizeof(m));
|
||||
if (low <= c && c <= high) {
|
||||
TEST_EQUAL(m, 0xff);
|
||||
} else {
|
||||
TEST_EQUAL(m, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
|
||||
void enc_chars()
|
||||
{
|
||||
|
|
|
@ -438,7 +438,7 @@ void mpi_lt_mpi_ct(int size_X, char *input_X,
|
|||
|
||||
TEST_ASSERT(mbedtls_mpi_lt_mpi_ct(&X, &Y, &ret) == input_err);
|
||||
if (input_err == 0) {
|
||||
TEST_ASSERT(ret == input_uret);
|
||||
TEST_EQUAL(ret, input_uret);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
|
|
@ -358,7 +358,7 @@ void mpi_core_lt_ct(char *input_X, char *input_Y, int exp_ret)
|
|||
TEST_CF_SECRET(Y, X_limbs * sizeof(mbedtls_mpi_uint));
|
||||
|
||||
ret = mbedtls_mpi_core_lt_ct(X, Y, X_limbs);
|
||||
TEST_EQUAL(ret, exp_ret);
|
||||
TEST_EQUAL(!!ret, exp_ret);
|
||||
|
||||
exit:
|
||||
mbedtls_free(X);
|
||||
|
@ -384,24 +384,24 @@ void mpi_core_uint_le_mpi(char *input_A)
|
|||
|
||||
TEST_CF_SECRET(A, A_limbs * sizeof(*A));
|
||||
|
||||
TEST_EQUAL(mbedtls_mpi_core_uint_le_mpi(0, A, A_limbs), 1);
|
||||
TEST_EQUAL(mbedtls_mpi_core_uint_le_mpi(A[0], A, A_limbs), 1);
|
||||
TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(0, A, A_limbs), 1);
|
||||
TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0], A, A_limbs), 1);
|
||||
|
||||
if (is_large) {
|
||||
TEST_EQUAL(mbedtls_mpi_core_uint_le_mpi(A[0] + 1,
|
||||
TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0] + 1,
|
||||
A, A_limbs), 1);
|
||||
TEST_EQUAL(mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1) >> 1,
|
||||
TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1) >> 1,
|
||||
A, A_limbs), 1);
|
||||
TEST_EQUAL(mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1),
|
||||
TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1),
|
||||
A, A_limbs), 1);
|
||||
} else {
|
||||
TEST_EQUAL(mbedtls_mpi_core_uint_le_mpi(A[0] + 1,
|
||||
TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0] + 1,
|
||||
A, A_limbs),
|
||||
A[0] + 1 <= A[0]);
|
||||
TEST_EQUAL(mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1) >> 1,
|
||||
TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1) >> 1,
|
||||
A, A_limbs),
|
||||
(mbedtls_mpi_uint) (-1) >> 1 <= A[0]);
|
||||
TEST_EQUAL(mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1),
|
||||
TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1),
|
||||
A, A_limbs),
|
||||
(mbedtls_mpi_uint) (-1) <= A[0]);
|
||||
}
|
||||
|
@ -447,7 +447,7 @@ void mpi_core_cond_assign(char *input_X,
|
|||
TEST_CF_SECRET(X, bytes);
|
||||
TEST_CF_SECRET(Y, bytes);
|
||||
|
||||
mbedtls_mpi_core_cond_assign(X, Y, copy_limbs, 1);
|
||||
mbedtls_mpi_core_cond_assign(X, Y, copy_limbs, mbedtls_ct_bool(1));
|
||||
|
||||
TEST_CF_PUBLIC(X, bytes);
|
||||
TEST_CF_PUBLIC(Y, bytes);
|
||||
|
@ -515,7 +515,7 @@ void mpi_core_cond_swap(char *input_X,
|
|||
TEST_CF_SECRET(X, bytes);
|
||||
TEST_CF_SECRET(Y, bytes);
|
||||
|
||||
mbedtls_mpi_core_cond_swap(X, Y, copy_limbs, 1);
|
||||
mbedtls_mpi_core_cond_swap(X, Y, copy_limbs, mbedtls_ct_bool(1));
|
||||
|
||||
TEST_CF_PUBLIC(X, bytes);
|
||||
TEST_CF_PUBLIC(Y, bytes);
|
||||
|
|
|
@ -134,7 +134,7 @@ void mpi_core_random_basic(int min, char *bound_bytes, int expected_ret)
|
|||
|
||||
if (expected_ret == 0) {
|
||||
TEST_EQUAL(0, mbedtls_mpi_core_lt_ct(result, lower_bound, limbs));
|
||||
TEST_EQUAL(1, mbedtls_mpi_core_lt_ct(result, upper_bound, limbs));
|
||||
TEST_ASSERT(0 != mbedtls_mpi_core_lt_ct(result, upper_bound, limbs));
|
||||
}
|
||||
|
||||
exit:
|
||||
|
@ -429,8 +429,7 @@ void mpi_mod_random_validation(int min, char *bound_hex,
|
|||
* size as the modulus, otherwise it's a mistake in the test data. */
|
||||
TEST_EQUAL(result_limbs, N.limbs);
|
||||
/* Sanity check: check that the result is in range */
|
||||
TEST_EQUAL(mbedtls_mpi_core_lt_ct(result_digits, N.p, N.limbs),
|
||||
1);
|
||||
TEST_ASSERT(0 != mbedtls_mpi_core_lt_ct(result_digits, N.p, N.limbs));
|
||||
/* Check result >= min (changes result) */
|
||||
TEST_EQUAL(mbedtls_mpi_core_sub_int(result_digits, result_digits, min,
|
||||
result_limbs),
|
||||
|
@ -444,8 +443,7 @@ void mpi_mod_random_validation(int min, char *bound_hex,
|
|||
mbedtls_test_rnd_std_rand, NULL),
|
||||
expected_ret);
|
||||
if (expected_ret == 0) {
|
||||
TEST_EQUAL(mbedtls_mpi_core_lt_ct(result_digits, N.p, N.limbs),
|
||||
1);
|
||||
TEST_ASSERT(0 != mbedtls_mpi_core_lt_ct(result_digits, N.p, N.limbs));
|
||||
TEST_EQUAL(mbedtls_mpi_core_sub_int(result_digits, result.p, min,
|
||||
result_limbs),
|
||||
0);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# these are the numbers we'd get with an empty plaintext and truncated HMAC
|
||||
Constant-flow memcpy from offset: small
|
||||
ssl_cf_memcpy_offset:0:5:10
|
||||
mbedtls_ct_memcpy_offset:0:5:10
|
||||
|
||||
# we could get this with 255-bytes plaintext and untruncated SHA-256
|
||||
Constant-flow memcpy from offset: medium
|
||||
ssl_cf_memcpy_offset:0:255:32
|
||||
mbedtls_ct_memcpy_offset:0:255:32
|
||||
|
||||
# we could get this with 255-bytes plaintext and untruncated SHA-384
|
||||
Constant-flow memcpy from offset: large
|
||||
ssl_cf_memcpy_offset:100:339:48
|
||||
mbedtls_ct_memcpy_offset:100:339:48
|
||||
|
||||
mbedtls_ct_memcmp NULL
|
||||
mbedtls_ct_memcmp_null
|
||||
|
@ -91,47 +91,611 @@ mbedtls_ct_memcmp:-1:17:2
|
|||
mbedtls_ct_memcmp len 17 offset 3
|
||||
mbedtls_ct_memcmp:-1:17:3
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 1 offset 0
|
||||
mbedtls_ct_memcpy_if_eq:1:1:0
|
||||
mbedtls_ct_memcpy_if len 1 offset 0
|
||||
mbedtls_ct_memcpy_if:1:1:0
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 1 offset 1
|
||||
mbedtls_ct_memcpy_if_eq:1:1:1
|
||||
mbedtls_ct_memcpy_if len 1 offset 1
|
||||
mbedtls_ct_memcpy_if:1:1:1
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 4 offset 0
|
||||
mbedtls_ct_memcpy_if_eq:1:1:0
|
||||
mbedtls_ct_memcpy_if len 4 offset 0
|
||||
mbedtls_ct_memcpy_if:1:1:0
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 4 offset 1
|
||||
mbedtls_ct_memcpy_if_eq:1:1:1
|
||||
mbedtls_ct_memcpy_if len 4 offset 1
|
||||
mbedtls_ct_memcpy_if:1:1:1
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 4 offset 2
|
||||
mbedtls_ct_memcpy_if_eq:1:1:2
|
||||
mbedtls_ct_memcpy_if len 4 offset 2
|
||||
mbedtls_ct_memcpy_if:1:1:2
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 4 offset 3
|
||||
mbedtls_ct_memcpy_if_eq:1:1:3
|
||||
mbedtls_ct_memcpy_if len 4 offset 3
|
||||
mbedtls_ct_memcpy_if:1:1:3
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 15 offset 0
|
||||
mbedtls_ct_memcpy_if_eq:1:15:0
|
||||
mbedtls_ct_memcpy_if len 15 offset 0
|
||||
mbedtls_ct_memcpy_if:1:15:0
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 15 offset 1
|
||||
mbedtls_ct_memcpy_if_eq:1:15:1
|
||||
mbedtls_ct_memcpy_if len 15 offset 1
|
||||
mbedtls_ct_memcpy_if:1:15:1
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 16 offset 0
|
||||
mbedtls_ct_memcpy_if_eq:1:16:0
|
||||
mbedtls_ct_memcpy_if len 16 offset 0
|
||||
mbedtls_ct_memcpy_if:1:16:0
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 16 offset 1
|
||||
mbedtls_ct_memcpy_if_eq:1:16:1
|
||||
mbedtls_ct_memcpy_if len 16 offset 1
|
||||
mbedtls_ct_memcpy_if:1:16:1
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 17 offset 0
|
||||
mbedtls_ct_memcpy_if_eq:1:17:0
|
||||
mbedtls_ct_memcpy_if len 17 offset 0
|
||||
mbedtls_ct_memcpy_if:1:17:0
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 17 offset 1
|
||||
mbedtls_ct_memcpy_if_eq:1:17:1
|
||||
mbedtls_ct_memcpy_if len 17 offset 1
|
||||
mbedtls_ct_memcpy_if:1:17:1
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 0 not eq
|
||||
mbedtls_ct_memcpy_if_eq:0:17:0
|
||||
mbedtls_ct_memcpy_if len 0 not eq
|
||||
mbedtls_ct_memcpy_if:0:17:0
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 5 offset 1 not eq
|
||||
mbedtls_ct_memcpy_if_eq:0:5:1
|
||||
mbedtls_ct_memcpy_if len 5 offset 1 not eq
|
||||
mbedtls_ct_memcpy_if:0:5:1
|
||||
|
||||
mbedtls_ct_memcpy_if_eq len 17 offset 3 not eq
|
||||
mbedtls_ct_memcpy_if_eq:0:17:3
|
||||
mbedtls_ct_memcpy_if len 17 offset 3 not eq
|
||||
mbedtls_ct_memcpy_if:0:17:3
|
||||
|
||||
mbedtls_ct_bool 0
|
||||
mbedtls_ct_bool:"0x0"
|
||||
|
||||
mbedtls_ct_bool 1
|
||||
mbedtls_ct_bool:"0x1"
|
||||
|
||||
mbedtls_ct_bool 4
|
||||
mbedtls_ct_bool:"0x4"
|
||||
|
||||
mbedtls_ct_bool 0xfffffff
|
||||
mbedtls_ct_bool:"0xfffffff"
|
||||
|
||||
mbedtls_ct_bool 0x7fffffff
|
||||
mbedtls_ct_bool:"0x7fffffff"
|
||||
|
||||
mbedtls_ct_bool 0xfffffffe
|
||||
mbedtls_ct_bool:"0xfffffffe"
|
||||
|
||||
mbedtls_ct_bool 0xffffffff
|
||||
mbedtls_ct_bool:"0xffffffff"
|
||||
|
||||
mbedtls_ct_bool 0x0fffffffffffffff
|
||||
mbedtls_ct_bool:"0x0fffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool 0x7fffffffffffffff
|
||||
mbedtls_ct_bool:"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool 0xffffffffffffffff
|
||||
mbedtls_ct_bool:"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x0 0x0
|
||||
mbedtls_ct_bool_xxx:"0x0":"0x0"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x0 0x1
|
||||
mbedtls_ct_bool_xxx:"0x0":"0x1"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x0 0x7fffffff
|
||||
mbedtls_ct_bool_xxx:"0x0":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x0 0xffffffff
|
||||
mbedtls_ct_bool_xxx:"0x0":"0xffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x0 0x7fffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0x0":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x0 0xffffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0x0":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x1 0x0
|
||||
mbedtls_ct_bool_xxx:"0x1":"0x0"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x1 0x1
|
||||
mbedtls_ct_bool_xxx:"0x1":"0x1"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x1 0x7fffffff
|
||||
mbedtls_ct_bool_xxx:"0x1":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x1 0xffffffff
|
||||
mbedtls_ct_bool_xxx:"0x1":"0xffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x1 0x7fffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0x1":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x1 0xffffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0x1":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffff 0x0
|
||||
mbedtls_ct_bool_xxx:"0x7fffffff":"0x0"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffff 0x1
|
||||
mbedtls_ct_bool_xxx:"0x7fffffff":"0x1"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffff 0x7fffffff
|
||||
mbedtls_ct_bool_xxx:"0x7fffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffff 0xffffffff
|
||||
mbedtls_ct_bool_xxx:"0x7fffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0x7fffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffff 0xffffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0x7fffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffff 0x0
|
||||
mbedtls_ct_bool_xxx:"0xffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffff 0x1
|
||||
mbedtls_ct_bool_xxx:"0xffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffff 0x7fffffff
|
||||
mbedtls_ct_bool_xxx:"0xffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffff 0xffffffff
|
||||
mbedtls_ct_bool_xxx:"0xffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0xffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0xffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffffffffffff 0x0
|
||||
mbedtls_ct_bool_xxx:"0x7fffffffffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffffffffffff 0x1
|
||||
mbedtls_ct_bool_xxx:"0x7fffffffffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffffffffffff 0x7fffffff
|
||||
mbedtls_ct_bool_xxx:"0x7fffffffffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffffffffffff 0xffffffff
|
||||
mbedtls_ct_bool_xxx:"0x7fffffffffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffffffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0x7fffffffffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0x7fffffffffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0x7fffffffffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffffffffffff 0x0
|
||||
mbedtls_ct_bool_xxx:"0xffffffffffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffffffffffff 0x1
|
||||
mbedtls_ct_bool_xxx:"0xffffffffffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffffffffffff 0x7fffffff
|
||||
mbedtls_ct_bool_xxx:"0xffffffffffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffffffffffff 0xffffffff
|
||||
mbedtls_ct_bool_xxx:"0xffffffffffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffffffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0xffffffffffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 0xffffffffffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_bool_xxx:"0xffffffffffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_bool_xxx 138 256
|
||||
mbedtls_ct_bool_xxx:"138":"256"
|
||||
|
||||
mbedtls_ct_bool_xxx 256 138
|
||||
mbedtls_ct_bool_xxx:"256":"138"
|
||||
|
||||
mbedtls_ct_bool_xxx 6 6
|
||||
mbedtls_ct_bool_xxx:"0x6":"0x6"
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 0 0
|
||||
mbedtls_ct_uchar_in_range_if:0:0:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 0 100
|
||||
mbedtls_ct_uchar_in_range_if:0:0:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 0 255
|
||||
mbedtls_ct_uchar_in_range_if:0:0:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 65 0
|
||||
mbedtls_ct_uchar_in_range_if:0:65:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 65 100
|
||||
mbedtls_ct_uchar_in_range_if:0:65:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 65 255
|
||||
mbedtls_ct_uchar_in_range_if:0:65:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 90 0
|
||||
mbedtls_ct_uchar_in_range_if:0:90:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 90 100
|
||||
mbedtls_ct_uchar_in_range_if:0:90:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 90 255
|
||||
mbedtls_ct_uchar_in_range_if:0:90:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 255 0
|
||||
mbedtls_ct_uchar_in_range_if:0:255:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 255 100
|
||||
mbedtls_ct_uchar_in_range_if:0:255:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 0 255 255
|
||||
mbedtls_ct_uchar_in_range_if:0:255:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 0 0
|
||||
mbedtls_ct_uchar_in_range_if:65:0:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 0 100
|
||||
mbedtls_ct_uchar_in_range_if:65:0:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 0 255
|
||||
mbedtls_ct_uchar_in_range_if:65:0:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 65 0
|
||||
mbedtls_ct_uchar_in_range_if:65:65:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 65 100
|
||||
mbedtls_ct_uchar_in_range_if:65:65:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 65 255
|
||||
mbedtls_ct_uchar_in_range_if:65:65:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 90 0
|
||||
mbedtls_ct_uchar_in_range_if:65:90:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 90 100
|
||||
mbedtls_ct_uchar_in_range_if:65:90:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 90 255
|
||||
mbedtls_ct_uchar_in_range_if:65:90:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 255 0
|
||||
mbedtls_ct_uchar_in_range_if:65:255:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 255 100
|
||||
mbedtls_ct_uchar_in_range_if:65:255:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 65 255 255
|
||||
mbedtls_ct_uchar_in_range_if:65:255:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 0 0
|
||||
mbedtls_ct_uchar_in_range_if:90:0:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 0 100
|
||||
mbedtls_ct_uchar_in_range_if:90:0:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 0 255
|
||||
mbedtls_ct_uchar_in_range_if:90:0:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 65 0
|
||||
mbedtls_ct_uchar_in_range_if:90:65:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 65 100
|
||||
mbedtls_ct_uchar_in_range_if:90:65:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 65 255
|
||||
mbedtls_ct_uchar_in_range_if:90:65:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 90 0
|
||||
mbedtls_ct_uchar_in_range_if:90:90:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 90 100
|
||||
mbedtls_ct_uchar_in_range_if:90:90:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 90 255
|
||||
mbedtls_ct_uchar_in_range_if:90:90:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 255 0
|
||||
mbedtls_ct_uchar_in_range_if:90:255:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 255 100
|
||||
mbedtls_ct_uchar_in_range_if:90:255:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 90 255 255
|
||||
mbedtls_ct_uchar_in_range_if:90:255:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 0 0
|
||||
mbedtls_ct_uchar_in_range_if:255:0:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 0 100
|
||||
mbedtls_ct_uchar_in_range_if:255:0:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 0 255
|
||||
mbedtls_ct_uchar_in_range_if:255:0:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 65 0
|
||||
mbedtls_ct_uchar_in_range_if:255:65:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 65 100
|
||||
mbedtls_ct_uchar_in_range_if:255:65:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 65 255
|
||||
mbedtls_ct_uchar_in_range_if:255:65:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 90 0
|
||||
mbedtls_ct_uchar_in_range_if:255:90:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 90 100
|
||||
mbedtls_ct_uchar_in_range_if:255:90:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 90 255
|
||||
mbedtls_ct_uchar_in_range_if:255:90:255
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 255 0
|
||||
mbedtls_ct_uchar_in_range_if:255:255:0
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 255 100
|
||||
mbedtls_ct_uchar_in_range_if:255:255:100
|
||||
|
||||
mbedtls_ct_uchar_in_range_if 255 255 255
|
||||
mbedtls_ct_uchar_in_range_if:255:255:255
|
||||
|
||||
mbedtls_ct_if 0x0 0x0 0x0
|
||||
mbedtls_ct_if:"0x0":"0x0":"0x0"
|
||||
|
||||
mbedtls_ct_if 0x0 0x0 0x1
|
||||
mbedtls_ct_if:"0x0":"0x0":"0x1"
|
||||
|
||||
mbedtls_ct_if 0x0 0x0 0x7fffffff
|
||||
mbedtls_ct_if:"0x0":"0x0":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x0 0xffffffff
|
||||
mbedtls_ct_if:"0x0":"0x0":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x0 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0x0":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x0 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0x0":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x1 0x0
|
||||
mbedtls_ct_if:"0x0":"0x1":"0x0"
|
||||
|
||||
mbedtls_ct_if 0x0 0x1 0x1
|
||||
mbedtls_ct_if:"0x0":"0x1":"0x1"
|
||||
|
||||
mbedtls_ct_if 0x0 0x1 0x7fffffff
|
||||
mbedtls_ct_if:"0x0":"0x1":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x1 0xffffffff
|
||||
mbedtls_ct_if:"0x0":"0x1":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x1 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0x1":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x1 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0x1":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffff 0x0
|
||||
mbedtls_ct_if:"0x0":"0x7fffffff":"0x0"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffff 0x1
|
||||
mbedtls_ct_if:"0x0":"0x7fffffff":"0x1"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffff 0x7fffffff
|
||||
mbedtls_ct_if:"0x0":"0x7fffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffff 0xffffffff
|
||||
mbedtls_ct_if:"0x0":"0x7fffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0x7fffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffff 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0x7fffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffff 0x0
|
||||
mbedtls_ct_if:"0x0":"0xffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffff 0x1
|
||||
mbedtls_ct_if:"0x0":"0xffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffff 0x7fffffff
|
||||
mbedtls_ct_if:"0x0":"0xffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffff 0xffffffff
|
||||
mbedtls_ct_if:"0x0":"0xffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0xffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0xffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffffffffffff 0x0
|
||||
mbedtls_ct_if:"0x0":"0x7fffffffffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffffffffffff 0x1
|
||||
mbedtls_ct_if:"0x0":"0x7fffffffffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffffffffffff 0x7fffffff
|
||||
mbedtls_ct_if:"0x0":"0x7fffffffffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffffffffffff 0xffffffff
|
||||
mbedtls_ct_if:"0x0":"0x7fffffffffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffffffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0x7fffffffffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0x7fffffffffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0x7fffffffffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffffffffffff 0x0
|
||||
mbedtls_ct_if:"0x0":"0xffffffffffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffffffffffff 0x1
|
||||
mbedtls_ct_if:"0x0":"0xffffffffffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffffffffffff 0x7fffffff
|
||||
mbedtls_ct_if:"0x0":"0xffffffffffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffffffffffff 0xffffffff
|
||||
mbedtls_ct_if:"0x0":"0xffffffffffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffffffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0xffffffffffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0x0 0xffffffffffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0x0":"0xffffffffffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x0 0x0
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x0":"0x0"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x0 0x1
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x0":"0x1"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x0 0x7fffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x0":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x0 0xffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x0":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x0 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x0":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x0 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x0":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x1 0x0
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x1":"0x0"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x1 0x1
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x1":"0x1"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x1 0x7fffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x1":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x1 0xffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x1":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x1 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x1":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x1 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x1":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffff 0x0
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffff":"0x0"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffff 0x1
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffff":"0x1"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffff 0x7fffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffff 0xffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffff 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffff 0x0
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffff 0x1
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffff 0x7fffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffff 0xffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffffffffffff 0x0
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffffffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffffffffffff 0x1
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffffffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffffffffffff 0x7fffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffffffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffffffffffff 0xffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffffffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffffffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0x7fffffffffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0x7fffffffffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0x0
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0x0"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0x1
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0x1"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0x7fffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0x7fffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0xffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0xffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0x7fffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0x7fffffffffffffff"
|
||||
|
||||
mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff
|
||||
mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0xffffffffffffffff"
|
||||
|
||||
mbedtls_ct_zeroize_if 0x0 0
|
||||
mbedtls_ct_zeroize_if:"0x0":0
|
||||
|
||||
mbedtls_ct_zeroize_if 0x0 1
|
||||
mbedtls_ct_zeroize_if:"0x0":1
|
||||
|
||||
mbedtls_ct_zeroize_if 0x0 1024
|
||||
mbedtls_ct_zeroize_if:"0x0":1024
|
||||
|
||||
mbedtls_ct_zeroize_if 0xffffffffffffffff 0
|
||||
mbedtls_ct_zeroize_if:"0xffffffffffffffff":0
|
||||
|
||||
mbedtls_ct_zeroize_if 0xffffffffffffffff 1
|
||||
mbedtls_ct_zeroize_if:"0xffffffffffffffff":1
|
||||
|
||||
mbedtls_ct_zeroize_if 0xffffffffffffffff 4
|
||||
mbedtls_ct_zeroize_if:"0xffffffffffffffff":4
|
||||
|
||||
mbedtls_ct_zeroize_if 0xffffffffffffffff 5
|
||||
mbedtls_ct_zeroize_if:"0xffffffffffffffff":5
|
||||
|
||||
mbedtls_ct_zeroize_if 0xffffffffffffffff 7
|
||||
mbedtls_ct_zeroize_if:"0xffffffffffffffff":7
|
||||
|
||||
mbedtls_ct_zeroize_if 0xffffffffffffffff 8
|
||||
mbedtls_ct_zeroize_if:"0xffffffffffffffff":8
|
||||
|
||||
mbedtls_ct_zeroize_if 0xffffffffffffffff 9
|
||||
mbedtls_ct_zeroize_if:"0xffffffffffffffff":9
|
||||
|
||||
mbedtls_ct_zeroize_if 0xffffffffffffffff 1024
|
||||
mbedtls_ct_zeroize_if:"0xffffffffffffffff":1024
|
||||
|
||||
mbedtls_ct_memmove_left 0 0
|
||||
mbedtls_ct_memmove_left:0:0
|
||||
|
||||
mbedtls_ct_memmove_left 1 0
|
||||
mbedtls_ct_memmove_left:1:0
|
||||
|
||||
mbedtls_ct_memmove_left 1 1
|
||||
mbedtls_ct_memmove_left:1:1
|
||||
|
||||
mbedtls_ct_memmove_left 16 0
|
||||
mbedtls_ct_memmove_left:16:0
|
||||
|
||||
mbedtls_ct_memmove_left 16 1
|
||||
mbedtls_ct_memmove_left:16:1
|
||||
|
||||
mbedtls_ct_memmove_left 16 4
|
||||
mbedtls_ct_memmove_left:16:4
|
||||
|
||||
mbedtls_ct_memmove_left 16 15
|
||||
mbedtls_ct_memmove_left:16:15
|
||||
|
||||
mbedtls_ct_memmove_left 16 16
|
||||
mbedtls_ct_memmove_left:16:16
|
||||
|
|
|
@ -8,9 +8,15 @@
|
|||
* under MSan or Valgrind will detect a non-constant-time implementation.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <mbedtls/bignum.h>
|
||||
#include <mbedtls/constant_time.h>
|
||||
#include <constant_time_internal.h>
|
||||
#include <constant_time_invasive.h>
|
||||
|
||||
#include <test/constant_flow.h>
|
||||
/* END_HEADER */
|
||||
|
@ -25,6 +31,147 @@ void mbedtls_ct_memcmp_null()
|
|||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void mbedtls_ct_bool(char *input)
|
||||
{
|
||||
mbedtls_ct_uint_t v = (mbedtls_ct_uint_t) strtoull(input, NULL, 16);
|
||||
TEST_ASSERT(errno == 0);
|
||||
|
||||
mbedtls_ct_condition_t expected = (v != 0) ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_CF_SECRET(&v, sizeof(v));
|
||||
TEST_EQUAL(mbedtls_ct_bool(v), expected);
|
||||
TEST_CF_PUBLIC(&v, sizeof(v));
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void mbedtls_ct_bool_xxx(char *x_str, char *y_str)
|
||||
{
|
||||
mbedtls_ct_uint_t x = strtoull(x_str, NULL, 0);
|
||||
mbedtls_ct_uint_t y = strtoull(y_str, NULL, 0);
|
||||
|
||||
mbedtls_ct_uint_t x1 = x;
|
||||
mbedtls_ct_uint_t y1 = y;
|
||||
|
||||
TEST_CF_SECRET(&x, sizeof(x));
|
||||
TEST_CF_SECRET(&y, sizeof(y));
|
||||
|
||||
mbedtls_ct_condition_t expected = x1 ? MBEDTLS_CT_FALSE : MBEDTLS_CT_TRUE;
|
||||
TEST_EQUAL(mbedtls_ct_bool_not(mbedtls_ct_bool(x)), expected);
|
||||
|
||||
expected = x1 != y1 ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_uint_ne(x, y), expected);
|
||||
|
||||
expected = x1 == y1 ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_uint_eq(x, y), expected);
|
||||
|
||||
expected = x1 > y1 ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_uint_gt(x, y), expected);
|
||||
|
||||
expected = x1 < y1 ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_uint_lt(x, y), expected);
|
||||
|
||||
expected = x1 >= y1 ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_uint_ge(x, y), expected);
|
||||
|
||||
expected = x1 <= y1 ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_uint_le(x, y), expected);
|
||||
|
||||
expected = (!!x1) ^ (!!y1) ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_bool_xor(mbedtls_ct_bool(x), mbedtls_ct_bool(y)), expected);
|
||||
|
||||
expected = (!!x1) && (!!y1) ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_bool_and(mbedtls_ct_bool(x), mbedtls_ct_bool(y)), expected);
|
||||
|
||||
expected = (!!x1) || (!!y1) ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE;
|
||||
TEST_EQUAL(mbedtls_ct_bool_or(mbedtls_ct_bool(x), mbedtls_ct_bool(y)), expected);
|
||||
|
||||
TEST_CF_PUBLIC(&x, sizeof(x));
|
||||
TEST_CF_PUBLIC(&y, sizeof(y));
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_BASE64_C */
|
||||
void mbedtls_ct_uchar_in_range_if(int li, int hi, int ti)
|
||||
{
|
||||
unsigned char l = li, h = hi, t = ti;
|
||||
|
||||
for (unsigned x = 0; x <= 255; x++) {
|
||||
unsigned char expected = (x >= l) && (x <= h) ? t : 0;
|
||||
|
||||
TEST_CF_SECRET(&x, sizeof(x));
|
||||
TEST_CF_SECRET(&l, sizeof(l));
|
||||
TEST_CF_SECRET(&h, sizeof(h));
|
||||
TEST_CF_SECRET(&t, sizeof(t));
|
||||
|
||||
TEST_EQUAL(mbedtls_ct_uchar_in_range_if(l, h, (unsigned char) x, t), expected);
|
||||
|
||||
TEST_CF_PUBLIC(&x, sizeof(x));
|
||||
TEST_CF_PUBLIC(&l, sizeof(l));
|
||||
TEST_CF_PUBLIC(&h, sizeof(h));
|
||||
TEST_CF_PUBLIC(&t, sizeof(t));
|
||||
}
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void mbedtls_ct_if(char *c_str, char *t_str, char *f_str)
|
||||
{
|
||||
mbedtls_ct_condition_t c = mbedtls_ct_bool(strtoull(c_str, NULL, 16));
|
||||
mbedtls_ct_uint_t t = (mbedtls_ct_uint_t) strtoull(t_str, NULL, 16);
|
||||
mbedtls_ct_uint_t f = (mbedtls_ct_uint_t) strtoull(f_str, NULL, 16);
|
||||
|
||||
mbedtls_ct_uint_t expected = c ? t : f;
|
||||
mbedtls_ct_uint_t expected0 = c ? t : 0;
|
||||
|
||||
TEST_CF_SECRET(&c, sizeof(c));
|
||||
TEST_CF_SECRET(&t, sizeof(t));
|
||||
TEST_CF_SECRET(&f, sizeof(f));
|
||||
|
||||
TEST_EQUAL(mbedtls_ct_if(c, t, f), expected);
|
||||
TEST_EQUAL(mbedtls_ct_size_if(c, t, f), (size_t) expected);
|
||||
TEST_EQUAL(mbedtls_ct_uint_if(c, t, f), (unsigned) expected);
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
TEST_EQUAL(mbedtls_ct_mpi_uint_if(c, t, f), (mbedtls_mpi_uint) expected);
|
||||
#endif
|
||||
|
||||
TEST_EQUAL(mbedtls_ct_uint_if_else_0(c, t), (unsigned) expected0);
|
||||
TEST_EQUAL(mbedtls_ct_size_if_else_0(c, (size_t) t), (size_t) expected0);
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
TEST_EQUAL(mbedtls_ct_mpi_uint_if_else_0(c, t), (mbedtls_mpi_uint) expected0);
|
||||
#endif
|
||||
|
||||
TEST_CF_PUBLIC(&c, sizeof(c));
|
||||
TEST_CF_PUBLIC(&t, sizeof(t));
|
||||
TEST_CF_PUBLIC(&f, sizeof(f));
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:!MBEDTLS_RSA_ALT */
|
||||
void mbedtls_ct_zeroize_if(char *c_str, int len)
|
||||
{
|
||||
uint8_t *buf = NULL;
|
||||
mbedtls_ct_condition_t c = mbedtls_ct_bool(strtoull(c_str, NULL, 16));
|
||||
|
||||
TEST_CALLOC(buf, len);
|
||||
for (size_t i = 0; i < (size_t) len; i++) {
|
||||
buf[i] = 1;
|
||||
}
|
||||
|
||||
TEST_CF_SECRET(&c, sizeof(c));
|
||||
TEST_CF_SECRET(buf, len);
|
||||
mbedtls_ct_zeroize_if(c, buf, len);
|
||||
TEST_CF_PUBLIC(&c, sizeof(c));
|
||||
TEST_CF_PUBLIC(buf, len);
|
||||
|
||||
for (size_t i = 0; i < (size_t) len; i++) {
|
||||
TEST_EQUAL(buf[i], c != 0 ? 0 : 1);
|
||||
}
|
||||
exit:
|
||||
mbedtls_free(buf);
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void mbedtls_ct_memcmp(int same, int size, int offset)
|
||||
{
|
||||
|
@ -32,9 +179,6 @@ void mbedtls_ct_memcmp(int same, int size, int offset)
|
|||
TEST_CALLOC(a, size + offset);
|
||||
TEST_CALLOC(b, size + offset);
|
||||
|
||||
TEST_CF_SECRET(a + offset, size);
|
||||
TEST_CF_SECRET(b + offset, size);
|
||||
|
||||
/* Construct data that matches, if same == -1, otherwise
|
||||
* same gives the number of bytes (after the initial offset)
|
||||
* that will match; after that it will differ.
|
||||
|
@ -49,9 +193,15 @@ void mbedtls_ct_memcmp(int same, int size, int offset)
|
|||
}
|
||||
|
||||
int reference = memcmp(a + offset, b + offset, size);
|
||||
|
||||
TEST_CF_SECRET(a, size + offset);
|
||||
TEST_CF_SECRET(b, size + offset);
|
||||
|
||||
int actual = mbedtls_ct_memcmp(a + offset, b + offset, size);
|
||||
TEST_CF_PUBLIC(a + offset, size);
|
||||
TEST_CF_PUBLIC(b + offset, size);
|
||||
|
||||
TEST_CF_PUBLIC(a, size + offset);
|
||||
TEST_CF_PUBLIC(b, size + offset);
|
||||
TEST_CF_PUBLIC(&actual, sizeof(actual));
|
||||
|
||||
if (same == -1 || same >= size) {
|
||||
TEST_ASSERT(reference == 0);
|
||||
|
@ -66,59 +216,139 @@ exit:
|
|||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
void mbedtls_ct_memcpy_if_eq(int eq, int size, int offset)
|
||||
/* BEGIN_CASE */
|
||||
void mbedtls_ct_memcpy_if(int eq, int size, int offset)
|
||||
{
|
||||
uint8_t *src = NULL, *result = NULL, *expected = NULL;
|
||||
uint8_t *src = NULL, *src2 = NULL, *result = NULL, *expected = NULL;
|
||||
TEST_CALLOC(src, size + offset);
|
||||
TEST_CALLOC(src2, size + offset);
|
||||
TEST_CALLOC(result, size + offset);
|
||||
TEST_CALLOC(expected, size + offset);
|
||||
|
||||
/* Apply offset to result only */
|
||||
for (int i = 0; i < size + offset; i++) {
|
||||
src[i] = 1;
|
||||
result[i] = 0xff;
|
||||
expected[i] = eq ? 1 : 0xff;
|
||||
}
|
||||
|
||||
int one, secret_eq;
|
||||
TEST_CF_SECRET(&one, sizeof(one));
|
||||
int secret_eq = eq;
|
||||
TEST_CF_SECRET(&secret_eq, sizeof(secret_eq));
|
||||
one = 1;
|
||||
secret_eq = eq;
|
||||
TEST_CF_SECRET(src, size + offset);
|
||||
TEST_CF_SECRET(result, size + offset);
|
||||
|
||||
mbedtls_ct_memcpy_if_eq(result + offset, src, size, secret_eq, one);
|
||||
mbedtls_ct_memcpy_if(mbedtls_ct_bool(secret_eq), result + offset, src, NULL, size);
|
||||
|
||||
TEST_CF_PUBLIC(&one, sizeof(one));
|
||||
TEST_CF_PUBLIC(&secret_eq, sizeof(secret_eq));
|
||||
TEST_CF_PUBLIC(src, size + offset);
|
||||
TEST_CF_PUBLIC(result, size + offset);
|
||||
|
||||
TEST_MEMORY_COMPARE(expected, size, result + offset, size);
|
||||
|
||||
|
||||
/* Apply offset to src only */
|
||||
for (int i = 0; i < size + offset; i++) {
|
||||
src[i] = 1;
|
||||
result[i] = 0xff;
|
||||
expected[i] = eq ? 1 : 0xff;
|
||||
}
|
||||
|
||||
TEST_CF_SECRET(&one, sizeof(one));
|
||||
TEST_CF_SECRET(&secret_eq, sizeof(secret_eq));
|
||||
one = 1;
|
||||
secret_eq = eq;
|
||||
TEST_CF_SECRET(src, size + offset);
|
||||
TEST_CF_SECRET(result, size + offset);
|
||||
|
||||
mbedtls_ct_memcpy_if_eq(result, src + offset, size, secret_eq, one);
|
||||
mbedtls_ct_memcpy_if(mbedtls_ct_bool(secret_eq), result, src + offset, NULL, size);
|
||||
|
||||
TEST_CF_PUBLIC(&one, sizeof(one));
|
||||
TEST_CF_PUBLIC(&secret_eq, sizeof(secret_eq));
|
||||
TEST_CF_PUBLIC(src, size + offset);
|
||||
TEST_CF_PUBLIC(result, size + offset);
|
||||
|
||||
TEST_MEMORY_COMPARE(expected, size, result, size);
|
||||
|
||||
|
||||
/* Apply offset to src and src2 */
|
||||
for (int i = 0; i < size + offset; i++) {
|
||||
src[i] = 1;
|
||||
src2[i] = 2;
|
||||
result[i] = 0xff;
|
||||
expected[i] = eq ? 1 : 2;
|
||||
}
|
||||
|
||||
TEST_CF_SECRET(&secret_eq, sizeof(secret_eq));
|
||||
TEST_CF_SECRET(src, size + offset);
|
||||
TEST_CF_SECRET(src2, size + offset);
|
||||
TEST_CF_SECRET(result, size + offset);
|
||||
|
||||
mbedtls_ct_memcpy_if(mbedtls_ct_bool(secret_eq), result, src + offset, src2 + offset, size);
|
||||
|
||||
TEST_CF_PUBLIC(&secret_eq, sizeof(secret_eq));
|
||||
TEST_CF_PUBLIC(src, size + offset);
|
||||
TEST_CF_SECRET(src2, size + offset);
|
||||
TEST_CF_PUBLIC(result, size + offset);
|
||||
|
||||
TEST_MEMORY_COMPARE(expected, size, result, size);
|
||||
|
||||
|
||||
/* result == src == dest */
|
||||
for (int i = 0; i < size + offset; i++) {
|
||||
src[i] = 2;
|
||||
expected[i] = 2;
|
||||
}
|
||||
|
||||
TEST_CF_SECRET(&secret_eq, sizeof(secret_eq));
|
||||
TEST_CF_SECRET(src, size + offset);
|
||||
TEST_CF_SECRET(result, size + offset);
|
||||
|
||||
mbedtls_ct_memcpy_if(mbedtls_ct_bool(secret_eq), src + offset, src + offset, src + offset,
|
||||
size);
|
||||
|
||||
TEST_CF_PUBLIC(&secret_eq, sizeof(secret_eq));
|
||||
TEST_CF_PUBLIC(src, size + offset);
|
||||
TEST_CF_PUBLIC(result, size + offset);
|
||||
|
||||
TEST_MEMORY_COMPARE(expected, size, src + offset, size);
|
||||
exit:
|
||||
mbedtls_free(src);
|
||||
mbedtls_free(src2);
|
||||
mbedtls_free(result);
|
||||
mbedtls_free(expected);
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
|
||||
void ssl_cf_memcpy_offset(int offset_min, int offset_max, int len)
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:!MBEDTLS_RSA_ALT */
|
||||
void mbedtls_ct_memmove_left(int len, int offset)
|
||||
{
|
||||
size_t l = (size_t) len;
|
||||
size_t o = (size_t) offset;
|
||||
|
||||
uint8_t *buf = NULL, *buf_expected = NULL;
|
||||
TEST_CALLOC(buf, l);
|
||||
TEST_CALLOC(buf_expected, l);
|
||||
|
||||
for (size_t i = 0; i < l; i++) {
|
||||
buf[i] = (uint8_t) i;
|
||||
buf_expected[i] = buf[i];
|
||||
}
|
||||
|
||||
TEST_CF_SECRET(&o, sizeof(o));
|
||||
TEST_CF_SECRET(buf, l);
|
||||
mbedtls_ct_memmove_left(buf, l, o);
|
||||
TEST_CF_PUBLIC(&o, sizeof(o));
|
||||
TEST_CF_PUBLIC(buf, l);
|
||||
|
||||
if (l > 0) {
|
||||
memmove(buf_expected, buf_expected + o, l - o);
|
||||
memset(buf_expected + (l - o), 0, o);
|
||||
TEST_ASSERT(memcmp(buf, buf_expected, l) == 0);
|
||||
}
|
||||
exit:
|
||||
mbedtls_free(buf);
|
||||
mbedtls_free(buf_expected);
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void mbedtls_ct_memcpy_offset(int offset_min, int offset_max, int len)
|
||||
{
|
||||
unsigned char *dst = NULL;
|
||||
unsigned char *src = NULL;
|
||||
|
@ -135,9 +365,12 @@ void ssl_cf_memcpy_offset(int offset_min, int offset_max, int len)
|
|||
mbedtls_test_set_step((int) secret);
|
||||
|
||||
TEST_CF_SECRET(&secret, sizeof(secret));
|
||||
TEST_CF_SECRET(src, len);
|
||||
TEST_CF_SECRET(dst, len);
|
||||
mbedtls_ct_memcpy_offset(dst, src, secret,
|
||||
offset_min, offset_max, len);
|
||||
TEST_CF_PUBLIC(&secret, sizeof(secret));
|
||||
TEST_CF_PUBLIC(src, len);
|
||||
TEST_CF_PUBLIC(dst, len);
|
||||
|
||||
TEST_MEMORY_COMPARE(dst, len, src + secret, len);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <test/constant_flow.h>
|
||||
/* END_HEADER */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_MAC:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
|
||||
void ssl_cf_hmac(int hash)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -1622,7 +1622,7 @@ void ecp_mod_random(int id, int ctype)
|
|||
TEST_EQUAL(0, mbedtls_mpi_mod_random(&rX, 1, &m,
|
||||
mbedtls_test_rnd_std_rand, NULL));
|
||||
|
||||
TEST_ASSERT(mbedtls_mpi_core_lt_ct(rX.p, m.p, limbs) == 1);
|
||||
TEST_ASSERT(mbedtls_mpi_core_lt_ct(rX.p, m.p, limbs) == MBEDTLS_CT_TRUE);
|
||||
|
||||
exit:
|
||||
mbedtls_mpi_mod_modulus_free(&m);
|
||||
|
|
Loading…
Reference in a new issue