From ad808dd5f1ef7d418b83ab735107ee412aa86c23 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 20 Apr 2023 12:18:41 +0100 Subject: [PATCH 1/7] bignum_core: Extracted mbedtls_mpi_shift_l from prototype Signed-off-by: Minos Galanakis --- library/bignum_core.c | 48 +++++++++++++++++++++++++++++++++++++++++++ library/bignum_core.h | 12 +++++++++++ 2 files changed, 60 insertions(+) diff --git a/library/bignum_core.c b/library/bignum_core.c index c6d92fb061..26aff15f16 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -353,6 +353,54 @@ void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, } } +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, diff --git a/library/bignum_core.h b/library/bignum_core.h index b3d05a34ef..25e7e1a6be 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -293,6 +293,18 @@ int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A, void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, size_t count); +/** + * \brief Perform a left-shift on an MPI: X <<= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + /** * \brief Add two fixed-size large unsigned integers, returning the carry. * From ec09e2525147cb7cf7c82df3a8e1aa69dd62fcf1 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 20 Apr 2023 14:22:16 +0100 Subject: [PATCH 2/7] bignum_core: Aligned `xxx_core_shift_l` to `xxx_core_shift_r` This patch modifies the left-shift implementation to closely align in interface and behaviour to the existing right-shift method. Signed-off-by: Minos Galanakis --- library/bignum_core.c | 50 ++++++++++++++++++------------------------- library/bignum_core.h | 19 +++++++++------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 26aff15f16..92a9d558a3 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -353,52 +353,44 @@ void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, } } -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, + size_t count) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, v0, t1; + size_t i, v0, v1; mbedtls_mpi_uint r0 = 0, r1; - MPI_VALIDATE_RET( X != NULL ); - v0 = count / (biL ); - t1 = count & (biL - 1); + v0 = count / (biL); + v1 = count & (biL - 1); - i = mbedtls_mpi_bitlen( X ) + count; - - if( X->n * biL < i ) - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); - - ret = 0; + if (v0 > limbs || (v0 == limbs && v1 > 0)) { + memset(X, 0, limbs * ciL); + return; + } /* * shift by count / limb_size */ - if( v0 > 0 ) - { - for( i = X->n; i > v0; i-- ) - X->p[i - 1] = X->p[i - v0 - 1]; + if (v0 > 0) { + for (i = limbs; i > v0; i--) { + X[i - 1] = X[i - v0 - 1]; + } - for( ; i > 0; i-- ) - X->p[i - 1] = 0; + for (; i > 0; i--) { + X[i - 1] = 0; + } } /* * shift by count % limb_size */ - if( t1 > 0 ) - { - for( i = v0; i < X->n; i++ ) - { - r1 = X->p[i] >> (biL - t1); - X->p[i] <<= t1; - X->p[i] |= r0; + if (v1 > 0) { + for (i = v0; i < limbs; i++) { + r1 = X[i] >> (biL - v1); + X[i] <<= v1; + X[i] |= r0; r0 = r1; } } - -cleanup: - - return( ret ); } mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, diff --git a/library/bignum_core.h b/library/bignum_core.h index 25e7e1a6be..2b11ccaff3 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -278,7 +278,7 @@ int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A, unsigned char *output, size_t output_length); -/** \brief Shift an MPI right in place by a number of bits. +/** \brief Shift an MPI in-place right by a number of bits. * * Shifting by more bits than there are bit positions * in \p X is valid and results in setting \p X to 0. @@ -294,16 +294,19 @@ void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, size_t count); /** - * \brief Perform a left-shift on an MPI: X <<= count + * \brief Shift an MPI in-place left by a number of bits. * - * \param X The MPI to shift. This must point to an initialized MPI. - * \param count The number of bits to shift by. + * Shifting by more bits than there are bit positions + * in \p X is valid and results in setting \p X to 0. * - * \return \c 0 if successful. - * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. - * \return Another negative error code on different kinds of failure. + * This function's execution time depends on the value + * of \p count (and of course \p limbs). + * \param[in,out] X The number to shift. + * \param limbs The number of limbs of \p X. This must be at least 1. + * \param count The number of bits to shift by. */ -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); +void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, + size_t count); /** * \brief Add two fixed-size large unsigned integers, returning the carry. From cfb5a5fade70891269d0458c929eef3fc6be3250 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 25 Apr 2023 12:11:44 +0100 Subject: [PATCH 3/7] bignum_core_test_suite: Added `mpi_core_shift_l()` Signed-off-by: Minos Galanakis --- tests/suites/test_suite_bignum_core.function | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index e084b83252..6eba5fa786 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -532,6 +532,26 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void mpi_core_shift_l(char *input, int count, char *result) +{ + mbedtls_mpi_uint *X = NULL; + mbedtls_mpi_uint *Y = NULL; + size_t limbs, n; + + TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &limbs, input)); + TEST_EQUAL(0, mbedtls_test_read_mpi_core(&Y, &n, result)); + TEST_EQUAL(limbs, n); + + mbedtls_mpi_core_shift_l(X, limbs, count); + ASSERT_COMPARE(X, limbs * ciL, Y, limbs * ciL); + +exit: + mbedtls_free(X); + mbedtls_free(Y); +} +/* END_CASE */ + /* BEGIN_CASE */ void mpi_core_add_and_add_if(char *input_A, char *input_B, char *input_S, int carry) From c787cf73b35bd11033f48d84e072ca9ca3b7335d Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 25 Apr 2023 12:13:25 +0100 Subject: [PATCH 4/7] bignum_core.py: Add "BignumCoreShiftL()" This patch introduces automatic test input generation for `mpi_core_shift_l()` function. It also adds two utility functions in bignum_common. Signed-off-by: Minos Galanakis --- scripts/mbedtls_dev/bignum_common.py | 17 ++++++++ scripts/mbedtls_dev/bignum_core.py | 62 ++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py index d8ef4a84f5..20f7ff88b6 100644 --- a/scripts/mbedtls_dev/bignum_common.py +++ b/scripts/mbedtls_dev/bignum_common.py @@ -80,6 +80,23 @@ def hex_digits_for_limb(limbs: int, bits_in_limb: int) -> int: """ Retrun the hex digits need for a number of limbs. """ return 2 * (limbs * bits_in_limb // 8) +def hex_digits_max_int(val: str, bits_in_limb: int) -> int: + """ Return the first number exceeding maximum the limb space + required to store the input hex-string value. This method + weights on the input str_len rather than numerical value + and works with zero-padded inputs""" + n = ((1 << (len(val) * 4)) - 1) + l = limbs_mpi(n, bits_in_limb) + return bound_mpi_limbs(l, bits_in_limb) + +def zfill_match(reference: str, target: str) -> str: + """ Zero pad target hex-string the match the limb size of + the refference input """ + lt = len(target) + lr = len(reference) + targen_len = lr if lt < lr else lt + return "{:x}".format(int(target, 16)).zfill(targen_len) + class OperationCommon(test_data_generation.BaseTest): """Common features for bignum binary operations. diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py index 5801caef59..2abf77ac8a 100644 --- a/scripts/mbedtls_dev/bignum_core.py +++ b/scripts/mbedtls_dev/bignum_core.py @@ -68,6 +68,68 @@ class BignumCoreShiftR(BignumCoreTarget, test_data_generation.BaseTest): for count in counts: yield cls(input_hex, descr, count).create_test_case() + +class BignumCoreShiftL(BignumCoreTarget, bignum_common.ModOperationCommon): + """Test cases for mbedtls_bignum_core_shift_l().""" + + BIT_SHIFT_VALUES = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', + '1f', '20', '21', '3f', '40', '41', '47', '48', '4f', + '50', '51', '58', '80', '81', '88'] + DATA = ["0", "1", "40", "dee5ca1a7ef10a75", "a1055eb0bb1efa1150ff", + "002e7ab0070ad57001", "020100000000000000001011121314151617", + "1946e2958a85d8863ae21f4904fcc49478412534ed53eaf321f63f2a222" + "7a3c63acbf50b6305595f90cfa8327f6db80d986fe96080bcbb5df1bdbe" + "9b74fb8dedf2bddb3f8215b54dffd66409323bcc473e45a8fe9d08e77a51" + "1698b5dad0416305db7fcf"] + arity = 1 + test_function = "mpi_core_shift_l" + test_name = "Core shift(L)" + input_style = "arch_split" + symbol = "<<" + input_values = BIT_SHIFT_VALUES + moduli = DATA + + @property + def val_n_max_limbs(self) -> int: + """ Return the limb count required to store the maximum number that can + fit in a the number of digits used by val_n """ + m = bignum_common.hex_digits_max_int(self.val_n, self.bits_in_limb) - 1 + return bignum_common.limbs_mpi(m, self.bits_in_limb) + + def arguments(self) -> List[str]: + return [bignum_common.quote_str(self.val_n), + str(self.int_a) + ] + self.result() + + def description(self) -> str: + """ Format the output as: + #{count} {hex input} ({input bits} {limbs capacity}) << {bit shift} """ + bits = "({} bits in {} limbs)".format(self.int_n.bit_length(), self.val_n_max_limbs) + return "{} #{} {} {} {} {}".format(self.test_name, + self.count, + self.val_n, + bits, + self.symbol, + self.int_a) + + def format_result(self, res: int) -> str: + # Override to match zero-pading for leading digits between the output and input. + res_str = bignum_common.zfill_match(self.val_n, "{:x}".format(res)) + return bignum_common.quote_str(res_str) + + def result(self) -> List[str]: + result = (self.int_n << self.int_a) + # Calculate if there is space for shifting to the left(leading zero limbs) + mx = bignum_common.hex_digits_max_int(self.val_n, self.bits_in_limb) + # If there are empty limbs ahead, adjust the bitmask accordingly + result = result & (self.r - 1) if mx == self.r else result & (mx - 1) + return [self.format_result(result)] + + @property + def is_valid(self) -> bool: + return True + + class BignumCoreCTLookup(BignumCoreTarget, test_data_generation.BaseTest): """Test cases for mbedtls_mpi_core_ct_uint_table_lookup().""" test_function = "mpi_core_ct_uint_table_lookup" From b89440394f8d4424ddd5ce927a7ecc3dac8e5a7e Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Fri, 28 Apr 2023 14:09:44 +0100 Subject: [PATCH 5/7] bignum_core: Removed input checking for `mbedtls_mpi_core_shift_l` Signed-off-by: Minos Galanakis --- library/bignum_core.c | 5 ----- library/bignum_core.h | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 92a9d558a3..34223ee957 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -362,11 +362,6 @@ void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, v0 = count / (biL); v1 = count & (biL - 1); - if (v0 > limbs || (v0 == limbs && v1 > 0)) { - memset(X, 0, limbs * ciL); - return; - } - /* * shift by count / limb_size */ diff --git a/library/bignum_core.h b/library/bignum_core.h index 2b11ccaff3..f7194982dc 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -297,7 +297,7 @@ void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, * \brief Shift an MPI in-place left by a number of bits. * * Shifting by more bits than there are bit positions - * in \p X is valid and results in setting \p X to 0. + * in \p X will produce an unspecified result. * * This function's execution time depends on the value * of \p count (and of course \p limbs). From 013167ed7f0afa4739b6ffcbda8b9483b7d5780d Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 11 May 2023 10:54:44 +0100 Subject: [PATCH 6/7] bignum_common.py: Addressed minor typos Signed-off-by: Minos Galanakis --- scripts/mbedtls_dev/bignum_common.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py index 20f7ff88b6..51b25a3715 100644 --- a/scripts/mbedtls_dev/bignum_common.py +++ b/scripts/mbedtls_dev/bignum_common.py @@ -90,12 +90,12 @@ def hex_digits_max_int(val: str, bits_in_limb: int) -> int: return bound_mpi_limbs(l, bits_in_limb) def zfill_match(reference: str, target: str) -> str: - """ Zero pad target hex-string the match the limb size of - the refference input """ + """ Zero pad target hex-string to match the limb size of + the reference input """ lt = len(target) lr = len(reference) - targen_len = lr if lt < lr else lt - return "{:x}".format(int(target, 16)).zfill(targen_len) + target_len = lr if lt < lr else lt + return "{:x}".format(int(target, 16)).zfill(target_len) class OperationCommon(test_data_generation.BaseTest): """Common features for bignum binary operations. From 99453ad9f03c8cbbcd4b12f1818b104eec81814b Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 16 May 2023 15:26:06 +0100 Subject: [PATCH 7/7] bignum_core.py: Simplified result calculation for `BignumCoreShiftL` Signed-off-by: Minos Galanakis --- scripts/mbedtls_dev/bignum_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py index 2abf77ac8a..ff3fd23e68 100644 --- a/scripts/mbedtls_dev/bignum_core.py +++ b/scripts/mbedtls_dev/bignum_core.py @@ -122,7 +122,7 @@ class BignumCoreShiftL(BignumCoreTarget, bignum_common.ModOperationCommon): # Calculate if there is space for shifting to the left(leading zero limbs) mx = bignum_common.hex_digits_max_int(self.val_n, self.bits_in_limb) # If there are empty limbs ahead, adjust the bitmask accordingly - result = result & (self.r - 1) if mx == self.r else result & (mx - 1) + result = result & (mx - 1) return [self.format_result(result)] @property