pk_wrap: reuse a static buffer for signature extraction

Use a buffer left over after importing a key to hold an extracted signature.
This commit is contained in:
Andrzej Kurek 2018-11-19 17:41:58 -05:00
parent 3016de3eeb
commit 688ea8d10d

View file

@ -519,8 +519,8 @@ static int extract_ecdsa_sig_part( unsigned char **from, const unsigned char *en
/* /*
* Convert a signature from an ASN.1 sequence of two integers * Convert a signature from an ASN.1 sequence of two integers
* to a raw {r,s} buffer. Note: upon a successful call, the caller * to a raw {r,s} buffer. Note: the provided sig buffer should be at least
* takes ownership of the sig->p buffer. * twice as big as int_size.
*/ */
static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end, static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
mbedtls_asn1_buf *sig, size_t int_size ) mbedtls_asn1_buf *sig, size_t int_size )
@ -532,9 +532,8 @@ static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
} }
sig->p = mbedtls_calloc( 2, int_size );
if( sig->p == NULL ) if( sig->p == NULL )
return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
sig->tag = **p; sig->tag = **p;
@ -561,8 +560,6 @@ static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
return( 0 ); return( 0 );
cleanup: cleanup:
mbedtls_free( sig->p );
sig->p = NULL;
sig->len = 0; sig->len = 0;
sig->tag = 0; sig->tag = 0;
return( ret ); return( ret );
@ -640,12 +637,13 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
mbedtls_pk_context key; mbedtls_pk_context key;
mbedtls_asn1_buf signature; mbedtls_asn1_buf signature;
int key_len; int key_len;
const int buf_len = 30 + 2 * MBEDTLS_ECP_MAX_BYTES; // Equivalent of ECP_PUB_DER_MAX_BYTES const unsigned buf_len = 30 + 2 * MBEDTLS_ECP_MAX_BYTES; // Equivalent of ECP_PUB_DER_MAX_BYTES
unsigned char buf[buf_len]; unsigned char buf[buf_len];
unsigned char *p = (unsigned char*) sig; unsigned char *p = (unsigned char*) sig;
mbedtls_pk_info_t pk_info = mbedtls_eckey_info; mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
psa_algorithm_t psa_sig_md = mbedtls_psa_translate_md( md_alg ); psa_algorithm_t psa_sig_md = mbedtls_psa_translate_md( md_alg );
psa_ecc_curve_t curve = mbedtls_ecc_group_to_psa ( ( (mbedtls_ecdsa_context *) ctx )->grp.id ); psa_ecc_curve_t curve = mbedtls_ecc_group_to_psa ( ( (mbedtls_ecdsa_context *) ctx )->grp.id );
size_t signature_part_size = ( ( (mbedtls_ecdsa_context *) ctx ) ->grp.nbits + 7 ) / 8;
if( curve == 0 ) if( curve == 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
@ -660,22 +658,12 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
psa_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ); psa_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve );
if( ( ret = extract_ecdsa_sig( &p, p + sig_len, &signature,
( ( (mbedtls_ecdsa_context *) ctx )->grp.nbits + 7) / 8 ) ) != 0 )
return( ret );
key_len = mbedtls_pk_write_pubkey_der( &key, buf, buf_len ); key_len = mbedtls_pk_write_pubkey_der( &key, buf, buf_len );
if( key_len <= 0 ) if( key_len <= 0 )
{
mbedtls_free( signature.p );
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
}
if( ( ret = mbedtls_psa_get_free_key_slot( &key_slot ) ) != PSA_SUCCESS ) if( ( ret = mbedtls_psa_get_free_key_slot( &key_slot ) ) != PSA_SUCCESS )
{
mbedtls_free( signature.p );
return( mbedtls_psa_err_translate_pk( ret ) ); return( mbedtls_psa_err_translate_pk( ret ) );
}
psa_key_policy_init( &policy ); psa_key_policy_init( &policy );
psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, psa_sig_md ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, psa_sig_md );
@ -692,6 +680,20 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
goto cleanup; goto cleanup;
} }
/* Reuse the buffer of an already imported key */
if( 2 * signature_part_size > buf_len )
{
ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
goto cleanup;
}
signature.p = buf;
if( ( ret = extract_ecdsa_sig( &p, p + sig_len, &signature,
signature_part_size ) ) != 0 )
{
goto cleanup;
}
if( psa_asymmetric_verify( key_slot, psa_sig_md, if( psa_asymmetric_verify( key_slot, psa_sig_md,
hash, hash_len, hash, hash_len,
signature.p, signature.len ) signature.p, signature.len )
@ -704,7 +706,6 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
cleanup: cleanup:
psa_destroy_key( key_slot ); psa_destroy_key( key_slot );
mbedtls_free( signature.p );
return( ret ); return( ret );
} }
#else /* MBEDTLS_USE_PSA_CRYPTO */ #else /* MBEDTLS_USE_PSA_CRYPTO */