mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-01-06 11:41:12 +03:00
Merge pull request #7578 from daverodgman/safer-ct5
Improve constant-time interface
This commit is contained in:
@@ -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,
|
||||
const mbedtls_mpi_uint *A,
|
||||
size_t A_limbs)
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user