From eae6eee24c1c09839efcbaf38669073fc6239fa9 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 Jun 2018 13:56:01 +0200 Subject: [PATCH] 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. --- include/psa/crypto.h | 39 ++++------- library/psa_crypto.c | 86 +++++++++++++++---------- tests/suites/test_suite_psa_crypto.data | 14 ++-- 3 files changed, 75 insertions(+), 64 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 2f972d37d..dcf1ba227 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -698,6 +698,12 @@ typedef uint32_t psa_algorithm_t; * This is the ECDSA signature scheme defined by ANSI X9.62, * with a random per-message secret number (*k*). * + * The representation of the signature as a byte string consists of + * the concatentation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(alg) is true). * @@ -709,7 +715,7 @@ typedef uint32_t psa_algorithm_t; (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** ECDSA signature without hashing. * - * This is the signature scheme defined by ANSI X9.62, + * This is the same signature scheme as #PSA_ALG_ECDSA(), but * without specifying a hash algorithm. This algorithm may only be * used to sign or verify a sequence of bytes that should be an * already-calculated hash. Note that the input is padded with @@ -722,6 +728,8 @@ typedef uint32_t psa_algorithm_t; * * This is the deterministic ECDSA signature scheme defined by RFC 6979. * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * * Note that when this algorithm is used for verification, signatures * made with randomized ECDSA (#PSA_ALG_ECDSA(\c hash_alg)) with the * same private key are accepted. In other words, @@ -1728,34 +1736,15 @@ psa_status_t psa_aead_decrypt( psa_key_slot_t key, */ /** - * \brief Maximum ECDSA signature size for a given curve bit size + * \brief ECDSA signature size for a given curve bit size * - * \param curve_bits Curve size in bits - * \return Maximum signature size in bytes + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. * * \note This macro returns a compile-time constant if its argument is one. - * - * \warning This macro may evaluate its argument multiple times. */ -/* - * RFC 4492 page 20: - * - * Ecdsa-Sig-Value ::= SEQUENCE { - * r INTEGER, - * s INTEGER - * } - * - * Size is at most - * 1 (tag) + 1 (len) + 1 (initial 0) + curve_bytes for each of r and s, - * twice that + 1 (tag) + 2 (len) for the sequence - * (assuming curve_bytes is less than 126 for r and s, - * and less than 124 (total len <= 255) for the sequence) - */ -#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ - ( /*T,L of SEQUENCE*/ ((curve_bits) >= 61 * 8 ? 3 : 2) + \ - /*T,L of r,s*/ 2 * (((curve_bits) >= 127 * 8 ? 3 : 2) + \ - /*V of r,s*/ ((curve_bits) + 8) / 8)) - +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) /** Safe signature buffer size for psa_asymmetric_sign(). * diff --git a/library/psa_crypto.c b/library/psa_crypto.c index ffc587a1e..9454f478c 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 @@ static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, } #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 @@ static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, { 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 @@ static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, 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 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, { #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) */ { diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 2f9035438..1181fcd92 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -532,7 +532,7 @@ sign_deterministic:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84 PSA sign: deterministic ECDSA SECP256R1 SHA-256 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC -sign_deterministic:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" +sign_deterministic:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" PSA sign: RSA PKCS#1 v1.5 SHA-256, wrong hash size sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015":128:PSA_ERROR_INVALID_ARGUMENT @@ -542,7 +542,7 @@ sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5 PSA sign: deterministic ECDSA SECP256R1 SHA-256, output buffer too small depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":10:PSA_ERROR_BUFFER_TOO_SMALL +sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":63:PSA_ERROR_BUFFER_TOO_SMALL PSA sign: deterministic ECDSA SECP256R1, invalid hash depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC @@ -562,11 +562,15 @@ asymmetric_verify_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396 PSA verify: ECDSA SECP256R1, good depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -asymmetric_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" +asymmetric_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" -PSA verify: ECDSA SECP256R1, wrong signature +PSA verify: ECDSA SECP256R1, wrong signature size (correct but ASN1-encoded) depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -asymmetric_verify_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_ERROR_INVALID_SIGNATURE +asymmetric_verify_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE + +PSA verify: ECDSA SECP256R1, wrong signature of correct size +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +asymmetric_verify_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_ERROR_INVALID_SIGNATURE PSA encrypt-decrypt: RSA PKCS#1 v1.5 vector #1 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15