Expose ecdsa_signature_to_asn1

Expose ecdsa_signature_to_asn1 in the API. It's useful when converting
between RFC 4492 format and other representations that might be used
in external crypto processors.
diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h
index 3666ffe..c0088db 100644
--- a/include/mbedtls/ecdsa.h
+++ b/include/mbedtls/ecdsa.h
@@ -236,6 +236,28 @@
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
 /**
+ * \brief           Convert a signature from numbers to ASN.1
+ *
+ * \param r         First number of the signature
+ * \param s         Second number of the signature
+ * \param sig       Buffer that will hold the signature
+ * \param slen      Length of the signature written
+ * \param ssize     Size of the sig buffer
+ *
+ * \note            The size of the buffer \c ssize should be at least
+ *                  `MBEDTLS_ECDSA_MAX_SIG_LEN(grp->pbits)` bytes long if
+ *                  the signature was produced from curve \c grp,
+ *                  otherwise this function will return an error.
+ *
+ * \return          0 if successful,
+ *                  or a MBEDTLS_ERR_MPI_XXX or MBEDTLS_ERR_ASN1_XXX error code
+ *
+ */
+int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
+                             unsigned char *sig, size_t *slen,
+                             size_t ssize );
+
+/**
  * \brief           Read and verify an ECDSA signature
  *
  * \param ctx       ECDSA context
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 826fefe..fdd0afb 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -289,22 +289,22 @@
 /*
  * Convert a signature (given by context) to ASN.1
  */
-static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
-                                    unsigned char *sig, size_t *slen )
+int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
+                             unsigned char *sig, size_t *slen, size_t ssize )
 {
     int ret;
-    unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
-    unsigned char *p = buf + sizeof( buf );
+    unsigned char *p = sig + ssize;
     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_mpi( &p, sig, s ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, sig, 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_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig,
                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
 
-    memcpy( sig, p, len );
+    memmove( sig, p, len );
+    memset( sig + len, 0, ssize - len );
     *slen = len;
 
     return( 0 );
@@ -321,6 +321,7 @@
 {
     int ret;
     mbedtls_mpi r, s;
+    const size_t ssize = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->grp.pbits );
 
     mbedtls_mpi_init( &r );
     mbedtls_mpi_init( &s );
@@ -338,7 +339,7 @@
                          hash, hlen, f_rng, p_rng ) );
 #endif
 
-    MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
+    MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen, ssize ) );
 
 cleanup:
     mbedtls_mpi_free( &r );
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index b730953..8a96c02 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -142,7 +142,7 @@
     rnd_pseudo_info rnd_info;
     unsigned char hash[32];
     unsigned char sig[200];
-    size_t sig_len, i;
+    size_t sig_len, max_sig_len, i;
 
     mbedtls_ecdsa_init( &ctx );
     memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
@@ -162,8 +162,10 @@
     TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
                  sig, sig_len ) == 0 );
 
-    /* check we didn't write past the announced length */
-    for( i = sig_len; i < sizeof( sig ); i++ )
+    /* check we didn't write past the maximum length */
+    max_sig_len = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx.grp.pbits );
+    TEST_ASSERT( sig_len <= max_sig_len );
+    for( i = max_sig_len; i < sizeof( sig ); i++ )
         TEST_ASSERT( sig[i] == 0x2a );
 
     /* try verification with invalid length */