From 1fc17eb7dbbe373cbef970d1443bdfb8adf4e1ab Mon Sep 17 00:00:00 2001 From: Tomáš Mráz Date: Aug 03 2007 12:51:59 +0000 Subject: - use localhost in testsuite, hopefully fixes slow build in koji - CVE-2007-3108 - fix side channel attack on private keys (#250577) - make ssl session cache id matching strict (#233599) --- diff --git a/openssl-0.9.7a-ssl-strict-matching.patch b/openssl-0.9.7a-ssl-strict-matching.patch new file mode 100644 index 0000000..d0da06a --- /dev/null +++ b/openssl-0.9.7a-ssl-strict-matching.patch @@ -0,0 +1,69 @@ +*) In the SSL/TLS server implementation, be strict about session ID + context matching (which matters if an application uses a single + external cache for different purposes). Previously, + out-of-context reuse was forbidden only if SSL_VERIFY_PEER was + set. This did ensure strict client verification, but meant that, + with applications using a single external cache for quite + different requirements, clients could circumvent ciphersuite + restrictions for a given session ID context by starting a session + in a different context. +diff -up openssl-0.9.7a/ssl/ssl_sess.c.strict-matching openssl-0.9.7a/ssl/ssl_sess.c +--- openssl-0.9.7a/ssl/ssl_sess.c.strict-matching 2002-11-28 09:09:03.000000000 +0100 ++++ openssl-0.9.7a/ssl/ssl_sess.c 2007-08-02 16:17:29.000000000 +0200 +@@ -322,33 +322,35 @@ int ssl_get_prev_session(SSL *s, unsigne + + /* Now ret is non-NULL, and we own one of its reference counts. */ + +- if((s->verify_mode&SSL_VERIFY_PEER) +- && (!s->sid_ctx_length || ret->sid_ctx_length != s->sid_ctx_length +- || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))) +- { ++ if (ret->sid_ctx_length != s->sid_ctx_length ++ || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)) ++ { + /* We've found the session named by the client, but we don't + * want to use it in this context. */ +- +- if (s->sid_ctx_length == 0) +- { +- /* application should have used SSL[_CTX]_set_session_id_context +- * -- we could tolerate this and just pretend we never heard +- * of this session, but then applications could effectively +- * disable the session cache by accident without anyone noticing */ + +- SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); +- fatal = 1; +- goto err; +- } +- else +- { + #if 0 /* The client cannot always know when a session is not appropriate, +- * so we shouldn't generate an error message. */ ++ * so we shouldn't generate an error message. */ + +- SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); ++ SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); + #endif +- goto err; /* treat like cache miss */ +- } ++ goto err; /* treat like cache miss */ ++ } ++ ++ if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) ++ { ++ /* We can't be sure if this session is being used out of ++ * context, which is especially important for SSL_VERIFY_PEER. ++ * The application should have used SSL[_CTX]_set_session_id_context. ++ * ++ * For this error case, we generate an error instead of treating ++ * the event like a cache miss (otherwise it would be easy for ++ * applications to effectively disable the session cache by ++ * accident without anyone noticing). ++ */ ++ ++ SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); ++ fatal = 1; ++ goto err; + } + + if (ret->cipher == NULL) diff --git a/openssl-0.9.8b-cve-2007-3108.patch b/openssl-0.9.8b-cve-2007-3108.patch new file mode 100644 index 0000000..81fa59e --- /dev/null +++ b/openssl-0.9.8b-cve-2007-3108.patch @@ -0,0 +1,932 @@ +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; id[ri]); ++ ++ v=bn_sub_words(rp,ap,np,ri); ++ /* this -----------------------^^ works even in alri) 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>(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)); ++ ++ /* 'iN,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)<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 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)< 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); ++ } diff --git a/openssl-0.9.8b-test-use-localhost.patch b/openssl-0.9.8b-test-use-localhost.patch new file mode 100644 index 0000000..08adf1c --- /dev/null +++ b/openssl-0.9.8b-test-use-localhost.patch @@ -0,0 +1,24 @@ +diff -up openssl-0.9.8b/ssl/ssltest.c.use-localhost openssl-0.9.8b/ssl/ssltest.c +--- openssl-0.9.8b/ssl/ssltest.c.use-localhost 2006-02-24 18:58:35.000000000 +0100 ++++ openssl-0.9.8b/ssl/ssltest.c 2007-08-03 14:06:16.000000000 +0200 +@@ -839,19 +839,8 @@ bad: + #ifndef OPENSSL_NO_KRB5 + if (c_ssl && c_ssl->kssl_ctx) + { +- char localhost[MAXHOSTNAMELEN+2]; +- +- if (gethostname(localhost, sizeof localhost-1) == 0) +- { +- localhost[sizeof localhost-1]='\0'; +- if(strlen(localhost) == sizeof localhost-1) +- { +- BIO_printf(bio_err,"localhost name too long\n"); +- goto end; +- } + kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER, +- localhost); +- } ++ "localhost"); + } + #endif /* OPENSSL_NO_KRB5 */ + diff --git a/openssl.spec b/openssl.spec index 7a55561..31d3921 100644 --- a/openssl.spec +++ b/openssl.spec @@ -21,7 +21,7 @@ Summary: The OpenSSL toolkit Name: openssl Version: 0.9.8b -Release: 12%{?dist} +Release: 14%{?dist} Source: openssl-%{version}-usa.tar.bz2 Source1: hobble-openssl Source2: Makefile.certificate @@ -63,8 +63,11 @@ Patch60: openssl-0.9.8b-cve-2006-4343.patch Patch61: openssl-0.9.8b-aliasing-bug.patch Patch62: openssl-0.9.8b-x509-name-cmp.patch Patch63: openssl-0.9.8b-x509-add-dir.patch +Patch64: openssl-0.9.8b-test-use-localhost.patch +Patch65: openssl-0.9.8b-cve-2007-3108.patch +Patch66: openssl-0.9.7a-ssl-strict-matching.patch -License: BSDish +License: OpenSSL Group: System Environment/Libraries URL: http://www.openssl.org/ BuildRoot: %{_tmppath}/%{name}-%{version}-root @@ -81,6 +84,7 @@ protocols. Summary: Files for development of applications which will use OpenSSL Group: Development/Libraries Requires: %{name} = %{version}-%{release}, krb5-devel, zlib-devel +Requires: pkgconfig %description devel OpenSSL is a toolkit for supporting cryptography. The openssl-devel @@ -135,6 +139,9 @@ from other formats to the formats used by the OpenSSL toolkit. %patch61 -p1 -b .aliasing-bug %patch62 -p1 -b .name-cmp %patch63 -p1 -b .add-dir +%patch64 -p1 -b .use-localhost +%patch65 -p1 -b .no-branch +%patch66 -p1 -b .strict-matching # Modify the various perl scripts to reference perl in the right location. perl util/perlpath.pl `dirname %{__perl}` @@ -167,6 +174,9 @@ sslarch="linux-generic32 -DB_ENDIAN -DNO_ASM -fno-regmove" %ifarch s390x sslarch="linux-generic64 -DB_ENDIAN -DNO_ASM" %endif +%ifarch %{arm} +sslarch=linux-generic32 +%endif # ia64, x86_64, ppc, ppc64 are OK by default # Configure the build tree. Override OpenSSL defaults with known-good defaults # usable on all platforms. The Configure script already knows to use -fPIC and @@ -270,6 +280,9 @@ EOF cat %{SOURCE3} RHNS-blurb.txt %{SOURCE4} > ca-bundle.crt install -m644 ca-bundle.crt $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/certs/ ln -s certs/ca-bundle.crt $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/cert.pem +# Reference timestamps to prevent multilib conflicts +touch -r %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/certs/ca-bundle.crt +touch -r %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/openssl.cnf # Fix libdir. pushd $RPM_BUILD_ROOT/%{_libdir}/pkgconfig @@ -369,6 +382,16 @@ rm -rf $RPM_BUILD_ROOT/%{_bindir}/openssl_fips_fingerprint %postun -p /sbin/ldconfig %changelog +* Fri Aug 3 2007 Tomas Mraz 0.9.8b-14 +- use localhost in testsuite, hopefully fixes slow build in koji +- CVE-2007-3108 - fix side channel attack on private keys (#250577) +- make ssl session cache id matching strict (#233599) + +* Wed Jul 25 2007 Tomas Mraz 0.9.8b-13 +- allow building on ARM architectures (#245417) +- use reference timestamps to prevent multilib conflicts (#218064) +- -devel package must require pkgconfig (#241031) + * Mon Dec 11 2006 Tomas Mraz 0.9.8b-12 - detect duplicates in add_dir properly (#206346)