Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a function that decompresses EC public keys #521

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions include/mbedtls/ecp.h
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,21 @@ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
*/
int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv );

/**
* \brief Decompresses an EC Public Keypair
*
* \param grp ECP group
* \param input Compressed EC Public Key (Created using mbedtls_ecp_point_write_binary with format = MBEDTLS_ECP_PF_COMPRESSED)
* \param ilen Input length
* \param output Uncompressed EC Public Key
* \param olen Uncompressed EC Public Key output length
* \param osize Size of the output buffer
*
* \return 0 on success, or a specific error code.
*/
int mbedtls_ecp_decompress_pubkey( const mbedtls_ecp_group *grp, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize );

#if defined(MBEDTLS_SELF_TEST)
/**
* \brief Checkup routine
Expand Down
58 changes: 58 additions & 0 deletions library/ecp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1958,6 +1958,64 @@ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ec
return( ret );
}

/*
* Decompresses an EC Public Key
*/
int mbedtls_ecp_decompress_pubkey( const mbedtls_ecp_group *grp, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize ){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line length and the following indentation don't match our coding style.


int ret;
mbedtls_mpi x, x3, ax, z, zexp, y;
size_t plen;

plen = mbedtls_mpi_size( &grp->P );
*olen = 2 * plen + 1;

if( ilen != plen + 1 || input[0] == 0x04 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );

if( osize < 1 )
return( 0 );

if( osize < *olen )
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );

mbedtls_mpi_init( &x );
mbedtls_mpi_init( &x3 );
mbedtls_mpi_init( &ax );
mbedtls_mpi_init( &z );
mbedtls_mpi_init( &zexp );
mbedtls_mpi_init( &y );


MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &x, input+1, ilen-1 ) ); // X point of the pubkey
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &x3, &x, &x ) ); // X^2
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &x3, &x3, &x ) ); // X^3
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ax, &grp->A, &x ) ); // AX
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &z, &x3, &ax ) ); // X^3 + AX
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &z, &z, &grp->B ) ); // X^3 + AX + B
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &zexp, &grp->P) ); // Z exponent
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &zexp, &zexp, 1 ) ); // Z exponent + 1
MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( &zexp, 0, &zexp, 4 ) ); // Z exponent / 4
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &y, &z, &zexp, &grp->P, 0 ) ); // Z^Zexp % P
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way of extracting square roots mod P only works for some Ps (those that are congruent to 3 mod 4), but will not work for all curves supported by Mbed TLS.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mpg what curves use Ps that are congruent to 3 mod 4? I would like to add that to my readme here: https://github.com/mwarning/mbedtls_ecp_compression

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's easy to check:

#include "mbedtls/ecp.h"
#include <stdio.h>

int main(void)
{
    const mbedtls_ecp_curve_info *info;
    mbedtls_ecp_group grp;
    mbedtls_mpi_uint r;

    for( info = mbedtls_ecp_curve_list(); info->name != NULL; info++ )
    {
        mbedtls_ecp_group_init( &grp );
        mbedtls_ecp_group_load( &grp, info->grp_id );
        mbedtls_mpi_mod_int( &r, &grp.P, 4 );
        printf( "%s: p = %u mod 4\n", info->name, (unsigned) r );
        mbedtls_ecp_group_free( &grp );
    }
}

then

% make lib && gcc -Iinclude p-mod-4.c library/libmbedcrypto.a -o p-mod-4 && ./p-mod-4                                                                  git|development|
secp521r1: p = 3 mod 4
brainpoolP512r1: p = 3 mod 4
secp384r1: p = 3 mod 4
brainpoolP384r1: p = 3 mod 4
secp256r1: p = 3 mod 4
secp256k1: p = 3 mod 4
brainpoolP256r1: p = 3 mod 4
secp224r1: p = 1 mod 4
secp224k1: p = 1 mod 4
secp192r1: p = 3 mod 4
secp192k1: p = 3 mod 4

MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &y, 0, input[0] == 0x03 ? 1 : 0 ) ); // Setting the correct sign

output[0] = 0x04; // Uncompressed format
memcpy( output+1, input+1, ilen-1 ); //0x04 + X
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &y, (output+1+ilen-1), plen ) ); // 0x04 + X + Y

cleanup:
mbedtls_mpi_free( &x );
mbedtls_mpi_free( &x3 );
mbedtls_mpi_free( &ax );
mbedtls_mpi_free( &z );
mbedtls_mpi_free( &zexp );
mbedtls_mpi_free( &y );


return( ret );
}


#if defined(MBEDTLS_SELF_TEST)

/*
Expand Down