diff --git a/ChangeLog b/ChangeLog index d33897c8a..3220df9a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,11 @@ Bugfix SSL_VERIFY_OPTIONAL and to reflect bad EC curves within verification result. +Changes + * Clarify ECDSA documentation and improve the sample code to avoid + misunderstandings and potentially dangerous use of the API. Pointed out + by Jean-Philippe Aumasson. + = mbed TLS 1.3.19 branch released 2017-03-08 Security diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h index 5eb83d9d2..47b644ef6 100644 --- a/include/polarssl/ecdsa.h +++ b/include/polarssl/ecdsa.h @@ -26,6 +26,23 @@ #include "ecp.h" #include "md.h" +/* + * RFC 4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * (assuming ECP_MAX_BYTES is less than 126 for r and s, + * and less than 124 (total len <= 255) for the sequence) + * + */ +/** Maximum size of an ECDSA signature in bytes */ +#define POLARSSL_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + POLARSSL_ECP_MAX_BYTES ) ) /** * \brief ECDSA context structure @@ -58,6 +75,10 @@ extern "C" { * \param f_rng RNG function * \param p_rng RNG parameter * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * prescribed by SEC1 4.1.3 step 5. + * * \return 0 if successful, * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code */ @@ -78,6 +99,10 @@ int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s, * \param blen Length of buf * \param md_alg MD algorithm used to hash the message * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * prescribed by SEC1 4.1.3 step 5. + * * \return 0 if successful, * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code */ @@ -96,6 +121,10 @@ int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s, * \param r First integer of the signature * \param s Second integer of the signature * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * prescribed by SEC1 4.1.4 step 3. + * * \return 0 if successful, * POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code @@ -121,6 +150,10 @@ int ecdsa_verify( ecp_group *grp, * size of the curve used, plus 7 (eg. 71 bytes if a 256-bit * curve is used). * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * prescribed by SEC1 4.1.3 step 5. + * * \return 0 if successful, * or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or * POLARSSL_ERR_ASN1 error code @@ -168,6 +201,10 @@ int ecdsa_write_signature_det( ecdsa_context *ctx, * \param sig Signature to read and verify * \param slen Size of sig * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * prescribed by SEC1 4.1.4 step 3. + * * \return 0 if successful, * POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid, * POLARSSL_ERR_ECP_SIG_LEN_MISTMATCH if the signature is diff --git a/programs/pkey/ecdsa.c b/programs/pkey/ecdsa.c index aa8eafb97..1411e42b0 100644 --- a/programs/pkey/ecdsa.c +++ b/programs/pkey/ecdsa.c @@ -38,6 +38,7 @@ #include "polarssl/entropy.h" #include "polarssl/ctr_drbg.h" #include "polarssl/ecdsa.h" +#include "polarssl/sha256.h" #include #endif @@ -102,16 +103,20 @@ int main( int argc, char *argv[] ) ecdsa_context ctx_sign, ctx_verify; entropy_context entropy; ctr_drbg_context ctr_drbg; - unsigned char hash[] = "This should be the hash of a message."; - unsigned char sig[512]; + sha256_context sha256_ctx; + unsigned char message[100]; + unsigned char hash[32]; + unsigned char sig[POLARSSL_ECDSA_MAX_LEN]; size_t sig_len; const char *pers = "ecdsa"; ((void) argv); ecdsa_init( &ctx_sign ); ecdsa_init( &ctx_verify ); + sha256_init( &sha256_ctx ); - memset(sig, 0, sizeof( sig ) ); + memset( sig, 0, sizeof( sig ) ); + memset( message, 0x25, sizeof( message ) ); ret = 1; if( argc != 1 ) @@ -155,9 +160,24 @@ int main( int argc, char *argv[] ) dump_pubkey( " + Public key: ", &ctx_sign ); /* - * Sign some message hash + * Compute message hash */ polarssl_printf( " . Signing message..." ); + polarssl_printf( " . Computing message hash..." ); + fflush( stdout ); + + sha256_starts( &sha256_ctx, 0 ); + sha256_update( &sha256_ctx, message, sizeof( message ) ); + sha256_finish( &sha256_ctx, hash ); + + polarssl_printf( " ok\n" ); + + dump_buf( " + Hash: ", hash, sizeof( hash ) ); + + /* + * Sign message hash + */ + polarssl_printf( " . Signing message hash..." ); fflush( stdout ); if( ( ret = ecdsa_write_signature( &ctx_sign, @@ -170,7 +190,6 @@ int main( int argc, char *argv[] ) } polarssl_printf( " ok (signature length = %u)\n", (unsigned int) sig_len ); - dump_buf( " + Hash: ", hash, sizeof hash ); dump_buf( " + Signature: ", sig, sig_len ); /* @@ -233,6 +252,7 @@ exit: ecdsa_free( &ctx_sign ); ctr_drbg_free( &ctr_drbg ); entropy_free( &entropy ); + sha256_free( &sha256_ctx ); return( ret ); }