Change ECDSA signature representation to r||s
Change the representation of an ECDSA signature from the ASN.1 DER
encoding used in TLS and X.509, to the concatenation of r and s
in big-endian order with a fixed size. A fixed size helps memory and
buffer management and this representation is generally easier to use
for anything that doesn't require the ASN.1 representation. This is
the same representation as PKCS#11 (Cryptoki) except that PKCS#11
allows r and s to be truncated (both to the same length), which
complicates the implementation and negates the advantage of a
fixed-size representation.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index ffc587a..9454f47 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -40,7 +40,6 @@
#include "mbedtls/arc4.h"
#include "mbedtls/asn1.h"
-#include "mbedtls/asn1write.h"
#include "mbedtls/bignum.h"
#include "mbedtls/blowfish.h"
#include "mbedtls/camellia.h"
@@ -1640,28 +1639,6 @@
}
#if defined(MBEDTLS_ECDSA_C)
-/* Temporary copy from ecdsa.c */
-static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
- unsigned char *sig, size_t *slen )
-{
- int ret;
- unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
- unsigned char *p = buf + sizeof( buf );
- 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_len( &p, buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
-
- memcpy( sig, p, len );
- *slen = len;
-
- return( 0 );
-}
-
/* `ecp` cannot be const because `ecp->grp` needs to be non-const
* for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det()
* (even though these functions don't modify it). */
@@ -1675,11 +1652,16 @@
{
int ret;
mbedtls_mpi r, s;
+ size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
mbedtls_mpi_init( &r );
mbedtls_mpi_init( &s );
- if( signature_size < PSA_ECDSA_SIGNATURE_SIZE( ecp->grp.pbits ) )
- return( PSA_ERROR_BUFFER_TOO_SMALL );
+ *signature_length = 0;
+ if( signature_size < 2 * curve_bytes )
+ {
+ ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+ goto cleanup;
+ }
if( PSA_ALG_DSA_IS_DETERMINISTIC( alg ) )
{
@@ -1697,8 +1679,48 @@
mbedtls_ctr_drbg_random,
&global_data.ctr_drbg ) );
}
- MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s,
- signature, signature_length ) );
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r,
+ signature,
+ curve_bytes ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s,
+ signature + curve_bytes,
+ curve_bytes ) );
+
+cleanup:
+ mbedtls_mpi_free( &r );
+ mbedtls_mpi_free( &s );
+ if( ret == 0 )
+ *signature_length = 2 * curve_bytes;
+ memset( signature + *signature_length, 0,
+ signature_size - *signature_length );
+ return( mbedtls_to_psa_error( ret ) );
+}
+
+static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_length )
+{
+ int ret;
+ mbedtls_mpi r, s;
+ size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
+ mbedtls_mpi_init( &r );
+ mbedtls_mpi_init( &s );
+
+ if( signature_length != 2 * curve_bytes )
+ return( PSA_ERROR_INVALID_SIGNATURE );
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
+ signature,
+ curve_bytes ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
+ signature + curve_bytes,
+ curve_bytes ) );
+
+ ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length,
+ &ecp->Q, &r, &s );
cleanup:
mbedtls_mpi_free( &r );
@@ -1883,13 +1905,9 @@
{
#if defined(MBEDTLS_ECDSA_C)
if( PSA_ALG_IS_ECDSA( alg ) )
- {
- int ret;
- ret = mbedtls_ecdsa_read_signature( slot->data.ecp,
- hash, hash_length,
- signature, signature_length );
- return( mbedtls_to_psa_error( ret ) );
- }
+ return( psa_ecdsa_verify( slot->data.ecp,
+ hash, hash_length,
+ signature, signature_length ) );
else
#endif /* defined(MBEDTLS_ECDSA_C) */
{