From b6673f0f193dac31232a7ddc23e9b9c4f66bacf5 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 30 Sep 2022 14:13:14 +0100 Subject: [PATCH 01/20] Add modular exponentiation to bignum core Signed-off-by: Janos Follath --- library/bignum_core.c | 135 ++++++++++++++++++++++++++++++++++++++++++ library/bignum_core.h | 23 +++++++ 2 files changed, 158 insertions(+) diff --git a/library/bignum_core.c b/library/bignum_core.c index 34aecda501..227351b70b 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -582,6 +582,141 @@ cleanup: /* BEGIN MERGE SLOT 1 */ +static size_t mpi_exp_mod_get_window_size( size_t Ebits ) +{ + size_t wsize = ( Ebits > 671 ) ? 6 : ( Ebits > 239 ) ? 5 : + ( Ebits > 79 ) ? 4 : ( Ebits > 23 ) ? 3 : 1; + +#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; +#endif + + return( wsize ); +} + +int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, + mbedtls_mpi_uint const *A, + const mbedtls_mpi_uint *N, + size_t n, + const mbedtls_mpi_uint *E, + size_t E_len, + const mbedtls_mpi_uint *RR ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* heap allocated memory pool */ + mbedtls_mpi_uint *mempool = NULL; + /* pointers to temporaries within memory pool */ + mbedtls_mpi_uint *Wtbl, *Wselect, *temp; + /* pointers to table entries */ + mbedtls_mpi_uint *Wcur, *Wlast, *W1; + + size_t wsize, welem; + mbedtls_mpi_uint one = 1, mm; + + mm = mbedtls_mpi_core_montmul_init( N ); /* Compute Montgomery constant */ + E += E_len; /* Skip to end of exponent buffer */ + + wsize = mpi_exp_mod_get_window_size( E_len * biL ); + welem = 1 << wsize; + + /* Allocate memory pool and set pointers to parts of it */ + const size_t table_limbs = welem * n; + const size_t temp_limbs = 2 * n + 1; + const size_t wselect_limbs = n; + const size_t total_limbs = table_limbs + temp_limbs + wselect_limbs; + + mempool = mbedtls_calloc( total_limbs, sizeof(mbedtls_mpi_uint) ); + if( mempool == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + Wtbl = mempool; + Wselect = Wtbl + table_limbs; + temp = Wselect + wselect_limbs; + + /* + * Window precomputation + */ + + /* W[0] = 1 (in Montgomery presentation) */ + memset( Wtbl, 0, n * ciL ); Wtbl[0] = 1; + mbedtls_mpi_core_montmul( Wtbl, Wtbl, RR, n, N, n, mm, temp ); + Wcur = Wtbl + n; + /* W[1] = A * R^2 * R^-1 mod N = A * R mod N */ + memcpy( Wcur, A, n * ciL ); + mbedtls_mpi_core_montmul( Wcur, Wcur, RR, n, N, n, mm, temp ); + W1 = Wcur; + Wcur += n; + /* W[i+1] = W[i] * W[1], i >= 2 */ + Wlast = W1; + for( size_t i=2; i < welem; i++, Wlast += n, Wcur += n ) + mbedtls_mpi_core_montmul( Wcur, Wlast, W1, n, N, n, mm, temp ); + + /* + * Sliding window exponentiation + */ + + /* X = 1 (in Montgomery presentation) initially */ + memcpy( X, Wtbl, n * ciL ); + + size_t limb_bits_remaining = 0; + mbedtls_mpi_uint window = 0; + size_t window_bits = 0, cur_limb; + while( 1 ) + { + size_t window_bits_missing = wsize - window_bits; + + const int no_more_bits = + ( limb_bits_remaining == 0 ) && ( E_len == 0 ); + const int window_full = + ( window_bits_missing == 0 ); + + /* Clear window if it's full or if we don't have further bits. */ + if( window_full || no_more_bits ) + { + if( window_bits == 0 ) + break; + /* Select table entry, square and multiply */ + mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtbl, + n, welem, window ); + mbedtls_mpi_core_montmul( X, X, Wselect, n, N, n, mm, temp ); + window = window_bits = 0; + continue; + } + + /* Load next exponent limb if necessary */ + if( limb_bits_remaining == 0 ) + { + cur_limb = *--E; + E_len--; + limb_bits_remaining = biL; + } + + /* Square */ + mbedtls_mpi_core_montmul( X, X, X, n, N, n, mm, temp ); + + /* Insert next exponent bit into window */ + window <<= 1; + window |= ( cur_limb >> ( biL - 1 ) ); + cur_limb <<= 1; + window_bits++; + limb_bits_remaining--; + } + + /* Convert X back to normal presentation */ + mbedtls_mpi_core_montmul( X, X, &one, 1, N, n, mm, temp ); + + ret = 0; + +cleanup: + + mbedtls_free( mempool ); + return( ret ); +} + /* END MERGE SLOT 1 */ /* BEGIN MERGE SLOT 2 */ diff --git a/library/bignum_core.h b/library/bignum_core.h index ad04e08283..82da142163 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -496,6 +496,29 @@ int mbedtls_mpi_core_fill_random( mbedtls_mpi_uint *X, size_t X_limbs, /* BEGIN MERGE SLOT 1 */ +/** + * \brief Perform a modular exponentiation with secret exponent: + * X = A^E mod N + * + * \param[out] X The destination MPI, as a little endian array of length + * \p limbs. + * \param[in] A The base MPI, as a little endian array of length \p limbs. + * \param[in] N The modulus, as a little endian array of length \p limbs. + * \param limbs The number of limbs in \p X, \p A, \p N, \p RR. + * \param[in] E The exponent, as a little endian array of length \p E_limbs. + * \param E_limbs The number of limbs in \p E. + * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little + * endian array of length \p limbs. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + */ +int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, size_t limbs, + const mbedtls_mpi_uint *E, size_t E_limbs, + const mbedtls_mpi_uint *RR ); + /* END MERGE SLOT 1 */ /* BEGIN MERGE SLOT 2 */ From bad42c4d0dbda9787ca476ad3df40de7f0d69264 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 9 Nov 2022 14:30:44 +0000 Subject: [PATCH 02/20] mpi_core_exp_mod: fix local variable type On platforms with size_t different from int, mismatch between size_t and mpi_uint can cause incorrect results or complaints from the compiler. Signed-off-by: Janos Follath mpi_core_exp_mod: Cast local variable explicitly Signed-off-by: Janos Follath --- library/bignum_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 227351b70b..3b660d0056 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -618,7 +618,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, E += E_len; /* Skip to end of exponent buffer */ wsize = mpi_exp_mod_get_window_size( E_len * biL ); - welem = 1 << wsize; + welem = ( (size_t) 1 ) << wsize; /* Allocate memory pool and set pointers to parts of it */ const size_t table_limbs = welem * n; @@ -663,8 +663,8 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, memcpy( X, Wtbl, n * ciL ); size_t limb_bits_remaining = 0; - mbedtls_mpi_uint window = 0; - size_t window_bits = 0, cur_limb; + mbedtls_mpi_uint cur_limb, window = 0; + size_t window_bits = 0; while( 1 ) { size_t window_bits_missing = wsize - window_bits; From 59cbd1be27f7aef2bad1f6b16333a67df7461e16 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 28 Oct 2022 18:13:43 +0100 Subject: [PATCH 03/20] Make mbedtls_mpi_core_ct_uint_table_lookup static Now that we have a function that calls mbedtls_mpi_core_ct_uint_table_lookup(), the compiler won't complain if we make it static. Signed-off-by: Janos Follath --- library/bignum_core.c | 1 + library/bignum_core.h | 2 ++ tests/suites/test_suite_bignum_core.function | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 3b660d0056..2337ae5214 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -540,6 +540,7 @@ cleanup: return( ret ); } +MBEDTLS_STATIC_TESTABLE void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest, const mbedtls_mpi_uint *table, size_t limbs, diff --git a/library/bignum_core.h b/library/bignum_core.h index 82da142163..ede8161256 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -452,6 +452,7 @@ void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X, int mbedtls_mpi_core_get_mont_r2_unsafe( mbedtls_mpi *X, const mbedtls_mpi *N ); +#if defined(MBEDTLS_TEST_HOOKS) /** * Copy an MPI from a table without leaking the index. * @@ -469,6 +470,7 @@ void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest, size_t limbs, size_t count, size_t index ); +#endif /* MBEDTLS_TEST_HOOKS */ /** * \brief Fill an integer with a number of random bytes. diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index 612a7c6bd4..46689468ba 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -935,7 +935,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */ void mpi_core_ct_uint_table_lookup( int bitlen, int window_size ) { size_t limbs = BITS_TO_LIMBS( bitlen ); From 0f0d1e88a2afa2349d3f14182f6ef6bffd1b8d40 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 6 Oct 2022 13:36:21 +0100 Subject: [PATCH 04/20] mpi_core_exp_mod: add unit tests The test cases aim to mirror the legacy function, but needed the some cases to be removed because: - Null representation is not valid in core - There are no negative numbers in core - Bignum core doesn't do parameter checking and there are no promises for even N The _size variant of the test has been removed as bignum core doesn't do parameter checking and there is no promises for inputs that are larger than MBEDTLS_MPI_MAX_SIZE. Signed-off-by: Janos Follath --- tests/suites/test_suite_bignum_core.function | 53 +++++++++++++++++++ tests/suites/test_suite_bignum_core.misc.data | 25 +++++++++ 2 files changed, 78 insertions(+) diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index 46689468ba..e262ec1039 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -1041,6 +1041,59 @@ exit: /* BEGIN MERGE SLOT 1 */ +/* BEGIN_CASE */ +void mpi_core_exp_mod( char * input_A, char * input_E, + char * input_N, char * input_X ) +{ + mbedtls_mpi_uint *A = NULL; + size_t A_limbs; + mbedtls_mpi_uint *E = NULL; + size_t E_limbs; + mbedtls_mpi_uint *N = NULL; + size_t N_limbs; + mbedtls_mpi_uint *X = NULL; + size_t X_limbs; + const mbedtls_mpi_uint *R2 = NULL; + mbedtls_mpi_uint *Y = NULL; + /* Legacy MPIs for computing R2 */ + mbedtls_mpi N_mpi; + mbedtls_mpi_init( &N_mpi ); + mbedtls_mpi R2_mpi; + mbedtls_mpi_init( &R2_mpi ); + + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) ); + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &E, &E_limbs, input_E ) ); + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &N_limbs, input_N ) ); + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) ); + ASSERT_ALLOC( Y, N_limbs ); + + TEST_EQUAL( A_limbs, N_limbs ); + TEST_EQUAL( X_limbs, N_limbs ); + + TEST_EQUAL( 0, mbedtls_mpi_grow( &N_mpi, N_limbs ) ); + memcpy( N_mpi.p, N, N_limbs * sizeof( *N ) ); + N_mpi.n = N_limbs; + TEST_EQUAL( 0, + mbedtls_mpi_core_get_mont_r2_unsafe( &R2_mpi, &N_mpi ) ); + TEST_EQUAL( 0, mbedtls_mpi_grow( &R2_mpi, N_limbs ) ); + R2 = R2_mpi.p; + + TEST_EQUAL( 0, + mbedtls_mpi_core_exp_mod( Y, A, N, N_limbs, E, E_limbs, R2 ) ); + TEST_EQUAL( 0, memcmp( X, Y, N_limbs * sizeof( mbedtls_mpi_uint ) ) ); + +exit: + mbedtls_free( A ); + mbedtls_free( E ); + mbedtls_free( N ); + mbedtls_free( X ); + mbedtls_free( Y ); + mbedtls_mpi_free( &N_mpi ); + mbedtls_mpi_free( &R2_mpi ); + // R2 doesn't need to be freed as it is only aliasing R2_mpi +} +/* END_CASE */ + /* END MERGE SLOT 1 */ /* BEGIN MERGE SLOT 2 */ diff --git a/tests/suites/test_suite_bignum_core.misc.data b/tests/suites/test_suite_bignum_core.misc.data index 62480e47f7..58e45a3f67 100644 --- a/tests/suites/test_suite_bignum_core.misc.data +++ b/tests/suites/test_suite_bignum_core.misc.data @@ -430,6 +430,31 @@ mpi_core_fill_random:42:0:-5:0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA # BEGIN MERGE SLOT 1 +Base test mbedtls_mpi_core_exp_mod #1 +mpi_core_exp_mod:"17":"0d":"1d":"18" + +Test mbedtls_mpi_core_exp_mod: 0 (1 limb) ^ 0 (1 limb) mod 9 +mpi_core_exp_mod:"00":"00":"09":"01" + +Test mbedtls_mpi_core_exp_mod: 0 (1 limb) ^ 1 mod 9 +mpi_core_exp_mod:"00":"01":"09":"00" + +Test mbedtls_mpi_core_exp_mod: 0 (1 limb) ^ 2 mod 9 +mpi_core_exp_mod:"00":"02":"09":"00" + +Test mbedtls_mpi_core_exp_mod: 1 ^ 0 (1 limb) mod 9 +mpi_core_exp_mod:"01":"00":"09":"01" + +Test mbedtls_mpi_core_exp_mod: 4 ^ 0 (1 limb) mod 9 +mpi_core_exp_mod:"04":"00":"09":"01" + +Test mbedtls_mpi_core_exp_mod: 10 ^ 0 (1 limb) mod 9 +mpi_core_exp_mod:"0a":"00":"09":"01" + +Test mbedtls_mpi_core_exp_mod #1 +depends_on:MPI_MAX_BITS_LARGER_THAN_792 +mpi_core_exp_mod:"00000000000000000000000000109fe45714866e56fdd4ad9b6b686df27224afb7868cf4f0cbb794526932853cbf0beea61594166654d13cd9fe0d9da594a97ee20230f12fb5434de73fb4f8102725a01622b31b1ea42e3a265019039ac1df31869bd97930d792fb72cdaa971d8a8015af":"33ae3764fd06a00cdc3cba5c45dc79a9edb4e67e4d057cc74139d531c25190d111775fc4a0f4439b8b1930bbd766e7b46f170601f316c8a18ff8d5cb5ca5581f168345d101edb462b7d93b7c520ccb8fb276b447a63d869203cc11f67a1122dc4da034218de85e39":"011a9351d2d32ccd568e75bf8b4ebbb2a36be691b55832edac662ff79803df8af525fba453068be16ac3920bcc1b468f8f7fe786e0fa4ecbabcad31e5e3b05def802eb8600deaf11ef452487db878df20a80606e4bb6a163b83895d034cc8b53dbcd005be42ffdd2ce99bed06089a0b79d":"0037880b547b41bda303bddda307eefe24b4aedf076c9b814b903aaf328a10825c7e259a20afc6b70b487bb21a6d32d0ee98a0b9f42ff812c901e2f79237fe3e00856992dd69d93ebc0664c75863829621751b0ac35a8ae8a0965841607d3099b8e0ed24442749ba09acbcb165598dcd40" + # END MERGE SLOT 1 # BEGIN MERGE SLOT 2 From a77911e5c1e791854af8fb9e0b26319ac2b9e3be Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Sat, 8 Oct 2022 09:48:20 +0100 Subject: [PATCH 05/20] core_exp_mod: improve window selection We are looking at the exponent at limb granularity and therefore exponent bits can't go below 32. The `mpi_` prefix is also removed as it is better not to have prefix at all than to have just a partial. (Full prefix would be overly long and would hurt readability.) Signed-off-by: Janos Follath --- library/bignum_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 2337ae5214..79d5a720e3 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -583,10 +583,10 @@ cleanup: /* BEGIN MERGE SLOT 1 */ -static size_t mpi_exp_mod_get_window_size( size_t Ebits ) +static size_t exp_mod_get_window_size( size_t Ebits ) { size_t wsize = ( Ebits > 671 ) ? 6 : ( Ebits > 239 ) ? 5 : - ( Ebits > 79 ) ? 4 : ( Ebits > 23 ) ? 3 : 1; + ( Ebits > 79 ) ? 4 : 1; #if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) @@ -618,7 +618,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, mm = mbedtls_mpi_core_montmul_init( N ); /* Compute Montgomery constant */ E += E_len; /* Skip to end of exponent buffer */ - wsize = mpi_exp_mod_get_window_size( E_len * biL ); + wsize = exp_mod_get_window_size( E_len * biL ); welem = ( (size_t) 1 ) << wsize; /* Allocate memory pool and set pointers to parts of it */ From 0ec6e3f3949713328e22f5cdfe300e5a7649c799 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 14 Nov 2022 12:52:08 +0000 Subject: [PATCH 06/20] mpi_core_mod_exp: improve style and documentation No intended change in behaviour. Signed-off-by: Janos Follath --- library/bignum_core.c | 49 ++++++++++++++++++++++--------------------- library/bignum_core.h | 12 +++++------ 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 79d5a720e3..944b4be6a6 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -597,11 +597,11 @@ static size_t exp_mod_get_window_size( size_t Ebits ) } int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, - mbedtls_mpi_uint const *A, + const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, - size_t n, + size_t AN_limbs, const mbedtls_mpi_uint *E, - size_t E_len, + size_t E_limbs, const mbedtls_mpi_uint *RR ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -616,15 +616,15 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, mbedtls_mpi_uint one = 1, mm; mm = mbedtls_mpi_core_montmul_init( N ); /* Compute Montgomery constant */ - E += E_len; /* Skip to end of exponent buffer */ + E += E_limbs; /* Skip to end of exponent buffer */ - wsize = exp_mod_get_window_size( E_len * biL ); + wsize = exp_mod_get_window_size( E_limbs * biL ); welem = ( (size_t) 1 ) << wsize; /* Allocate memory pool and set pointers to parts of it */ - const size_t table_limbs = welem * n; - const size_t temp_limbs = 2 * n + 1; - const size_t wselect_limbs = n; + const size_t table_limbs = welem * AN_limbs; + const size_t temp_limbs = 2 * AN_limbs + 1; + const size_t wselect_limbs = AN_limbs; const size_t total_limbs = table_limbs + temp_limbs + wselect_limbs; mempool = mbedtls_calloc( total_limbs, sizeof(mbedtls_mpi_uint) ); @@ -643,25 +643,26 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, */ /* W[0] = 1 (in Montgomery presentation) */ - memset( Wtbl, 0, n * ciL ); Wtbl[0] = 1; - mbedtls_mpi_core_montmul( Wtbl, Wtbl, RR, n, N, n, mm, temp ); - Wcur = Wtbl + n; + memset( Wtbl, 0, AN_limbs * ciL ); + Wtbl[0] = 1; + mbedtls_mpi_core_montmul( Wtbl, Wtbl, RR, AN_limbs, N, AN_limbs, mm, temp ); + Wcur = Wtbl + AN_limbs; /* W[1] = A * R^2 * R^-1 mod N = A * R mod N */ - memcpy( Wcur, A, n * ciL ); - mbedtls_mpi_core_montmul( Wcur, Wcur, RR, n, N, n, mm, temp ); + memcpy( Wcur, A, AN_limbs * ciL ); + mbedtls_mpi_core_montmul( Wcur, Wcur, RR, AN_limbs, N, AN_limbs, mm, temp ); W1 = Wcur; - Wcur += n; + Wcur += AN_limbs; /* W[i+1] = W[i] * W[1], i >= 2 */ Wlast = W1; - for( size_t i=2; i < welem; i++, Wlast += n, Wcur += n ) - mbedtls_mpi_core_montmul( Wcur, Wlast, W1, n, N, n, mm, temp ); + for( size_t i = 2; i < welem; i++, Wlast += AN_limbs, Wcur += AN_limbs ) + mbedtls_mpi_core_montmul( Wcur, Wlast, W1, AN_limbs, N, AN_limbs, mm, temp ); /* - * Sliding window exponentiation + * Fixed window exponentiation */ /* X = 1 (in Montgomery presentation) initially */ - memcpy( X, Wtbl, n * ciL ); + memcpy( X, Wtbl, AN_limbs * ciL ); size_t limb_bits_remaining = 0; mbedtls_mpi_uint cur_limb, window = 0; @@ -671,7 +672,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, size_t window_bits_missing = wsize - window_bits; const int no_more_bits = - ( limb_bits_remaining == 0 ) && ( E_len == 0 ); + ( limb_bits_remaining == 0 ) && ( E_limbs == 0 ); const int window_full = ( window_bits_missing == 0 ); @@ -682,8 +683,8 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, break; /* Select table entry, square and multiply */ mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtbl, - n, welem, window ); - mbedtls_mpi_core_montmul( X, X, Wselect, n, N, n, mm, temp ); + AN_limbs, welem, window ); + mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp ); window = window_bits = 0; continue; } @@ -692,12 +693,12 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, if( limb_bits_remaining == 0 ) { cur_limb = *--E; - E_len--; + E_limbs--; limb_bits_remaining = biL; } /* Square */ - mbedtls_mpi_core_montmul( X, X, X, n, N, n, mm, temp ); + mbedtls_mpi_core_montmul( X, X, X, AN_limbs, N, AN_limbs, mm, temp ); /* Insert next exponent bit into window */ window <<= 1; @@ -708,7 +709,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, } /* Convert X back to normal presentation */ - mbedtls_mpi_core_montmul( X, X, &one, 1, N, n, mm, temp ); + mbedtls_mpi_core_montmul( X, X, &one, 1, N, AN_limbs, mm, temp ); ret = 0; diff --git a/library/bignum_core.h b/library/bignum_core.h index ede8161256..58a9f5a670 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -503,21 +503,21 @@ int mbedtls_mpi_core_fill_random( mbedtls_mpi_uint *X, size_t X_limbs, * X = A^E mod N * * \param[out] X The destination MPI, as a little endian array of length - * \p limbs. - * \param[in] A The base MPI, as a little endian array of length \p limbs. - * \param[in] N The modulus, as a little endian array of length \p limbs. - * \param limbs The number of limbs in \p X, \p A, \p N, \p RR. + * \p AN_limbs. + * \param[in] A The base MPI, as a little endian array of length \p AN_limbs. + * \param[in] N The modulus, as a little endian array of length \p AN_limbs. + * \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR. * \param[in] E The exponent, as a little endian array of length \p E_limbs. * \param E_limbs The number of limbs in \p E. * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little - * endian array of length \p limbs. + * endian array of length \p AN_limbs. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. */ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, - const mbedtls_mpi_uint *N, size_t limbs, + const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *E, size_t E_limbs, const mbedtls_mpi_uint *RR ); From 07f2c69511303ddc667756c0bb56c90d737573b4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 19:48:23 +0100 Subject: [PATCH 07/20] More consistent variable names Signed-off-by: Gilles Peskine --- library/bignum_core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 944b4be6a6..957f190986 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -608,7 +608,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, /* heap allocated memory pool */ mbedtls_mpi_uint *mempool = NULL; /* pointers to temporaries within memory pool */ - mbedtls_mpi_uint *Wtbl, *Wselect, *temp; + mbedtls_mpi_uint *Wtable, *Wselect, *temp; /* pointers to table entries */ mbedtls_mpi_uint *Wcur, *Wlast, *W1; @@ -624,8 +624,8 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, /* Allocate memory pool and set pointers to parts of it */ const size_t table_limbs = welem * AN_limbs; const size_t temp_limbs = 2 * AN_limbs + 1; - const size_t wselect_limbs = AN_limbs; - const size_t total_limbs = table_limbs + temp_limbs + wselect_limbs; + const size_t select_limbs = AN_limbs; + const size_t total_limbs = table_limbs + temp_limbs + select_limbs; mempool = mbedtls_calloc( total_limbs, sizeof(mbedtls_mpi_uint) ); if( mempool == NULL ) @@ -634,19 +634,19 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, goto cleanup; } - Wtbl = mempool; - Wselect = Wtbl + table_limbs; - temp = Wselect + wselect_limbs; + Wtable = mempool; + Wselect = Wtable + table_limbs; + temp = Wselect + select_limbs; /* * Window precomputation */ /* W[0] = 1 (in Montgomery presentation) */ - memset( Wtbl, 0, AN_limbs * ciL ); - Wtbl[0] = 1; - mbedtls_mpi_core_montmul( Wtbl, Wtbl, RR, AN_limbs, N, AN_limbs, mm, temp ); - Wcur = Wtbl + AN_limbs; + memset( Wtable, 0, AN_limbs * ciL ); + Wtable[0] = 1; + mbedtls_mpi_core_montmul( Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp ); + Wcur = Wtable + AN_limbs; /* W[1] = A * R^2 * R^-1 mod N = A * R mod N */ memcpy( Wcur, A, AN_limbs * ciL ); mbedtls_mpi_core_montmul( Wcur, Wcur, RR, AN_limbs, N, AN_limbs, mm, temp ); @@ -662,7 +662,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, */ /* X = 1 (in Montgomery presentation) initially */ - memcpy( X, Wtbl, AN_limbs * ciL ); + memcpy( X, Wtable, AN_limbs * ciL ); size_t limb_bits_remaining = 0; mbedtls_mpi_uint cur_limb, window = 0; @@ -682,7 +682,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, if( window_bits == 0 ) break; /* Select table entry, square and multiply */ - mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtbl, + mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtable, AN_limbs, welem, window ); mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp ); window = window_bits = 0; From 7af166b827226e059118d8cb5c6e1ecb8e2ed3cf Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 19:52:30 +0100 Subject: [PATCH 08/20] Change E closer to where it's used Signed-off-by: Gilles Peskine --- library/bignum_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 957f190986..a6aa5a83b9 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -616,7 +616,6 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, mbedtls_mpi_uint one = 1, mm; mm = mbedtls_mpi_core_montmul_init( N ); /* Compute Montgomery constant */ - E += E_limbs; /* Skip to end of exponent buffer */ wsize = exp_mod_get_window_size( E_limbs * biL ); welem = ( (size_t) 1 ) << wsize; @@ -664,6 +663,9 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, /* X = 1 (in Montgomery presentation) initially */ memcpy( X, Wtable, AN_limbs * ciL ); + /* Start from the end of exponent buffer */ + E += E_limbs; + size_t limb_bits_remaining = 0; mbedtls_mpi_uint cur_limb, window = 0; size_t window_bits = 0; From cf979b0fc1ff4033c907ad5adf980ad4530e2f41 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 20:04:00 +0100 Subject: [PATCH 09/20] Define variables closer to their use Make variables const where possible. Signed-off-by: Gilles Peskine --- library/bignum_core.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index a6aa5a83b9..c38daa48c2 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -607,18 +607,9 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* heap allocated memory pool */ mbedtls_mpi_uint *mempool = NULL; - /* pointers to temporaries within memory pool */ - mbedtls_mpi_uint *Wtable, *Wselect, *temp; - /* pointers to table entries */ - mbedtls_mpi_uint *Wcur, *Wlast, *W1; - size_t wsize, welem; - mbedtls_mpi_uint one = 1, mm; - - mm = mbedtls_mpi_core_montmul_init( N ); /* Compute Montgomery constant */ - - wsize = exp_mod_get_window_size( E_limbs * biL ); - welem = ( (size_t) 1 ) << wsize; + const size_t wsize = exp_mod_get_window_size( E_limbs * biL ); + const size_t welem = ( (size_t) 1 ) << wsize; /* Allocate memory pool and set pointers to parts of it */ const size_t table_limbs = welem * AN_limbs; @@ -633,14 +624,20 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, goto cleanup; } - Wtable = mempool; - Wselect = Wtable + table_limbs; - temp = Wselect + select_limbs; + /* pointers to temporaries within memory pool */ + mbedtls_mpi_uint *const Wtable = mempool; + mbedtls_mpi_uint *const Wselect = Wtable + table_limbs; + mbedtls_mpi_uint *const temp = Wselect + select_limbs; /* * Window precomputation */ + const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init( N ); + + /* pointers to table entries */ + mbedtls_mpi_uint *Wcur, *Wlast, *W1; + /* W[0] = 1 (in Montgomery presentation) */ memset( Wtable, 0, AN_limbs * ciL ); Wtable[0] = 1; @@ -667,8 +664,11 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, E += E_limbs; size_t limb_bits_remaining = 0; - mbedtls_mpi_uint cur_limb, window = 0; + mbedtls_mpi_uint window = 0; size_t window_bits = 0; + /* Will be initialized properly in the first loop iteration */ + mbedtls_mpi_uint cur_limb = 0; + while( 1 ) { size_t window_bits_missing = wsize - window_bits; @@ -711,6 +711,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, } /* Convert X back to normal presentation */ + const mbedtls_mpi_uint one = 1; mbedtls_mpi_core_montmul( X, X, &one, 1, N, AN_limbs, mm, temp ); ret = 0; From 0de0a049f1f0c53da0ead6307ab7034d9d4b8534 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 20:12:49 +0100 Subject: [PATCH 10/20] Move window precomputation into an auxiliary function Signed-off-by: Gilles Peskine --- library/bignum_core.c | 49 ++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index c38daa48c2..14f2f5a876 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -596,6 +596,34 @@ static size_t exp_mod_get_window_size( size_t Ebits ) return( wsize ); } +static void exp_mod_precompute_window( const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + const mbedtls_mpi_uint *RR, + size_t welem, + mbedtls_mpi_uint *Wtable, + mbedtls_mpi_uint *temp ) +{ + /* pointers to table entries */ + mbedtls_mpi_uint *Wcur, *Wlast, *W1; + + /* W[0] = 1 (in Montgomery presentation) */ + memset( Wtable, 0, AN_limbs * ciL ); + Wtable[0] = 1; + mbedtls_mpi_core_montmul( Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp ); + Wcur = Wtable + AN_limbs; + /* W[1] = A * R^2 * R^-1 mod N = A * R mod N */ + memcpy( Wcur, A, AN_limbs * ciL ); + mbedtls_mpi_core_montmul( Wcur, Wcur, RR, AN_limbs, N, AN_limbs, mm, temp ); + W1 = Wcur; + Wcur += AN_limbs; + /* W[i+1] = W[i] * W[1], i >= 2 */ + Wlast = W1; + for( size_t i = 2; i < welem; i++, Wlast += AN_limbs, Wcur += AN_limbs ) + mbedtls_mpi_core_montmul( Wcur, Wlast, W1, AN_limbs, N, AN_limbs, mm, temp ); +} + int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, @@ -635,23 +663,10 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init( N ); - /* pointers to table entries */ - mbedtls_mpi_uint *Wcur, *Wlast, *W1; - - /* W[0] = 1 (in Montgomery presentation) */ - memset( Wtable, 0, AN_limbs * ciL ); - Wtable[0] = 1; - mbedtls_mpi_core_montmul( Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp ); - Wcur = Wtable + AN_limbs; - /* W[1] = A * R^2 * R^-1 mod N = A * R mod N */ - memcpy( Wcur, A, AN_limbs * ciL ); - mbedtls_mpi_core_montmul( Wcur, Wcur, RR, AN_limbs, N, AN_limbs, mm, temp ); - W1 = Wcur; - Wcur += AN_limbs; - /* W[i+1] = W[i] * W[1], i >= 2 */ - Wlast = W1; - for( size_t i = 2; i < welem; i++, Wlast += AN_limbs, Wcur += AN_limbs ) - mbedtls_mpi_core_montmul( Wcur, Wlast, W1, AN_limbs, N, AN_limbs, mm, temp ); + /* Set Wtable[i] = A^(2^i) (in Montgomery representation) */ + exp_mod_precompute_window( A, N, AN_limbs, + mm, RR, + welem, Wtable, temp ); /* * Fixed window exponentiation From d83b5cb504cfc8ff17faf55fff20c68f25b44a86 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 20:26:14 +0100 Subject: [PATCH 11/20] Local readability improvements Signed-off-by: Gilles Peskine --- library/bignum_core.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 14f2f5a876..b7d6b62534 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -605,23 +605,23 @@ static void exp_mod_precompute_window( const mbedtls_mpi_uint *A, mbedtls_mpi_uint *Wtable, mbedtls_mpi_uint *temp ) { - /* pointers to table entries */ - mbedtls_mpi_uint *Wcur, *Wlast, *W1; - /* W[0] = 1 (in Montgomery presentation) */ memset( Wtable, 0, AN_limbs * ciL ); Wtable[0] = 1; mbedtls_mpi_core_montmul( Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp ); - Wcur = Wtable + AN_limbs; + /* W[1] = A * R^2 * R^-1 mod N = A * R mod N */ - memcpy( Wcur, A, AN_limbs * ciL ); - mbedtls_mpi_core_montmul( Wcur, Wcur, RR, AN_limbs, N, AN_limbs, mm, temp ); - W1 = Wcur; - Wcur += AN_limbs; + mbedtls_mpi_uint *W1 = Wtable + AN_limbs; + mbedtls_mpi_core_montmul( W1, A, RR, AN_limbs, N, AN_limbs, mm, temp ); + /* W[i+1] = W[i] * W[1], i >= 2 */ - Wlast = W1; - for( size_t i = 2; i < welem; i++, Wlast += AN_limbs, Wcur += AN_limbs ) - mbedtls_mpi_core_montmul( Wcur, Wlast, W1, AN_limbs, N, AN_limbs, mm, temp ); + mbedtls_mpi_uint *Wprev = W1; + for( size_t i = 2; i < welem; i++ ) + { + mbedtls_mpi_uint *Wcur = Wprev + AN_limbs; + mbedtls_mpi_core_montmul( Wcur, Wprev, W1, AN_limbs, N, AN_limbs, mm, temp ); + Wprev = Wcur; + } } int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, @@ -702,15 +702,17 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtable, AN_limbs, welem, window ); mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp ); - window = window_bits = 0; + window = 0; + window_bits = 0; continue; } /* Load next exponent limb if necessary */ if( limb_bits_remaining == 0 ) { - cur_limb = *--E; - E_limbs--; + --E; + cur_limb = *E; + --E_limbs; limb_bits_remaining = biL; } @@ -721,8 +723,8 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, window <<= 1; window |= ( cur_limb >> ( biL - 1 ) ); cur_limb <<= 1; - window_bits++; - limb_bits_remaining--; + ++window_bits; + --limb_bits_remaining; } /* Convert X back to normal presentation */ From c718a3ce94897377670a057851a60edca148c4e2 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 20:42:09 +0100 Subject: [PATCH 12/20] Simplify exponent bit selection Use indices instead of mutating data to extract the bits of the exponent. Signed-off-by: Gilles Peskine --- library/bignum_core.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index b7d6b62534..c05e603226 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -675,21 +675,20 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, /* X = 1 (in Montgomery presentation) initially */ memcpy( X, Wtable, AN_limbs * ciL ); - /* Start from the end of exponent buffer */ - E += E_limbs; - - size_t limb_bits_remaining = 0; + /* We'll process the bits of E from most significant + * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant + * (limb_index=0, E_bit_index=0). */ + size_t E_limb_index = E_limbs; + size_t E_bit_index = 0; mbedtls_mpi_uint window = 0; size_t window_bits = 0; - /* Will be initialized properly in the first loop iteration */ - mbedtls_mpi_uint cur_limb = 0; while( 1 ) { size_t window_bits_missing = wsize - window_bits; const int no_more_bits = - ( limb_bits_remaining == 0 ) && ( E_limbs == 0 ); + ( E_bit_index == 0 ) && ( E_limb_index == 0 ); const int window_full = ( window_bits_missing == 0 ); @@ -707,24 +706,22 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, continue; } - /* Load next exponent limb if necessary */ - if( limb_bits_remaining == 0 ) - { - --E; - cur_limb = *E; - --E_limbs; - limb_bits_remaining = biL; - } - /* Square */ mbedtls_mpi_core_montmul( X, X, X, AN_limbs, N, AN_limbs, mm, temp ); /* Insert next exponent bit into window */ - window <<= 1; - window |= ( cur_limb >> ( biL - 1 ) ); - cur_limb <<= 1; + if( E_bit_index == 0 ) + { + --E_limb_index; + E_bit_index = biL - 1; + } + else + { + --E_bit_index; + } ++window_bits; - --limb_bits_remaining; + window <<= 1; + window |= ( E[E_limb_index] >> E_bit_index ) & 1; } /* Convert X back to normal presentation */ From 3b63d09fead5623c42cb3f0e54e36d52604ccfe8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 22:06:18 +0100 Subject: [PATCH 13/20] Make the main loop's logic clearer The loop ends when there are no more bits to process, with one twist: when that happens, we need to clear the window one last time. Since the window does not start empty (E_limbs==0 is not supported), the loop always starts with a non-empty window and some bits to process. So it's correct to move the window clearing logic to the end of the loop. This lets us exit the loop when the end of the exponent is reached. It would be clearer not to do the final window clearing inside the loop, so we wouldn't need to repeat the loop termination condition (end of exponent reached) inside the loop. However, this requires duplicating the code to clear the window. Empirically, this causes a significant code size increase, even if the window clearing code is placed into a function. Signed-off-by: Gilles Peskine --- library/bignum_core.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index c05e603226..737e08df2f 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -683,29 +683,8 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, mbedtls_mpi_uint window = 0; size_t window_bits = 0; - while( 1 ) + do { - size_t window_bits_missing = wsize - window_bits; - - const int no_more_bits = - ( E_bit_index == 0 ) && ( E_limb_index == 0 ); - const int window_full = - ( window_bits_missing == 0 ); - - /* Clear window if it's full or if we don't have further bits. */ - if( window_full || no_more_bits ) - { - if( window_bits == 0 ) - break; - /* Select table entry, square and multiply */ - mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtable, - AN_limbs, welem, window ); - mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp ); - window = 0; - window_bits = 0; - continue; - } - /* Square */ mbedtls_mpi_core_montmul( X, X, X, AN_limbs, N, AN_limbs, mm, temp ); @@ -722,7 +701,21 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, ++window_bits; window <<= 1; window |= ( E[E_limb_index] >> E_bit_index ) & 1; + + /* Clear window if it's full. Also clear the window at the end, + * when we've finished processing the exponent. */ + if( window_bits == wsize || + ( E_bit_index == 0 && E_limb_index == 0 ) ) + { + /* Select table entry, square and multiply */ + mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtable, + AN_limbs, welem, window ); + mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp ); + window = 0; + window_bits = 0; + } } + while( ! ( E_bit_index == 0 && E_limb_index == 0 ) ); /* Convert X back to normal presentation */ const mbedtls_mpi_uint one = 1; From 4380d7b7f30785b6bacc032b68f19f2e2a47d786 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 22:20:59 +0100 Subject: [PATCH 14/20] Simplify cleanup logic Take advantage of the fact that there's a single point of failure. Signed-off-by: Gilles Peskine --- library/bignum_core.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 737e08df2f..a8879b327f 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -632,10 +632,6 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, size_t E_limbs, const mbedtls_mpi_uint *RR ) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* heap allocated memory pool */ - mbedtls_mpi_uint *mempool = NULL; - const size_t wsize = exp_mod_get_window_size( E_limbs * biL ); const size_t welem = ( (size_t) 1 ) << wsize; @@ -645,11 +641,12 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, const size_t select_limbs = AN_limbs; const size_t total_limbs = table_limbs + temp_limbs + select_limbs; - mempool = mbedtls_calloc( total_limbs, sizeof(mbedtls_mpi_uint) ); + /* heap allocated memory pool */ + mbedtls_mpi_uint *mempool = + mbedtls_calloc( total_limbs, sizeof(mbedtls_mpi_uint) ); if( mempool == NULL ) { - ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; - goto cleanup; + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); } /* pointers to temporaries within memory pool */ @@ -721,12 +718,8 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, const mbedtls_mpi_uint one = 1; mbedtls_mpi_core_montmul( X, X, &one, 1, N, AN_limbs, mm, temp ); - ret = 0; - -cleanup: - mbedtls_free( mempool ); - return( ret ); + return( 0 ); } /* END MERGE SLOT 1 */ From 0b270a560340856fed09deb58df8801326cf82d6 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 22:54:03 +0100 Subject: [PATCH 15/20] Explain a little more Signed-off-by: Gilles Peskine --- library/bignum_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index a8879b327f..247600c521 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -677,8 +677,10 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, * (limb_index=0, E_bit_index=0). */ size_t E_limb_index = E_limbs; size_t E_bit_index = 0; - mbedtls_mpi_uint window = 0; + /* At any given time, window contains window_bits bits from E. + * window_bits can go up to wsize. */ size_t window_bits = 0; + mbedtls_mpi_uint window = 0; do { @@ -704,9 +706,11 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, if( window_bits == wsize || ( E_bit_index == 0 && E_limb_index == 0 ) ) { - /* Select table entry, square and multiply */ + /* Select Wtable[window] without leaking window through + * memory access patterns. */ mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtable, AN_limbs, welem, window ); + /* Multiply X by the selected element. */ mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp ); window = 0; window_bits = 0; From 7d89d351e603564cea00942b0d817c90407c8811 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 16 Nov 2022 22:54:14 +0100 Subject: [PATCH 16/20] Zeroize sensitive data Signed-off-by: Gilles Peskine --- library/bignum_core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/bignum_core.c b/library/bignum_core.c index 247600c521..71a2fb16a4 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -624,6 +624,12 @@ static void exp_mod_precompute_window( const mbedtls_mpi_uint *A, } } +/* Exponentiation: X := A^E mod N. + * + * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero. + * + * RR must contain 2^{2*biL} mod N. + */ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, @@ -722,6 +728,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, const mbedtls_mpi_uint one = 1; mbedtls_mpi_core_montmul( X, X, &one, 1, N, AN_limbs, mm, temp ); + mbedtls_platform_zeroize( mempool, total_limbs * sizeof(mbedtls_mpi_uint) ); mbedtls_free( mempool ); return( 0 ); } From 3321b5842c2f4d4135c2595c3d01f2f621261b80 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 22 Nov 2022 21:08:33 +0000 Subject: [PATCH 17/20] mpi_exp_mod: improve documentation Signed-off-by: Janos Follath --- library/bignum_core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 71a2fb16a4..2b3405ffc9 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -629,6 +629,10 @@ static void exp_mod_precompute_window( const mbedtls_mpi_uint *A, * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero. * * RR must contain 2^{2*biL} mod N. + * + * The algorithm is a variant of Left-to-right k-ary exponentiation: HAC 14.82 + * (The difference is that the body in our loop processes a single bit instead + * of a full window.) */ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, @@ -693,7 +697,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, /* Square */ mbedtls_mpi_core_montmul( X, X, X, AN_limbs, N, AN_limbs, mm, temp ); - /* Insert next exponent bit into window */ + /* Move to the next bit of the exponent */ if( E_bit_index == 0 ) { --E_limb_index; @@ -703,6 +707,7 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, { --E_bit_index; } + /* Insert next exponent bit into window */ ++window_bits; window <<= 1; window |= ( E[E_limb_index] >> E_bit_index ) & 1; @@ -717,7 +722,8 @@ int mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X, mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtable, AN_limbs, welem, window ); /* Multiply X by the selected element. */ - mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp ); + mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm, + temp ); window = 0; window_bits = 0; } From 05867cb036c40af689c174ee06f49a6a53c73de5 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 22 Nov 2022 21:37:10 +0000 Subject: [PATCH 18/20] mpi_core_exp_mod: add generated tests Signed-off-by: Janos Follath --- scripts/mbedtls_dev/bignum_core.py | 21 ++++++++++++++++++++ tests/suites/test_suite_bignum_core.function | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py index 4910daea87..f85fb2e36a 100644 --- a/scripts/mbedtls_dev/bignum_core.py +++ b/scripts/mbedtls_dev/bignum_core.py @@ -755,6 +755,27 @@ def mpi_modmul_case_generate() -> None: # BEGIN MERGE SLOT 1 +class BignumCoreExpMod(BignumCoreTarget, bignum_common.ModOperationCommon): + """Test cases for bignum core exponentiation.""" + symbol = "^" + test_function = "mpi_core_exp_mod" + test_name = "Core modular exponentiation" + input_style = "fixed" + + def result(self) -> List[str]: + result = pow(self.int_a, self.int_b, self.int_n) + return [self.format_result(result)] + + @property + def is_valid(self) -> bool: + # The base needs to be canonical, but the exponent can be larger than + # the modulus (see for example exponent blinding) + if self.int_a < self.int_n: + return True + else: + return False + + # END MERGE SLOT 1 # BEGIN MERGE SLOT 2 diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index e262ec1039..f9a768c0ca 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -1042,8 +1042,8 @@ exit: /* BEGIN MERGE SLOT 1 */ /* BEGIN_CASE */ -void mpi_core_exp_mod( char * input_A, char * input_E, - char * input_N, char * input_X ) +void mpi_core_exp_mod( char * input_N, char * input_A, + char * input_E, char * input_X ) { mbedtls_mpi_uint *A = NULL; size_t A_limbs; From cf0e86c9b8ac88ec5dca7522824a53c1c518f036 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 22 Nov 2022 21:40:24 +0000 Subject: [PATCH 19/20] mpi_core_exp_mod: remove manual tests The previous commit added generated tests, we don't need the manually added tests anymore. Signed-off-by: Janos Follath --- tests/suites/test_suite_bignum_core.misc.data | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/tests/suites/test_suite_bignum_core.misc.data b/tests/suites/test_suite_bignum_core.misc.data index 58e45a3f67..62480e47f7 100644 --- a/tests/suites/test_suite_bignum_core.misc.data +++ b/tests/suites/test_suite_bignum_core.misc.data @@ -430,31 +430,6 @@ mpi_core_fill_random:42:0:-5:0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA # BEGIN MERGE SLOT 1 -Base test mbedtls_mpi_core_exp_mod #1 -mpi_core_exp_mod:"17":"0d":"1d":"18" - -Test mbedtls_mpi_core_exp_mod: 0 (1 limb) ^ 0 (1 limb) mod 9 -mpi_core_exp_mod:"00":"00":"09":"01" - -Test mbedtls_mpi_core_exp_mod: 0 (1 limb) ^ 1 mod 9 -mpi_core_exp_mod:"00":"01":"09":"00" - -Test mbedtls_mpi_core_exp_mod: 0 (1 limb) ^ 2 mod 9 -mpi_core_exp_mod:"00":"02":"09":"00" - -Test mbedtls_mpi_core_exp_mod: 1 ^ 0 (1 limb) mod 9 -mpi_core_exp_mod:"01":"00":"09":"01" - -Test mbedtls_mpi_core_exp_mod: 4 ^ 0 (1 limb) mod 9 -mpi_core_exp_mod:"04":"00":"09":"01" - -Test mbedtls_mpi_core_exp_mod: 10 ^ 0 (1 limb) mod 9 -mpi_core_exp_mod:"0a":"00":"09":"01" - -Test mbedtls_mpi_core_exp_mod #1 -depends_on:MPI_MAX_BITS_LARGER_THAN_792 -mpi_core_exp_mod:"00000000000000000000000000109fe45714866e56fdd4ad9b6b686df27224afb7868cf4f0cbb794526932853cbf0beea61594166654d13cd9fe0d9da594a97ee20230f12fb5434de73fb4f8102725a01622b31b1ea42e3a265019039ac1df31869bd97930d792fb72cdaa971d8a8015af":"33ae3764fd06a00cdc3cba5c45dc79a9edb4e67e4d057cc74139d531c25190d111775fc4a0f4439b8b1930bbd766e7b46f170601f316c8a18ff8d5cb5ca5581f168345d101edb462b7d93b7c520ccb8fb276b447a63d869203cc11f67a1122dc4da034218de85e39":"011a9351d2d32ccd568e75bf8b4ebbb2a36be691b55832edac662ff79803df8af525fba453068be16ac3920bcc1b468f8f7fe786e0fa4ecbabcad31e5e3b05def802eb8600deaf11ef452487db878df20a80606e4bb6a163b83895d034cc8b53dbcd005be42ffdd2ce99bed06089a0b79d":"0037880b547b41bda303bddda307eefe24b4aedf076c9b814b903aaf328a10825c7e259a20afc6b70b487bb21a6d32d0ee98a0b9f42ff812c901e2f79237fe3e00856992dd69d93ebc0664c75863829621751b0ac35a8ae8a0965841607d3099b8e0ed24442749ba09acbcb165598dcd40" - # END MERGE SLOT 1 # BEGIN MERGE SLOT 2 From 43d3de4977a86be1cf19bc6e3b7a558ab86737a6 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 22 Nov 2022 21:50:22 +0000 Subject: [PATCH 20/20] Make pylint happy Signed-off-by: Janos Follath --- scripts/mbedtls_dev/bignum_core.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py index f85fb2e36a..ed6ecbd004 100644 --- a/scripts/mbedtls_dev/bignum_core.py +++ b/scripts/mbedtls_dev/bignum_core.py @@ -770,11 +770,7 @@ class BignumCoreExpMod(BignumCoreTarget, bignum_common.ModOperationCommon): def is_valid(self) -> bool: # The base needs to be canonical, but the exponent can be larger than # the modulus (see for example exponent blinding) - if self.int_a < self.int_n: - return True - else: - return False - + return bool(self.int_a < self.int_n) # END MERGE SLOT 1