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
{