From b91a393a318b1385bf03b24c09b38f261c3b37bf Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Thu, 1 Mar 2018 09:09:55 -0500 Subject: [PATCH] ECDSA: Add mbedtls_raw_ecdsa_signature_to_asn1 without MPI usage Refactor mbedtls_ecdsa_signature_to_raw to allow overlapping buffers --- include/mbedtls/ecdsa.h | 23 ++++++++++++ library/ecdsa.c | 83 ++++++++++++++++++++++++++++++++++++----- library/pkcs11_client.c | 15 ++------ 3 files changed, 99 insertions(+), 22 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index 2b25aa6f3..8baa6b1b8 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -280,6 +280,29 @@ int mbedtls_ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, unsigned char *sig, size_t *slen, size_t ssize ); +/** + * \brief Convert a signature from a raw representation to ASN.1 + * + * \param r First number of the signature + * \param s Second number of the signature + * \param num_len Length of each number in bytes + * \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 mbedtls_raw_ecdsa_signature_to_asn1(const unsigned char *r, + const unsigned char *s, uint16_t num_len, + 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 7c8733e2f..6be57d5c0 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -298,7 +298,7 @@ int mbedtls_ecdsa_signature_to_raw( const unsigned char *sig, unsigned char *p = (unsigned char *) sig; unsigned char *buf_ptr; const unsigned char *end = sig + ssize; - size_t len, bytes_skipped, i; + size_t len, bytes_skipped; if( 2 * byte_len > bufsize ) { @@ -335,10 +335,7 @@ int mbedtls_ecdsa_signature_to_raw( const unsigned char *sig, } *buflen = len - bytes_skipped; - for( i = bytes_skipped; i < len; i++ ) - { - buf_ptr[i - bytes_skipped] = p[i]; - } + memmove(buf_ptr, &p[bytes_skipped], *buflen); p += len; buf_ptr += *buflen; @@ -358,11 +355,7 @@ int mbedtls_ecdsa_signature_to_raw( const unsigned char *sig, } *buflen += len - bytes_skipped; - - for( i = bytes_skipped; i < len; i++ ) - { - buf_ptr[i - bytes_skipped] = p[i]; - } + memmove(buf_ptr, &p[bytes_skipped], len - bytes_skipped); return( ret ); } @@ -388,6 +381,76 @@ int mbedtls_ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, memset( sig + len, 0, ssize - len ); *slen = len; + return( 0 ); + } + +int mbedtls_raw_ecdsa_signature_to_asn1( const unsigned char *r, + const unsigned char *s, uint16_t num_len, + unsigned char *sig, size_t *slen, size_t ssize ) +{ + int ret; + unsigned char *p = sig + ssize; + size_t total_len = 0; + size_t padding_len = 0; + + /* + * Step 1: write S + */ + memmove( p - num_len, s, num_len ); + p -= num_len; + total_len += num_len; + if( *p & 0x80 ) + { + if( p - sig < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--p = 0x00; + padding_len += 1; + } + total_len += padding_len; + + MBEDTLS_ASN1_CHK_ADD( total_len, mbedtls_asn1_write_len( &p, sig, + num_len + padding_len ) ); + MBEDTLS_ASN1_CHK_ADD( total_len, mbedtls_asn1_write_tag( &p, sig, + MBEDTLS_ASN1_INTEGER ) ); + + padding_len = 0; + + /* + * Step 2: write R + */ + memmove( p - num_len, r, num_len ); + p -= num_len; + total_len += num_len; + if( *p & 0x80 ) + { + if( p - sig < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--p = 0x00; + padding_len += 1; + } + total_len += padding_len; + + MBEDTLS_ASN1_CHK_ADD( total_len, mbedtls_asn1_write_len( &p, sig, + num_len + padding_len ) ); + MBEDTLS_ASN1_CHK_ADD( total_len, mbedtls_asn1_write_tag( &p, sig, + MBEDTLS_ASN1_INTEGER ) ); + + /* + * Step 3: write rest of the data + */ + MBEDTLS_ASN1_CHK_ADD( total_len, mbedtls_asn1_write_len( &p, sig, total_len ) ); + MBEDTLS_ASN1_CHK_ADD( total_len, mbedtls_asn1_write_tag( &p, sig, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Step 4: move to the beginning of the buffer, zeroize the rest + */ + memmove( sig, p, total_len ); + memset( sig + total_len, 0, ssize - total_len ); + *slen = total_len; + return( 0 ); } diff --git a/library/pkcs11_client.c b/library/pkcs11_client.c index b328d8c7f..439c50cff 100644 --- a/library/pkcs11_client.c +++ b/library/pkcs11_client.c @@ -191,9 +191,7 @@ static int pkcs11_sign( void *ctx_arg, */ uint16_t byte_len = ( ( ctx->bit_length + 7 ) / 8 ); size_t sig_size = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->bit_length ); - mbedtls_mpi r, s; - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &s ); + rv = CKR_OK; if( ck_sig_len != 2 * byte_len ) { @@ -201,22 +199,15 @@ static int pkcs11_sign( void *ctx_arg, rv = CKR_GENERAL_ERROR; goto ecdsa_exit; } - if( mbedtls_mpi_read_binary( &r, sig, byte_len ) != 0 || - mbedtls_mpi_read_binary( &s, sig + byte_len, byte_len ) != 0 ) - { - rv = CKR_HOST_MEMORY; - goto ecdsa_exit; - } + /* The signature buffer is guaranteed to have enough room for the encoded signature by the pk_sign interface. */ - if( mbedtls_ecdsa_signature_to_asn1( &r, &s, sig, sig_len, sig_size ) != 0 ) + if( mbedtls_raw_ecdsa_signature_to_asn1( sig, sig + byte_len, byte_len, sig, sig_len, sig_size ) != 0 ) { rv = CKR_GENERAL_ERROR; goto ecdsa_exit; } ecdsa_exit: - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &s ); if( rv != CKR_OK ) goto exit; }