Skip to content

Commit

Permalink
mbedtls_ecp_point_read_binary from compressed fmt
Browse files Browse the repository at this point in the history
mbedtls_ecp_point_read_binary from MBEDTLS_ECP_PF_COMPRESSED format

Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com>
  • Loading branch information
gstrauss committed Sep 15, 2022
1 parent 208257b commit 0b65d06
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 6 deletions.
2 changes: 2 additions & 0 deletions ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Features
* mbedtls_ecp_point_read_binary from MBEDTLS_ECP_PF_COMPRESSED format
77 changes: 71 additions & 6 deletions library/ecp.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,58 @@ int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
return( ret );
}

#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
static int mbedtls_ecp_sw_derive_y( const mbedtls_ecp_group *grp,
const mbedtls_mpi *X,
mbedtls_mpi *Y,
int parity_bit )
{
/* y^2 = x^3 + ax + b (where a = -3 for short weierstrass)
* sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */

if( mbedtls_mpi_get_bit( &grp->P, 0 ) != 1 || /*(p = 3 mod 4)*/
mbedtls_mpi_get_bit( &grp->P, 1 ) != 1 ) /*(p = 3 mod 4)*/
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );

int ret;
mbedtls_mpi exp;
mbedtls_mpi_init(&exp);

/*(use Y to store intermediate results)*/
/* y^2 = x^3 + ax + b = (x^2 + a)x + b */
/* x^2 */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( Y, X, X ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( Y, Y, &grp->P ) );
/* x^2 + a */
if( !grp->A.p ) /*(temporarily set exp = -3 for a if A not set)*/
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &exp, -3 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( Y, Y, grp->A.p ? &grp->A : &exp ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( Y, Y, &grp->P ) );
/* (x^2 + a)x */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( Y, Y, X ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( Y, Y, &grp->P ) );
/* (x^2 + a)x + b */
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( Y, Y, &grp->B ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( Y, Y, &grp->P ) );

/* w = y^2 */ /*(Y contains y^2 intermediate result)*/
/* exp = ((p+1)/4) */
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &exp, &grp->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &exp, 2 ) );
/* sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( Y, Y /*y^2*/, &exp, &grp->P, NULL ) );

/* check parity bit match or else invert Y */
if( mbedtls_mpi_get_bit( Y, 0 ) != parity_bit )
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( Y, &grp->P, Y ) );

cleanup:

mbedtls_mpi_free(&exp);
return( ret );
}
#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */

/*
* Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748)
*/
Expand Down Expand Up @@ -808,16 +860,29 @@ int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
}

if( buf[0] != 0x04 )
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );

if( ilen != 2 * plen + 1 )
if( ilen < 1 + plen )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );

MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y,
buf + 1 + plen, plen ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );

if( buf[0] == 0x04 )
{
/* format == MBEDTLS_ECP_PF_UNCOMPRESSED */
if( ilen != 1 + plen * 2 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
return( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
}
else if( buf[0] == 0x02 || buf[0] == 0x03 )
{
/* format == MBEDTLS_ECP_PF_COMPRESSED */
if( ilen != 1 + plen )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
return( mbedtls_ecp_sw_derive_y( grp, &pt->X, &pt->Y,
( buf[0] & 1 ) ) );
}
else
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
}
#endif

Expand Down
9 changes: 9 additions & 0 deletions tests/suites/test_suite_ecp.function
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,15 @@ void ecp_read_binary( int id, data_t * buf, char * x, char * y, char * z,
{
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Y, &Y ) == 0 );
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Z, &Z ) == 0 );

if( buf->x[0] == 0x04 )
{
/* re-encode in compressed format and test read again */
mbedtls_mpi_free( &P.Y );
buf->x[0] = 0x02 + mbedtls_mpi_get_bit( &Y, 0 );
TEST_ASSERT( mbedtls_ecp_point_read_binary( &grp, &P, buf->x, buf->len/2+1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Y, &Y ) == 0 );
}
}
}

Expand Down

0 comments on commit 0b65d06

Please sign in to comment.