Merge remote-tracking branch 'origin/mbedtls-2.7' into mbedtls-2.7-restricted

* origin/mbedtls-2.7:
  ssl-opt.sh: wait for proxy to start before running the script further
diff --git a/ChangeLog b/ChangeLog
index 55f416e..f09995f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,28 @@
 
 = mbed TLS x.x.x branch released xxxx-xx-xx
 
+Security
+   * Fix a missing error detection in ECJPAKE. This could have caused a
+     predictable shared secret if a hardware accelerator failed and the other
+     side of the key exchange had a similar bug.
+   * The deterministic ECDSA calculation reused the scheme's HMAC-DRBG to
+     implement blinding. Because of this for the same key and message the same
+     blinding value was generated. This reduced the effectiveness of the
+     countermeasure and leaked information about the private key through side
+     channels. Reported by Jack Lloyd.
+   * When writing a private EC key, use a constant size for the private
+     value, as specified in RFC 5915. Previously, the value was written
+     as an ASN.1 INTEGER, which caused the size of the key to leak
+     about 1 bit of information on average and could cause the value to be
+     1 byte too large for the output buffer.
+
+API Changes
+   * The new function mbedtls_ecdsa_sign_det_ext() is similar to
+     mbedtls_ecdsa_sign_det() but allows passing an external RNG for the
+     purpose of blinding.
+   * The new function mbedtls_ecp_gen_privkey() allows to generate a private
+     key without generating the public part of the pair.
+
 Bugfix
    * Fix to allow building test suites with any warning that detects unused
      functions. Fixes #1628.
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 48e96e5..8ea1c15 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -107,7 +107,7 @@
 #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || (   \
+#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || (    \
     !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) &&                  \
     !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) &&                  \
     !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) &&                  \
@@ -118,7 +118,8 @@
     !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)   &&                  \
     !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) &&                  \
     !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) &&                  \
-    !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) )
+    !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) &&                  \
+    !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) ) )
 #error "MBEDTLS_ECP_C defined, but not all prerequisites"
 #endif
 
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 75d5eb1..fa88ebf 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -333,6 +333,16 @@
  *            dependencies on them, and considering stronger message digests
  *            and ciphers instead.
  *
+ * \warning   If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are
+ *            enabled, then the deterministic ECDH signature functions pass the
+ *            the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore
+ *            alternative implementations should use the RNG only for generating
+ *            the ephemeral key and nothing else. If this is not possible, then
+ *            MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative
+ *            implementation should be provided for mbedtls_ecdsa_sign_det_ext()
+ *            (and for mbedtls_ecdsa_sign_det() too if backward compatibility is
+ *            desirable).
+ *
  */
 //#define MBEDTLS_MD2_PROCESS_ALT
 //#define MBEDTLS_MD4_PROCESS_ALT
diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h
index cfd1370..08811a3 100644
--- a/include/mbedtls/ecdsa.h
+++ b/include/mbedtls/ecdsa.h
@@ -107,6 +107,20 @@
  *                  Usage of the Digital Signature Algorithm (DSA) and Elliptic
  *                  Curve Digital Signature Algorithm (ECDSA)</em>.
  *
+ *
+ * \warning         Since the output of the internal RNG is always the same for
+ *                  the same key and message, this limits the efficiency of
+ *                  blinding and leaks information through side channels. For
+ *                  secure behavior use mbedtls_ecdsa_sign_det_ext() instead.
+ *
+ *                  (Optimally the blinding is a random value that is different
+ *                  on every execution. In this case the blinding is still
+ *                  random from the attackers perspective, but is the same on
+ *                  each execution. This means that this blinding does not
+ *                  prevent attackers from recovering secrets by combining
+ *                  several measurement traces, but may prevent some attacks
+ *                  that exploit relationships between secret data.)
+ *
  * \param grp       The ECP group.
  * \param r         The first output integer.
  * \param s         The second output integer.
@@ -127,9 +141,56 @@
  *
  * \see             ecp.h
  */
-int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
-                    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                    mbedtls_md_type_t md_alg );
+int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                            mbedtls_mpi *s, const mbedtls_mpi *d,
+                            const unsigned char *buf, size_t blen,
+                            mbedtls_md_type_t md_alg );
+/**
+ * \brief           This function computes the ECDSA signature of a
+ *                  previously-hashed message, deterministic version.
+ *
+ *                  For more information, see <em>RFC-6979: Deterministic
+ *                  Usage of the Digital Signature Algorithm (DSA) and Elliptic
+ *                  Curve Digital Signature Algorithm (ECDSA)</em>.
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated as
+ *                  defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.3, step 5.
+ *
+ * \see             ecp.h
+ *
+ * \param grp           The context for the elliptic curve to use.
+ *                      This must be initialized and have group parameters
+ *                      set, for example through mbedtls_ecp_group_load().
+ * \param r             The MPI context in which to store the first part
+ *                      the signature. This must be initialized.
+ * \param s             The MPI context in which to store the second part
+ *                      the signature. This must be initialized.
+ * \param d             The private signing key. This must be initialized
+ *                      and setup, for example through mbedtls_ecp_gen_privkey().
+ * \param buf           The hashed content to be signed. This must be a readable
+ *                      buffer of length \p blen Bytes. It may be \c NULL if
+ *                      \p blen is zero.
+ * \param blen          The length of \p buf in Bytes.
+ * \param md_alg        The hash algorithm used to hash the original data.
+ * \param f_rng_blind   The RNG function used for blinding. This must not be
+ *                      \c NULL.
+ * \param p_rng_blind   The RNG context to be passed to \p f_rng. This may be
+ *                      \c NULL if \p f_rng doesn't need a context parameter.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
+ *                  error code on failure.
+ */
+int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                                mbedtls_mpi *s, const mbedtls_mpi *d,
+                                const unsigned char *buf, size_t blen,
+                                mbedtls_md_type_t md_alg,
+                                int (*f_rng_blind)(void *, unsigned char *,
+                                                   size_t),
+                                void *p_rng_blind );
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
 /**
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index 6c43c00..691415e 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -602,6 +602,22 @@
 int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d );
 
 /**
+ * \brief           Generate a private key
+ *
+ * \param grp       ECP group
+ * \param d         Destination MPI (secret part)
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful,
+ *                  or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
+ */
+int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
+                     mbedtls_mpi *d,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
  * \brief           Generate a keypair with configurable base point
  *
  * \param grp       ECP group
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index ee06b2f..8beb2af 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -343,6 +343,10 @@
  *
  * \note            For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0.
  *                  For ECDSA, md_alg may never be MBEDTLS_MD_NONE.
+ *
+ * \note            In order to ensure enough space for the signature, the
+ *                  \p sig buffer size must be of at least
+ *                  `max(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)` bytes.
  */
 int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
              const unsigned char *hash, size_t hash_len,
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index 23e0ebb..a1298da 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -819,6 +819,7 @@
  *
  * \note           The \p sig buffer must be as large as the size
  *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *                 A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe.
  *
  * \note           For PKCS#1 v2.1 encoding, see comments on
  *                 mbedtls_rsa_rsassa_pss_sign() for details on
@@ -862,6 +863,7 @@
  *
  * \note           The \p sig buffer must be as large as the size
  *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *                 A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe.
  */
 int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
                                int (*f_rng)(void *, unsigned char *, size_t),
@@ -902,6 +904,7 @@
  *
  * \note           The \p sig buffer must be as large as the size
  *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *                 A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe.
  *
  * \note           The \p hash_id in the RSA context is the one used for the
  *                 encoding. \p md_alg in the function call is the type of hash
diff --git a/library/ecdsa.c b/library/ecdsa.c
index ab75620..c635a50 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -70,9 +70,14 @@
  * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
  * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
  */
-int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
-                const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int ecdsa_sign_internal( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                                mbedtls_mpi *s, const mbedtls_mpi *d,
+                                const unsigned char *buf, size_t blen,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng,
+                                int (*f_rng_blind)(void *, unsigned char *,
+                                                   size_t),
+                                void *p_rng_blind )
 {
     int ret, key_tries, sign_tries, blind_tries;
     mbedtls_ecp_point R;
@@ -99,7 +104,10 @@
         key_tries = 0;
         do
         {
-            MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
+            MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &k, f_rng, p_rng ) );
+
+            MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &R, &k, &grp->G,
+                                              f_rng_blind, p_rng_blind ) );
             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
 
             if( key_tries++ > 10 )
@@ -118,15 +126,20 @@
         /*
          * Generate a random value to blind inv_mod in next step,
          * avoiding a potential timing leak.
+         *
+         * This loop does the same job as mbedtls_ecp_gen_privkey() and it is
+         * replaced by a call to it in the mainline. This change is not
+         * necessary to backport the fix separating the blinding and ephemeral
+         * key generating RNGs, therefore the original code is kept.
          */
         blind_tries = 0;
         do
         {
             size_t n_size = ( grp->nbits + 7 ) / 8;
-            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng_blind,
+                                                      p_rng_blind ) );
             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
 
-            /* See mbedtls_ecp_gen_keypair() */
             if( ++blind_tries > 30 )
                 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
         }
@@ -158,15 +171,27 @@
 
     return( ret );
 }
+
+int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+                        const mbedtls_mpi *d, const unsigned char *buf,
+                        size_t blen,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng )
+{
+    /* Use the same RNG for both blinding and ephemeral key generation */
+    return( ecdsa_sign_internal( grp, r, s, d, buf, blen, f_rng, p_rng,
+                                 f_rng, p_rng ) );
+}
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-/*
- * Deterministic signature wrapper
- */
-int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
-                    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                    mbedtls_md_type_t md_alg )
+static int ecdsa_sign_det_internal( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                                    mbedtls_mpi *s, const mbedtls_mpi *d,
+                                    const unsigned char *buf, size_t blen,
+                                    mbedtls_md_type_t md_alg,
+                                    int (*f_rng_blind)(void *, unsigned char *,
+                                                       size_t),
+                                    void *p_rng_blind )
 {
     int ret;
     mbedtls_hmac_drbg_context rng_ctx;
@@ -174,12 +199,16 @@
     size_t grp_len = ( grp->nbits + 7 ) / 8;
     const mbedtls_md_info_t *md_info;
     mbedtls_mpi h;
+    /* Variables for deterministic blinding fallback */
+    const char* blind_label = "BLINDING CONTEXT";
+    mbedtls_hmac_drbg_context rng_ctx_blind;
 
     if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
     mbedtls_mpi_init( &h );
     mbedtls_hmac_drbg_init( &rng_ctx );
+    mbedtls_hmac_drbg_init( &rng_ctx_blind );
 
     /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
@@ -187,15 +216,71 @@
     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
     mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
 
-    ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
-                      mbedtls_hmac_drbg_random, &rng_ctx );
+    if( f_rng_blind != NULL )
+        ret = ecdsa_sign_internal( grp, r, s, d, buf, blen,
+                                   mbedtls_hmac_drbg_random, &rng_ctx,
+                                   f_rng_blind, p_rng_blind );
+    else
+    {
+        /*
+         * To avoid reusing rng_ctx and risking incorrect behavior we seed a
+         * second HMAC-DRBG with the same seed. We also apply a label to avoid
+         * reusing the bits of the ephemeral key for blinding and eliminate the
+         * risk that they leak this way.
+         */
+
+        mbedtls_hmac_drbg_seed_buf( &rng_ctx_blind, md_info,
+                                    data, 2 * grp_len );
+        ret = mbedtls_hmac_drbg_update_ret( &rng_ctx_blind,
+                                            (const unsigned char*) blind_label,
+                                            strlen( blind_label ) );
+        if( ret != 0 )
+            goto cleanup;
+
+        /*
+         * Since the output of the RNGs is always the same for the same key and
+         * message, this limits the efficiency of blinding and leaks information
+         * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL
+         * won't be a valid value for f_rng_blind anymore. Therefore it should
+         * be checked by the caller and this branch and check can be removed.
+         */
+        ret = ecdsa_sign_internal( grp, r, s, d, buf, blen,
+                                   mbedtls_hmac_drbg_random, &rng_ctx,
+                                   mbedtls_hmac_drbg_random, &rng_ctx_blind );
+
+    }
 
 cleanup:
     mbedtls_hmac_drbg_free( &rng_ctx );
+    mbedtls_hmac_drbg_free( &rng_ctx_blind );
     mbedtls_mpi_free( &h );
 
     return( ret );
 }
+
+/*
+ * Deterministic signature wrappers
+ */
+int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                            mbedtls_mpi *s, const mbedtls_mpi *d,
+                            const unsigned char *buf, size_t blen,
+                            mbedtls_md_type_t md_alg )
+{
+    return( ecdsa_sign_det_internal( grp, r, s, d, buf, blen, md_alg,
+                                     NULL, NULL ) );
+}
+
+int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                                mbedtls_mpi *s, const mbedtls_mpi *d,
+                                const unsigned char *buf, size_t blen,
+                                mbedtls_md_type_t md_alg,
+                                int (*f_rng_blind)(void *, unsigned char *,
+                                                   size_t),
+                                void *p_rng_blind )
+{
+    return( ecdsa_sign_det_internal( grp, r, s, d, buf, blen, md_alg,
+                                     f_rng_blind, p_rng_blind ) );
+}
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
 #if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
@@ -326,17 +411,15 @@
     mbedtls_mpi_init( &s );
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-    (void) f_rng;
-    (void) p_rng;
-
-    MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
-                             hash, hlen, md_alg ) );
+    MBEDTLS_MPI_CHK( ecdsa_sign_det_internal( &ctx->grp, &r, &s, &ctx->d,
+                                              hash, hlen, md_alg,
+                                              f_rng, p_rng ) );
 #else
     (void) md_alg;
 
     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
                          hash, hlen, f_rng, p_rng ) );
-#endif
+#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
     MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
 
diff --git a/library/ecjpake.c b/library/ecjpake.c
index 0cd79d0..65ba0d0 100644
--- a/library/ecjpake.c
+++ b/library/ecjpake.c
@@ -213,7 +213,7 @@
     p += id_len;
 
     /* Compute hash */
-    mbedtls_md( md_info, buf, p - buf, hash );
+    MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
 
     /* Turn it into an integer mod n */
     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
diff --git a/library/ecp.c b/library/ecp.c
index 75233f8..cb8e947 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -1918,15 +1918,14 @@
 }
 
 /*
- * Generate a keypair with configurable base point
+ * Generate a private key
  */
-int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
-                     const mbedtls_ecp_point *G,
-                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
+int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
+                     mbedtls_mpi *d,
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     size_t n_size = ( grp->nbits + 7 ) / 8;
 
 #if defined(ECP_MONTGOMERY)
@@ -1951,8 +1950,8 @@
         MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
     }
-    else
 #endif /* ECP_MONTGOMERY */
+
 #if defined(ECP_SHORTWEIERSTRASS)
     if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
     {
@@ -1986,15 +1985,28 @@
         while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
                mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
     }
-    else
 #endif /* ECP_SHORTWEIERSTRASS */
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
 cleanup:
-    if( ret != 0 )
-        return( ret );
+    return( ret );
+}
 
-    return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+/*
+ * Generate a keypair with configurable base point
+ */
+int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
+                     const mbedtls_ecp_point *G,
+                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret;
+
+    MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+
+cleanup:
+    return( ret );
 }
 
 /*
diff --git a/library/pkwrite.c b/library/pkwrite.c
index 8eabd88..fa93470 100644
--- a/library/pkwrite.c
+++ b/library/pkwrite.c
@@ -37,6 +37,7 @@
 #include "mbedtls/rsa.h"
 #endif
 #if defined(MBEDTLS_ECP_C)
+#include "mbedtls/bignum.h"
 #include "mbedtls/ecp.h"
 #endif
 #if defined(MBEDTLS_ECDSA_C)
@@ -54,6 +55,13 @@
 #define mbedtls_free       free
 #endif
 
+#if defined(MBEDTLS_ECP_C)
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
+}
+#endif /* MBEDTLS_ECP_C */
+
 #if defined(MBEDTLS_RSA_C)
 /*
  *  RSAPublicKey ::= SEQUENCE {
@@ -143,6 +151,26 @@
 
     return( (int) len );
 }
+
+/*
+ * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
+ */
+static int pk_write_ec_private( unsigned char **p, unsigned char *start,
+                                mbedtls_ecp_keypair *ec )
+{
+    int ret;
+    size_t byte_length = ( ec->grp.pbits + 7 ) / 8;
+    unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
+
+    ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length );
+    if( ret != 0 )
+        goto exit;
+    ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length );
+
+exit:
+    mbedtls_zeroize( tmp, byte_length );
+    return( ret );
+}
 #endif /* MBEDTLS_ECP_C */
 
 int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
@@ -340,9 +368,8 @@
                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
         len += par_len;
 
-        /* privateKey: write as MPI then fix tag */
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) );
-        *c = MBEDTLS_ASN1_OCTET_STRING;
+        /* privateKey */
+        MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) );
 
         /* version */
         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 4cdb941..905de4c 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -49,6 +49,16 @@
     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
 }
 
+/*
+ * For the currently used signature algorithms the buffer to store any signature
+ * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
+ */
+#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
+#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
+#else
+#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
+#endif
+
 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
@@ -338,7 +348,7 @@
     size_t sig_oid_len = 0;
     unsigned char *c, *c2;
     unsigned char hash[64];
-    unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
+    unsigned char sig[SIGNATURE_MAX_SIZE];
     unsigned char tmp_buf[2048];
     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
     size_t len = 0;
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
index d59354d..d6e8c13 100644
--- a/library/x509write_csr.c
+++ b/library/x509write_csr.c
@@ -48,6 +48,16 @@
     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
 }
 
+/*
+ * For the currently used signature algorithms the buffer to store any signature
+ * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
+ */
+#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
+#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
+#else
+#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
+#endif
+
 void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
@@ -163,7 +173,7 @@
     size_t sig_oid_len = 0;
     unsigned char *c, *c2;
     unsigned char hash[64];
-    unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
+    unsigned char sig[SIGNATURE_MAX_SIZE];
     unsigned char tmp_buf[2048];
     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
     size_t len = 0;
diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c
index 7ec4675..0f08db9 100644
--- a/programs/pkey/pk_sign.c
+++ b/programs/pkey/pk_sign.c
@@ -59,6 +59,16 @@
 #include <stdio.h>
 #include <string.h>
 
+/*
+ * For the currently used signature algorithms the buffer to store any signature
+ * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
+ */
+#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
+#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
+#else
+#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
+#endif
+
 int main( int argc, char *argv[] )
 {
     FILE *f;
@@ -68,7 +78,7 @@
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
     unsigned char hash[32];
-    unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
+    unsigned char buf[SIGNATURE_MAX_SIZE];
     char filename[512];
     const char *pers = "mbedtls_pk_sign";
     size_t olen = 0;
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 2ffb706..658aa22 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -762,6 +762,14 @@
 	$(MBEDTLS_CERT_REQ) output_file=$@ filename=$< subject_name="C=NL,O=PolarSSL,CN=PolarSSL Server 1" md=SHA1 force_ns_cert_type=1
 all_final += server1.req.cert_type_empty
 
+###
+### A generic SECP521R1 private key
+###
+
+secp521r1_prv.der:
+	$(OPENSSL) ecparam -genkey -name secp521r1 -noout -out secp521r1_prv.der
+all_final += secp521r1_prv.der
+
 ################################################################
 ### Generate certificates for CRT write check tests
 ################################################################
diff --git a/tests/data_files/ec_256_long_prv.pem b/tests/data_files/ec_256_long_prv.pem
new file mode 100644
index 0000000..5141e30
--- /dev/null
+++ b/tests/data_files/ec_256_long_prv.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIIcex4mqXsQamUKTVf8vXmTAJrQvGjh5mXG8p9+OR4xAoAoGCCqGSM49
+AwEHoUQDQgAEqJ2HQjPpc6fDwE/vSa6U35USXawkTo98y4U6NsAl+rOGuqMPEFXf
+P1Srm/Jrzwa/RuppRL5kgyAsGJTUmwZEzQ==
+-----END EC PRIVATE KEY-----
diff --git a/tests/data_files/ec_521_short_prv.pem b/tests/data_files/ec_521_short_prv.pem
new file mode 100644
index 0000000..427b7ad
--- /dev/null
+++ b/tests/data_files/ec_521_short_prv.pem
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIAOXdk7W+Hf5L7Hc9fKe44wmpaRNs5ERFTkv5CrlXv/Bu3y28M673q
+vBNo7a/UE/6NNQHu2pQODEYFpMg6R34b5SigBwYFK4EEACOhgYkDgYYABAFUMHXV
+KPA4vkMgq+pFgDoH96XoM517gF2GJFV6h2gLhykzIHL/otAyEpAStw7MBvbU0V21
+ixB+hjqzO7Snxaj9mwB8g87OKxm5eGfsqvJNPdJ0RZ/EKy06Ukg6KThlhQeyrtIk
+g5PTCrPnNszlffAy6/jCOe3Moi59g15H13sSzwfX6g==
+-----END EC PRIVATE KEY-----
diff --git a/tests/data_files/secp521r1_prv.der b/tests/data_files/secp521r1_prv.der
new file mode 100644
index 0000000..4d342bd
--- /dev/null
+++ b/tests/data_files/secp521r1_prv.der
Binary files differ
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 427ab6d..44eee7a 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -591,6 +591,23 @@
 #### Build and test many configurations and targets
 ################################################################
 
+component_test_large_ecdsa_key_signature () {
+
+    SMALL_MPI_MAX_SIZE=136 # Small enough to interfere with the EC signatures
+
+    msg "build: cmake + MBEDTLS_MPI_MAX_SIZE=${SMALL_MPI_MAX_SIZE}, gcc, ASan" # ~ 1 min 50s
+    scripts/config.pl set MBEDTLS_MPI_MAX_SIZE $SMALL_MPI_MAX_SIZE
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+
+    INEVITABLY_PRESENT_FILE=Makefile
+    SIGNATURE_FILE="${INEVITABLY_PRESENT_FILE}.sig" # Warning, this is rm -f'ed below
+
+    msg "test: pk_sign secp521r1_prv.der for MBEDTLS_MPI_MAX_SIZE=${SMALL_MPI_MAX_SIZE} (ASan build)" # ~ 5s
+    if_build_succeeded programs/pkey/pk_sign tests/data_files/secp521r1_prv.der $INEVITABLY_PRESENT_FILE
+    rm -f $SIGNATURE_FILE
+}
+
 component_test_default_out_of_box () {
     msg "build: make, default config (out-of-box)" # ~1min
     make
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index 9b1315f..74fc49b 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -129,6 +129,16 @@
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &r, &r_check ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 );
 
+    mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s );
+    mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s );
+
+    TEST_ASSERT(
+                mbedtls_ecdsa_sign_det_ext( &grp, &r, &s, &d, hash, hlen,
+                                            md_alg, rnd_std_rand, NULL )
+                == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &r, &r_check ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 );
 exit:
     mbedtls_ecp_group_free( &grp );
     mbedtls_mpi_free( &d ); mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s );
diff --git a/tests/suites/test_suite_ecjpake.data b/tests/suites/test_suite_ecjpake.data
index 1a772a9..2b9821f 100644
--- a/tests/suites/test_suite_ecjpake.data
+++ b/tests/suites/test_suite_ecjpake.data
@@ -1,6 +1,9 @@
 ECJPAKE selftest
 ecjpake_selftest:
 
+ECJPAKE fail read corrupt MD
+read_bad_md:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51620934d74eb43e54df424fd96306c0117bf131afabf90a9d33d1198d905193735144104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb12"
+
 ECJPAKE round one: client, valid
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51620934d74eb43e54df424fd96306c0117bf131afabf90a9d33d1198d905193735144104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb12":0
 
diff --git a/tests/suites/test_suite_ecjpake.function b/tests/suites/test_suite_ecjpake.function
index 5c8856b..2f986f3 100644
--- a/tests/suites/test_suite_ecjpake.function
+++ b/tests/suites/test_suite_ecjpake.function
@@ -106,6 +106,37 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */
+void read_bad_md( char *data )
+{
+    mbedtls_ecjpake_context corrupt_ctx;
+
+    const unsigned char * pw = NULL;
+    const size_t pw_len = 0;
+
+    unsigned char *msg;
+    size_t len;
+
+    int any_role = MBEDTLS_ECJPAKE_CLIENT;
+
+    mbedtls_ecjpake_init( &corrupt_ctx );
+
+    msg = unhexify_alloc( data, &len );
+    TEST_ASSERT( msg != NULL );
+
+    TEST_ASSERT( mbedtls_ecjpake_setup( &corrupt_ctx, any_role,
+                 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, pw, pw_len ) == 0 );
+    corrupt_ctx.md_info = NULL;
+
+    TEST_ASSERT( mbedtls_ecjpake_read_round_one( &corrupt_ctx, msg,
+                 len ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+exit:
+    mbedtls_ecjpake_free( &corrupt_ctx );
+    mbedtls_free( msg );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */
 void read_round_one( int role, char *data, int ref_ret )
 {
     mbedtls_ecjpake_context ctx;
diff --git a/tests/suites/test_suite_pkwrite.data b/tests/suites/test_suite_pkwrite.data
index c8ff177..e0101cc 100644
--- a/tests/suites/test_suite_pkwrite.data
+++ b/tests/suites/test_suite_pkwrite.data
@@ -30,10 +30,18 @@
 depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 pk_write_key_check:"data_files/ec_prv.sec1.pem"
 
+Private key write check EC 256 bits (top bit set)
+depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_write_key_check:"data_files/ec_256_long_prv.pem"
+
 Private key write check EC 521 bits
 depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED
 pk_write_key_check:"data_files/ec_521_prv.pem"
 
+Private key write check EC 521 bits (top byte is 0)
+depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+pk_write_key_check:"data_files/ec_521_short_prv.pem"
+
 Private key write check EC Brainpool 512 bits
 depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_BP512R1_ENABLED
 pk_write_key_check:"data_files/ec_bp512_prv.pem"