From e50f2f1a8e5d56d162cf7dd58b835c5ee96295a1 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 Oct 2022 15:14:33 +0100 Subject: [PATCH 1/7] Add mbedtls_mpi_core_ct_uint_table_lookup This will be needed for extracting modular exponentiation from the prototype. The function signature is kept aligned to the prototype, but the implementation is new. (The implementation of this function in the prototype has further optimisations which are out of scope for now.) The function is not reused in the bignum counterpart as it will become redundant soon. This function is meant to be static, but doesn't have the qualifier as it is not used yet and would cause compiler warnings. The MBEDTLS_STATIC_TESTABLE macro will be added in a later commit. Signed-off-by: Janos Follath --- library/bignum_core.c | 14 ++++++++++++++ library/bignum_core.h | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/library/bignum_core.c b/library/bignum_core.c index b401fa36cb..c1da93d0a0 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -540,4 +540,18 @@ cleanup: return( ret ); } +void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *table, + size_t limbs, + size_t count, + size_t index ) +{ + for( size_t i = 0; i < count; i++ ) + { + unsigned char assign = mbedtls_ct_size_bool_eq( i, index ); + const mbedtls_mpi_uint *current = table + i * limbs; + mbedtls_mpi_core_cond_assign( dest, current, limbs, assign ); + } +} + #endif /* MBEDTLS_BIGNUM_C */ diff --git a/library/bignum_core.h b/library/bignum_core.h index 9a5b89fc6e..3618e42006 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -452,4 +452,23 @@ void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X, int mbedtls_mpi_core_get_mont_r2_unsafe( mbedtls_mpi *X, const mbedtls_mpi *N ); +/** + * Select an MPI from a table without leaking the index. + * + * \param dest The destination buffer. This must point to a writable + * buffer of at least \p limbs limbs. + * \param table The address of the table. This must point to a readable + * array of \p count elements of + * \p limbs limbs each each. + * \param limbs The length of a table entry in limbs. + * \param count The number of elements in \p table. + * \param index The secret table index to look up. This must be in the + * range `0,..,count-1`. + */ +void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *table, + size_t limbs, + size_t count, + size_t index ); + #endif /* MBEDTLS_BIGNUM_CORE_H */ From 032924f29759f6ca43395e9b42cf615c7e1da0ce Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 Oct 2022 19:10:29 +0100 Subject: [PATCH 2/7] Add mbedtls_mpi_core_ct_uint_table_lookup tests Signed-off-by: Janos Follath --- scripts/mbedtls_dev/bignum_core.py | 38 ++++++++++++++++++++ tests/suites/test_suite_bignum_core.function | 37 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py index 0d238e714b..e88f469a14 100644 --- a/scripts/mbedtls_dev/bignum_core.py +++ b/scripts/mbedtls_dev/bignum_core.py @@ -69,6 +69,44 @@ class BignumCoreShiftR(BignumCoreTarget, metaclass=ABCMeta): for count in counts: yield cls(input_hex, descr, count).create_test_case() +class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta): + """Test cases for mbedtls_mpi_core_ct_uint_table_lookup().""" + count = 0 + test_function = "mpi_core_ct_uint_table_lookup" + test_name = "Constant time MPI table lookup" + + bitsizes = [ + (32, "One limb"), + (192, "Smallest curve sized"), + (512, "Largest curve sized"), + (2048, "Small FF/RSA sized"), + (4096, "Large FF/RSA sized"), + ] + + window_sizes = [ 0, 1, 2, 3, 4, 5, 6 ] + + def __init__(self, + bitsize: int, descr: str, window_size: int) -> None: + self.bitsize = bitsize + self.bitsize_description = descr + self.window_size = window_size + + def arguments(self) -> List[str]: + return [str(self.bitsize), str(self.window_size)] + + def description(self) -> str: + return '{} - {} MPI with {} bit window'.format( + BignumCoreCTLookup.test_name, + self.bitsize_description, + self.window_size + ) + + @classmethod + def generate_function_tests(cls) -> Iterator[test_case.TestCase]: + for bitsize, bitsize_description in cls.bitsizes: + for window_size in cls.window_sizes: + yield (cls(bitsize, bitsize_description, window_size) + .create_test_case()) class BignumCoreOperation(bignum_common.OperationCommon, BignumCoreTarget, metaclass=ABCMeta): #pylint: disable=abstract-method diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index 57c2f37387..696d873eaf 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -941,3 +941,40 @@ exit: mbedtls_mpi_free( &RR_REF ); } /* END_CASE */ + +/* BEGIN_CASE */ +void mpi_core_ct_uint_table_lookup( int bitlen, int window_size ) +{ + size_t limbs = BITS_TO_LIMBS( bitlen ); + size_t count = ( (size_t) 1 ) << window_size; + + mbedtls_mpi_uint *table = NULL; + ASSERT_ALLOC( table, limbs * count ); + + mbedtls_mpi_uint *dest = NULL; + ASSERT_ALLOC( dest, limbs ); + + /* + * Fill the table with a unique counter so that differences are easily + * detected. (And have their relationship to the index relatively non-trivial just + * to be sure.) + */ + for( size_t i = 0; i < count * limbs; i++ ) + { + table[i] = ~i - 1; + } + + for( size_t i = 0; i < count; i++ ) + { + memset( dest, 0x00, limbs * sizeof( *dest ) ); + mbedtls_mpi_core_ct_uint_table_lookup( dest, table, limbs, count, i ); + + mbedtls_mpi_uint *current = table + i * limbs; + ASSERT_COMPARE( dest, limbs * sizeof( *dest ), + current, limbs * sizeof( *current ) ); + } + +exit: + ; +} +/* END_CASE */ From 133f4e427b65354095dc3c6f96087fc14e1b4df4 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 28 Oct 2022 10:54:46 +0100 Subject: [PATCH 3/7] Test mpi_core_table_lookup for constant timeness Signed-off-by: Janos Follath --- tests/suites/test_suite_bignum_core.function | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index 696d873eaf..f4fd51c160 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -966,12 +966,23 @@ void mpi_core_ct_uint_table_lookup( int bitlen, int window_size ) for( size_t i = 0; i < count; i++ ) { + /* + * We shouldn't leak anything through timing. + * We need to set these in every loop as we need to make the loop + * variable public for the loop head and comparison macros make the + * rest public automatically. + */ + TEST_CF_SECRET( &i, sizeof( i ) ); + TEST_CF_SECRET( dest, limbs * sizeof( mbedtls_mpi_uint ) ); + TEST_CF_SECRET( table, count * limbs * sizeof( mbedtls_mpi_uint ) ); + memset( dest, 0x00, limbs * sizeof( *dest ) ); mbedtls_mpi_core_ct_uint_table_lookup( dest, table, limbs, count, i ); mbedtls_mpi_uint *current = table + i * limbs; ASSERT_COMPARE( dest, limbs * sizeof( *dest ), current, limbs * sizeof( *current ) ); + TEST_CF_PUBLIC( &i, sizeof( i ) ); } exit: From 88e3177fccd7fb3ea1db4ef0b5a1addc6b770c45 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 31 Oct 2022 14:32:46 +0000 Subject: [PATCH 4/7] Make pylint happy Signed-off-by: Janos Follath --- scripts/mbedtls_dev/bignum_core.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py index e88f469a14..f8ba12b025 100644 --- a/scripts/mbedtls_dev/bignum_core.py +++ b/scripts/mbedtls_dev/bignum_core.py @@ -76,14 +76,14 @@ class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta): test_name = "Constant time MPI table lookup" bitsizes = [ - (32, "One limb"), - (192, "Smallest curve sized"), - (512, "Largest curve sized"), - (2048, "Small FF/RSA sized"), - (4096, "Large FF/RSA sized"), - ] + (32, "One limb"), + (192, "Smallest curve sized"), + (512, "Largest curve sized"), + (2048, "Small FF/RSA sized"), + (4096, "Large FF/RSA sized"), + ] - window_sizes = [ 0, 1, 2, 3, 4, 5, 6 ] + window_sizes = [0, 1, 2, 3, 4, 5, 6] def __init__(self, bitsize: int, descr: str, window_size: int) -> None: @@ -96,10 +96,10 @@ class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta): def description(self) -> str: return '{} - {} MPI with {} bit window'.format( - BignumCoreCTLookup.test_name, - self.bitsize_description, - self.window_size - ) + BignumCoreCTLookup.test_name, + self.bitsize_description, + self.window_size + ) @classmethod def generate_function_tests(cls) -> Iterator[test_case.TestCase]: From ef67d38bc0a7c610f021154ef296207b4ea1bc6e Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 31 Oct 2022 15:11:49 +0000 Subject: [PATCH 5/7] Fix memory leak in mpi_core_ct_uint_table_lookup test Signed-off-by: Janos Follath --- tests/suites/test_suite_bignum_core.function | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index f4fd51c160..c0bee70d26 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -949,9 +949,9 @@ void mpi_core_ct_uint_table_lookup( int bitlen, int window_size ) size_t count = ( (size_t) 1 ) << window_size; mbedtls_mpi_uint *table = NULL; - ASSERT_ALLOC( table, limbs * count ); - mbedtls_mpi_uint *dest = NULL; + + ASSERT_ALLOC( table, limbs * count ); ASSERT_ALLOC( dest, limbs ); /* @@ -986,6 +986,7 @@ void mpi_core_ct_uint_table_lookup( int bitlen, int window_size ) } exit: - ; + mbedtls_free(table); + mbedtls_free(dest); } /* END_CASE */ From 8904a2db297aeff67cceb16ff9369b7c03116865 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 31 Oct 2022 15:32:28 +0000 Subject: [PATCH 6/7] mpi_core_ct_uint_table_lookup: style and docs Signed-off-by: Janos Follath --- library/bignum_core.c | 13 ++++++------- library/bignum_core.h | 13 ++++++------- scripts/mbedtls_dev/bignum_core.py | 1 - 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index c1da93d0a0..b3bb3bcb88 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -541,16 +541,15 @@ cleanup: } void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest, - const mbedtls_mpi_uint *table, - size_t limbs, - size_t count, - size_t index ) + const mbedtls_mpi_uint *table, + size_t limbs, + size_t count, + size_t index ) { - for( size_t i = 0; i < count; i++ ) + for( size_t i = 0; i < count; i++, table += limbs ) { unsigned char assign = mbedtls_ct_size_bool_eq( i, index ); - const mbedtls_mpi_uint *current = table + i * limbs; - mbedtls_mpi_core_cond_assign( dest, current, limbs, assign ); + mbedtls_mpi_core_cond_assign( dest, table, limbs, assign ); } } diff --git a/library/bignum_core.h b/library/bignum_core.h index 3618e42006..ccccebbffa 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -453,17 +453,16 @@ int mbedtls_mpi_core_get_mont_r2_unsafe( mbedtls_mpi *X, const mbedtls_mpi *N ); /** - * Select an MPI from a table without leaking the index. + * Copy an MPI from a table without leaking the index. * * \param dest The destination buffer. This must point to a writable * buffer of at least \p limbs limbs. * \param table The address of the table. This must point to a readable - * array of \p count elements of - * \p limbs limbs each each. - * \param limbs The length of a table entry in limbs. - * \param count The number of elements in \p table. - * \param index The secret table index to look up. This must be in the - * range `0,..,count-1`. + * array of \p count elements of \p limbs limbs each. + * \param limbs The number of limbs in each table entry. + * \param count The number of entries in \p table. + * \param index The (secret) table index to look up. This must be in the + * range `0 .. count-1`. */ void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest, const mbedtls_mpi_uint *table, diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py index f8ba12b025..9929e13fa3 100644 --- a/scripts/mbedtls_dev/bignum_core.py +++ b/scripts/mbedtls_dev/bignum_core.py @@ -71,7 +71,6 @@ class BignumCoreShiftR(BignumCoreTarget, metaclass=ABCMeta): class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta): """Test cases for mbedtls_mpi_core_ct_uint_table_lookup().""" - count = 0 test_function = "mpi_core_ct_uint_table_lookup" test_name = "Constant time MPI table lookup" From 28f85e6683adb7a6f6c01252a8cd01ee4f12a012 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 2 Nov 2022 09:51:02 +0000 Subject: [PATCH 7/7] Fix const time in mpi_core_ct_uint_table_lookup test Signed-off-by: Janos Follath --- tests/suites/test_suite_bignum_core.function | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index c0bee70d26..d5d58d870b 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -966,20 +966,22 @@ void mpi_core_ct_uint_table_lookup( int bitlen, int window_size ) for( size_t i = 0; i < count; i++ ) { + mbedtls_mpi_uint *current = table + i * limbs; + memset( dest, 0x00, limbs * sizeof( *dest ) ); + /* * We shouldn't leak anything through timing. * We need to set these in every loop as we need to make the loop - * variable public for the loop head and comparison macros make the - * rest public automatically. + * variable public for the loop head and the buffers for comparison. */ TEST_CF_SECRET( &i, sizeof( i ) ); - TEST_CF_SECRET( dest, limbs * sizeof( mbedtls_mpi_uint ) ); - TEST_CF_SECRET( table, count * limbs * sizeof( mbedtls_mpi_uint ) ); + TEST_CF_SECRET( dest, limbs * sizeof( *dest ) ); + TEST_CF_SECRET( table, count * limbs * sizeof( *table ) ); - memset( dest, 0x00, limbs * sizeof( *dest ) ); mbedtls_mpi_core_ct_uint_table_lookup( dest, table, limbs, count, i ); - mbedtls_mpi_uint *current = table + i * limbs; + TEST_CF_PUBLIC( dest, limbs * sizeof( *dest ) ); + TEST_CF_PUBLIC( table, count * limbs * sizeof( *table ) ); ASSERT_COMPARE( dest, limbs * sizeof( *dest ), current, limbs * sizeof( *current ) ); TEST_CF_PUBLIC( &i, sizeof( i ) );