diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h index 0727917c5..c4d768658 100644 --- a/include/mbedtls/bignum.h +++ b/include/mbedtls/bignum.h @@ -522,6 +522,24 @@ int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); +/** + * \brief Export X into unsigned binary data, little endian. + * Always fills the whole buffer, which will end with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ); + /** * \brief Perform a left-shift on an MPI: X <<= count * diff --git a/library/bignum.c b/library/bignum.c index eb3264082..f0882db4b 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -888,6 +888,45 @@ cleanup: return( ret ); } +/* + * Export X into unsigned binary data, little endian + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes = X->n * ciL; + size_t bytes_to_copy; + size_t i; + + if( stored_bytes < buflen ) + { + bytes_to_copy = stored_bytes; + } + else + { + bytes_to_copy = buflen; + + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + buf[i] = GET_BYTE( X, i ); + + if( stored_bytes < buflen ) + { + /* Write trailing 0 bytes */ + memset( buf + stored_bytes, 0, buflen - stored_bytes ); + } + + return( 0 ); +} + /* * Export X into unsigned binary data, big endian */ diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data index 7ad7ef663..f2be14816 100644 --- a/tests/suites/test_suite_mpi.data +++ b/tests/suites/test_suite_mpi.data @@ -70,6 +70,15 @@ mbedtls_mpi_write_binary:16:"123123123123123123123123123":"012312312312312312312 Test mbedtls_mpi_write_binary #2 (Buffer too small) mbedtls_mpi_write_binary:16:"123123123123123123123123123":"23123123123123123123123123":13:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL +Base test mbedtls_mpi_write_binary_le #1 +mbedtls_mpi_write_binary_le:10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924":"24448b952fbbef93f89286ba330e62528b151eac265cc8ce3038519d09e148af89288e91f48b41acad55d9dc5e2b18097c106be4ce132721bf6359eaf403e7ff90623e8866ee5c192320418daa682f144adedf84f25de11f49d1fe009d374109":200:0 + +Test mbedtls_mpi_write_binary_le #1 (Buffer just fits) +mbedtls_mpi_write_binary_le:16:"123123123123123123123123123":"2331122331122331122331122301":14:0 + +Test mbedtls_mpi_write_binary_le #2 (Buffer too small) +mbedtls_mpi_write_binary_le:16:"123123123123123123123123123":"23311223311223311223311223":13:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL + Base test mbedtls_mpi_read_file #1 mbedtls_mpi_read_file:10:"data_files/mpi_10":"01f55332c3a48b910f9942f6c914e58bef37a47ee45cb164a5b6b8d1006bf59a059c21449939ebebfdf517d2e1dbac88010d7b1f141e997bd6801ddaec9d05910f4f2de2b2c4d714e2c14a72fc7f17aa428d59c531627f09":0 diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function index 0ec45f655..5358379f0 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -378,6 +378,37 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void mbedtls_mpi_write_binary_le( int radix_X, char * input_X, + data_t * input_A, int output_size, + int result ) +{ + mbedtls_mpi X; + unsigned char buf[1000]; + size_t buflen; + + memset( buf, 0x00, 1000 ); + + mbedtls_mpi_init( &X ); + + TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 ); + + buflen = mbedtls_mpi_size( &X ); + if( buflen > (size_t) output_size ) + buflen = (size_t) output_size; + + TEST_ASSERT( mbedtls_mpi_write_binary_le( &X, buf, buflen ) == result ); + if( result == 0) + { + + TEST_ASSERT( hexcmp( buf, input_A->x, buflen, input_A->len ) == 0 ); + } + +exit: + mbedtls_mpi_free( &X ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ void mbedtls_mpi_read_file( int radix_X, char * input_file, data_t * input_A, int result )