diff --git a/library/bignum_core.c b/library/bignum_core.c index 4e5012b79b..35510e6823 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -293,6 +293,89 @@ int mbedtls_mpi_core_write_be( const mbedtls_mpi_uint *X, return( 0 ); } +mbedtls_mpi_uint mbedtls_mpi_core_add_if( mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs, + unsigned cond ) +{ + mbedtls_mpi_uint c = 0, t; + for( size_t i = 0; i < limbs; i++ ) + { + mbedtls_mpi_uint add = cond * B[i]; + t = c; + t += A[i]; c = ( t < A[i] ); + t += add; c += ( t < add ); + A[i] = t; + } + return( c ); +} + +mbedtls_mpi_uint mbedtls_mpi_core_sub( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs ) +{ + mbedtls_mpi_uint c = 0; + + for( size_t i = 0; i < limbs; i++ ) + { + mbedtls_mpi_uint z = ( A[i] < c ); + mbedtls_mpi_uint t = A[i] - c; + c = ( t < B[i] ) + z; + X[i] = t - B[i]; + } + + return( c ); +} + +mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len, + const mbedtls_mpi_uint *s, size_t s_len, + mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0; /* carry */ + if( d_len < s_len ) + s_len = d_len; + size_t excess_len = d_len - s_len; + size_t steps_x8 = s_len / 8; + size_t steps_x1 = s_len & 7; + + while( steps_x8-- ) + { + MULADDC_X8_INIT + MULADDC_X8_CORE + MULADDC_X8_STOP + } + + while( steps_x1-- ) + { + MULADDC_X1_INIT + MULADDC_X1_CORE + MULADDC_X1_STOP + } + + while( excess_len-- ) + { + *d += c; c = ( *d < c ); d++; + } + + return( c ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis). + */ +mbedtls_mpi_uint mbedtls_mpi_montg_init( const mbedtls_mpi_uint *N ) +{ + mbedtls_mpi_uint x = N[0]; + + x += ( ( N[0] + 2 ) & 4 ) << 1; + + for( unsigned int i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( N[0] * x ) ); + + return( ~x + 1 ); +} + void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, @@ -345,87 +428,4 @@ void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X, mbedtls_ct_mpi_uint_cond_assign( AN_limbs, X, T, (unsigned char) ( carry ^ borrow ) ); } -/* - * Fast Montgomery initialization (thanks to Tom St Denis). - */ -mbedtls_mpi_uint mbedtls_mpi_montg_init( const mbedtls_mpi_uint *N ) -{ - mbedtls_mpi_uint x = N[0]; - - x += ( ( N[0] + 2 ) & 4 ) << 1; - - for( unsigned int i = biL; i >= 8; i /= 2 ) - x *= ( 2 - ( N[0] * x ) ); - - return( ~x + 1 ); -} - -mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len, - const mbedtls_mpi_uint *s, size_t s_len, - mbedtls_mpi_uint b ) -{ - mbedtls_mpi_uint c = 0; /* carry */ - if( d_len < s_len ) - s_len = d_len; - size_t excess_len = d_len - s_len; - size_t steps_x8 = s_len / 8; - size_t steps_x1 = s_len & 7; - - while( steps_x8-- ) - { - MULADDC_X8_INIT - MULADDC_X8_CORE - MULADDC_X8_STOP - } - - while( steps_x1-- ) - { - MULADDC_X1_INIT - MULADDC_X1_CORE - MULADDC_X1_STOP - } - - while( excess_len-- ) - { - *d += c; c = ( *d < c ); d++; - } - - return( c ); -} - -mbedtls_mpi_uint mbedtls_mpi_core_sub( mbedtls_mpi_uint *X, - const mbedtls_mpi_uint *A, - const mbedtls_mpi_uint *B, - size_t limbs ) -{ - mbedtls_mpi_uint c = 0; - - for( size_t i = 0; i < limbs; i++ ) - { - mbedtls_mpi_uint z = ( A[i] < c ); - mbedtls_mpi_uint t = A[i] - c; - c = ( t < B[i] ) + z; - X[i] = t - B[i]; - } - - return( c ); -} - -mbedtls_mpi_uint mbedtls_mpi_core_add_if( mbedtls_mpi_uint *A, - const mbedtls_mpi_uint *B, - size_t limbs, - unsigned cond ) -{ - mbedtls_mpi_uint c = 0, t; - for( size_t i = 0; i < limbs; i++ ) - { - mbedtls_mpi_uint add = cond * B[i]; - t = c; - t += A[i]; c = ( t < A[i] ); - t += add; c += ( t < add ); - A[i] = t; - } - return( c ); -} - #endif /* MBEDTLS_BIGNUM_C */ diff --git a/library/bignum_core.h b/library/bignum_core.h index cf7caee942..279dca2741 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -155,86 +155,6 @@ int mbedtls_mpi_core_write_be( const mbedtls_mpi_uint *A, #define GET_BYTE( X, i ) \ ( ( (X)[(i) / ciL] >> ( ( (i) % ciL ) * 8 ) ) & 0xff ) -/** - * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36) - * - * \param[out] X The destination MPI, as a little-endian array of - * length \p AN_limbs. - * On successful completion, X contains the result of - * the multiplication A * B * R^-1 mod N where - * R = (2^ciL)^AN_limbs. - * \param[in] A Little-endian presentation of first operand. - * Must have exactly \p AN_limbs limbs. - * \param[in] B Little-endian presentation of second operand. - * \param[in] B_limbs The number of limbs in \p B. - * \param[in] N Little-endian presentation of the modulus. - * This must be odd and have exactly \p AN_limbs limbs. - * \param[in] AN_limbs The number of limbs in \p X, \p A, \p N. - * \param mm The Montgomery constant for \p N: -N^-1 mod 2^ciL. - * This can be calculated by `mbedtls_mpi_montg_init()`. - * \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs. - * Its initial content is unused and - * its final content is indeterminate. - */ -void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X, - const mbedtls_mpi_uint *A, - const mbedtls_mpi_uint *B, size_t B_limbs, - const mbedtls_mpi_uint *N, size_t AN_limbs, - mbedtls_mpi_uint mm, mbedtls_mpi_uint *T ); - -/** - * \brief Calculate initialisation value for fast Montgomery modular - * multiplication - * - * \param[in] N Little-endian presentation of the modulus. This must have - * at least one limb. - * - * \return The initialisation value for fast Montgomery modular multiplication - */ -mbedtls_mpi_uint mbedtls_mpi_montg_init( const mbedtls_mpi_uint *N ); - -/** - * \brief Perform a known-size multiply accumulate operation: A += c * B - * - * \param[in,out] A The pointer to the (little-endian) array - * representing the bignum to accumulate onto. - * \param A_limbs The number of limbs of \p A. This must be - * at least \p B_limbs. - * \param[in] B The pointer to the (little-endian) array - * representing the bignum to multiply with. - * This may be the same as \p A. Otherwise, - * it must be disjoint from \p A. - * \param B_limbs The number of limbs of \p B. - * \param c A scalar to multiply with. - * - * \return The carry at the end of the operation. - */ -mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *A, size_t A_limbs, - const mbedtls_mpi_uint *B, size_t B_limbs, - mbedtls_mpi_uint c ); - -/** - * \brief Subtract two known-size large unsigned integers, returning the borrow. - * - * Calculate A - B where A and B have the same size. - * This function operates modulo (2^ciL)^limbs and returns the carry - * (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise). - * - * X may be aliased to A or B. - * - * \param[out] X The result of the subtraction. - * \param[in] A Little-endian presentation of left operand. - * \param[in] B Little-endian presentation of right operand. - * \param limbs Number of limbs of \p X, \p A and \p B. - * - * \return 1 if `A < B`. - * 0 if `A >= B`. - */ -mbedtls_mpi_uint mbedtls_mpi_core_sub( mbedtls_mpi_uint *X, - const mbedtls_mpi_uint *A, - const mbedtls_mpi_uint *B, - size_t limbs ); - /** * \brief Conditional addition of two known-size large unsigned integers, * returning the carry. @@ -267,4 +187,84 @@ mbedtls_mpi_uint mbedtls_mpi_core_add_if( mbedtls_mpi_uint *A, size_t limbs, unsigned cond ); +/** + * \brief Subtract two known-size large unsigned integers, returning the borrow. + * + * Calculate A - B where A and B have the same size. + * This function operates modulo (2^ciL)^limbs and returns the carry + * (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise). + * + * X may be aliased to A or B. + * + * \param[out] X The result of the subtraction. + * \param[in] A Little-endian presentation of left operand. + * \param[in] B Little-endian presentation of right operand. + * \param limbs Number of limbs of \p X, \p A and \p B. + * + * \return 1 if `A < B`. + * 0 if `A >= B`. + */ +mbedtls_mpi_uint mbedtls_mpi_core_sub( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs ); + +/** + * \brief Perform a known-size multiply accumulate operation: A += c * B + * + * \param[in,out] A The pointer to the (little-endian) array + * representing the bignum to accumulate onto. + * \param A_limbs The number of limbs of \p A. This must be + * at least \p B_limbs. + * \param[in] B The pointer to the (little-endian) array + * representing the bignum to multiply with. + * This may be the same as \p A. Otherwise, + * it must be disjoint from \p A. + * \param B_limbs The number of limbs of \p B. + * \param c A scalar to multiply with. + * + * \return The carry at the end of the operation. + */ +mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *A, size_t A_limbs, + const mbedtls_mpi_uint *B, size_t B_limbs, + mbedtls_mpi_uint c ); + +/** + * \brief Calculate initialisation value for fast Montgomery modular + * multiplication + * + * \param[in] N Little-endian presentation of the modulus. This must have + * at least one limb. + * + * \return The initialisation value for fast Montgomery modular multiplication + */ +mbedtls_mpi_uint mbedtls_mpi_montg_init( const mbedtls_mpi_uint *N ); + +/** + * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36) + * + * \param[out] X The destination MPI, as a little-endian array of + * length \p AN_limbs. + * On successful completion, X contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^AN_limbs. + * \param[in] A Little-endian presentation of first operand. + * Must have exactly \p AN_limbs limbs. + * \param[in] B Little-endian presentation of second operand. + * \param[in] B_limbs The number of limbs in \p B. + * \param[in] N Little-endian presentation of the modulus. + * This must be odd and have exactly \p AN_limbs limbs. + * \param[in] AN_limbs The number of limbs in \p X, \p A, \p N. + * \param mm The Montgomery constant for \p N: -N^-1 mod 2^ciL. + * This can be calculated by `mbedtls_mpi_montg_init()`. + * \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs. + * Its initial content is unused and + * its final content is indeterminate. + */ +void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, size_t B_limbs, + const mbedtls_mpi_uint *N, size_t AN_limbs, + mbedtls_mpi_uint mm, mbedtls_mpi_uint *T ); + #endif /* MBEDTLS_BIGNUM_CORE_H */