1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-08-01 10:06:53 +03:00

Merge pull request #7578 from daverodgman/safer-ct5

Improve constant-time interface
This commit is contained in:
Manuel Pégourié-Gonnard
2023-08-10 16:57:39 +00:00
committed by GitHub
24 changed files with 2412 additions and 1369 deletions

View File

@ -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;
}