Merge remote-tracking branch 'janos/mbedtls-1.3-iotssl-1156-ecdsa-sample-and-doc-clarification' into mbedtls-1.3
* janos/mbedtls-1.3-iotssl-1156-ecdsa-sample-and-doc-clarification:
Clarify the use of ECDSA API
diff --git a/ChangeLog b/ChangeLog
index d33897c..3220df9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,11 @@
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 5eb83d9..47b644e 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 @@
* \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 @@
* \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 @@
* \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 @@
* 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 @@
* \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 aa8eafb..1411e42 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 <string.h>
#endif
@@ -102,16 +103,20 @@
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 @@
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 @@
}
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 @@
ecdsa_free( &ctx_sign );
ctr_drbg_free( &ctr_drbg );
entropy_free( &entropy );
+ sha256_free( &sha256_ctx );
return( ret );
}