diff --git a/library/bignum.c b/library/bignum.c index e47e25917d9d2fa6ecb1ce91b8c576b1f03a0e19..9d91ff4e8b8ab7e2958160772113bfc2761eae26 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -1872,43 +1872,20 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_ /* * Fast Montgomery initialization (thanks to Tom St Denis) */ -static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +mbedtls_mpi_uint mbedtls_mpi_montmul_init(const mbedtls_mpi_uint *N) { - mbedtls_mpi_uint x, m0 = N->p[0]; - unsigned int i; + mbedtls_mpi_uint x = N[0]; - x = m0; - x += ( ( m0 + 2 ) & 4 ) << 1; + x += ((N[0] + 2) & 4) << 1; - for( i = biL; i >= 8; i /= 2 ) - x *= ( 2 - ( m0 * x ) ); + for (unsigned int i = biL; i >= 8; i /= 2) { + x *= (2 - (N[0] * x)); + } - *mm = ~x + 1; + return ~x + 1; } -/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) - * - * \param[in,out] A One of the numbers to multiply. - * It must have at least as many limbs as N - * (A->n >= N->n), and any limbs beyond n are ignored. - * On successful completion, A contains the result of - * the multiplication A * B * R^-1 mod N where - * R = (2^ciL)^n. - * \param[in] B One of the numbers to multiply. - * It must be nonzero and must not have more limbs than N - * (B->n <= N->n). - * \param[in] N The modulo. N must be odd. - * \param mm The value calculated by `mpi_montg_init(&mm, N)`. - * This is -N^-1 mod 2^ciL. - * \param[in,out] T A bignum for temporary storage. - * It must be at least twice the limb size of N plus 2 - * (T->n >= 2 * (N->n + 1)). - * Its initial content is unused and - * its final content is indeterminate. - * Note that unlike the usual convention in the library - * for `const mbedtls_mpi*`, the content of T can change. - */ -static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, +void mbedtls_mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) { size_t i, n, m; @@ -1969,7 +1946,7 @@ static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, U.n = U.s = (int) z; U.p = &z; - mpi_montmul( A, &U, N, mm, T ); + mbedtls_mpi_montmul( A, &U, N, mm, T ); } /** @@ -2001,6 +1978,20 @@ cleanup: return( ret ); } +int mbedtls_mpi_get_mont_r2_unsafe(mbedtls_mpi *X, + const mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n)); + +cleanup: + return ret; +} + /* * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) */ @@ -2034,7 +2025,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, /* * Init temps and window size */ - mpi_montg_init( &mm, N ); + mm = mbedtls_mpi_montmul_init(N->p); mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &Apos ); mbedtls_mpi_init( &WW ); @@ -2076,10 +2067,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, */ if( prec_RR == NULL || prec_RR->p == NULL ) { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); - + mbedtls_mpi_get_mont_r2_unsafe(&RR, N); if( prec_RR != NULL ) memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) ); } @@ -2102,7 +2090,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, /* Note that this is safe because W[1] always has at least N->n limbs * (it grew above and was preserved by mbedtls_mpi_copy()). */ - mpi_montmul( &W[1], &RR, N, mm, &T ); + mbedtls_mpi_montmul( &W[1], &RR, N, mm, &T ); /* * X = R^2 * R^-1 mod N = R mod N @@ -2121,7 +2109,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); for( i = 0; i < wsize - 1; i++ ) - mpi_montmul( &W[j], &W[j], N, mm, &T ); + mbedtls_mpi_montmul( &W[j], &W[j], N, mm, &T ); /* * W[i] = W[i - 1] * W[1] @@ -2131,7 +2119,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); - mpi_montmul( &W[i], &W[1], N, mm, &T ); + mbedtls_mpi_montmul( &W[i], &W[1], N, mm, &T ); } } diff --git a/library/bignum_internal.h b/library/bignum_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..5435ebb464905428b68f759630503696e598c0b4 --- /dev/null +++ b/library/bignum_internal.h @@ -0,0 +1,71 @@ +/** + * Low level bignum functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_BIGNUM_INTERNAL_H +#define MBEDTLS_BIGNUM_INTERNAL_H + +#include "mbedtls/bignum.h" + +/** + * \brief Calculate the square of the Montgomery constant. (Needed + * for conversion and operations in Montgomery form.) + * + * \param[out] X A pointer to the result of the calculation of + * the square of the Montgomery constant: + * 2^{2*n*biL} mod N. + * \param[in] N Little-endian presentation of the modulus, which must be odd. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space + * to store the value of Montgomery constant squared. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative. + */ +int mbedtls_mpi_get_mont_r2_unsafe(mbedtls_mpi *X, + const mbedtls_mpi *N); + +/** + * \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_montmul_init(const mbedtls_mpi_uint *N); + +/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by + * `mbedtls_mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. + */ +void mbedtls_mpi_montmul(mbedtls_mpi *A, + const mbedtls_mpi *B, + const mbedtls_mpi *N, + mbedtls_mpi_uint mm, + const mbedtls_mpi *T); + +#endif /* MBEDTLS_BIGNUM_INTERNAL_H */ diff --git a/library/rsa.c b/library/rsa.c index 36f487f3a77733421db0c289d59f36e075a8a054..2df3cd4c7d504c6261d90c91f1cebd34d7b3f449 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -46,7 +46,7 @@ #include "mbedtls/error.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" - +#include "bignum_internal.h" #include #if defined(MBEDTLS_PKCS1_V21) @@ -867,6 +867,47 @@ cleanup: */ #define RSA_EXPONENT_BLINDING 28 +/* + * Unblind + * T = T * Vf mod N + */ +static int rsa_unblind(mbedtls_mpi *T, mbedtls_mpi *Vf, const mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t nlimbs = N->n; + const size_t tlimbs = 2 * (nlimbs + 1); + + mbedtls_mpi_uint mm = mbedtls_mpi_montmul_init(N->p); + + mbedtls_mpi RR, M_T; + + mbedtls_mpi_init(&RR); + mbedtls_mpi_init(&M_T); + + MBEDTLS_MPI_CHK(mbedtls_mpi_get_mont_r2_unsafe(&RR, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&M_T, tlimbs)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(T, nlimbs)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Vf, nlimbs)); + + /* T = T * Vf mod N + * Reminder: montmul(A, B, N) = A * B * R^-1 mod N + * Usually both operands are multiplied by R mod N beforehand, yielding a + * result that's also * R mod N (aka "in the Montgomery domain"). Here we + * only multiply one operand by R mod N, so the result is directly what we + * want - no need to call `mpi_montred()` on it. */ + mbedtls_mpi_montmul(T, &RR, N, mm, &M_T); + mbedtls_mpi_montmul(T, Vf, N, mm, &M_T); + +cleanup: + + mbedtls_mpi_free(&RR); + mbedtls_mpi_free(&M_T); + + return ret; +} + + /* * Do an RSA private key operation */ @@ -909,7 +950,7 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, /* Temporaries holding the initial input and the double * checked result; should be the same in the end. */ - mbedtls_mpi I, C; + mbedtls_mpi input_blinded, check_result_blinded; RSA_VALIDATE_RET( ctx != NULL ); RSA_VALIDATE_RET( input != NULL ); @@ -1010,6 +1051,8 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, DQ = &DQ_blind; #endif /* MBEDTLS_RSA_NO_CRT */ + /* Make a copy of the input (after blinding if there was any) */ + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&input_blinded, &T)); #if defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); #else @@ -1053,6 +1096,8 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, goto cleanup; } + MBEDTLS_MPI_CHK(rsa_unblind(&T, &ctx->Vf, &ctx->N)); + olen = ctx->len; MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); @@ -1113,6 +1158,8 @@ static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, hlen = mbedtls_md_get_size( md_ctx->md_info ); + hlen = mbedtls_md_get_size( md_ctx->md_info ); + /* Generate and apply dbMask */ p = dst; @@ -1246,6 +1293,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, RSA_VALIDATE_RET( ilen == 0 || input != NULL ); olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); /* first comparison checks for overflow */ if( ilen + 11 < ilen || olen < ilen + 11 ) @@ -1273,7 +1321,6 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); p++; - } *p++ = 0; if( ilen != 0 ) @@ -1568,6 +1615,10 @@ static int rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, if( f_rng == NULL ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + olen = ctx->len; if( md_alg != MBEDTLS_MD_NONE ) @@ -1891,7 +1942,6 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, { ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; goto cleanup; - } memcpy( sig, sig_try, ctx->len );