Blob Blame Raw
diff -up openssl-0.9.8b/crypto/rsa/rsa.h.no-branch openssl-0.9.8b/crypto/rsa/rsa.h
--- openssl-0.9.8b/crypto/rsa/rsa.h.no-branch	2007-08-03 13:58:54.000000000 +0200
+++ openssl-0.9.8b/crypto/rsa/rsa.h	2007-08-03 13:58:58.000000000 +0200
@@ -189,13 +189,17 @@ struct rsa_st
                                                 * 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_FLAG_NO_CONSTTIME		0x0100 /* new with 0.9.8f; the built-in RSA
+						* implementation now uses constant time
+						* operations by default in private key operations,
+						* e.g., constant time modular exponentiation, 
+                                                * modular inverse without leaking branches, 
+                                                * division without leaking branches. This 
+                                                * flag disables these constant time 
+                                                * operations and results in faster RSA 
+                                                * private key operations.
+                                                */ 
+#define RSA_FLAG_NO_EXP_CONSTTIME RSA_FLAG_NO_CONSTTIME /* deprecated name for the flag*/
 
 #define RSA_PKCS1_PADDING	1
 #define RSA_SSLV23_PADDING	2
diff -up openssl-0.9.8b/crypto/rsa/rsa_lib.c.no-branch openssl-0.9.8b/crypto/rsa/rsa_lib.c
--- openssl-0.9.8b/crypto/rsa/rsa_lib.c.no-branch	2005-11-25 15:26:12.000000000 +0100
+++ openssl-0.9.8b/crypto/rsa/rsa_lib.c	2007-08-03 13:58:58.000000000 +0200
@@ -361,7 +361,8 @@ err:
 
 BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
 {
-	BIGNUM *e;
+	BIGNUM local_n;
+	BIGNUM *e,*n;
 	BN_CTX *ctx;
 	BN_BLINDING *ret = NULL;
 
@@ -400,7 +401,16 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa
 		RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0);
 		}
 
-	ret = BN_BLINDING_create_param(NULL, e, rsa->n, ctx,
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		/* Set BN_FLG_CONSTTIME flag */
+		n = &local_n;
+		BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
+		}
+	else
+		n = rsa->n;
+
+	ret = BN_BLINDING_create_param(NULL, e, n, ctx,
 			rsa->meth->bn_mod_exp, rsa->_method_mod_n);
 	if (ret == NULL)
 		{
diff -up openssl-0.9.8b/crypto/rsa/rsa_gen.c.no-branch openssl-0.9.8b/crypto/rsa/rsa_gen.c
--- openssl-0.9.8b/crypto/rsa/rsa_gen.c.no-branch	2006-03-14 00:12:08.000000000 +0100
+++ openssl-0.9.8b/crypto/rsa/rsa_gen.c	2007-08-03 13:58:58.000000000 +0200
@@ -85,6 +85,8 @@ int RSA_generate_key_ex(RSA *rsa, int bi
 static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
 	{
 	BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp;
+	BIGNUM local_r0,local_d,local_p;
+	BIGNUM *pr0,*d,*p;
 	int bitsp,bitsq,ok= -1,n=0;
 	BN_CTX *ctx=NULL;
 
@@ -165,16 +167,39 @@ static int rsa_builtin_keygen(RSA *rsa, 
 	if (!BN_sub(r1,rsa->p,BN_value_one())) goto err;	/* p-1 */
 	if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;	/* q-1 */
 	if (!BN_mul(r0,r1,r2,ctx)) goto err;	/* (p-1)(q-1) */
-	if (!BN_mod_inverse(rsa->d,rsa->e,r0,ctx)) goto err;	/* d */
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		  pr0 = &local_r0;
+		  BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
+		}
+	else
+	  pr0 = r0;
+	if (!BN_mod_inverse(rsa->d,rsa->e,pr0,ctx)) goto err;	/* d */
+
+	/* set up d for correct BN_FLG_CONSTTIME flag */
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		d = &local_d;
+		BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
+		}
+	else
+		d = rsa->d;
 
 	/* calculate d mod (p-1) */
-	if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err;
+	if (!BN_mod(rsa->dmp1,d,r1,ctx)) goto err;
 
 	/* calculate d mod (q-1) */
-	if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err;
+	if (!BN_mod(rsa->dmq1,d,r2,ctx)) goto err;
 
 	/* calculate inverse of q mod p */
-	if (!BN_mod_inverse(rsa->iqmp,rsa->q,rsa->p,ctx)) goto err;
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		p = &local_p;
+		BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
+		}
+	else
+		p = rsa->p;
+	if (!BN_mod_inverse(rsa->iqmp,rsa->q,p,ctx)) goto err;
 
 	ok=1;
 err:
diff -up openssl-0.9.8b/crypto/rsa/rsa_eay.c.no-branch openssl-0.9.8b/crypto/rsa/rsa_eay.c
--- openssl-0.9.8b/crypto/rsa/rsa_eay.c.no-branch	2007-08-03 13:58:54.000000000 +0200
+++ openssl-0.9.8b/crypto/rsa/rsa_eay.c	2007-08-03 13:58:58.000000000 +0200
@@ -429,11 +429,11 @@ static int RSA_eay_private_encrypt(int f
 		BIGNUM local_d;
 		BIGNUM *d = NULL;
 		
-		if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+		if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
 			{
 			BN_init(&local_d);
 			d = &local_d;
-			BN_with_flags(d, rsa->d, BN_FLG_EXP_CONSTTIME);
+			BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
 			}
 		else
 			d = rsa->d;
@@ -551,10 +551,10 @@ static int RSA_eay_private_decrypt(int f
 		BIGNUM local_d;
 		BIGNUM *d = NULL;
 		
-		if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+		if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
 			{
 			d = &local_d;
-			BN_with_flags(d, rsa->d, BN_FLG_EXP_CONSTTIME);
+			BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
 			}
 		else
 			d = rsa->d;
@@ -724,8 +724,9 @@ err:
 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;
+	BIGNUM local_dmp1,local_dmq1,local_c,local_r1;
+	BIGNUM *dmp1,*dmq1,*c,*pr1;
+	int bn_flags;
 	int ret=0;
 
 	BN_CTX_start(ctx);
@@ -733,26 +734,72 @@ static int RSA_eay_mod_exp(BIGNUM *r0, c
 	m1 = BN_CTX_get(ctx);
 	vrfy = BN_CTX_get(ctx);
 
+	/* Make sure mod_inverse in montgomerey intialization use correct 
+	 * BN_FLG_CONSTTIME flag.
+	 */
+	bn_flags = rsa->p->flags;
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		rsa->p->flags |= BN_FLG_CONSTTIME;
+		}
 	MONT_HELPER(rsa, ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
+	/* We restore bn_flags back */
+	rsa->p->flags = bn_flags;
+
+        /* Make sure mod_inverse in montgomerey intialization use correct
+         * BN_FLG_CONSTTIME flag.
+         */
+	bn_flags = rsa->q->flags;
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		rsa->q->flags |= BN_FLG_CONSTTIME;
+		}
 	MONT_HELPER(rsa, ctx, q, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
+	/* We restore bn_flags back */
+	rsa->q->flags = bn_flags;	
+
 	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->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+	/* compute I mod q */
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		c = &local_c;
+		BN_with_flags(c, I, BN_FLG_CONSTTIME);
+		if (!BN_mod(r1,c,rsa->q,ctx)) goto err;
+		}
+	else
+		{
+		if (!BN_mod(r1,I,rsa->q,ctx)) goto err;
+		}
+
+	/* compute r1^dmq1 mod q */
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
 		{
 		dmq1 = &local_dmq1;
-		BN_with_flags(dmq1, rsa->dmq1, BN_FLG_EXP_CONSTTIME);
+		BN_with_flags(dmq1, rsa->dmq1, BN_FLG_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->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+	/* compute I mod p */
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		c = &local_c;
+		BN_with_flags(c, I, BN_FLG_CONSTTIME);
+		if (!BN_mod(r1,c,rsa->p,ctx)) goto err;
+		}
+	else
+		{
+		if (!BN_mod(r1,I,rsa->p,ctx)) goto err;
+		}
+
+	/* compute r1^dmp1 mod p */
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
 		{
 		dmp1 = &local_dmp1;
-		BN_with_flags(dmp1, rsa->dmp1, BN_FLG_EXP_CONSTTIME);
+		BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
 		}
 	else
 		dmp1 = rsa->dmp1;
@@ -766,7 +813,17 @@ static int RSA_eay_mod_exp(BIGNUM *r0, c
 		if (!BN_add(r0,r0,rsa->p)) goto err;
 
 	if (!BN_mul(r1,r0,rsa->iqmp,ctx)) goto err;
-	if (!BN_mod(r0,r1,rsa->p,ctx)) goto err;
+
+	/* Turn BN_FLG_CONSTTIME flag on before division operation */
+	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+		{
+		pr1 = &local_r1;
+		BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
+		}
+	else
+		pr1 = r1;
+	if (!BN_mod(r0,pr1,rsa->p,ctx)) goto err;
+
 	/* If p < q it is occasionally possible for the correction of
          * adding 'p' if r0 is negative above to leave the result still
 	 * negative. This can break the private key operations: the following
@@ -799,10 +856,10 @@ static int RSA_eay_mod_exp(BIGNUM *r0, c
 			BIGNUM local_d;
 			BIGNUM *d = NULL;
 		
-			if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME))
+			if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
 				{
 				d = &local_d;
-				BN_with_flags(d, rsa->d, BN_FLG_EXP_CONSTTIME);
+				BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
 				}
 			else
 				d = rsa->d;
diff -up openssl-0.9.8b/crypto/rsa/rsa_test.c.no-branch openssl-0.9.8b/crypto/rsa/rsa_test.c
--- openssl-0.9.8b/crypto/rsa/rsa_test.c.no-branch	2005-05-16 03:43:31.000000000 +0200
+++ openssl-0.9.8b/crypto/rsa/rsa_test.c	2007-08-03 13:58:58.000000000 +0200
@@ -242,7 +242,7 @@ int main(int argc, char *argv[])
 	clen = key3(key, ctext_ex);
 	break;
 	}
-	if (v/3 > 1) key->flags |= RSA_FLAG_NO_EXP_CONSTTIME;
+	if (v/3 >= 1) key->flags |= RSA_FLAG_NO_CONSTTIME;
 
 	num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
 				 RSA_PKCS1_PADDING);
diff -up openssl-0.9.8b/crypto/bn/bn.h.no-branch openssl-0.9.8b/crypto/bn/bn.h
--- openssl-0.9.8b/crypto/bn/bn.h.no-branch	2007-08-03 13:58:54.000000000 +0200
+++ openssl-0.9.8b/crypto/bn/bn.h	2007-08-03 13:58:58.000000000 +0200
@@ -245,8 +245,15 @@ extern "C" {
 
 #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) */
+#define BN_FLG_CONSTTIME	0x04 /* avoid leaking exponent information through timing,
+                                      * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime,
+                                      * BN_div() will call BN_div_no_branch,
+                                      * BN_mod_inverse() will call BN_mod_inverse_no_branch.
+                                      */
+#define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME /* deprecated name for the flag */
+                                      /* 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
@@ -534,7 +541,7 @@ BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_M
 #define	BN_BLINDING_NO_UPDATE	0x00000001
 #define	BN_BLINDING_NO_RECREATE	0x00000002
 
-BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod);
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, /* const */ BIGNUM *mod);
 void BN_BLINDING_free(BN_BLINDING *b);
 int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx);
 int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
@@ -546,7 +553,7 @@ void BN_BLINDING_set_thread_id(BN_BLINDI
 unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
 void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
 BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
-	const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
+	const BIGNUM *e, /* const */ BIGNUM *m, BN_CTX *ctx,
 	int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
 			  const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx),
 	BN_MONT_CTX *m_ctx);
diff -up openssl-0.9.8b/crypto/bn/bn_mont.c.no-branch openssl-0.9.8b/crypto/bn/bn_mont.c
--- openssl-0.9.8b/crypto/bn/bn_mont.c.no-branch	2007-08-03 13:58:54.000000000 +0200
+++ openssl-0.9.8b/crypto/bn/bn_mont.c	2007-08-03 13:58:58.000000000 +0200
@@ -159,6 +159,7 @@ int BN_from_montgomery(BIGNUM *ret, cons
 	BIGNUM *n,*r;
 	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
 	int al,nl,max,i,x,ri;
+	size_t m1,m2;
 
 	BN_CTX_start(ctx);
 	if ((r = BN_CTX_get(ctx)) == NULL) goto err;
@@ -176,7 +177,6 @@ int BN_from_montgomery(BIGNUM *ret, cons
 
 	max=(nl+al+1); /* allow for overflow (no?) XXX */
 	if (bn_wexpand(r,max) == NULL) goto err;
-	if (bn_wexpand(ret,max) == NULL) goto err;
 
 	r->neg=a->neg^n->neg;
 	np=n->d;
@@ -228,37 +228,56 @@ int BN_from_montgomery(BIGNUM *ret, cons
 		}
 	bn_correct_top(r);
 	
-	/* mont->ri will be a multiple of the word size */
-#if 0
-	BN_rshift(ret,r,mont->ri);
-#else
+	/* mont->ri will be a multiple of the word size and below code
+	 * is kind of BN_rshift(ret,r,mont->ri) equivalent */
+	if (r->top <= ri)
+		{
+		ret->top=0;
+		retn=1;
+		goto err;
+		}
+	al=r->top-ri;
+	if (bn_wexpand(ret,ri) == NULL) goto err;
+	x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
+	ret->top=x=(ri&~x)|(al&x);	/* min(ri,al) */
 	ret->neg = r->neg;
-	x=ri;
+
 	rp=ret->d;
-	ap= &(r->d[x]);
-	if (r->top < x)
-		al=0;
-	else
-		al=r->top-x;
-	ret->top=al;
-	al-=4;
-	for (i=0; i<al; i+=4)
+	ap=&(r->d[ri]);
+
+	v=bn_sub_words(rp,ap,np,ri);
+	/* this -----------------------^^ works even in al<ri case
+	 * thanks to zealous zeroing of top of the vector in the
+	 * beginning. */
+
+	/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
+	/* in other words if subtraction result is real, then
+	 * trick unconditional memcpy below to perform in-place
+	 * "refresh" instead of actual copy. */
+	m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);	/* al<ri */
+	m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);	/* al>ri */
+	m1|=m2;			/* (al!=ri) */
+	m1|=(0-(size_t)v);	/* (al!=ri || v) */
+	m1&=~m2;		/* (al!=ri || v) && !al>ri */
+	nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
+
+	/* 'i<ri' is chosen to eliminate dependency on input data, even
+	 * though it results in redundant copy in al<ri case. */
+	for (i=0,ri-=4; i<ri; i+=4)
 		{
 		BN_ULONG t1,t2,t3,t4;
 		
-		t1=ap[i+0];
-		t2=ap[i+1];
-		t3=ap[i+2];
-		t4=ap[i+3];
-		rp[i+0]=t1;
-		rp[i+1]=t2;
+		t1=nrp[i+0];
+		t2=nrp[i+1];
+		t3=nrp[i+2];	ap[i+0]=0;
+		t4=nrp[i+3];	ap[i+1]=0;
+		rp[i+0]=t1;	ap[i+2]=0;
+		rp[i+1]=t2;	ap[i+3]=0;
 		rp[i+2]=t3;
 		rp[i+3]=t4;
 		}
-	al+=4;
-	for (; i<al; i++)
-		rp[i]=ap[i];
-#endif
+	for (ri+=4; i<ri; i++)
+		rp[i]=nrp[i], ap[i]=0;
 #else /* !MONT_WORD */ 
 	BIGNUM *t1,*t2;
 
@@ -276,12 +295,12 @@ int BN_from_montgomery(BIGNUM *ret, cons
 	if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
 	if (!BN_add(t2,a,t1)) goto err;
 	if (!BN_rshift(ret,t2,mont->ri)) goto err;
-#endif /* MONT_WORD */
 
 	if (BN_ucmp(ret, &(mont->N)) >= 0)
 		{
 		if (!BN_usub(ret,ret,&(mont->N))) goto err;
 		}
+#endif /* MONT_WORD */
 	retn=1;
 	bn_check_top(ret);
  err:
diff -up openssl-0.9.8b/crypto/bn/bn_lib.c.no-branch openssl-0.9.8b/crypto/bn/bn_lib.c
--- openssl-0.9.8b/crypto/bn/bn_lib.c.no-branch	2005-05-03 22:27:00.000000000 +0200
+++ openssl-0.9.8b/crypto/bn/bn_lib.c	2007-08-03 13:58:58.000000000 +0200
@@ -763,7 +763,7 @@ int BN_is_bit_set(const BIGNUM *a, int n
 	i=n/BN_BITS2;
 	j=n%BN_BITS2;
 	if (a->top <= i) return 0;
-	return((a->d[i]&(((BN_ULONG)1)<<j))?1:0);
+	return(((a->d[i])>>j)&((BN_ULONG)1));
 	}
 
 int BN_mask_bits(BIGNUM *a, int n)
diff -up openssl-0.9.8b/crypto/bn/bn_blind.c.no-branch openssl-0.9.8b/crypto/bn/bn_blind.c
--- openssl-0.9.8b/crypto/bn/bn_blind.c.no-branch	2005-05-26 06:30:48.000000000 +0200
+++ openssl-0.9.8b/crypto/bn/bn_blind.c	2007-08-03 13:58:58.000000000 +0200
@@ -131,7 +131,7 @@ struct bn_blinding_st
 			  BN_MONT_CTX *m_ctx);
 	};
 
-BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, /* const */ BIGNUM *mod)
 	{
 	BN_BLINDING *ret=NULL;
 
@@ -151,7 +151,12 @@ BN_BLINDING *BN_BLINDING_new(const BIGNU
 		{
 		if ((ret->Ai = BN_dup(Ai)) == NULL) goto err;
 		}
-	ret->mod = mod;
+
+	/* save a copy of mod in the BN_BLINDING structure */
+	if ((ret->mod = BN_dup(mod)) == NULL) goto err;
+	if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
+		BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
+
 	ret->counter = BN_BLINDING_COUNTER;
 	return(ret);
 err:
@@ -167,6 +172,7 @@ void BN_BLINDING_free(BN_BLINDING *r)
 	if (r->A  != NULL) BN_free(r->A );
 	if (r->Ai != NULL) BN_free(r->Ai);
 	if (r->e  != NULL) BN_free(r->e );
+	if (r->mod != NULL) BN_free(r->mod); 
 	OPENSSL_free(r);
 	}
 
@@ -278,7 +284,7 @@ void BN_BLINDING_set_flags(BN_BLINDING *
 	}
 
 BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
-	const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
+	const BIGNUM *e, /* const */ BIGNUM *m, BN_CTX *ctx,
 	int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
 			  const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx),
 	BN_MONT_CTX *m_ctx)
diff -up openssl-0.9.8b/crypto/bn/bn_div.c.no-branch openssl-0.9.8b/crypto/bn/bn_div.c
--- openssl-0.9.8b/crypto/bn/bn_div.c.no-branch	2005-08-29 01:20:43.000000000 +0200
+++ openssl-0.9.8b/crypto/bn/bn_div.c	2007-08-03 13:58:58.000000000 +0200
@@ -169,13 +169,15 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, cons
 #endif /* OPENSSL_NO_ASM */
 
 
-/* BN_div computes  dv := num / divisor,  rounding towards zero, and sets up
- * rm  such that  dv*divisor + rm = num  holds.
+/* BN_div[_no_branch] computes  dv := num / divisor,  rounding towards
+ * zero, and sets up rm  such that  dv*divisor + rm = num  holds.
  * Thus:
  *     dv->neg == num->neg ^ divisor->neg  (unless the result is zero)
  *     rm->neg == num->neg                 (unless the remainder is zero)
  * If 'dv' or 'rm' is NULL, the respective value is not returned.
  */
+static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
+        const BIGNUM *divisor, BN_CTX *ctx);
 int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
 	   BN_CTX *ctx)
 	{
@@ -185,6 +187,11 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const
 	BN_ULONG d0,d1;
 	int num_n,div_n;
 
+	if (BN_get_flags(num, BN_FLG_CONSTTIME) != 0)
+		{
+		return BN_div_no_branch(dv, rm, num, divisor, ctx);
+		}
+
 	bn_check_top(dv);
 	bn_check_top(rm);
 	bn_check_top(num);
@@ -397,4 +404,229 @@ err:
 	return(0);
 	}
 
+
+/* BN_div_no_branch is a special version of BN_div. It does not contain
+ * branches that may leak sensitive information.
+ */
+static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, 
+	const BIGNUM *divisor, BN_CTX *ctx)
+	{
+	int norm_shift,i,loop;
+	BIGNUM *tmp,wnum,*snum,*sdiv,*res;
+	BN_ULONG *resp,*wnump;
+	BN_ULONG d0,d1;
+	int num_n,div_n;
+
+	bn_check_top(dv);
+	bn_check_top(rm);
+	bn_check_top(num);
+	bn_check_top(divisor);
+
+	if (BN_is_zero(divisor))
+		{
+		BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO);
+		return(0);
+		}
+
+	BN_CTX_start(ctx);
+	tmp=BN_CTX_get(ctx);
+	snum=BN_CTX_get(ctx);
+	sdiv=BN_CTX_get(ctx);
+	if (dv == NULL)
+		res=BN_CTX_get(ctx);
+	else	res=dv;
+	if (sdiv == NULL || res == NULL) goto err;
+
+	/* First we normalise the numbers */
+	norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2);
+	if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err;
+	sdiv->neg=0;
+	norm_shift+=BN_BITS2;
+	if (!(BN_lshift(snum,num,norm_shift))) goto err;
+	snum->neg=0;
+
+	/* Since we don't know whether snum is larger than sdiv,
+	 * we pad snum with enough zeroes without changing its
+	 * value. 
+	 */
+	if (snum->top <= sdiv->top+1) 
+		{
+		if (bn_wexpand(snum, sdiv->top + 2) == NULL) goto err;
+		for (i = snum->top; i < sdiv->top + 2; i++) snum->d[i] = 0;
+		snum->top = sdiv->top + 2;
+		}
+	else
+		{
+		if (bn_wexpand(snum, snum->top + 1) == NULL) goto err;
+		snum->d[snum->top] = 0;
+		snum->top ++;
+		}
+
+	div_n=sdiv->top;
+	num_n=snum->top;
+	loop=num_n-div_n;
+	/* Lets setup a 'window' into snum
+	 * This is the part that corresponds to the current
+	 * 'area' being divided */
+	wnum.neg   = 0;
+	wnum.d     = &(snum->d[loop]);
+	wnum.top   = div_n;
+	/* only needed when BN_ucmp messes up the values between top and max */
+	wnum.dmax  = snum->dmax - loop; /* so we don't step out of bounds */
+
+	/* Get the top 2 words of sdiv */
+	/* div_n=sdiv->top; */
+	d0=sdiv->d[div_n-1];
+	d1=(div_n == 1)?0:sdiv->d[div_n-2];
+
+	/* pointer to the 'top' of snum */
+	wnump= &(snum->d[num_n-1]);
+
+	/* Setup to 'res' */
+	res->neg= (num->neg^divisor->neg);
+	if (!bn_wexpand(res,(loop+1))) goto err;
+	res->top=loop-1;
+	resp= &(res->d[loop-1]);
+
+	/* space for temp */
+	if (!bn_wexpand(tmp,(div_n+1))) goto err;
+
+	/* if res->top == 0 then clear the neg value otherwise decrease
+	 * the resp pointer */
+	if (res->top == 0)
+		res->neg = 0;
+	else
+		resp--;
+
+	for (i=0; i<loop-1; i++, wnump--, resp--)
+		{
+		BN_ULONG q,l0;
+		/* the first part of the loop uses the top two words of
+		 * snum and sdiv to calculate a BN_ULONG q such that
+		 * | wnum - sdiv * q | < sdiv */
+#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
+		BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG);
+		q=bn_div_3_words(wnump,d1,d0);
+#else
+		BN_ULONG n0,n1,rem=0;
+
+		n0=wnump[0];
+		n1=wnump[-1];
+		if (n0 == d0)
+			q=BN_MASK2;
+		else 			/* n0 < d0 */
+			{
+#ifdef BN_LLONG
+			BN_ULLONG t2;
+
+#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
+			q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0);
+#else
+			q=bn_div_words(n0,n1,d0);
+#ifdef BN_DEBUG_LEVITTE
+			fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
+X) -> 0x%08X\n",
+				n0, n1, d0, q);
+#endif
+#endif
+
+#ifndef REMAINDER_IS_ALREADY_CALCULATED
+			/*
+			 * rem doesn't have to be BN_ULLONG. The least we
+			 * know it's less that d0, isn't it?
+			 */
+			rem=(n1-q*d0)&BN_MASK2;
+#endif
+			t2=(BN_ULLONG)d1*q;
+
+			for (;;)
+				{
+				if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2]))
+					break;
+				q--;
+				rem += d0;
+				if (rem < d0) break; /* don't let rem overflow */
+				t2 -= d1;
+				}
+#else /* !BN_LLONG */
+			BN_ULONG t2l,t2h,ql,qh;
+
+			q=bn_div_words(n0,n1,d0);
+#ifdef BN_DEBUG_LEVITTE
+			fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
+X) -> 0x%08X\n",
+				n0, n1, d0, q);
+#endif
+#ifndef REMAINDER_IS_ALREADY_CALCULATED
+			rem=(n1-q*d0)&BN_MASK2;
+#endif
+
+#if defined(BN_UMULT_LOHI)
+			BN_UMULT_LOHI(t2l,t2h,d1,q);
+#elif defined(BN_UMULT_HIGH)
+			t2l = d1 * q;
+			t2h = BN_UMULT_HIGH(d1,q);
+#else
+			t2l=LBITS(d1); t2h=HBITS(d1);
+			ql =LBITS(q);  qh =HBITS(q);
+			mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */
+#endif
+
+			for (;;)
+				{
+				if ((t2h < rem) ||
+					((t2h == rem) && (t2l <= wnump[-2])))
+					break;
+				q--;
+				rem += d0;
+				if (rem < d0) break; /* don't let rem overflow */
+				if (t2l < d1) t2h--; t2l -= d1;
+				}
+#endif /* !BN_LLONG */
+			}
+#endif /* !BN_DIV3W */
+
+		l0=bn_mul_words(tmp->d,sdiv->d,div_n,q);
+		tmp->d[div_n]=l0;
+		wnum.d--;
+		/* ingore top values of the bignums just sub the two 
+		 * BN_ULONG arrays with bn_sub_words */
+		if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n+1))
+			{
+			/* Note: As we have considered only the leading
+			 * two BN_ULONGs in the calculation of q, sdiv * q
+			 * might be greater than wnum (but then (q-1) * sdiv
+			 * is less or equal than wnum)
+			 */
+			q--;
+			if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n))
+				/* we can't have an overflow here (assuming
+				 * that q != 0, but if q == 0 then tmp is
+				 * zero anyway) */
+				(*wnump)++;
+			}
+		/* store part of the result */
+		*resp = q;
+		}
+	bn_correct_top(snum);
+	if (rm != NULL)
+		{
+		/* Keep a copy of the neg flag in num because if rm==num
+		 * BN_rshift() will overwrite it.
+		 */
+		int neg = num->neg;
+		BN_rshift(rm,snum,norm_shift);
+		if (!BN_is_zero(rm))
+			rm->neg = neg;
+		bn_check_top(rm);
+		}
+	bn_correct_top(res);
+	BN_CTX_end(ctx);
+	return(1);
+err:
+	bn_check_top(rm);
+	BN_CTX_end(ctx);
+	return(0);
+	}
+
 #endif
diff -up openssl-0.9.8b/crypto/bn/bn_gcd.c.no-branch openssl-0.9.8b/crypto/bn/bn_gcd.c
--- openssl-0.9.8b/crypto/bn/bn_gcd.c.no-branch	2005-08-29 01:20:43.000000000 +0200
+++ openssl-0.9.8b/crypto/bn/bn_gcd.c	2007-08-03 13:58:58.000000000 +0200
@@ -203,6 +203,8 @@ err:
 
 
 /* solves ax == 1 (mod n) */
+static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
+        const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
 BIGNUM *BN_mod_inverse(BIGNUM *in,
 	const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
 	{
@@ -210,6 +212,11 @@ BIGNUM *BN_mod_inverse(BIGNUM *in,
 	BIGNUM *ret=NULL;
 	int sign;
 
+	if (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)
+		{
+		return BN_mod_inverse_no_branch(in, a, n, ctx);
+		}
+
 	bn_check_top(a);
 	bn_check_top(n);
 
@@ -491,3 +498,157 @@ err:
 	bn_check_top(ret);
 	return(ret);
 	}
+
+
+/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. 
+ * It does not contain branches that may leak sensitive information.
+ */
+static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
+	const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
+	{
+	BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL;
+	BIGNUM local_A, local_B;
+	BIGNUM *pA, *pB;
+	BIGNUM *ret=NULL;
+	int sign;
+
+	bn_check_top(a);
+	bn_check_top(n);
+
+	BN_CTX_start(ctx);
+	A = BN_CTX_get(ctx);
+	B = BN_CTX_get(ctx);
+	X = BN_CTX_get(ctx);
+	D = BN_CTX_get(ctx);
+	M = BN_CTX_get(ctx);
+	Y = BN_CTX_get(ctx);
+	T = BN_CTX_get(ctx);
+	if (T == NULL) goto err;
+
+	if (in == NULL)
+		R=BN_new();
+	else
+		R=in;
+	if (R == NULL) goto err;
+
+	BN_one(X);
+	BN_zero(Y);
+	if (BN_copy(B,a) == NULL) goto err;
+	if (BN_copy(A,n) == NULL) goto err;
+	A->neg = 0;
+
+	if (B->neg || (BN_ucmp(B, A) >= 0))
+		{
+		/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
+	 	 * BN_div_no_branch will be called eventually.
+	 	 */
+		pB = &local_B;
+		BN_with_flags(pB, B, BN_FLG_CONSTTIME);	
+		if (!BN_nnmod(B, pB, A, ctx)) goto err;
+		}
+	sign = -1;
+	/* From  B = a mod |n|,  A = |n|  it follows that
+	 *
+	 *      0 <= B < A,
+	 *     -sign*X*a  ==  B   (mod |n|),
+	 *      sign*Y*a  ==  A   (mod |n|).
+	 */
+
+	while (!BN_is_zero(B))
+		{
+		BIGNUM *tmp;
+		
+		/*
+		 *      0 < B < A,
+		 * (*) -sign*X*a  ==  B   (mod |n|),
+		 *      sign*Y*a  ==  A   (mod |n|)
+		 */
+
+		/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
+	 	 * BN_div_no_branch will be called eventually.
+	 	 */
+		pA = &local_A;
+		BN_with_flags(pA, A, BN_FLG_CONSTTIME);	
+		
+		/* (D, M) := (A/B, A%B) ... */		
+		if (!BN_div(D,M,pA,B,ctx)) goto err;
+		
+		/* Now
+		 *      A = D*B + M;
+		 * thus we have
+		 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
+		 */
+		
+		tmp=A; /* keep the BIGNUM object, the value does not matter */
+		
+		/* (A, B) := (B, A mod B) ... */
+		A=B;
+		B=M;
+		/* ... so we have  0 <= B < A  again */
+		
+		/* Since the former  M  is now  B  and the former  B  is now  A,
+		 * (**) translates into
+		 *       sign*Y*a  ==  D*A + B    (mod |n|),
+		 * i.e.
+		 *       sign*Y*a - D*A  ==  B    (mod |n|).
+		 * Similarly, (*) translates into
+		 *      -sign*X*a  ==  A          (mod |n|).
+		 *
+		 * Thus,
+		 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
+		 * i.e.
+		 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
+		 *
+		 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
+		 *      -sign*X*a  ==  B   (mod |n|),
+		 *       sign*Y*a  ==  A   (mod |n|).
+		 * Note that  X  and  Y  stay non-negative all the time.
+		 */
+			
+		if (!BN_mul(tmp,D,X,ctx)) goto err;
+		if (!BN_add(tmp,tmp,Y)) goto err;
+
+		M=Y; /* keep the BIGNUM object, the value does not matter */
+		Y=X;
+		X=tmp;
+		sign = -sign;
+		}
+		
+	/*
+	 * The while loop (Euclid's algorithm) ends when
+	 *      A == gcd(a,n);
+	 * we have
+	 *       sign*Y*a  ==  A  (mod |n|),
+	 * where  Y  is non-negative.
+	 */
+
+	if (sign < 0)
+		{
+		if (!BN_sub(Y,n,Y)) goto err;
+		}
+	/* Now  Y*a  ==  A  (mod |n|).  */
+
+	if (BN_is_one(A))
+		{
+		/* Y*a == 1  (mod |n|) */
+		if (!Y->neg && BN_ucmp(Y,n) < 0)
+			{
+			if (!BN_copy(R,Y)) goto err;
+			}
+		else
+			{
+			if (!BN_nnmod(R,Y,n,ctx)) goto err;
+			}
+		}
+	else
+		{
+		BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE);
+		goto err;
+		}
+	ret=R;
+err:
+	if ((ret == NULL) && (in == NULL)) BN_free(R);
+	BN_CTX_end(ctx);
+	bn_check_top(ret);
+	return(ret);
+	}