diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h index a718c0ef57..0fab07ecca 100644 --- a/include/polarssl/ecdsa.h +++ b/include/polarssl/ecdsa.h @@ -137,6 +137,34 @@ int ecdsa_write_signature( ecdsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/** + * \brief Compute ECDSA signature and write it to buffer, + * serialized as defined in RFC 4492 page 20. + * Deterministic version, RFC 6979. + * (Not thread-safe to use same context in multiple threads) + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Length of hash + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param md_alg MD algorithm used to hash the message + * + * \note The "sig" buffer must be at least as large as twice the + * size of the curve used, plus 7 (eg. 71 bytes if a 256-bit + * curve is used). + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or + * POLARSSL_ERR_ASN1 error code + */ +int ecdsa_write_signature_det( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + md_type_t md_alg ); +#endif + /** * \brief Read and verify an ECDSA signature * diff --git a/library/ecdsa.c b/library/ecdsa.c index 0bd0e97f7b..e2b6a770ac 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -372,25 +372,16 @@ cleanup: #define MAX_SIG_LEN ( 3 + 2 * ( 2 + POLARSSL_ECP_MAX_BYTES ) ) /* - * Compute and write signature + * Convert a signature (given by context) to ASN.1 */ -int ecdsa_write_signature( ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +static int ecdsa_signature_to_asn1( ecdsa_context *ctx, + unsigned char *sig, size_t *slen ) { int ret; unsigned char buf[MAX_SIG_LEN]; unsigned char *p = buf + sizeof( buf ); size_t len = 0; - if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d, - hash, hlen, f_rng, p_rng ) ) != 0 ) - { - return( ret ); - } - ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->s ) ); ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->r ) ); @@ -404,6 +395,45 @@ int ecdsa_write_signature( ecdsa_context *ctx, return( 0 ); } +/* + * Compute and write signature + */ +int ecdsa_write_signature( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d, + hash, hlen, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + return( ecdsa_signature_to_asn1( ctx, sig, slen ) ); +} + +/* + * Compute and write signature deterministically + */ +int ecdsa_write_signature_det( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + md_type_t md_alg ) +{ + int ret; + + if( ( ret = ecdsa_sign_det( &ctx->grp, &ctx->r, &ctx->s, &ctx->d, + hash, hlen, md_alg ) ) != 0 ) + { + return( ret ); + } + + return( ecdsa_signature_to_asn1( ctx, sig, slen ) ); +} + /* * Read and check signature */ diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index 6441b81003..501bdebd6d 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -249,3 +249,27 @@ ecdsa_det_test_vectors:POLARSSL_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA75 ECDSA deterministic test vector rfc 6979 p521 sha512 depends_on:POLARSSL_ECP_DP_SECP521R1_ENABLED:POLARSSL_SHA512_C ecdsa_det_test_vectors:POLARSSL_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":POLARSSL_MD_SHA512:"test":"13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D":"1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3" + +ECDSA deterministic read-write random p256 sha256 +depends_on:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_SHA256_C +ecdsa_write_read_det_random:POLARSSL_ECP_DP_SECP256R1:POLARSSL_MD_SHA256 + +ECDSA deterministic read-write random p256 sha384 +depends_on:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_SHA512_C +ecdsa_write_read_det_random:POLARSSL_ECP_DP_SECP256R1:POLARSSL_MD_SHA384 + +ECDSA deterministic read-write random p384 sha256 +depends_on:POLARSSL_ECP_DP_SECP384R1_ENABLED:POLARSSL_SHA256_C +ecdsa_write_read_det_random:POLARSSL_ECP_DP_SECP384R1:POLARSSL_MD_SHA256 + +ECDSA deterministic read-write random p384 sha384 +depends_on:POLARSSL_ECP_DP_SECP384R1_ENABLED:POLARSSL_SHA512_C +ecdsa_write_read_det_random:POLARSSL_ECP_DP_SECP384R1:POLARSSL_MD_SHA384 + +ECDSA deterministic read-write random p521 sha256 +depends_on:POLARSSL_ECP_DP_SECP521R1_ENABLED:POLARSSL_SHA256_C +ecdsa_write_read_det_random:POLARSSL_ECP_DP_SECP521R1:POLARSSL_MD_SHA256 + +ECDSA deterministic read-write random p521 sha384 +depends_on:POLARSSL_ECP_DP_SECP521R1_ENABLED:POLARSSL_SHA512_C +ecdsa_write_read_det_random:POLARSSL_ECP_DP_SECP521R1:POLARSSL_MD_SHA384 diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index edf1f735e8..398b2889ff 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -186,3 +186,35 @@ void ecdsa_write_read_random( int id ) ecdsa_free( &ctx ); } /* END_CASE */ + +/* BEGIN_CASE */ +void ecdsa_write_read_det_random( int id, int md_alg ) +{ + ecdsa_context ctx; + rnd_pseudo_info rnd_info; + unsigned char msg[100]; + unsigned char hash[POLARSSL_MD_MAX_SIZE]; + unsigned char sig[200]; + size_t sig_len; + + ecdsa_init( &ctx ); + memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); + memset( hash, 0, sizeof( hash ) ); + memset( sig, 0x2a, sizeof( sig ) ); + + /* prepare material for signature */ + TEST_ASSERT( rnd_pseudo_rand( &rnd_info, msg, sizeof( msg ) ) == 0 ); + md( md_info_from_type( md_alg ), msg, sizeof( msg ), hash ); + + /* generate signing key */ + TEST_ASSERT( ecdsa_genkey( &ctx, id, &rnd_pseudo_rand, &rnd_info ) == 0 ); + + /* generate and write signature, then read and verify it */ + TEST_ASSERT( ecdsa_write_signature_det( &ctx, hash, sizeof( hash ), + sig, &sig_len, md_alg ) == 0 ); + TEST_ASSERT( ecdsa_read_signature( &ctx, hash, sizeof( hash ), + sig, sig_len ) == 0 ); + + ecdsa_free( &ctx ); +} +/* END_CASE */