diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 96c135b56..a875d7ec8 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -209,6 +209,20 @@ int ecp_group_read_string( ecp_group *grp, int radix, const char *p, const char *b, const char *gx, const char *gy, const char *n); +/** + * \brief Export a point into unsigned binary data, uncompressed + * + * \param grp Group the point belongs to + * \param P Point to export + * \param olen Length of the actual ouput + * \param buf Output buffer + * \param buflen Length of the output buffer + * + * \return 0 if successful, or POLARSSL_ERR_ECP_GENERIC + */ +int ecp_write_binary( const ecp_group *grp, const ecp_point *P, + size_t *olen, unsigned char *buf, size_t buflen ); + /** * \brief Set a group using well-known domain parameters * diff --git a/library/ecp.c b/library/ecp.c index 40732885c..854da58c8 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -173,6 +173,43 @@ cleanup: return( ret ); } +/* + * Export a point into unsigned binary data, uncompressed format (SEC1 2.3.3) + */ +int ecp_write_binary( const ecp_group *grp, const ecp_point *P, + size_t *olen, unsigned char *buf, size_t buflen ) +{ + int ret; + size_t plen; + + /* + * Case P == 0 + */ + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mpi_size( &grp->P ); + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( POLARSSL_ERR_ECP_GENERIC ); + + buf[0] = 0x04; + MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); + MPI_CHK( mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + +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 15f90945d..20ae3cd68 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -133,6 +133,18 @@ ecp_small_check_pub:0:2:1:0 ECP small check pubkey #10 ecp_small_check_pub:10:25:1:POLARSSL_ERR_ECP_GENERIC +ECP write binary #1 (zero, buffer just fits) +ecp_write_binary:SECP192R1:"01":"01":"00":"00":1:0 + +ECP write binary #2 (zero, buffer too small) +ecp_write_binary:SECP192R1:"01":"01":"00":"00":0:POLARSSL_ERR_ECP_GENERIC + +ECP write binary #3 (non-zero, buffer just fits) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":49:0 + +ECP write binary #4 (non-zero, buffer too small) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":48:POLARSSL_ERR_ECP_GENERIC + 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 0fcc842da..1e50499b8 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -224,6 +224,39 @@ ecp_fast_mod:id:N } END_CASE +BEGIN_CASE +ecp_write_binary:id:x:y:z:out:blen:ret +{ + ecp_group grp; + ecp_point P; + unsigned char buf[256], str[512]; + size_t olen; + + memset( buf, 0, sizeof( buf ) ); + memset( str, 0, sizeof( str ) ); + + ecp_group_init( &grp ); ecp_point_init( &P ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( mpi_read_string( &P.X, 16, {x} ) == 0 ); + TEST_ASSERT( mpi_read_string( &P.Y, 16, {y} ) == 0 ); + TEST_ASSERT( mpi_read_string( &P.Z, 16, {z} ) == 0 ); + + TEST_ASSERT( ecp_write_binary( &grp, &P, &olen, buf, {blen} ) == {ret} ); + + if( {ret} == 0 ) + { + TEST_ASSERT( olen == strlen({out}) / 2 ); + + hexify( str, buf, {blen} ); + TEST_ASSERT( strcasecmp( (char *) str, {out} ) == 0 ); + } + + ecp_group_free( &grp ); ecp_point_free( &P ); +} +END_CASE + BEGIN_CASE ecp_selftest: {