diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index 3666ffec4..c0088db5e 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -235,6 +235,28 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +/** + * \brief Convert a signature from numbers to ASN.1 + * + * \param r First number of the signature + * \param s Second number of the signature + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param ssize Size of the sig buffer + * + * \note The size of the buffer \c ssize should be at least + * `MBEDTLS_ECDSA_MAX_SIG_LEN(grp->pbits)` bytes long if + * the signature was produced from curve \c grp, + * otherwise this function will return an error. + * + * \return 0 if successful, + * or a MBEDTLS_ERR_MPI_XXX or MBEDTLS_ERR_ASN1_XXX error code + * + */ +int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen, + size_t ssize ); + /** * \brief Read and verify an ECDSA signature * diff --git a/library/ecdsa.c b/library/ecdsa.c index 826fefe5c..fdd0afb46 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -289,22 +289,22 @@ cleanup: /* * Convert a signature (given by context) to ASN.1 */ -static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, - unsigned char *sig, size_t *slen ) +int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen, size_t ssize ) { int ret; - unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; - unsigned char *p = buf + sizeof( buf ); + unsigned char *p = sig + ssize; size_t len = 0; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, sig, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, sig, r ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); - memcpy( sig, p, len ); + memmove( sig, p, len ); + memset( sig + len, 0, ssize - len ); *slen = len; return( 0 ); @@ -321,6 +321,7 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t { int ret; mbedtls_mpi r, s; + const size_t ssize = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->grp.pbits ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); @@ -338,7 +339,7 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t hash, hlen, f_rng, p_rng ) ); #endif - MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen, ssize ) ); cleanup: mbedtls_mpi_free( &r ); diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index b73095388..8a96c024b 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -142,7 +142,7 @@ void ecdsa_write_read_random( int id ) rnd_pseudo_info rnd_info; unsigned char hash[32]; unsigned char sig[200]; - size_t sig_len, i; + size_t sig_len, max_sig_len, i; mbedtls_ecdsa_init( &ctx ); memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); @@ -162,8 +162,10 @@ void ecdsa_write_read_random( int id ) TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ), sig, sig_len ) == 0 ); - /* check we didn't write past the announced length */ - for( i = sig_len; i < sizeof( sig ); i++ ) + /* check we didn't write past the maximum length */ + max_sig_len = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx.grp.pbits ); + TEST_ASSERT( sig_len <= max_sig_len ); + for( i = max_sig_len; i < sizeof( sig ); i++ ) TEST_ASSERT( sig[i] == 0x2a ); /* try verification with invalid length */