1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-29 11:41:15 +03:00

Merge pull request #6289 from gabor-mezei-arm/6237_Add_conditional_assign_and_swap_for_bignum

Bignum: Add safe conditional assign and swap for the new MPI types
This commit is contained in:
Gilles Peskine
2022-10-19 15:51:19 +02:00
committed by GitHub
7 changed files with 548 additions and 19 deletions

View File

@ -25,6 +25,7 @@
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "constant_time_internal.h"
#include "mbedtls/platform.h"
@ -153,6 +154,36 @@ void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
}
}
void mbedtls_mpi_core_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned char assign )
{
if( X == A )
return;
mbedtls_ct_mpi_uint_cond_assign( limbs, X, A, assign );
}
void mbedtls_mpi_core_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
size_t limbs,
unsigned char 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 );
}
}
int mbedtls_mpi_core_read_le( mbedtls_mpi_uint *X,
size_t X_limbs,
const unsigned char *input,

View File

@ -74,6 +74,58 @@ size_t mbedtls_mpi_core_bitlen( const mbedtls_mpi_uint *A, size_t A_limbs );
void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
size_t A_limbs );
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether assignment was done or not.
*
* \param[out] X The address of the destination MPI.
* This must be initialized. Must have enough limbs to
* store the full value of \p A.
* \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.
*
* \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 );
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
* whether the swap was done or not.
*
* \param[in,out] X The address of the first MPI.
* This must be initialized.
* \param[in,out] Y The address of the second MPI.
* 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.
*
* \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 );
/** Import X from unsigned binary data, little-endian.
*
* The MPI needs to have enough limbs to store the full value (including any

View File

@ -33,6 +33,22 @@
#include "bignum_mod.h"
#include "constant_time_internal.h"
void mbedtls_mpi_mod_raw_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign )
{
mbedtls_mpi_core_cond_assign( X, A, N->limbs, assign );
}
void mbedtls_mpi_mod_raw_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap )
{
mbedtls_mpi_core_cond_swap( X, Y, N->limbs, swap );
}
int mbedtls_mpi_mod_raw_read( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m,
const unsigned char *input,

View File

@ -33,6 +33,60 @@
#include "bignum_mod.h"
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether the assignment was done or not.
*
* The size to copy is determined by \p N.
*
* \param[out] X The address of the destination MPI.
* This must be initialized. Must have enough limbs to
* store the full value of \p A.
* \param[in] A The address of the source MPI. This must be initialized.
* \param[in] N The address of the modulus related to \p X and \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.
*
* \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_mod_raw_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign );
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
* whether the swap was done or not.
*
* The size to swap is determined by \p N.
*
* \param[in,out] X The address of the first MPI. This must be initialized.
* \param[in,out] Y The address of the second MPI. This must be initialized.
* \param[in] N The address of the modulus related to \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.
*
* \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_mod_raw_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap );
/** Import X from unsigned binary data.
*
* The MPI needs to have enough limbs to store the full value (including any

View File

@ -30,6 +30,7 @@
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#include "bignum_core.h"
#endif
#if defined(MBEDTLS_SSL_TLS_C)
@ -678,21 +679,19 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X,
unsigned char assign )
{
int ret = 0;
size_t i;
mbedtls_mpi_uint limb_mask;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( Y != NULL );
/* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
limb_mask = mbedtls_ct_mpi_uint_mask( assign );;
mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask( assign );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
X->s = mbedtls_ct_cond_select_sign( assign, Y->s, X->s );
mbedtls_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign );
mbedtls_mpi_core_cond_assign( X->p, Y->p, Y->n, assign );
for( i = Y->n; i < X->n; i++ )
for( size_t i = Y->n; i < X->n; i++ )
X->p[i] &= ~limb_mask;
cleanup:
@ -709,19 +708,14 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
mbedtls_mpi *Y,
unsigned char swap )
{
int ret, s;
size_t i;
mbedtls_mpi_uint limb_mask;
mbedtls_mpi_uint tmp;
int ret = 0;
int s;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( Y != NULL );
if( X == Y )
return( 0 );
/* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
limb_mask = mbedtls_ct_mpi_uint_mask( swap );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
@ -729,13 +723,7 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
X->s = mbedtls_ct_cond_select_sign( swap, Y->s, X->s );
Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s );
for( i = 0; i < X->n; i++ )
{
tmp = X->p[i];
X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
}
mbedtls_mpi_core_cond_swap( X->p, Y->p, X->n, swap );
cleanup:
return( ret );