From 2f5947e1f63d48fb2e8072fcc2911fd1f8be3ee9 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Wed, 18 May 2011 15:47:11 +0000 Subject: [PATCH] - Added mpi_get_bit() and mpi_set_bit() individual bit setter/getter functions. --- ChangeLog | 2 ++ include/polarssl/bignum.h | 26 +++++++++++++++++++ library/bignum.c | 38 ++++++++++++++++++++++++++++ tests/suites/test_suite_mpi.data | 27 ++++++++++++++++++++ tests/suites/test_suite_mpi.function | 27 ++++++++++++++++++++ 5 files changed, 120 insertions(+) diff --git a/ChangeLog b/ChangeLog index 76f8696fc..b620783cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,8 @@ Features by undefining POLARSSL_FS_IO * A error_strerror function() has been added to translate between error codes and their description. + * Added mpi_get_bit() and mpi_set_bit() individual bit setter/getter + functions. Changes * Major argument / variable rewrite. Introduced use of size_t diff --git a/include/polarssl/bignum.h b/include/polarssl/bignum.h index 96b0391ce..793840670 100644 --- a/include/polarssl/bignum.h +++ b/include/polarssl/bignum.h @@ -146,6 +146,32 @@ void mpi_swap( mpi *X, mpi *Y ); */ int mpi_lset( mpi *X, t_sint z ); +/* + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mpi_get_bit( mpi *X, size_t pos ); + +/* + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ); + /** * \brief Return the number of least significant bits * diff --git a/library/bignum.c b/library/bignum.c index 2e3595c5e..5635bd2f0 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -170,6 +170,44 @@ cleanup: return( ret ); } +/* + * Get a specific bit + */ +int mpi_get_bit( mpi *X, size_t pos ) +{ + if( X->n * biL <= pos ) + return( 0 ); + + return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01; +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if( val != 0 && val != 1 ) + return POLARSSL_ERR_MPI_BAD_INPUT_DATA; + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return ( 0 ); + + MPI_CHK( mpi_grow( X, off + 1 ) ); + } + + X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx ); + +cleanup: + + return( ret ); +} + /* * Return the number of least significant bits */ diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data index 889f73de5..87e095c62 100644 --- a/tests/suites/test_suite_mpi.data +++ b/tests/suites/test_suite_mpi.data @@ -518,6 +518,33 @@ mpi_is_prime:10:"32452867":0 Test mpi_is_prime #20 mpi_is_prime:10:"49979687":0 +Test bit getting (Value bit 25) +mpi_get_bit:10:"49979687":25:1 + +Test bit getting (Larger but same limb) +mpi_get_bit:10:"49979687":26:0 + +Test bit getting (Larger and non-existing limb) +mpi_get_bit:10:"49979687":500:0 + +Test bit getting (Value bit 24) +mpi_get_bit:10:"49979687":24:0 + +Test bit getting (Value bit 23) +mpi_get_bit:10:"49979687":23:1 + +Test bit set (Change existing value with a 1) +mpi_set_bit:10:"49979687":24:1:10:"66756903" + +Test bit set (Change existing value with a 0) +mpi_set_bit:10:"49979687":25:0:10:"16425255" + +Test bit set (Add above existing limbs with a 0) +mpi_set_bit:10:"49979687":80:0:10:"49979687" + +Test bit set (Add above existing limbs with a 1) +mpi_set_bit:10:"49979687":80:1:10:"1208925819614629224685863" + MPI Selftest depends_on:POLARSSL_SELF_TEST mpi_selftest: diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function index c31589e8f..905f1c37a 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -142,6 +142,33 @@ mpi_write_file:radix_X:input_X:output_radix:output_file } END_CASE +BEGIN_CASE +mpi_get_bit:radix_X:input_X:pos:val +{ + mpi X; + mpi_init( &X ); + TEST_ASSERT( mpi_read_string( &X, {radix_X}, {input_X} ) == 0 ); + TEST_ASSERT( mpi_get_bit( &X, {pos} ) == {val} ); + + mpi_free( &X ); +} +END_CASE + +BEGIN_CASE +mpi_set_bit:radix_X:input_X:pos:val:radix_Y:output_Y +{ + mpi X, Y; + mpi_init( &X ); mpi_init( &Y ); + + TEST_ASSERT( mpi_read_string( &X, {radix_X}, {input_X} ) == 0 ); + TEST_ASSERT( mpi_read_string( &Y, {radix_Y}, {output_Y} ) == 0 ); + TEST_ASSERT( mpi_set_bit( &X, {pos}, {val} ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &X, &Y ) == 0 ); + + mpi_free( &X ); +} +END_CASE + BEGIN_CASE mpi_lsb:radix_X:input_X:nr_bits {