Implement DH blinding
diff --git a/include/polarssl/dhm.h b/include/polarssl/dhm.h
index 4d7bd8a..4874bc8 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;
 
@@ -223,6 +226,9 @@
  * \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.
  */
 int dhm_calc_secret( dhm_context *ctx,
                      unsigned char *output, size_t *olen,
diff --git a/library/dhm.c b/library/dhm.c
index a5c3e90..11eee2a 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -246,6 +246,60 @@
 }
 
 /*
+ * 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;
+
+    /*
+     * We can just update the previous values (by squaring them) if:
+     * - the values are initialized, and
+     * - our secret exponent did not change.
+     */
+    if( ctx->Vi.p != NULL &&
+        mpi_cmp_mpi( &ctx->X, &ctx->_X ) == 0 )
+    {
+        MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
+        MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
+
+        return( 0 );
+    }
+
+    /*
+     * Otherwise, we need to generate new values from scratch for this secret
+     */
+
+    /* 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 );
+
+    /* 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,
@@ -254,24 +308,43 @@
                      void *p_rng )
 {
     int ret;
-
-    (void) f_rng;
-    (void) p_rng;
+    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 != 0 )
+    {
+        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 != 0 )
+    {
+        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 );
@@ -284,6 +357,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/tests/suites/test_suite_dhm.data b/tests/suites/test_suite_dhm.data
index 99f4482..0c0dce8 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -4,5 +4,5 @@
 Diffie-Hellman full exchange #2
 dhm_do_dhm:1024:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
 
-Diffie-Hellman full exchange #2
+Diffie-Hellman full exchange #3
 dhm_do_dhm:1024:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index e6fadfb..31a9004 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -35,18 +35,53 @@
     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, &rnd_pseudo_rand, &rnd_info ) == 0 );