Merged blinding additions for EC, RSA and DHM into development
diff --git a/include/polarssl/dhm.h b/include/polarssl/dhm.h
index da787c3..09de70b 100644
--- a/include/polarssl/dhm.h
+++ b/include/polarssl/dhm.h
@@ -147,6 +147,9 @@
     mpi GY;     /*!<  peer = G^Y mod P  */
     mpi K;      /*!<  key = GY^X mod P  */
     mpi RP;     /*!<  cached R^2 mod P  */
+    mpi Vi;     /*!<  blinding value    */
+    mpi Vf;     /*!<  un-blinding value */
+    mpi _X;     /*!<  previous X        */
 }
 dhm_context;
 
@@ -219,11 +222,23 @@
  * \param ctx      DHM context
  * \param output   destination buffer
  * \param olen     number of chars written
+ * \param f_rng    RNG function, for blinding purposes
+ * \param p_rng    RNG parameter
  *
  * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ *
+ * \note           If f_rng is not NULL, it is used to blind the input as
+ *                 countermeasure against timing attacks. This is only useful
+ *                 when this function is called repeatedly with the same
+ *                 secret value (X field), eg when using DH key exchange as
+ *                 opposed to DHE. It is recommended to use a non-NULL f_rng
+ *                 only when needed, since otherwise this countermeasure has
+ *                 high overhead.
  */
 int dhm_calc_secret( dhm_context *ctx,
-                     unsigned char *output, size_t *olen );
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
 
 /**
  * \brief          Free the components of a DHM key
diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h
index 2184ab9..d91aea5 100644
--- a/include/polarssl/ecdh.h
+++ b/include/polarssl/ecdh.h
@@ -70,12 +70,20 @@
  * \param z         Destination MPI (shared secret)
  * \param Q         Public key from other party
  * \param d         Our secret exponent
+ * \param f_rng     RNG function (see notes)
+ * \param p_rng     RNG parameter
  *
  * \return          0 if successful,
  *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ *
+ * \note            If f_rng is not NULL, it is used to implement
+ *                  countermeasures against potential elaborate timing
+ *                  attacks, see \c ecp_mul() for details.
  */
 int ecdh_compute_shared( const ecp_group *grp, mpi *z,
-                         const ecp_point *Q, const mpi *d );
+                         const ecp_point *Q, const mpi *d,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng );
 
 /**
  * \brief           Initialize context
@@ -156,11 +164,15 @@
  * \param olen      number of bytes written
  * \param buf       destination buffer
  * \param blen      buffer length
+ * \param f_rng     RNG function, see notes for \c ecdh_compute_shared()
+ * \param p_rng     RNG parameter
  *
  * \return          0 if successful, or an POLARSSL_ERR_ECP_XXX error code
  */
 int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
-                      unsigned char *buf, size_t blen );
+                      unsigned char *buf, size_t blen,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng );
 
 /**
  * \brief          Checkup routine
diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h
index ad31bff..31f9e6d 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -411,17 +411,31 @@
  * \param R         Destination point
  * \param m         Integer by which to multiply
  * \param P         Point to multiply
+ * \param f_rng     RNG function (see notes)
+ * \param p_rng     RNG parameter
  *
  * \return          0 if successful,
  *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- *                  POLARSSL_ERR_ECP_GENERIC if m < 0 of m has greater bit
- *                  length than N, the number of points in the group.
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if m < 0 of m has greater
+ *                  bit length than N, the number of points in the group.
  *
- * \note            This function executes a constant number of operations
- *                  for random m in the allowed range.
+ * \note            In order to prevent simple timing attacks, this function
+ *                  executes a constant number of operations (that is, point
+ *                  doubling and addition of distinct points) for random m in
+ *                  the allowed range.
+ *
+ * \note            If f_rng is not NULL, it is used to randomize projective
+ *                  coordinates of indermediate results, in order to prevent
+ *                  more elaborate timing attacks relying on intermediate
+ *                  operations. (This is a prophylactic measure since no such
+ *                  attack has been published yet.) Since this contermeasure
+ *                  has very low overhead, it is recommended to always provide
+ *                  a non-NULL f_rng parameter when using secret inputs.
  */
 int ecp_mul( const ecp_group *grp, ecp_point *R,
-             const mpi *m, const ecp_point *P );
+             const mpi *m, const ecp_point *P,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
 
 /**
  * \brief           Check that a point is a valid public key on this curve
diff --git a/include/polarssl/rsa.h b/include/polarssl/rsa.h
index 4e85ca6..71fbff2 100644
--- a/include/polarssl/rsa.h
+++ b/include/polarssl/rsa.h
@@ -89,6 +89,11 @@
     mpi RP;                     /*!<  cached R^2 mod P  */
     mpi RQ;                     /*!<  cached R^2 mod Q  */
 
+#if !defined(POLARSSL_RSA_NO_CRT)
+    mpi Vi;                     /*!<  cached blinding value     */
+    mpi Vf;                     /*!<  cached un-blinding value  */
+#endif
+
     int padding;                /*!<  RSA_PKCS_V15 for 1.5 padding and
                                       RSA_PKCS_v21 for OAEP/PSS         */
     int hash_id;                /*!<  Hash identifier of md_type_t as
diff --git a/library/dhm.c b/library/dhm.c
index 0c65dfe..b95f899 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -246,27 +246,112 @@
 }
 
 /*
+ * Use the blinding method and optimisation suggested in section 10 of:
+ *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
+ *  DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer
+ *  Berlin Heidelberg, 1996. p. 104-113.
+ */
+static int dhm_update_blinding( dhm_context *ctx,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret, count;
+
+    /*
+     * If Vi is initialized, update it by squaring it
+     */
+    if( ctx->Vi.p != NULL )
+    {
+        MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
+    }
+    else
+    {
+        /* Vi = random( 2, P-1 ) */
+        count = 0;
+        do
+        {
+            mpi_fill_random( &ctx->Vi, mpi_size( &ctx->P ), f_rng, p_rng );
+
+            while( mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
+                mpi_shift_r( &ctx->Vi, 1 );
+
+            if( count++ > 10 )
+                return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+        }
+        while( mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
+    }
+
+    /*
+     * If X did not change, update Vf by squaring it too
+     */
+    if( mpi_cmp_mpi( &ctx->X, &ctx->_X ) == 0 )
+    {
+        MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
+        return( 0 );
+    }
+
+    /*
+     * Otherwise, compute Vf from scratch
+     */
+
+    /* Vf = Vi^-X mod P */
+    MPI_CHK( mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
+    MPI_CHK( mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
+
+    /* Remember secret associated with Vi and Vf */
+    MPI_CHK( mpi_copy( &ctx->_X, &ctx->X ) );;
+
+cleanup:
+    return( ret );
+}
+
+/*
  * Derive and export the shared secret (G^Y)^X mod P
  */
 int dhm_calc_secret( dhm_context *ctx,
-                     unsigned char *output, size_t *olen )
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
 {
     int ret;
+    mpi GYb;
 
     if( ctx == NULL || *olen < ctx->len )
         return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
 
-    MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
-                          &ctx->P, &ctx->RP ) );
-
     if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
         return( ret );
 
+    mpi_init( &GYb );
+
+    /* Blind peer's value */
+    if( f_rng != NULL )
+    {
+        MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
+        MPI_CHK( mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
+    }
+    else
+        MPI_CHK( mpi_copy( &GYb, &ctx->GY ) );
+
+    /* Do modular exponentiation */
+    MPI_CHK( mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
+                          &ctx->P, &ctx->RP ) );
+
+    /* Unblind secret value */
+    if( f_rng != NULL )
+    {
+        MPI_CHK( mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
+    }
+
     *olen = mpi_size( &ctx->K );
 
     MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
 
 cleanup:
+    mpi_free( &GYb );
 
     if( ret != 0 )
         return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
@@ -279,6 +364,7 @@
  */
 void dhm_free( dhm_context *ctx )
 {
+    mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf );
     mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
     mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
     mpi_free( &ctx->P );
diff --git a/library/ecdh.c b/library/ecdh.c
index d76596e..8ef02f5 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -50,7 +50,9 @@
  * Compute shared secret (SEC1 3.3.1)
  */
 int ecdh_compute_shared( const ecp_group *grp, mpi *z,
-                         const ecp_point *Q, const mpi *d )
+                         const ecp_point *Q, const mpi *d,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng )
 {
     int ret;
     ecp_point P;
@@ -62,7 +64,7 @@
      */
     MPI_CHK( ecp_check_pubkey( grp, Q ) );
 
-    MPI_CHK( ecp_mul( grp, &P, d, Q ) );
+    MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
 
     if( ecp_is_zero( &P ) )
     {
@@ -202,16 +204,20 @@
  * Derive and export the shared secret
  */
 int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
-                      unsigned char *buf, size_t blen )
+                      unsigned char *buf, size_t blen,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng )
 {
     int ret;
 
     if( ctx == NULL )
         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
-    if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d ) )
-                != 0 )
+    if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
+                                     f_rng, p_rng ) ) != 0 )
+    {
         return( ret );
+    }
 
     if( mpi_size( &ctx->z ) > blen )
         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 67774c9..dc169ce 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -161,9 +161,12 @@
 
     /*
      * Step 5: R = u1 G + u2 Q
+     *
+     * Since we're not using any secret data, no need to pass a RNG to
+     * ecp_mul() for countermesures.
      */
-    MPI_CHK( ecp_mul( grp, &R, &u1, &grp->G ) );
-    MPI_CHK( ecp_mul( grp, &P, &u2, Q ) );
+    MPI_CHK( ecp_mul( grp, &R, &u1, &grp->G, NULL, NULL ) );
+    MPI_CHK( ecp_mul( grp, &P, &u2, Q, NULL, NULL ) );
     MPI_CHK( ecp_add( grp, &R, &R, &P ) );
 
     if( ecp_is_zero( &R ) )
@@ -217,8 +220,8 @@
                            void *p_rng )
 {
     int ret;
-    unsigned char buf[MAX_SIG_LEN];
-    unsigned char *p = buf + MAX_SIG_LEN - 1;
+    unsigned char buf[MAX_SIG_LEN + 3];
+    unsigned char *p = buf + MAX_SIG_LEN;
     size_t len = 0;
 
     if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d,
diff --git a/library/ecp.c b/library/ecp.c
index 09a021b..a80ddac 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -30,6 +30,17 @@
  * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
  * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
  * RFC 4492 for the related TLS structures and constants
+ *
+ * [1] OKEYA, Katsuyuki and TAKAGI, Tsuyoshi. The width-w NAF method provides
+ *     small memory and fast elliptic scalar multiplications secure against
+ *     side channel attacks. In : Topics in Cryptology—CT-RSA 2003. Springer
+ *     Berlin Heidelberg, 2003. p. 328-343.
+ *     <http://rd.springer.com/chapter/10.1007/3-540-36563-X_23>.
+ *
+ * [2] CORON, Jean-Sébastien. Resistance against differential power analysis
+ *     for elliptic curve cryptosystems. In : Cryptographic Hardware and
+ *     Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
+ *     <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
  */
 
 #include "polarssl/config.h"
@@ -51,7 +62,7 @@
 #if defined(POLARSSL_SELF_TEST)
 /*
  * Counts of point addition and doubling operations.
- * Used to test resistance of point multiplication to SPA/timing attacks.
+ * Used to test resistance of point multiplication to simple timing attacks.
  */
 unsigned long add_count, dbl_count;
 #endif
@@ -777,7 +788,7 @@
  * (See for example Cohen's "A Course in Computational Algebraic Number
  * Theory", Algorithm 10.3.4.)
  *
- * Warning: fails if one of the points is zero!
+ * Warning: fails (returning an error) if one of the points is zero!
  * This should never happen, see choice of w in ecp_mul().
  */
 static int ecp_normalize_many( const ecp_group *grp,
@@ -1049,11 +1060,10 @@
 
 /*
  * Compute a modified width-w non-adjacent form (NAF) of a number,
- * with a fixed pattern for resistance to SPA/timing attacks,
- * see <http://rd.springer.com/chapter/10.1007/3-540-36563-X_23>.
- * (The resulting multiplication algorithm can also been seen as a
- * modification of 2^w-ary multiplication, with signed coefficients,
- * all of them odd.)
+ * with a fixed pattern for resistance to simple timing attacks (even SPA),
+ * see [1]. (The resulting multiplication algorithm can also been seen as a
+ * modification of 2^w-ary multiplication, with signed coefficients, all of
+ * them odd.)
  *
  * Input:
  * m must be an odd positive mpi less than w * k bits long
@@ -1145,6 +1155,51 @@
 }
 
 /*
+ * Randomize jacobian coordinates:
+ * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
+ * This is sort of the reverse operation of ecp_normalize().
+ */
+static int ecp_randomize_coordinates( const ecp_group *grp, ecp_point *pt,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
+    mpi l, ll;
+    size_t p_size = (grp->pbits + 7) / 8;
+    int count = 0;
+
+    mpi_init( &l ); mpi_init( &ll );
+
+    /* Generate l such that 1 < l < p */
+    do
+    {
+        mpi_fill_random( &l, p_size, f_rng, p_rng );
+
+        while( mpi_cmp_mpi( &l, &grp->P ) >= 0 )
+            mpi_shift_r( &l, 1 );
+
+        if( count++ > 10 )
+            return( POLARSSL_ERR_ECP_GENERIC );
+    }
+    while( mpi_cmp_int( &l, 1 ) <= 0 );
+
+    /* Z = l * Z */
+    MPI_CHK( mpi_mul_mpi( &pt->Z,   &pt->Z,     &l  ) ); MOD_MUL( pt->Z );
+
+    /* X = l^2 * X */
+    MPI_CHK( mpi_mul_mpi( &ll,      &l,         &l  ) ); MOD_MUL( ll );
+    MPI_CHK( mpi_mul_mpi( &pt->X,   &pt->X,     &ll ) ); MOD_MUL( pt->X );
+
+    /* Y = l^3 * Y */
+    MPI_CHK( mpi_mul_mpi( &ll,      &ll,        &l  ) ); MOD_MUL( ll );
+    MPI_CHK( mpi_mul_mpi( &pt->Y,   &pt->Y,     &ll ) ); MOD_MUL( pt->Y );
+
+cleanup:
+    mpi_free( &l ); mpi_free( &ll );
+
+    return( ret );
+}
+
+/*
  * Maximum length of the precomputed table
  */
 #define MAX_PRE_LEN     ( 1 << (POLARSSL_ECP_WINDOW_SIZE - 1) )
@@ -1159,14 +1214,19 @@
 /*
  * Integer multiplication: R = m * P
  *
- * Based on fixed-pattern width-w NAF, see comments of ecp_w_naf_fixed()
- * and <http://rd.springer.com/chapter/10.1007/3-540-36563-X_23>.
+ * Based on fixed-pattern width-w NAF, see comments of ecp_w_naf_fixed().
  *
  * This function executes a fixed number of operations for
  * random m in the range 0 .. 2^nbits - 1.
+ *
+ * As an additional countermeasure against potential elaborate timing attacks,
+ * we randomize coordinates after each addition. This was suggested as a
+ * countermeasure against DPA in 5.3 of [2] (with the obvious adaptation that
+ * we use jacobian coordinates, not standard projective coordinates).
  */
 int ecp_mul( const ecp_group *grp, ecp_point *R,
-             const mpi *m, const ecp_point *P )
+             const mpi *m, const ecp_point *P,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
     int ret;
     unsigned char w, m_is_odd;
@@ -1176,17 +1236,17 @@
     mpi M;
 
     if( mpi_cmp_int( m, 0 ) < 0 || mpi_msb( m ) > grp->nbits )
-        return( POLARSSL_ERR_ECP_GENERIC );
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
     w = grp->nbits >= 521 ? 6 :
         grp->nbits >= 224 ? 5 :
-        4;
+                            4;
 
     /*
      * Make sure w is within the limits.
      * The last test ensures that none of the precomputed points is zero,
      * which wouldn't be handled correctly by ecp_normalize_many().
-     * It is only useful for small curves, as used in the test suite.
+     * It is only useful for very small curves, as used in the test suite.
      */
     if( w > POLARSSL_ECP_WINDOW_SIZE )
         w = POLARSSL_ECP_WINDOW_SIZE;
@@ -1237,6 +1297,10 @@
             MPI_CHK( ecp_add_mixed( grp, &Q, &Q, &T[ naf[i] ], +1 ) );
         }
 
+        /* Countermeasure (see comments above) */
+        if( f_rng != NULL )
+            ecp_randomize_coordinates( grp, &Q, f_rng, p_rng );
+
         if( i == 0 )
             break;
         i--;
@@ -1348,7 +1412,7 @@
     }
     while( mpi_cmp_int( d, 1 ) < 0 );
 
-    return( ecp_mul( grp, Q, d, &grp->G ) );
+    return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) );
 }
 
 #if defined(POLARSSL_SELF_TEST)
@@ -1402,12 +1466,12 @@
 #endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
 
     if( verbose != 0 )
-        printf( "  ECP test #1 (SPA resistance): " );
+        printf( "  ECP test #1 (resistance to simple timing attacks): " );
 
     add_count = 0;
     dbl_count = 0;
     MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) );
-    MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G ) );
+    MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
 
     for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
     {
@@ -1417,7 +1481,7 @@
         dbl_count = 0;
 
         MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) );
-        MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G ) );
+        MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
 
         if( add_count != add_c_prev || dbl_count != dbl_c_prev )
         {
diff --git a/library/rsa.c b/library/rsa.c
index c39a338..c82ffaa 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -253,6 +253,41 @@
     return( 0 );
 }
 
+#if !defined(POLARSSL_RSA_NO_CRT)
+/*
+ * Generate or update blinding values, see section 10 of:
+ *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
+ *  DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer
+ *  Berlin Heidelberg, 1996. p. 104-113.
+ */
+static int rsa_prepare_blinding( rsa_context *ctx,
+                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
+
+    if( ctx->Vf.p != NULL )
+    {
+        /* We already have blinding values, just update them by squaring */
+        MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
+        MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
+
+        return( 0 );
+    }
+
+    /* Unblinding value: Vf = random number */
+    MPI_CHK( mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) );
+
+    /* Blinding value: Vi =  Vf^(-e) mod N */
+    MPI_CHK( mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) );
+    MPI_CHK( mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) );
+
+cleanup:
+    return( ret );
+}
+#endif
+
 /*
  * Do an RSA private key operation
  */
@@ -265,11 +300,8 @@
     int ret;
     size_t olen;
     mpi T, T1, T2;
-    mpi A, X;
-
 
     mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
-    mpi_init( &A ); mpi_init( &X );
 
     MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
     if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
@@ -284,14 +316,12 @@
     if( f_rng != NULL )
     {
         /*
-         * RSA Blinding
-         * A = rnd MPI
-         * T = A^E * T mod N
+         * Blinding
+         * T = T * Vi mod N
          */
-        MPI_CHK( mpi_fill_random( &A, ctx->len - 1, f_rng, p_rng ) );
-        MPI_CHK( mpi_exp_mod( &X, &A, &ctx->E, &ctx->N, NULL ) );
-        MPI_CHK( mpi_mul_mpi( &X, &X, &T ) );
-        MPI_CHK( mpi_mod_mpi( &T, &X, &ctx->N ) );
+        MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) );
+        MPI_CHK( mpi_mul_mpi( &T, &T, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
     }
 
     /*
@@ -320,10 +350,9 @@
     {
         /*
          * Unblind
-         * T = T / A mod N
+         * T = T * Vf mod N
          */
-        MPI_CHK( mpi_inv_mod( &A, &A, &ctx->N ) );
-        MPI_CHK( mpi_mul_mpi( &T, &T, &A ) );
+        MPI_CHK( mpi_mul_mpi( &T, &T, &ctx->Vf ) );
         MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
     }
 #endif
@@ -334,7 +363,6 @@
 cleanup:
 
     mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
-    mpi_free( &A ); mpi_free( &X );
 
     if( ret != 0 )
         return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );
@@ -1280,6 +1308,9 @@
     MPI_CHK( mpi_copy( &dst->RP, &src->RP ) );
     MPI_CHK( mpi_copy( &dst->RQ, &src->RQ ) );
 
+    MPI_CHK( mpi_copy( &dst->Vi, &src->Vi ) );
+    MPI_CHK( mpi_copy( &dst->Vf, &src->Vf ) );
+
     dst->padding = src->padding;
     dst->hash_id = src->padding;
 
@@ -1295,6 +1326,7 @@
  */
 void rsa_free( rsa_context *ctx )
 {
+    mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf );
     mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
     mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
     mpi_free( &ctx->Q  ); mpi_free( &ctx->P  ); mpi_free( &ctx->D );
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 0fccf34..19f0cb6 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -1711,9 +1711,11 @@
 
         ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
 
+        /* No blinding needed for DHE, but will be needed for fixed DH! */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
                                       ssl->handshake->premaster,
-                                     &ssl->handshake->pmslen ) ) != 0 )
+                                     &ssl->handshake->pmslen,
+                                     NULL, NULL ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( ret );
@@ -1748,7 +1750,8 @@
         if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
                                       &ssl->handshake->pmslen,
                                        ssl->handshake->premaster,
-                                       POLARSSL_MPI_MAX_SIZE ) ) != 0 )
+                                       POLARSSL_MPI_MAX_SIZE,
+                                       ssl->f_rng, ssl->p_rng ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret );
             return( ret );
@@ -1840,8 +1843,9 @@
 
         *(p++) = (unsigned char)( ssl->handshake->dhm_ctx.len >> 8 );
         *(p++) = (unsigned char)( ssl->handshake->dhm_ctx.len      );
+        /* No blinding needed since this is ephemeral DHM */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                      p, &n ) ) != 0 )
+                                      p, &n, NULL, NULL ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( ret );
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 7608d78..8edc57f 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -2384,9 +2384,11 @@
 
         ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
 
+        /* No blinding needed for DHE, but will be needed for fixed DH! */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
                                       ssl->handshake->premaster,
-                                     &ssl->handshake->pmslen ) ) != 0 )
+                                     &ssl->handshake->pmslen,
+                                      NULL, NULL ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
@@ -2410,7 +2412,8 @@
         if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
                                       &ssl->handshake->pmslen,
                                        ssl->handshake->premaster,
-                                       POLARSSL_MPI_MAX_SIZE ) ) != 0 )
+                                       POLARSSL_MPI_MAX_SIZE,
+                                       ssl->f_rng, ssl->p_rng ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret );
             return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
@@ -2470,8 +2473,9 @@
 
         n = ssl->handshake->dhm_ctx.len;
 
+        /* No blinding needed since this is ephemeral DHM */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                      p, &n ) ) != 0 )
+                                      p, &n, NULL, NULL ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index f06b906..c5c6f75 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -239,7 +239,7 @@
     fflush( stdout );
 
     n = dhm.len;
-    if( ( ret = dhm_calc_secret( &dhm, buf, &n ) ) != 0 )
+    if( ( ret = dhm_calc_secret( &dhm, buf, &n, NULL, NULL ) ) != 0 )
     {
         printf( " failed\n  ! dhm_calc_secret returned %d\n\n", ret );
         goto exit;
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index 1eba806..3382307 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -242,7 +242,7 @@
     printf( "\n  . Shared secret: " );
     fflush( stdout );
 
-    if( ( ret = dhm_calc_secret( &dhm, buf, &n ) ) != 0 )
+    if( ( ret = dhm_calc_secret( &dhm, buf, &n, NULL, NULL ) ) != 0 )
     {
         printf( " failed\n  ! dhm_calc_secret returned %d\n\n", ret );
         goto exit;
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index c33f5b5..e0d65d3 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -92,7 +92,7 @@
 #else
 int main( int argc, char *argv[] )
 {
-    int keysize;
+    int ret, keysize;
     unsigned long i, j, tsc;
     unsigned char tmp[64];
 #if defined(POLARSSL_ARC4_C)
@@ -431,25 +431,33 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_public( &rsa, buf, buf );
+        ret = rsa_public( &rsa, buf, buf );
     }
 
-    printf( "%9lu  public/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu  public/s\n", i / 3 );
 
     printf( HEADER_FORMAT, "RSA-1024" );
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_private( &rsa, buf, buf );
+        ret = rsa_private( &rsa, myrand, NULL, buf, buf );
     }
 
-    printf( "%9lu private/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu private/s\n", i / 3 );
 
     rsa_free( &rsa );
 
@@ -460,25 +468,33 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_public( &rsa, buf, buf );
+        ret = rsa_public( &rsa, buf, buf );
     }
 
-    printf( "%9lu  public/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu  public/s\n", i / 3 );
 
     printf( HEADER_FORMAT, "RSA-2048" );
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_private( &rsa, buf, buf );
+        ret = rsa_private( &rsa, myrand, NULL, buf, buf );
     }
 
-    printf( "%9lu private/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu private/s\n", i / 3 );
 
     rsa_free( &rsa );
 
@@ -489,25 +505,33 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_public( &rsa, buf, buf );
+        ret = rsa_public( &rsa, buf, buf );
     }
 
-    printf( "%9lu  public/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu  public/s\n", i / 3 );
 
     printf( HEADER_FORMAT, "RSA-4096" );
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_private( &rsa, buf, buf );
+        ret = rsa_private( &rsa, myrand, NULL, buf, buf );
     }
 
-    printf( "%9lu private/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu private/s\n", i / 3 );
 
     rsa_free( &rsa );
 #endif
@@ -525,13 +549,34 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
-        dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
-        dhm_calc_secret( &dhm, buf, &olen );
+        olen = sizeof( buf );
+        ret |= dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, NULL, NULL );
     }
 
-    printf( "%9lu handshake/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
+
+    printf( HEADER_FORMAT, "fixed-DHM-1024" );
+    fflush( stdout );
+    set_alarm( 3 );
+
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
+    {
+        olen = sizeof( buf );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, myrand, NULL );
+    }
+
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
 
     dhm_free( &dhm );
 
@@ -547,16 +592,36 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
-        dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
-        dhm_calc_secret( &dhm, buf, &olen );
+        olen = sizeof( buf );
+        ret |= dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, myrand, NULL );
     }
 
-    printf( "%9lu handshake/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
+
+    printf( HEADER_FORMAT, "fixed-DHM-2048" );
+    fflush( stdout );
+    set_alarm( 3 );
+
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
+    {
+        olen = sizeof( buf );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, NULL, NULL );
+    }
+
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
 
     dhm_free( &dhm );
-
     memset( &dhm, 0, sizeof( dhm_context ) );
 
     mpi_read_string( &dhm.P, 16, POLARSSL_DHM_RFC3526_MODP_3072_P );
@@ -569,13 +634,34 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
-        dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
-        dhm_calc_secret( &dhm, buf, &olen );
+        olen = sizeof( buf );
+        ret |= dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, NULL, NULL );
     }
 
-    printf( "%9lu handshake/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
+
+    printf( HEADER_FORMAT, "fixed-DHM-3072" );
+    fflush( stdout );
+    set_alarm( 3 );
+
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
+    {
+        olen = sizeof( buf );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, myrand, NULL );
+    }
+
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
 
     dhm_free( &dhm );
 #endif
diff --git a/programs/test/ecp-bench.c b/programs/test/ecp-bench.c
index 0a0e015..9231118 100644
--- a/programs/test/ecp-bench.c
+++ b/programs/test/ecp-bench.c
@@ -28,6 +28,29 @@
 
 #else
 
+static int myrand( void *rng_state, unsigned char *output, size_t len )
+{
+    size_t use_len;
+    int rnd;
+
+    if( rng_state != NULL )
+        rng_state  = NULL;
+
+    while( len > 0 )
+    {
+        use_len = len;
+        if( use_len > sizeof(int) )
+            use_len = sizeof(int);
+
+        rnd = rand();
+        memcpy( output, &rnd, use_len );
+        output += use_len;
+        len -= use_len;
+    }
+
+    return( 0 );
+}
+
 static void dhm_bench_case( const char *s, const char *p,
                             const char *g, const char *x )
 {
@@ -161,7 +184,7 @@
     set_alarm( 3 );
 
     for( i = 1; ! alarmed; i++ )
-        ecp_mul( &grp, &R, &M, &grp.G );
+        ecp_mul( &grp, &R, &M, &grp.G, myrand, NULL );
 
     printf( "%9lu mul/s\n", i / 3 );
 
diff --git a/tests/suites/test_suite_dhm.data b/tests/suites/test_suite_dhm.data
index 99f4482..168c77c 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -1,8 +1,8 @@
 Diffie-Hellman full exchange #1
-dhm_do_dhm:1024:10:"23":10:"5"
+dhm_do_dhm:10:"23":10:"5"
 
 Diffie-Hellman full exchange #2
-dhm_do_dhm:1024:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
+dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
 
-Diffie-Hellman full exchange #2
-dhm_do_dhm:1024:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
+Diffie-Hellman full exchange #3
+dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index e6524cc..e8d9cea 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -8,7 +8,7 @@
  */
 
 /* BEGIN_CASE */
-void dhm_do_dhm( int NOTUSED, int radix_P, char *input_P,
+void dhm_do_dhm( int radix_P, char *input_P,
                  int radix_G, char *input_G )
 {
     dhm_context ctx_srv;
@@ -25,8 +25,6 @@
     int x_size;
     rnd_pseudo_info rnd_info;
 
-    ((void)NOTUSED);
-
     memset( &ctx_srv, 0x00, sizeof( dhm_context ) );
     memset( &ctx_cli, 0x00, sizeof( dhm_context ) );
     memset( ske, 0x00, 1000 );
@@ -35,22 +33,57 @@
     memset( sec_cli, 0x00, 1000 );
     memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
 
+    /*
+     * Set params
+     */
     TEST_ASSERT( mpi_read_string( &ctx_srv.P, radix_P, input_P ) == 0 );
     TEST_ASSERT( mpi_read_string( &ctx_srv.G, radix_G, input_G ) == 0 );
     x_size = mpi_size( &ctx_srv.P );
+    pub_cli_len = x_size;
+
+    /*
+     * First key exchange
+     */
+    TEST_ASSERT( dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+    ske[ske_len++] = 0;
+    ske[ske_len++] = 0;
+    TEST_ASSERT( dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
+
+    TEST_ASSERT( dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
+
+    TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( dhm_calc_secret( &ctx_cli, sec_cli, &sec_cli_len, NULL, NULL ) == 0 );
+
+    TEST_ASSERT( sec_srv_len == sec_cli_len );
+    TEST_ASSERT( sec_srv_len != 0 );
+    TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
+
+    /* Re-do calc_secret on server to test update of blinding values */
+    sec_srv_len = 1000;
+    TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+
+    TEST_ASSERT( sec_srv_len == sec_cli_len );
+    TEST_ASSERT( sec_srv_len != 0 );
+    TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
+
+    /*
+     * Second key exchange to test change of blinding values on server
+     */
+    sec_cli_len = 1000;
+    sec_srv_len = 1000;
+    p = ske;
 
     TEST_ASSERT( dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
     ske[ske_len++] = 0;
     ske[ske_len++] = 0;
     TEST_ASSERT( dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
 
-    pub_cli_len = x_size;
     TEST_ASSERT( dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
-
     TEST_ASSERT( dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
 
-    TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len ) == 0 );
-    TEST_ASSERT( dhm_calc_secret( &ctx_cli, sec_cli, &sec_cli_len ) == 0 );
+    TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( dhm_calc_secret( &ctx_cli, sec_cli, &sec_cli_len, NULL, NULL ) == 0 );
 
     TEST_ASSERT( sec_srv_len == sec_cli_len );
     TEST_ASSERT( sec_srv_len != 0 );
diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function
index 5bfd63d..ba35c76 100644
--- a/tests/suites/test_suite_ecdh.function
+++ b/tests/suites/test_suite_ecdh.function
@@ -27,8 +27,10 @@
                  == 0 );
     TEST_ASSERT( ecdh_gen_public( &grp, &dB, &qB, &rnd_pseudo_rand, &rnd_info )
                  == 0 );
-    TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA ) == 0 );
-    TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB ) == 0 );
+    TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA,
+                                      &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB,
+                                      NULL, NULL ) == 0 );
 
     TEST_ASSERT( mpi_cmp_mpi( &zA, &zB ) == 0 );
 
@@ -70,9 +72,9 @@
     TEST_ASSERT( mpi_cmp_mpi( &qB.Y, &check ) == 0 );
 
     TEST_ASSERT( mpi_read_string( &check, 16, z_str ) == 0 );
-    TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA ) == 0 );
+    TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &zA, &check ) == 0 );
-    TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB ) == 0 );
+    TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &zB, &check ) == 0 );
 
     ecp_group_free( &grp );
@@ -107,8 +109,9 @@
                                    &rnd_pseudo_rand, &rnd_info ) == 0 );
     TEST_ASSERT( ecdh_read_public( &srv, buf, len ) == 0 );
 
-    TEST_ASSERT( ecdh_calc_secret( &srv, &len, buf, 1000 ) == 0 );
-    TEST_ASSERT( ecdh_calc_secret( &cli, &len, buf, 1000 ) == 0 );
+    TEST_ASSERT( ecdh_calc_secret( &srv, &len, buf, 1000,
+                                   &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( ecdh_calc_secret( &cli, &len, buf, 1000, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &srv.z, &cli.z ) == 0 );
 
     ecdh_free( &srv );
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index ce92633..55a3453 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -50,7 +50,7 @@
 ecp_small_sub:0:"14":"11":0:"14":"36":0:27:30
 
 ECP small multiplication negative
-ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_GENERIC
+ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_BAD_INPUT_DATA
 
 ECP small multiplication #0
 ecp_small_mul:0:1:0:0:0
@@ -101,7 +101,7 @@
 ecp_small_mul:2:0:20:01:0
 
 ECP small multiplication too big
-ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_GENERIC
+ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_BAD_INPUT_DATA
 
 ECP small check pubkey #1
 ecp_small_check_pub:1:1:0:POLARSSL_ERR_ECP_GENERIC
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 62c5de2..5b1ab60 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -101,17 +101,33 @@
     ecp_group grp;
     ecp_point R;
     mpi m;
+    rnd_pseudo_info rnd_info;
 
     ecp_group_init( &grp );
     ecp_point_init( &R );
     mpi_init( &m );
+    memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
 
     TEST_ASSERT( ecp_group_read_string( &grp, 10,
                 "47", "4", "17", "42", "13" ) == 0 );
 
     TEST_ASSERT( mpi_lset( &m, m_str ) == 0 );
 
-    TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G ) == ret );
+    TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) == ret );
+
+    if( r_zero )
+        TEST_ASSERT( mpi_cmp_int( &R.Z, 0 ) == 0 );
+    else
+    {
+        TEST_ASSERT( mpi_cmp_int( &R.X, x_r ) == 0 );
+        TEST_ASSERT( mpi_cmp_int( &R.Y, y_r ) == 0 );
+    }
+
+    /* try again with randomization */
+    ecp_point_free( &R );
+
+    TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G,
+                          &rnd_pseudo_rand, &rnd_info ) == ret );
 
     if( r_zero )
         TEST_ASSERT( mpi_cmp_int( &R.Z, 0 ) == 0 );
@@ -158,10 +174,12 @@
     ecp_group grp;
     ecp_point R;
     mpi dA, xA, yA, dB, xB, yB, xZ, yZ;
+    rnd_pseudo_info rnd_info;
 
     ecp_group_init( &grp ); ecp_point_init( &R );
     mpi_init( &dA ); mpi_init( &xA ); mpi_init( &yA ); mpi_init( &dB );
     mpi_init( &xB ); mpi_init( &yB ); mpi_init( &xZ ); mpi_init( &yZ );
+    memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
 
     TEST_ASSERT( ecp_use_known_dp( &grp, id ) == 0 );
 
@@ -176,20 +194,22 @@
     TEST_ASSERT( mpi_read_string( &xZ, 16, xZ_str ) == 0 );
     TEST_ASSERT( mpi_read_string( &yZ, 16, yZ_str ) == 0 );
 
-    TEST_ASSERT( ecp_mul( &grp, &R, &dA, &grp.G ) == 0 );
+    TEST_ASSERT( ecp_mul( &grp, &R, &dA, &grp.G,
+                          &rnd_pseudo_rand, &rnd_info ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.X, &xA ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yA ) == 0 );
     TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 );
-    TEST_ASSERT( ecp_mul( &grp, &R, &dB, &R ) == 0 );
+    TEST_ASSERT( ecp_mul( &grp, &R, &dB, &R, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.X, &xZ ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yZ ) == 0 );
     TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 );
 
-    TEST_ASSERT( ecp_mul( &grp, &R, &dB, &grp.G ) == 0 );
+    TEST_ASSERT( ecp_mul( &grp, &R, &dB, &grp.G, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.X, &xB ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yB ) == 0 );
     TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 );
-    TEST_ASSERT( ecp_mul( &grp, &R, &dA, &R ) == 0 );
+    TEST_ASSERT( ecp_mul( &grp, &R, &dA, &R,
+                          &rnd_pseudo_rand, &rnd_info ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.X, &xZ ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yZ ) == 0 );
     TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 );