ECDSA: Add mbedtls_raw_ecdsa_signature_to_asn1 without MPI usage

Refactor mbedtls_ecdsa_signature_to_raw to allow overlapping buffers
This commit is contained in:
Andrzej Kurek 2018-03-01 09:09:55 -05:00
parent dfedd825c8
commit b91a393a31
3 changed files with 99 additions and 22 deletions

View File

@ -280,6 +280,29 @@ int mbedtls_ecdsa_signature_to_asn1( const mbedtls_mpi *r,
const mbedtls_mpi *s, unsigned char *sig, const mbedtls_mpi *s, unsigned char *sig,
size_t *slen, size_t ssize ); 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 * \brief Read and verify an ECDSA signature
* *

View File

@ -298,7 +298,7 @@ int mbedtls_ecdsa_signature_to_raw( const unsigned char *sig,
unsigned char *p = (unsigned char *) sig; unsigned char *p = (unsigned char *) sig;
unsigned char *buf_ptr; unsigned char *buf_ptr;
const unsigned char *end = sig + ssize; const unsigned char *end = sig + ssize;
size_t len, bytes_skipped, i; size_t len, bytes_skipped;
if( 2 * byte_len > bufsize ) if( 2 * byte_len > bufsize )
{ {
@ -335,10 +335,7 @@ int mbedtls_ecdsa_signature_to_raw( const unsigned char *sig,
} }
*buflen = len - bytes_skipped; *buflen = len - bytes_skipped;
for( i = bytes_skipped; i < len; i++ ) memmove(buf_ptr, &p[bytes_skipped], *buflen);
{
buf_ptr[i - bytes_skipped] = p[i];
}
p += len; p += len;
buf_ptr += *buflen; buf_ptr += *buflen;
@ -358,11 +355,7 @@ int mbedtls_ecdsa_signature_to_raw( const unsigned char *sig,
} }
*buflen += len - bytes_skipped; *buflen += len - bytes_skipped;
memmove(buf_ptr, &p[bytes_skipped], len - bytes_skipped);
for( i = bytes_skipped; i < len; i++ )
{
buf_ptr[i - bytes_skipped] = p[i];
}
return( ret ); 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 ); memset( sig + len, 0, ssize - len );
*slen = 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 ); return( 0 );
} }

View File

@ -191,9 +191,7 @@ static int pkcs11_sign( void *ctx_arg,
*/ */
uint16_t byte_len = ( ( ctx->bit_length + 7 ) / 8 ); uint16_t byte_len = ( ( ctx->bit_length + 7 ) / 8 );
size_t sig_size = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->bit_length ); 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; rv = CKR_OK;
if( ck_sig_len != 2 * byte_len ) if( ck_sig_len != 2 * byte_len )
{ {
@ -201,22 +199,15 @@ static int pkcs11_sign( void *ctx_arg,
rv = CKR_GENERAL_ERROR; rv = CKR_GENERAL_ERROR;
goto ecdsa_exit; 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 signature buffer is guaranteed to have enough room for
the encoded signature by the pk_sign interface. */ 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; rv = CKR_GENERAL_ERROR;
goto ecdsa_exit; goto ecdsa_exit;
} }
ecdsa_exit: ecdsa_exit:
mbedtls_mpi_free( &r );
mbedtls_mpi_free( &s );
if( rv != CKR_OK ) if( rv != CKR_OK )
goto exit; goto exit;
} }