diff --git a/include/polarssl/bignum.h b/include/polarssl/bignum.h index 9bed027d9..1052c5aa0 100644 --- a/include/polarssl/bignum.h +++ b/include/polarssl/bignum.h @@ -201,6 +201,17 @@ void mpi_free( mpi *X ); */ int mpi_grow( mpi *X, size_t nblimbs ); +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shrink( mpi *X, size_t nblimbs ); + /** * \brief Copy the contents of Y into X * diff --git a/library/bignum.c b/library/bignum.c index 2a97a5902..55f7463a9 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -119,6 +119,45 @@ int mpi_grow( mpi *X, size_t nblimbs ) return( 0 ); } +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mpi_shrink( mpi *X, size_t nblimbs ) +{ + t_uint *p; + size_t i; + + /* Actually resize up in this case */ + if( X->n <= nblimbs ) + return( mpi_grow( X, nblimbs ) ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (t_uint *) polarssl_malloc( i * ciL ) ) == NULL ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + memset( p, 0, i * ciL ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + memset( X->p, 0, X->n * ciL ); + polarssl_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + /* * Copy the contents of Y into X */ diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data index 924f364d9..e763374ae 100644 --- a/tests/suites/test_suite_mpi.data +++ b/tests/suites/test_suite_mpi.data @@ -181,6 +181,30 @@ mpi_copy_self:14 Base test mpi_swap #1 mpi_swap:0:1500 +Test mpi_shrink #1 +mpi_shrink:2:2:4:4 + +Test mpi_shrink #2 +mpi_shrink:4:2:4:4 + +Test mpi_shrink #3 +mpi_shrink:8:2:4:4 + +Test mpi_shrink #4 +mpi_shrink:8:4:4:4 + +Test mpi_shrink #5 +mpi_shrink:8:6:4:6 + +Test mpi_shrink #6 +mpi_shrink:4:2:0:2 + +Test mpi_shrink #7 +mpi_shrink:4:1:0:1 + +Test mpi_shrink #8 +mpi_shrink:4:0:0:1 + Base test mpi_add_abs #1 mpi_add_abs:10:"12345678":10:"642531":10:"12988209" diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function index e08b48d09..d3a0d4898 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -292,6 +292,22 @@ void mpi_copy_self( int input_X ) } /* END_CASE */ +/* BEGIN_CASE */ +void mpi_shrink( int before, int used, int min, int after ) +{ + mpi X; + mpi_init( &X ); + + TEST_ASSERT( mpi_grow( &X, before ) == 0 ); + TEST_ASSERT( used <= before ); + memset( X.p, 0x2a, used * sizeof( t_uint ) ); + TEST_ASSERT( mpi_shrink( &X, min ) == 0 ); + TEST_ASSERT( X.n == (size_t) after ); + + mpi_free( &X ); +} +/* END_CASE */ + /* BEGIN_CASE */ void mpi_swap( int input_X, int input_Y ) {