Fix NFS deadlock vulnerability. [SA-14:05]
Fix "Heartbleed" vulnerability and ECDSA Cache Side-channel Attack in OpenSSL. [SA-14:06]
This commit is contained in:
parent
6f50d7f091
commit
7ec723c6ae
@ -538,6 +538,8 @@ BIGNUM *BN_mod_inverse(BIGNUM *ret,
|
||||
BIGNUM *BN_mod_sqrt(BIGNUM *ret,
|
||||
const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
|
||||
|
||||
void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords);
|
||||
|
||||
/* Deprecated versions */
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,
|
||||
@ -774,11 +776,20 @@ int RAND_pseudo_bytes(unsigned char *buf,int num);
|
||||
|
||||
#define bn_fix_top(a) bn_check_top(a)
|
||||
|
||||
#define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2)
|
||||
#define bn_wcheck_size(bn, words) \
|
||||
do { \
|
||||
const BIGNUM *_bnum2 = (bn); \
|
||||
assert(words <= (_bnum2)->dmax && words >= (_bnum2)->top); \
|
||||
} while(0)
|
||||
|
||||
#else /* !BN_DEBUG */
|
||||
|
||||
#define bn_pollute(a)
|
||||
#define bn_check_top(a)
|
||||
#define bn_fix_top(a) bn_correct_top(a)
|
||||
#define bn_check_size(bn, bits)
|
||||
#define bn_wcheck_size(bn, words)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -824,3 +824,55 @@ int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b,
|
||||
}
|
||||
return bn_cmp_words(a,b,cl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constant-time conditional swap of a and b.
|
||||
* a and b are swapped if condition is not 0. The code assumes that at most one bit of condition is set.
|
||||
* nwords is the number of words to swap. The code assumes that at least nwords are allocated in both a and b,
|
||||
* and that no more than nwords are used by either a or b.
|
||||
* a and b cannot be the same number
|
||||
*/
|
||||
void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
|
||||
{
|
||||
BN_ULONG t;
|
||||
int i;
|
||||
|
||||
bn_wcheck_size(a, nwords);
|
||||
bn_wcheck_size(b, nwords);
|
||||
|
||||
assert(a != b);
|
||||
assert((condition & (condition - 1)) == 0);
|
||||
assert(sizeof(BN_ULONG) >= sizeof(int));
|
||||
|
||||
condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1;
|
||||
|
||||
t = (a->top^b->top) & condition;
|
||||
a->top ^= t;
|
||||
b->top ^= t;
|
||||
|
||||
#define BN_CONSTTIME_SWAP(ind) \
|
||||
do { \
|
||||
t = (a->d[ind] ^ b->d[ind]) & condition; \
|
||||
a->d[ind] ^= t; \
|
||||
b->d[ind] ^= t; \
|
||||
} while (0)
|
||||
|
||||
|
||||
switch (nwords) {
|
||||
default:
|
||||
for (i = 10; i < nwords; i++)
|
||||
BN_CONSTTIME_SWAP(i);
|
||||
/* Fallthrough */
|
||||
case 10: BN_CONSTTIME_SWAP(9); /* Fallthrough */
|
||||
case 9: BN_CONSTTIME_SWAP(8); /* Fallthrough */
|
||||
case 8: BN_CONSTTIME_SWAP(7); /* Fallthrough */
|
||||
case 7: BN_CONSTTIME_SWAP(6); /* Fallthrough */
|
||||
case 6: BN_CONSTTIME_SWAP(5); /* Fallthrough */
|
||||
case 5: BN_CONSTTIME_SWAP(4); /* Fallthrough */
|
||||
case 4: BN_CONSTTIME_SWAP(3); /* Fallthrough */
|
||||
case 3: BN_CONSTTIME_SWAP(2); /* Fallthrough */
|
||||
case 2: BN_CONSTTIME_SWAP(1); /* Fallthrough */
|
||||
case 1: BN_CONSTTIME_SWAP(0);
|
||||
}
|
||||
#undef BN_CONSTTIME_SWAP
|
||||
}
|
||||
|
@ -208,11 +208,15 @@ static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIG
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Computes scalar*point and stores the result in r.
|
||||
* point can not equal r.
|
||||
* Uses algorithm 2P of
|
||||
* Uses a modified algorithm 2P of
|
||||
* Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation" (CHES '99, LNCS 1717).
|
||||
*
|
||||
* To protect against side-channel attack the function uses constant time swap,
|
||||
* avoiding conditional branches.
|
||||
*/
|
||||
static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
const EC_POINT *point, BN_CTX *ctx)
|
||||
@ -246,6 +250,11 @@ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r,
|
||||
x2 = &r->X;
|
||||
z2 = &r->Y;
|
||||
|
||||
bn_wexpand(x1, group->field.top);
|
||||
bn_wexpand(z1, group->field.top);
|
||||
bn_wexpand(x2, group->field.top);
|
||||
bn_wexpand(z2, group->field.top);
|
||||
|
||||
if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */
|
||||
if (!BN_one(z1)) goto err; /* z1 = 1 */
|
||||
if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */
|
||||
@ -270,16 +279,12 @@ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r,
|
||||
word = scalar->d[i];
|
||||
while (mask)
|
||||
{
|
||||
if (word & mask)
|
||||
{
|
||||
if (!gf2m_Madd(group, &point->X, x1, z1, x2, z2, ctx)) goto err;
|
||||
if (!gf2m_Mdouble(group, x2, z2, ctx)) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err;
|
||||
if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err;
|
||||
}
|
||||
BN_consttime_swap(word & mask, x1, x2, group->field.top);
|
||||
BN_consttime_swap(word & mask, z1, z2, group->field.top);
|
||||
if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err;
|
||||
if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err;
|
||||
BN_consttime_swap(word & mask, x1, x2, group->field.top);
|
||||
BN_consttime_swap(word & mask, z1, z2, group->field.top);
|
||||
mask >>= 1;
|
||||
}
|
||||
mask = BN_TBIT;
|
||||
|
@ -1458,26 +1458,36 @@ dtls1_process_heartbeat(SSL *s)
|
||||
unsigned int payload;
|
||||
unsigned int padding = 16; /* Use minimum padding */
|
||||
|
||||
/* Read type and payload length first */
|
||||
hbtype = *p++;
|
||||
n2s(p, payload);
|
||||
pl = p;
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
|
||||
&s->s3->rrec.data[0], s->s3->rrec.length,
|
||||
s, s->msg_callback_arg);
|
||||
|
||||
/* Read type and payload length first */
|
||||
if (1 + 2 + 16 > s->s3->rrec.length)
|
||||
return 0; /* silently discard */
|
||||
hbtype = *p++;
|
||||
n2s(p, payload);
|
||||
if (1 + 2 + payload + 16 > s->s3->rrec.length)
|
||||
return 0; /* silently discard per RFC 6520 sec. 4 */
|
||||
pl = p;
|
||||
|
||||
if (hbtype == TLS1_HB_REQUEST)
|
||||
{
|
||||
unsigned char *buffer, *bp;
|
||||
unsigned int write_length = 1 /* heartbeat type */ +
|
||||
2 /* heartbeat length */ +
|
||||
payload + padding;
|
||||
int r;
|
||||
|
||||
if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
|
||||
return 0;
|
||||
|
||||
/* Allocate memory for the response, size is 1 byte
|
||||
* message type, plus 2 bytes payload length, plus
|
||||
* payload, plus padding
|
||||
*/
|
||||
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
|
||||
buffer = OPENSSL_malloc(write_length);
|
||||
bp = buffer;
|
||||
|
||||
/* Enter response type, length and copy payload */
|
||||
@ -1488,11 +1498,11 @@ dtls1_process_heartbeat(SSL *s)
|
||||
/* Random padding */
|
||||
RAND_pseudo_bytes(bp, padding);
|
||||
|
||||
r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
|
||||
r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
|
||||
|
||||
if (r >= 0 && s->msg_callback)
|
||||
s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
|
||||
buffer, 3 + payload + padding,
|
||||
buffer, write_length,
|
||||
s, s->msg_callback_arg);
|
||||
|
||||
OPENSSL_free(buffer);
|
||||
|
@ -2486,16 +2486,20 @@ tls1_process_heartbeat(SSL *s)
|
||||
unsigned int payload;
|
||||
unsigned int padding = 16; /* Use minimum padding */
|
||||
|
||||
/* Read type and payload length first */
|
||||
hbtype = *p++;
|
||||
n2s(p, payload);
|
||||
pl = p;
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
|
||||
&s->s3->rrec.data[0], s->s3->rrec.length,
|
||||
s, s->msg_callback_arg);
|
||||
|
||||
/* Read type and payload length first */
|
||||
if (1 + 2 + 16 > s->s3->rrec.length)
|
||||
return 0; /* silently discard */
|
||||
hbtype = *p++;
|
||||
n2s(p, payload);
|
||||
if (1 + 2 + payload + 16 > s->s3->rrec.length)
|
||||
return 0; /* silently discard per RFC 6520 sec. 4 */
|
||||
pl = p;
|
||||
|
||||
if (hbtype == TLS1_HB_REQUEST)
|
||||
{
|
||||
unsigned char *buffer, *bp;
|
||||
|
@ -1457,10 +1457,23 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
|
||||
nfsvno_relpathbuf(&fromnd);
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Unlock dp in this code section, so it is unlocked before
|
||||
* tdp gets locked. This avoids a potential LOR if tdp is the
|
||||
* parent directory of dp.
|
||||
*/
|
||||
if (nd->nd_flag & ND_NFSV4) {
|
||||
tdp = todp;
|
||||
tnes = *toexp;
|
||||
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, p, 0);
|
||||
if (dp != tdp) {
|
||||
NFSVOPUNLOCK(dp, 0);
|
||||
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
|
||||
p, 0); /* Might lock tdp. */
|
||||
} else {
|
||||
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
|
||||
p, 1);
|
||||
NFSVOPUNLOCK(dp, 0);
|
||||
}
|
||||
} else {
|
||||
tfh.nfsrvfh_len = 0;
|
||||
error = nfsrv_mtofh(nd, &tfh);
|
||||
@ -1481,10 +1494,12 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
|
||||
tnes = *exp;
|
||||
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
|
||||
p, 1);
|
||||
NFSVOPUNLOCK(dp, 0);
|
||||
} else {
|
||||
NFSVOPUNLOCK(dp, 0);
|
||||
nd->nd_cred->cr_uid = nd->nd_saveduid;
|
||||
nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL,
|
||||
0, p);
|
||||
0, p); /* Locks tdp. */
|
||||
if (tdp) {
|
||||
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor,
|
||||
nd->nd_cred, p, 1);
|
||||
@ -1499,7 +1514,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
|
||||
if (error) {
|
||||
if (tdp)
|
||||
vrele(tdp);
|
||||
vput(dp);
|
||||
vrele(dp);
|
||||
nfsvno_relpathbuf(&fromnd);
|
||||
nfsvno_relpathbuf(&tond);
|
||||
goto out;
|
||||
@ -1514,7 +1529,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
|
||||
}
|
||||
if (tdp)
|
||||
vrele(tdp);
|
||||
vput(dp);
|
||||
vrele(dp);
|
||||
nfsvno_relpathbuf(&fromnd);
|
||||
nfsvno_relpathbuf(&tond);
|
||||
goto out;
|
||||
@ -1523,7 +1538,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
|
||||
/*
|
||||
* Done parsing, now down to business.
|
||||
*/
|
||||
nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 1, exp, p, &fdirp);
|
||||
nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 0, exp, p, &fdirp);
|
||||
if (nd->nd_repstat) {
|
||||
if (nd->nd_flag & ND_NFSV3) {
|
||||
nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret,
|
||||
|
Loading…
Reference in New Issue
Block a user