Implement fixed-window exponentiation to mitigate hyper-threading
timing attacks.

BN_FLG_EXP_CONSTTIME requests this algorithm, and this done by default for
RSA/DSA/DH private key computations unless
RSA_FLAG_NO_EXP_CONSTTIME/DSA_FLAG_NO_EXP_CONSTTIME/
DH_FLAG_NO_EXP_CONSTTIME is set.

Submitted by: Matthew D Wood
Reviewed by: Bodo Moeller
diff --git a/CHANGES b/CHANGES
index cd3dba1..54df558 100644
--- a/CHANGES
+++ b/CHANGES
@@ -799,6 +799,21 @@
 
  Changes between 0.9.7g and 0.9.7h  [XX xxx XXXX]
 
+  *) Make a new fixed-window mod_exp implementation the default for
+     RSA, DSA, and DH private-key operations to mitigate the
+     hyper-threading timing attacks pointed out by Colin Percival
+     (http://www.daemonology.net/hyperthreading-considered-harmful/),
+     and potential related attacks.
+
+     BN_mod_exp_mont_consttime() is the new exponentiation implementation,
+     and this is automatically used by BN_mod_exp_mont() if the new flag
+     BN_FLG_EXP_CONSTTIME is set for the exponent.  RSA, DSA, and DH
+     will use this BN flag for private exponents unless the flag
+     RSA_FLAG_NO_EXP_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME, or
+     DH_FLAG_NO_EXP_CONSTTIME, respectively, is set.
+
+     [Matthew D Wood (Intel Corp), with some changes by Bodo Moeller]
+
   *) Change the client implementation for SSLv23_method() and
      SSLv23_client_method() so that is uses the SSL 3.0/TLS 1.0
      Client Hello message format if the SSL_OP_NO_SSLv2 option is set.
diff --git a/apps/speed.c b/apps/speed.c
index bd5b217..2ecbb1e 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -2365,7 +2365,7 @@
 				k,rsa_bits[k],rsa_results[k][0],
 				rsa_results[k][1]);
 		else
-			fprintf(stdout,"rsa %4u bits %8.4fs %8.4fs %8.1f %8.1f\n",
+			fprintf(stdout,"rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
 				rsa_bits[k],rsa_results[k][0],rsa_results[k][1],
 				1.0/rsa_results[k][0],1.0/rsa_results[k][1]);
 		}
@@ -2384,7 +2384,7 @@
 			fprintf(stdout,"+F3:%u:%u:%f:%f\n",
 				k,dsa_bits[k],dsa_results[k][0],dsa_results[k][1]);
 		else
-			fprintf(stdout,"dsa %4u bits %8.4fs %8.4fs %8.1f %8.1f\n",
+			fprintf(stdout,"dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
 				dsa_bits[k],dsa_results[k][0],dsa_results[k][1],
 				1.0/dsa_results[k][0],1.0/dsa_results[k][1]);
 		}
diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h
index 99faf8f..6d52735 100644
--- a/crypto/bn/bn.h
+++ b/crypto/bn/bn.h
@@ -245,12 +245,23 @@
 
 #define BN_FLG_MALLOCED		0x01
 #define BN_FLG_STATIC_DATA	0x02
+#define BN_FLG_EXP_CONSTTIME	0x04 /* avoid leaking exponent information through timings
+                            	      * (BN_mod_exp_mont() will call BN_mod_exp_mont_consttime) */
 #ifndef OPENSSL_NO_DEPRECATED
 #define BN_FLG_FREE		0x8000	/* used for debuging */
 #endif
 #define BN_set_flags(b,n)	((b)->flags|=(n))
 #define BN_get_flags(b,n)	((b)->flags&(n))
 
+#define BN_with_flags(dest,b,n)  ((dest)->d=(b)->d, \
+                                  (dest)->top=(b)->top, \
+                                  (dest)->dmax=(b)->dmax, \
+                                  (dest)->neg=(b)->neg, \
+                                  (dest)->flags=(((dest)->flags & BN_FLG_MALLOCED) \
+                                                 |  ((b)->flags & ~BN_FLG_MALLOCED) \
+                                                 |  BN_FLG_STATIC_DATA \
+                                                 |  (n)))
+
 /* Already declared in ossl_typ.h */
 #if 0
 typedef struct bignum_st BIGNUM;
@@ -439,6 +450,8 @@
 	const BIGNUM *m,BN_CTX *ctx);
 int	BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
 	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont);
 int	BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
 	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
 int	BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
@@ -728,9 +741,9 @@
 /* Error codes for the BN functions. */
 
 /* Function codes. */
-#define BN_F_BNRAND					 114
+#define BN_F_BNRAND					 127
 #define BN_F_BN_BLINDING_CONVERT_EX			 100
-#define BN_F_BN_BLINDING_CREATE_PARAM			 133
+#define BN_F_BN_BLINDING_CREATE_PARAM			 128
 #define BN_F_BN_BLINDING_INVERT_EX			 101
 #define BN_F_BN_BLINDING_NEW				 102
 #define BN_F_BN_BLINDING_UPDATE				 103
@@ -738,28 +751,32 @@
 #define BN_F_BN_BN2HEX					 105
 #define BN_F_BN_CTX_GET					 116
 #define BN_F_BN_CTX_NEW					 106
-#define BN_F_BN_CTX_START				 130
+#define BN_F_BN_CTX_START				 129
 #define BN_F_BN_DIV					 107
-#define BN_F_BN_DIV_RECP				 131
+#define BN_F_BN_DIV_RECP				 130
+#define BN_F_BN_EXP					 123
 #define BN_F_BN_EXPAND2					 108
 #define BN_F_BN_EXPAND_INTERNAL				 120
-#define BN_F_BN_GF2M_MOD				 126
-#define BN_F_BN_GF2M_MOD_DIV				 123
-#define BN_F_BN_GF2M_MOD_EXP				 127
-#define BN_F_BN_GF2M_MOD_MUL				 124
-#define BN_F_BN_GF2M_MOD_SOLVE_QUAD			 128
-#define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR			 129
-#define BN_F_BN_GF2M_MOD_SQR				 125
-#define BN_F_BN_GF2M_MOD_SQRT				 132
+#define BN_F_BN_GF2M_MOD				 131
+#define BN_F_BN_GF2M_MOD_EXP				 132
+#define BN_F_BN_GF2M_MOD_MUL				 133
+#define BN_F_BN_GF2M_MOD_SOLVE_QUAD			 134
+#define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR			 135
+#define BN_F_BN_GF2M_MOD_SQR				 136
+#define BN_F_BN_GF2M_MOD_SQRT				 137
 #define BN_F_BN_MOD_EXP2_MONT				 118
 #define BN_F_BN_MOD_EXP_MONT				 109
+#define BN_F_BN_MOD_EXP_MONT_CONSTTIME			 124
 #define BN_F_BN_MOD_EXP_MONT_WORD			 117
+#define BN_F_BN_MOD_EXP_RECP				 125
+#define BN_F_BN_MOD_EXP_SIMPLE				 126
 #define BN_F_BN_MOD_INVERSE				 110
 #define BN_F_BN_MOD_LSHIFT_QUICK			 119
 #define BN_F_BN_MOD_MUL_RECIPROCAL			 111
 #define BN_F_BN_MOD_SQRT				 121
 #define BN_F_BN_MPI2BN					 112
 #define BN_F_BN_NEW					 113
+#define BN_F_BN_RAND					 114
 #define BN_F_BN_RAND_RANGE				 122
 #define BN_F_BN_USUB					 115
 
@@ -775,10 +792,9 @@
 #define BN_R_INVALID_LENGTH				 106
 #define BN_R_INVALID_RANGE				 115
 #define BN_R_NOT_A_SQUARE				 111
-#define BN_R_NOT_IMPLEMENTED				 116
 #define BN_R_NOT_INITIALIZED				 107
 #define BN_R_NO_INVERSE					 108
-#define BN_R_NO_SOLUTION				 117
+#define BN_R_NO_SOLUTION				 116
 #define BN_R_P_IS_NOT_PRIME				 112
 #define BN_R_TOO_MANY_ITERATIONS			 113
 #define BN_R_TOO_MANY_TEMPORARY_VARIABLES		 109
diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c
index 58a7d06..a253959 100644
--- a/crypto/bn/bn_err.c
+++ b/crypto/bn/bn_err.c
@@ -83,10 +83,10 @@
 {ERR_FUNC(BN_F_BN_CTX_START),	"BN_CTX_start"},
 {ERR_FUNC(BN_F_BN_DIV),	"BN_div"},
 {ERR_FUNC(BN_F_BN_DIV_RECP),	"BN_div_recp"},
+{ERR_FUNC(BN_F_BN_EXP),	"BN_exp"},
 {ERR_FUNC(BN_F_BN_EXPAND2),	"bn_expand2"},
 {ERR_FUNC(BN_F_BN_EXPAND_INTERNAL),	"BN_EXPAND_INTERNAL"},
 {ERR_FUNC(BN_F_BN_GF2M_MOD),	"BN_GF2m_mod"},
-{ERR_FUNC(BN_F_BN_GF2M_MOD_DIV),	"BN_GF2m_mod_div"},
 {ERR_FUNC(BN_F_BN_GF2M_MOD_EXP),	"BN_GF2m_mod_exp"},
 {ERR_FUNC(BN_F_BN_GF2M_MOD_MUL),	"BN_GF2m_mod_mul"},
 {ERR_FUNC(BN_F_BN_GF2M_MOD_SOLVE_QUAD),	"BN_GF2m_mod_solve_quad"},
@@ -95,13 +95,17 @@
 {ERR_FUNC(BN_F_BN_GF2M_MOD_SQRT),	"BN_GF2m_mod_sqrt"},
 {ERR_FUNC(BN_F_BN_MOD_EXP2_MONT),	"BN_mod_exp2_mont"},
 {ERR_FUNC(BN_F_BN_MOD_EXP_MONT),	"BN_mod_exp_mont"},
+{ERR_FUNC(BN_F_BN_MOD_EXP_MONT_CONSTTIME),	"BN_mod_exp_mont_consttime"},
 {ERR_FUNC(BN_F_BN_MOD_EXP_MONT_WORD),	"BN_mod_exp_mont_word"},
+{ERR_FUNC(BN_F_BN_MOD_EXP_RECP),	"BN_mod_exp_recp"},
+{ERR_FUNC(BN_F_BN_MOD_EXP_SIMPLE),	"BN_mod_exp_simple"},
 {ERR_FUNC(BN_F_BN_MOD_INVERSE),	"BN_mod_inverse"},
 {ERR_FUNC(BN_F_BN_MOD_LSHIFT_QUICK),	"BN_mod_lshift_quick"},
 {ERR_FUNC(BN_F_BN_MOD_MUL_RECIPROCAL),	"BN_mod_mul_reciprocal"},
 {ERR_FUNC(BN_F_BN_MOD_SQRT),	"BN_mod_sqrt"},
 {ERR_FUNC(BN_F_BN_MPI2BN),	"BN_mpi2bn"},
 {ERR_FUNC(BN_F_BN_NEW),	"BN_new"},
+{ERR_FUNC(BN_F_BN_RAND),	"BN_rand"},
 {ERR_FUNC(BN_F_BN_RAND_RANGE),	"BN_rand_range"},
 {ERR_FUNC(BN_F_BN_USUB),	"BN_usub"},
 {0,NULL}
@@ -120,7 +124,6 @@
 {ERR_REASON(BN_R_INVALID_LENGTH)         ,"invalid length"},
 {ERR_REASON(BN_R_INVALID_RANGE)          ,"invalid range"},
 {ERR_REASON(BN_R_NOT_A_SQUARE)           ,"not a square"},
-{ERR_REASON(BN_R_NOT_IMPLEMENTED)        ,"not implemented"},
 {ERR_REASON(BN_R_NOT_INITIALIZED)        ,"not initialized"},
 {ERR_REASON(BN_R_NO_INVERSE)             ,"no inverse"},
 {ERR_REASON(BN_R_NO_SOLUTION)            ,"no solution"},
diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c
index d6bb2b4..8f8c694 100644
--- a/crypto/bn/bn_exp.c
+++ b/crypto/bn/bn_exp.c
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -113,6 +113,7 @@
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
+/* maximum precomputation table size for *variable* sliding windows */
 #define TABLE_SIZE	32
 
 /* this one works - simple but works */
@@ -121,6 +122,13 @@
 	int i,bits,ret=0;
 	BIGNUM *v,*rr;
 
+	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
+		{
+		/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */
+		BNerr(BN_F_BN_EXP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return -1;
+		}
+
 	BN_CTX_start(ctx);
 	if ((r == a) || (r == p))
 		rr = BN_CTX_get(ctx);
@@ -205,7 +213,7 @@
 	if (BN_is_odd(m))
 		{
 #  ifdef MONT_EXP_WORD
-		if (a->top == 1 && !a->neg)
+		if (a->top == 1 && !a->neg && (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) == 0))
 			{
 			BN_ULONG A = a->d[0];
 			ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL);
@@ -237,6 +245,13 @@
 	BIGNUM *val[TABLE_SIZE];
 	BN_RECP_CTX recp;
 
+	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
+		{
+		/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */
+		BNerr(BN_F_BN_MOD_EXP_RECP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return -1;
+		}
+
 	bits=BN_num_bits(p);
 
 	if (bits == 0)
@@ -364,6 +379,11 @@
 	BIGNUM *val[TABLE_SIZE];
 	BN_MONT_CTX *mont=NULL;
 
+	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
+		{
+		return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
+		}
+
 	bn_check_top(a);
 	bn_check_top(p);
 	bn_check_top(m);
@@ -495,6 +515,212 @@
 	return(ret);
 	}
 
+
+/* BN_mod_exp_mont_consttime() stores the precomputed powers in a specific layout
+ * so that accessing any of these table values shows the same access pattern as far
+ * as cache lines are concerned.  The following functions are used to transfer a BIGNUM
+ * from/to that table. */
+
+static int MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width)
+	{
+	size_t i, j;
+
+	if (bn_wexpand(b, top) == NULL)
+		return 0;
+	while (b->top < top)
+		{
+		b->d[b->top++] = 0;
+		}
+	
+	for (i = 0, j=idx; i < top * sizeof b->d[0]; i++, j+=width)
+		{
+		buf[j] = ((unsigned char*)b->d)[i];
+		}
+
+	bn_correct_top(b);
+	return 1;
+	}
+
+static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width)
+	{
+	size_t i, j;
+
+	if (bn_wexpand(b, top) == NULL)
+		return 0;
+
+	for (i=0, j=idx; i < top * sizeof b->d[0]; i++, j+=width)
+		{
+		((unsigned char*)b->d)[i] = buf[j];
+		}
+
+	b->top = top;
+	bn_correct_top(b);
+	return 1;
+	}	
+
+/* Given a pointer value, compute the next address that is a cache line multiple. */
+#define MOD_EXP_CTIME_ALIGN(x_) \
+	((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((BN_ULONG)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK))))
+
+/* This variant of BN_mod_exp_mont() uses fixed windows and the special
+ * precomputation memory layout to limit data-dependency to a minimum
+ * to protect secret exponents (cf. the hyper-threading timing attacks
+ * pointed out by Colin Percival,
+ * http://www.daemonology.net/hyperthreading-considered-harmful/)
+ */
+int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+		    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
+	{
+	int i,bits,ret=0,idx,window,wvalue;
+	int top;
+ 	BIGNUM *r;
+	const BIGNUM *aa;
+	BN_MONT_CTX *mont=NULL;
+
+	int numPowers;
+	unsigned char *powerbufFree=NULL;
+	int powerbufLen = 0;
+	unsigned char *powerbuf=NULL;
+	BIGNUM *computeTemp=NULL, *am=NULL;
+
+	bn_check_top(a);
+	bn_check_top(p);
+	bn_check_top(m);
+
+	top = m->top;
+
+	if (!(m->d[0] & 1))
+		{
+		BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME,BN_R_CALLED_WITH_EVEN_MODULUS);
+		return(0);
+		}
+	bits=BN_num_bits(p);
+	if (bits == 0)
+		{
+		ret = BN_one(rr);
+		return ret;
+		}
+
+ 	/* Initialize BIGNUM context and allocate intermediate result */
+	BN_CTX_start(ctx);
+	r = BN_CTX_get(ctx);
+	if (r == NULL) goto err;
+
+	/* Allocate a montgomery context if it was not supplied by the caller.
+	 * If this is not done, things will break in the montgomery part.
+ 	 */
+	if (in_mont != NULL)
+		mont=in_mont;
+	else
+		{
+		if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
+		if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
+		}
+
+	/* Get the window size to use with size of p. */
+	window = BN_window_bits_for_ctime_exponent_size(bits);
+
+	/* Allocate a buffer large enough to hold all of the pre-computed
+	 * powers of a.
+	 */
+	numPowers = 1 << window;
+	powerbufLen = sizeof(m->d[0])*top*numPowers;
+	if ((powerbufFree=(unsigned char*)OPENSSL_malloc(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL)
+		goto err;
+		
+	powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
+	memset(powerbuf, 0, powerbufLen);
+
+ 	/* Initialize the intermediate result. Do this early to save double conversion,
+	 * once each for a^0 and intermediate result.
+	 */
+ 	if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
+	if (!MOD_EXP_CTIME_COPY_TO_PREBUF(r, top, powerbuf, 0, numPowers)) goto err;
+
+	/* Initialize computeTemp as a^1 with montgomery precalcs */
+	computeTemp = BN_CTX_get(ctx);
+	am = BN_CTX_get(ctx);
+	if (computeTemp==NULL || am==NULL) goto err;
+
+	if (a->neg || BN_ucmp(a,m) >= 0)
+		{
+		if (!BN_mod(am,a,m,ctx))
+			goto err;
+		aa= am;
+		}
+	else
+		aa=a;
+	if (!BN_to_montgomery(am,aa,mont,ctx)) goto err;
+	if (!BN_copy(computeTemp, am)) goto err;
+	if (!MOD_EXP_CTIME_COPY_TO_PREBUF(am, top, powerbuf, 1, numPowers)) goto err;
+
+	/* If the window size is greater than 1, then calculate
+	 * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1)
+	 * (even powers could instead be computed as (a^(i/2))^2
+	 * to use the slight performance advantage of sqr over mul).
+	 */
+	if (window > 1)
+		{
+		for (i=2; i<numPowers; i++)
+			{
+			/* Calculate a^i = a^(i-1) * a */
+			if (!BN_mod_mul_montgomery(computeTemp,am,computeTemp,mont,ctx))
+				goto err;
+			if (!MOD_EXP_CTIME_COPY_TO_PREBUF(computeTemp, top, powerbuf, i, numPowers)) goto err;
+			}
+		}
+
+ 	/* Adjust the number of bits up to a multiple of the window size.
+ 	 * If the exponent length is not a multiple of the window size, then
+ 	 * this pads the most significant bits with zeros to normalize the
+ 	 * scanning loop to there's no special cases.
+ 	 *
+ 	 * * NOTE: Making the window size a power of two less than the native
+	 * * word size ensures that the padded bits won't go past the last
+ 	 * * word in the internal BIGNUM structure. Going past the end will
+ 	 * * still produce the correct result, but causes a different branch
+ 	 * * to be taken in the BN_is_bit_set function.
+ 	 */
+ 	bits = ((bits+window-1)/window)*window;
+ 	idx=bits-1;	/* The top bit of the window */
+
+ 	/* Scan the exponent one window at a time starting from the most
+ 	 * significant bits.
+ 	 */
+ 	while (idx >= 0)
+  		{
+ 		wvalue=0; /* The 'value' of the window */
+ 		
+ 		/* Scan the window, squaring the result as we go */
+ 		for (i=0; i<window; i++,idx--)
+ 			{
+			if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))	goto err;
+			wvalue = (wvalue<<1)+BN_is_bit_set(p,idx);
+  			}
+ 		
+		/* Fetch the appropriate pre-computed value from the pre-buf */
+		if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(computeTemp, top, powerbuf, wvalue, numPowers)) goto err;
+
+ 		/* Multiply the result into the intermediate result */
+ 		if (!BN_mod_mul_montgomery(r,r,computeTemp,mont,ctx)) goto err;
+  		}
+
+ 	/* Convert the final result from montgomery to standard format */
+	if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
+	ret=1;
+err:
+	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
+	if (powerbuf!=NULL)
+		{
+		OPENSSL_cleanse(powerbuf,powerbufLen);
+		OPENSSL_free(powerbufFree);
+		}
+ 	if (am!=NULL) BN_clear(am);
+ 	if (computeTemp!=NULL) BN_clear(computeTemp);
+	BN_CTX_end(ctx);
+	return(ret);
+	}
+
 int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
                          const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
 	{
@@ -519,6 +745,13 @@
 #define BN_TO_MONTGOMERY_WORD(r, w, mont) \
 		(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
 
+	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
+		{
+		/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */
+		BNerr(BN_F_BN_MOD_EXP_MONT_WORD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return -1;
+		}
+
 	bn_check_top(p);
 	bn_check_top(m);
 
@@ -648,6 +881,13 @@
 	/* Table of variables obtained from 'ctx' */
 	BIGNUM *val[TABLE_SIZE];
 
+	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
+		{
+		/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */
+		BNerr(BN_F_BN_MOD_EXP_SIMPLE,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return -1;
+		}
+
 	bits=BN_num_bits(p);
 
 	if (bits == 0)
diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h
index 45e1922..1c680fc 100644
--- a/crypto/bn/bn_lcl.h
+++ b/crypto/bn/bn_lcl.h
@@ -163,6 +163,45 @@
 
 
 
+/* BN_mod_exp_mont_conttime is based on the assumption that the
+ * L1 data cache line width of the target processor is at least
+ * the following value.
+ */
+#define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH	( 64 )
+#define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK	(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1)
+
+/* Window sizes optimized for fixed window size modular exponentiation
+ * algorithm (BN_mod_exp_mont_consttime).
+ *
+ * To achieve the security goals of BN_mode_exp_mont_consttime, the
+ * maximum size of the window must not exceed
+ * log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH). 
+ *
+ * Window size thresholds are defined for cache line sizes of 32 and 64,
+ * cache line sizes where log_2(32)=5 and log_2(64)=6 respectively. A
+ * window size of 7 should only be used on processors that have a 128
+ * byte or greater cache line size.
+ */
+#if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64
+
+#  define BN_window_bits_for_ctime_exponent_size(b) \
+		((b) > 937 ? 6 : \
+		 (b) > 306 ? 5 : \
+		 (b) >  89 ? 4 : \
+		 (b) >  22 ? 3 : 1)
+#  define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE	(6)
+
+#elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32
+
+#  define BN_window_bits_for_ctime_exponent_size(b) \
+		((b) > 306 ? 5 : \
+		 (b) >  89 ? 4 : \
+		 (b) >  22 ? 3 : 1)
+#  define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE	(5)
+
+#endif
+
+
 /* Pentium pro 16,16,16,32,64 */
 /* Alpha       16,16,16,16.64 */
 #define BN_MULL_SIZE_NORMAL			(16) /* 32 */
diff --git a/crypto/bn/bntest.c b/crypto/bn/bntest.c
index 9169cc8..c885300 100644
--- a/crypto/bn/bntest.c
+++ b/crypto/bn/bntest.c
@@ -106,6 +106,7 @@
 int test_mod(BIO *bp,BN_CTX *ctx);
 int test_mod_mul(BIO *bp,BN_CTX *ctx);
 int test_mod_exp(BIO *bp,BN_CTX *ctx);
+int test_mod_exp_mont_consttime(BIO *bp,BN_CTX *ctx);
 int test_exp(BIO *bp,BN_CTX *ctx);
 int test_gf2m_add(BIO *bp);
 int test_gf2m_mod(BIO *bp);
@@ -246,6 +247,10 @@
 	if (!test_mod_exp(out,ctx)) goto err;
 	BIO_flush(out);
 
+	message(out,"BN_mod_exp_mont_consttime");
+	if (!test_mod_exp_mont_consttime(out,ctx)) goto err;
+	BIO_flush(out);
+
 	message(out,"BN_exp");
 	if (!test_exp(out,ctx)) goto err;
 	BIO_flush(out);
@@ -954,6 +959,57 @@
 	return(1);
 	}
 
+int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx)
+	{
+	BIGNUM *a,*b,*c,*d,*e;
+	int i;
+
+	a=BN_new();
+	b=BN_new();
+	c=BN_new();
+	d=BN_new();
+	e=BN_new();
+
+	BN_bntest_rand(c,30,0,1); /* must be odd for montgomery */
+	for (i=0; i<num2; i++)
+		{
+		BN_bntest_rand(a,20+i*5,0,0); /**/
+		BN_bntest_rand(b,2+i,0,0); /**/
+
+		if (!BN_mod_exp_mont_consttime(d,a,b,c,ctx,NULL))
+			return(00);
+
+		if (bp != NULL)
+			{
+			if (!results)
+				{
+				BN_print(bp,a);
+				BIO_puts(bp," ^ ");
+				BN_print(bp,b);
+				BIO_puts(bp," % ");
+				BN_print(bp,c);
+				BIO_puts(bp," - ");
+				}
+			BN_print(bp,d);
+			BIO_puts(bp,"\n");
+			}
+		BN_exp(e,a,b,ctx);
+		BN_sub(e,e,d);
+		BN_div(a,b,e,c,ctx);
+		if(!BN_is_zero(b))
+		    {
+		    fprintf(stderr,"Modulo exponentiation test failed!\n");
+		    return 0;
+		    }
+		}
+	BN_free(a);
+	BN_free(b);
+	BN_free(c);
+	BN_free(d);
+	BN_free(e);
+	return(1);
+	}
+
 int test_exp(BIO *bp, BN_CTX *ctx)
 	{
 	BIGNUM *a,*b,*d,*e,*one;
diff --git a/crypto/bn/expspeed.c b/crypto/bn/expspeed.c
index 07a1bcf..4d5f221 100644
--- a/crypto/bn/expspeed.c
+++ b/crypto/bn/expspeed.c
@@ -321,7 +321,7 @@
 #else /* TEST_SQRT */
 			"2*sqrt [prime == %d (mod 64)] %4d %4d mod %4d"
 #endif
-			" -> %8.3fms %5.1f (%ld)\n",
+			" -> %8.6fms %5.1f (%ld)\n",
 #ifdef TEST_SQRT
 			P_MOD_64,
 #endif
diff --git a/crypto/bn/exptest.c b/crypto/bn/exptest.c
index 37aec55..f598a07 100644
--- a/crypto/bn/exptest.c
+++ b/crypto/bn/exptest.c
@@ -77,7 +77,7 @@
 	BIO *out=NULL;
 	int i,ret;
 	unsigned char c;
-	BIGNUM *r_mont,*r_recp,*r_simple,*a,*b,*m;
+	BIGNUM *r_mont,*r_mont_const,*r_recp,*r_simple,*a,*b,*m;
 
 	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we don't
 	                                       * even check its return value
@@ -88,6 +88,7 @@
 	ctx=BN_CTX_new();
 	if (ctx == NULL) EXIT(1);
 	r_mont=BN_new();
+	r_mont_const=BN_new();
 	r_recp=BN_new();
 	r_simple=BN_new();
 	a=BN_new();
@@ -143,8 +144,17 @@
 			EXIT(1);
 			}
 
+		ret=BN_mod_exp_mont_consttime(r_mont_const,a,b,m,ctx,NULL);
+		if (ret <= 0)
+			{
+			printf("BN_mod_exp_mont_consttime() problems\n");
+			ERR_print_errors(out);
+			EXIT(1);
+			}
+
 		if (BN_cmp(r_simple, r_mont) == 0
-		    && BN_cmp(r_simple,r_recp) == 0)
+		    && BN_cmp(r_simple,r_recp) == 0
+			&& BN_cmp(r_simple,r_mont_const) == 0)
 			{
 			printf(".");
 			fflush(stdout);
@@ -153,6 +163,8 @@
 		  	{
 			if (BN_cmp(r_simple,r_mont) != 0)
 				printf("\nsimple and mont results differ\n");
+			if (BN_cmp(r_simple,r_mont) != 0)
+				printf("\nsimple and mont const time results differ\n");
 			if (BN_cmp(r_simple,r_recp) != 0)
 				printf("\nsimple and recp results differ\n");
 
@@ -162,11 +174,13 @@
 			printf("\nsimple   =");	BN_print(out,r_simple);
 			printf("\nrecp     =");	BN_print(out,r_recp);
 			printf("\nmont     ="); BN_print(out,r_mont);
+			printf("\nmont_ct  ="); BN_print(out,r_mont_const);
 			printf("\n");
 			EXIT(1);
 			}
 		}
 	BN_free(r_mont);
+	BN_free(r_mont_const);
 	BN_free(r_recp);
 	BN_free(r_simple);
 	BN_free(a);
diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h
index da44778..d1559fd 100644
--- a/crypto/dh/dh.h
+++ b/crypto/dh/dh.h
@@ -73,7 +73,14 @@
 #include <openssl/bn.h>
 #endif
 	
-#define DH_FLAG_CACHE_MONT_P	0x01
+#define DH_FLAG_CACHE_MONT_P     0x01
+#define DH_FLAG_NO_EXP_CONSTTIME 0x02 /* new with 0.9.7h; the built-in DH
+                                       * implementation now uses constant time
+                                       * modular exponentiation for secret exponents
+                                       * by default. This flag causes the
+                                       * faster variable sliding window method to
+                                       * be used for all exponents.
+                                       */
 
 #ifdef  __cplusplus
 extern "C" {
diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c
index 9148f17..e384286 100644
--- a/crypto/dh/dh_key.c
+++ b/crypto/dh/dh_key.c
@@ -141,8 +141,21 @@
 		l = dh->length ? dh->length : BN_num_bits(dh->p)-1; /* secret exponent length */
 		if (!BN_rand(priv_key, l, 0, 0)) goto err;
 		}
-	if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, priv_key,dh->p,ctx,mont))
-		goto err;
+
+	{
+		BIGNUM local_prk;
+		BIGNUM *prk;
+
+		if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0)
+			{
+			prk = &local_prk;
+			BN_with_flags(prk, priv_key, BN_FLG_EXP_CONSTTIME);
+			}
+		else
+			prk = priv_key;
+
+		if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) goto err;
+	}
 		
 	dh->pub_key=pub_key;
 	dh->priv_key=priv_key;
@@ -179,6 +192,11 @@
 		{
 		mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
 				CRYPTO_LOCK_DH, dh->p, ctx);
+		if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0)
+			{
+			/* XXX */
+			BN_set_flags(dh->priv_key, BN_FLG_EXP_CONSTTIME);
+			}
 		if (!mont)
 			goto err;
 		}
@@ -201,7 +219,10 @@
 			const BIGNUM *m, BN_CTX *ctx,
 			BN_MONT_CTX *m_ctx)
 	{
-	if (a->top == 1)
+	/* If a is only one word long and constant time is false, use the faster
+	 * exponenentiation function.
+	 */
+	if (a->top == 1 && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0))
 		{
 		BN_ULONG A = a->d[0];
 		return BN_mod_exp_mont_word(r,A,p,m,ctx,m_ctx);
diff --git a/crypto/dh/dhtest.c b/crypto/dh/dhtest.c
index 1b19364..882f5c3 100644
--- a/crypto/dh/dhtest.c
+++ b/crypto/dh/dhtest.c
@@ -145,6 +145,10 @@
 	b->g=BN_dup(a->g);
 	if ((b->p == NULL) || (b->g == NULL)) goto err;
 
+	/* Set a to run with normal modexp and b to use constant time */
+	a->flags &= ~DH_FLAG_NO_EXP_CONSTTIME;
+	b->flags |= DH_FLAG_NO_EXP_CONSTTIME;
+
 	if (!DH_generate_key(a)) goto err;
 	BIO_puts(out,"pri 1=");
 	BN_print(out,a->priv_key);
diff --git a/crypto/dsa/dsa.h b/crypto/dsa/dsa.h
index c7ba059..b12db98 100644
--- a/crypto/dsa/dsa.h
+++ b/crypto/dsa/dsa.h
@@ -85,6 +85,13 @@
 #endif
 
 #define DSA_FLAG_CACHE_MONT_P	0x01
+#define DSA_FLAG_NO_EXP_CONSTTIME       0x02 /* new with 0.9.7h; the built-in DSA
+                                              * implementation now uses constant time
+                                              * modular exponentiation for secret exponents
+                                              * by default. This flag causes the
+                                              * faster variable sliding window method to
+                                              * be used for all exponents.
+                                              */
 
 #ifdef  __cplusplus
 extern "C" {
diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c
index 8427b77..5ba885e 100644
--- a/crypto/dsa/dsa_key.c
+++ b/crypto/dsa/dsa_key.c
@@ -98,8 +98,21 @@
 		}
 	else
 		pub_key=dsa->pub_key;
+	
+	{
+		BIGNUM local_prk;
+		BIGNUM *prk;
 
-	if (!BN_mod_exp(pub_key,dsa->g,priv_key,dsa->p,ctx)) goto err;
+		if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0)
+			{
+			prk = &local_prk;
+			BN_with_flags(prk, priv_key, BN_FLG_EXP_CONSTTIME);
+			}
+		else
+			prk = priv_key;
+
+		if (!BN_mod_exp(pub_key,dsa->g,prk,dsa->p,ctx)) goto err;
+	}
 
 	dsa->priv_key=priv_key;
 	dsa->pub_key=pub_key;
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index 25cd848..2e5ede7 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -227,6 +227,10 @@
 	do
 		if (!BN_rand_range(&k, dsa->q)) goto err;
 	while (BN_is_zero(&k));
+	if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0)
+		{
+		BN_set_flags(&k, BN_FLG_EXP_CONSTTIME);
+		}
 
 	if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
 		{
diff --git a/crypto/dsa/dsatest.c b/crypto/dsa/dsatest.c
index ccc456e..66ff417 100644
--- a/crypto/dsa/dsatest.c
+++ b/crypto/dsa/dsatest.c
@@ -204,10 +204,19 @@
 		BIO_printf(bio_err,"g value is wrong\n");
 		goto end;
 		}
+
+	dsa->flags |= DSA_FLAG_NO_EXP_CONSTTIME;
 	DSA_generate_key(dsa);
 	DSA_sign(0, str1, 20, sig, &siglen, dsa);
 	if (DSA_verify(0, str1, 20, sig, siglen, dsa) == 1)
 		ret=1;
+
+	dsa->flags &= ~DSA_FLAG_NO_EXP_CONSTTIME;
+	DSA_generate_key(dsa);
+	DSA_sign(0, str1, 20, sig, &siglen, dsa);
+	if (DSA_verify(0, str1, 20, sig, siglen, dsa) == 1)
+		ret=1;
+
 end:
 	if (!ret)
 		ERR_print_errors(bio_err);
diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h
index f8bcbc3..dcefeba 100644
--- a/crypto/rsa/rsa.h
+++ b/crypto/rsa/rsa.h
@@ -162,28 +162,35 @@
 #define RSA_3	0x3L
 #define RSA_F4	0x10001L
 
-#define RSA_METHOD_FLAG_NO_CHECK	0x01 /* don't check pub/private match */
+#define RSA_METHOD_FLAG_NO_CHECK	0x0001 /* don't check pub/private match */
 
-#define RSA_FLAG_CACHE_PUBLIC		0x02
-#define RSA_FLAG_CACHE_PRIVATE		0x04
-#define RSA_FLAG_BLINDING		0x08
-#define RSA_FLAG_THREAD_SAFE		0x10
+#define RSA_FLAG_CACHE_PUBLIC		0x0002
+#define RSA_FLAG_CACHE_PRIVATE		0x0004
+#define RSA_FLAG_BLINDING		0x0008
+#define RSA_FLAG_THREAD_SAFE		0x0010
 /* This flag means the private key operations will be handled by rsa_mod_exp
  * and that they do not depend on the private key components being present:
  * for example a key stored in external hardware. Without this flag bn_mod_exp
  * gets called when private key components are absent.
  */
-#define RSA_FLAG_EXT_PKEY		0x20
+#define RSA_FLAG_EXT_PKEY		0x0020
 
 /* This flag in the RSA_METHOD enables the new rsa_sign, rsa_verify functions.
  */
-#define RSA_FLAG_SIGN_VER		0x40
+#define RSA_FLAG_SIGN_VER		0x0040
 
-#define RSA_FLAG_NO_BLINDING		0x80 /* new with 0.9.6j and 0.9.7b; the built-in
-                                              * RSA implementation now uses blinding by
-                                              * default (ignoring RSA_FLAG_BLINDING),
-                                              * but other engines might not need it
-                                              */
+#define RSA_FLAG_NO_BLINDING		0x0080 /* new with 0.9.6j and 0.9.7b; the built-in
+                                                * RSA implementation now uses blinding by
+                                                * default (ignoring RSA_FLAG_BLINDING),
+                                                * but other engines might not need it
+                                                */
+#define RSA_FLAG_NO_EXP_CONSTTIME	0x0100 /* new with 0.9.7h; the built-in RSA
+                                                * implementation now uses constant time
+                                                * modular exponentiation for secret exponents
+                                                * by default. This flag causes the
+                                                * faster variable sliding window method to
+                                                * be used for all exponents.
+                                                */
 
 #define RSA_PKCS1_PADDING	1
 #define RSA_SSLV23_PADDING	2
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c
index 21755c0..175ab8a 100644
--- a/crypto/rsa/rsa_eay.c
+++ b/crypto/rsa/rsa_eay.c
@@ -55,6 +55,59 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
+/* ====================================================================
+ * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
 
 #include <stdio.h>
 #include "cryptlib.h"
@@ -320,11 +373,25 @@
 		(rsa->dmp1 != NULL) &&
 		(rsa->dmq1 != NULL) &&
 		(rsa->iqmp != NULL)) )
-		{ if (!rsa->meth->rsa_mod_exp(ret,f,rsa,ctx)) goto err; }
+		{ 
+		if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx)) goto err;
+		}
 	else
 		{
+		BIGNUM local_d;
+		BIGNUM *d = NULL;
+		
+		if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+			{
+			d = &local_d;
+			BN_with_flags(d, rsa->d, BN_FLG_EXP_CONSTTIME);
+			}
+		else
+			d = rsa->d;
+
 		MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
-		if (!rsa->meth->bn_mod_exp(ret,f,rsa->d,rsa->n,ctx,
+
+		if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx,
 				rsa->_method_mod_n)) goto err;
 		}
 
@@ -416,13 +483,26 @@
 		(rsa->dmp1 != NULL) &&
 		(rsa->dmq1 != NULL) &&
 		(rsa->iqmp != NULL)) )
-		{ if (!rsa->meth->rsa_mod_exp(ret,f,rsa,ctx)) goto err; }
+		{
+		if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx)) goto err;
+		}
 	else
 		{
+		BIGNUM local_d;
+		BIGNUM *d = NULL;
+		
+		if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+			{
+			d = &local_d;
+			BN_with_flags(d, rsa->d, BN_FLG_EXP_CONSTTIME);
+			}
+		else
+			d = rsa->d;
+
 		MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
-		if (!rsa->meth->bn_mod_exp(ret,f,rsa->d,rsa->n,ctx,
+		if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx,
 				rsa->_method_mod_n))
-			goto err;
+		  goto err;
 		}
 
 	if (blinding)
@@ -547,6 +627,8 @@
 static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
 	{
 	BIGNUM *r1,*m1,*vrfy;
+	BIGNUM local_dmp1, local_dmq1;
+	BIGNUM *dmp1, *dmq1;
 	int ret=0;
 
 	BN_CTX_start(ctx);
@@ -559,11 +641,25 @@
 	MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
 
 	if (!BN_mod(r1,I,rsa->q,ctx)) goto err;
-	if (!rsa->meth->bn_mod_exp(m1,r1,rsa->dmq1,rsa->q,ctx,
+	if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+		{
+		dmq1 = &local_dmq1;
+		BN_with_flags(dmq1, rsa->dmq1, BN_FLG_EXP_CONSTTIME);
+		}
+	else
+		dmq1 = rsa->dmq1;
+	if (!rsa->meth->bn_mod_exp(m1,r1,dmq1,rsa->q,ctx,
 		rsa->_method_mod_q)) goto err;
 
 	if (!BN_mod(r1,I,rsa->p,ctx)) goto err;
-	if (!rsa->meth->bn_mod_exp(r0,r1,rsa->dmp1,rsa->p,ctx,
+	if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+		{
+		dmp1 = &local_dmp1;
+		BN_with_flags(dmp1, rsa->dmp1, BN_FLG_EXP_CONSTTIME);
+		}
+	else
+		dmp1 = rsa->dmp1;
+	if (!rsa->meth->bn_mod_exp(r0,r1,dmp1,rsa->p,ctx,
 		rsa->_method_mod_p)) goto err;
 
 	if (!BN_sub(r0,r0,m1)) goto err;
@@ -598,11 +694,24 @@
 		if (BN_is_negative(vrfy))
 			if (!BN_add(vrfy, vrfy, rsa->n)) goto err;
 		if (!BN_is_zero(vrfy))
+			{
 			/* 'I' and 'vrfy' aren't congruent mod n. Don't leak
 			 * miscalculated CRT output, just do a raw (slower)
 			 * mod_exp and return that instead. */
-			if (!rsa->meth->bn_mod_exp(r0,I,rsa->d,rsa->n,ctx,
-					rsa->_method_mod_n)) goto err;
+
+			BIGNUM local_d;
+			BIGNUM *d = NULL;
+		
+			if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+				{
+				d = &local_d;
+				BN_with_flags(d, rsa->d, BN_FLG_EXP_CONSTTIME);
+				}
+			else
+				d = rsa->d;
+			if (!rsa->meth->bn_mod_exp(r0,I,d,rsa->n,ctx,
+						   rsa->_method_mod_n)) goto err;
+			}
 		}
 	ret=1;
 err:
diff --git a/crypto/rsa/rsa_test.c b/crypto/rsa/rsa_test.c
index 6f0a28a..0f8059c 100644
--- a/crypto/rsa/rsa_test.c
+++ b/crypto/rsa/rsa_test.c
@@ -228,10 +228,10 @@
 
     plen = sizeof(ptext_ex) - 1;
 
-    for (v = 0; v < 3; v++)
+    for (v = 0; v < 6; v++)
 	{
 	key = RSA_new();
-	switch (v) {
+	switch (v%3) {
     case 0:
 	clen = key1(key, ctext_ex);
 	break;
@@ -242,6 +242,7 @@
 	clen = key3(key, ctext_ex);
 	break;
 	}
+	if (v/3 > 1) key->flags |= RSA_FLAG_NO_EXP_CONSTTIME;
 
 	num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
 				 RSA_PKCS1_PADDING);