From 8fd95c6757509432f5e09ef5ddf730b47aacf076 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 23 Jul 2020 21:58:50 +0200 Subject: [PATCH] Perform mbedtls_mpi_mul_int in place if possible Rewrite mbedtls_mpi_mul_int to call mpi_mul_hlp directly rather than create a temporary mpi object. This has the benefit of not performing an allocation when the multiplication is in place (mpi operand aliased with the result) and the result mpi is large enough. This saves about 40% of the calloc() calls in test_suite_ecp. There is no measurable performance difference on my Linux PC. The cost is a few bytes in bignum.o. When there is no aliasing, or when there is aliasing but the mpi object needs to be enlarged, the performance difference is negligible. Signed-off-by: Gilles Peskine --- library/bignum.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/library/bignum.c b/library/bignum.c index a847e5071..0eb212560 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -1658,17 +1658,30 @@ cleanup: */ int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) { - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; MPI_VALIDATE_RET( X != NULL ); MPI_VALIDATE_RET( A != NULL ); - _B.s = 1; - _B.n = 1; - _B.p = p; - p[0] = b; + /* mpi_mul_hlp can't deal with a leading 0. */ + size_t n = A->n; + while( n > 0 && A->p[n - 1] == 0 ) + --n; - return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); + /* The general method below doesn't work if n==0 or b==0. By chance + * calculating the result is trivial in those cases. */ + if( b == 0 || n == 0 ) + { + mbedtls_mpi_lset( X, 0 ); + return( 0 ); + } + + /* Calculate X*b as A + A*(b-1) to take advantage of mpi_mul_hlp */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + mpi_mul_hlp( n, A->p, X->p, b - 1 ); + +cleanup: + return( ret ); } /*