Add ecdsa_write_signature_det()
diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h
index a718c0e..0fab07e 100644
--- a/include/polarssl/ecdsa.h
+++ b/include/polarssl/ecdsa.h
@@ -137,6 +137,34 @@
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 0bd0e97..e2b6a77 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -372,25 +372,16 @@
#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 ) );
@@ -405,6 +396,45 @@
}
/*
+ * 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
*/
int ecdsa_read_signature( ecdsa_context *ctx,
diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data
index 6441b81..501bdeb 100644
--- a/tests/suites/test_suite_ecdsa.data
+++ b/tests/suites/test_suite_ecdsa.data
@@ -249,3 +249,27 @@
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 edf1f73..398b288 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -186,3 +186,35 @@
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 */