diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index cd4dd9b27..189e3f253 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -218,7 +218,7 @@ int ecp_group_read_string( ecp_group *grp, int radix, /** * \brief Export a point into unsigned binary data * - * \param grp Group the point belongs to + * \param grp Group to which the point should belong * \param P Point to export * \param format Point format, should be a POLARSSL_ECP_PF_XXX macro * \param olen Length of the actual ouput @@ -230,6 +230,25 @@ int ecp_group_read_string( ecp_group *grp, int radix, int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen ); +/** + * \brief Import a point from unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to import + * \param format Point format, must be POLARSSL_ECP_PF_UNCOMPRESSED for now + * \param buf Input buffer + * \param ilen Actual length of input + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_GENERIC if input is invalid + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * + * \note This function does NOT check that the point actually + * belongs to the given group, see ecp_check_pubkey() for + * that. + */ +int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, + const unsigned char *buf, size_t ilen ); /** * \brief Set a group using well-known domain parameters * diff --git a/library/ecp.c b/library/ecp.c index 6501fbe9f..dd913bead 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -228,6 +228,33 @@ cleanup: return( ret ); } +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, + const unsigned char *buf, size_t ilen ) { + int ret; + size_t plen; + + if( format != POLARSSL_ECP_PF_UNCOMPRESSED ) + return( POLARSSL_ERR_ECP_GENERIC ); + + if( ilen == 1 && buf[0] == 0x00 ) + return( ecp_set_zero( P ) ); + + plen = mpi_size( &grp-> P ); + + if( ilen != 2 * plen + 1 || buf[0] != 0x04 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + MPI_CHK( mpi_read_binary( &P->X, buf + 1, plen ) ); + MPI_CHK( mpi_read_binary( &P->Y, buf + 1 + plen, plen ) ); + MPI_CHK( mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + /* * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi. * See the documentation of struct ecp_group. diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index e84ac045e..605af820e 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -163,6 +163,27 @@ ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6 ECP write binary #7 (odd, compressed, buffer just fits) ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"93112b28345b7d1d7799611e49bea9d8290cb2d7afe1f9f3":"01":COMPRESSED:"0348d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":25:0 +ECP read binary #0 (invalid format) +ecp_read_binary:SECP192R1:"00":UNKNOWN:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #1 (zero, invalid ilen) +ecp_read_binary:SECP192R1:"0000":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #2 (zero, invalid first byte) +ecp_read_binary:SECP192R1:"01":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #3 (zero, OK) +ecp_read_binary:SECP192R1:"00":UNCOMPRESSED:"01":"01":"00":0 + +ECP read binary #4 (non-zero, invalid ilen) +ecp_read_binary:SECP192R1:"04001122":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #5 (non-zero, invalid first byte) +ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #6 (non-zero, OK) +ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 + ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index b273a70a1..fdd3da2a9 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -257,6 +257,44 @@ ecp_write_binary:id:x:y:z:format:out:blen:ret } END_CASE +BEGIN_CASE +ecp_read_binary:id:input:format:x:y:z:ret +{ + ecp_group grp; + ecp_point P; + mpi X, Y, Z; + int ilen; + unsigned char buf[256]; + + memset( buf, 0, sizeof( buf ) ); + + ecp_group_init( &grp ); ecp_point_init( &P ); + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( mpi_read_string( &X, 16, {x} ) == 0 ); + TEST_ASSERT( mpi_read_string( &Y, 16, {y} ) == 0 ); + TEST_ASSERT( mpi_read_string( &Z, 16, {z} ) == 0 ); + + ilen = unhexify( buf, {input} ); + +#define POLARSSL_ECP_PF_UNKNOWN -1 + TEST_ASSERT( ecp_read_binary( &grp, &P, POLARSSL_ECP_PF_{format}, + buf, ilen ) == {ret} ); + + if( {ret} == 0 ) + { + TEST_ASSERT( mpi_cmp_mpi( &P.X, &X ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &P.Y, &Y ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &P.Z, &Z ) == 0 ); + } + + ecp_group_free( &grp ); ecp_point_free( &P ); + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); +} +END_CASE + BEGIN_CASE ecp_selftest: {