svn commit: r306229 - in stable/9/crypto/openssl: crypto/bn crypto/dsa crypto/mdc2 ssl
Xin LI
delphij at FreeBSD.org
Fri Sep 23 07:44:13 UTC 2016
Author: delphij
Date: Fri Sep 23 07:44:10 2016
New Revision: 306229
URL: https://svnweb.freebsd.org/changeset/base/306229
Log:
Fix multiple OpenSSL vulnerabilities.
Security: FreeBSD-SA-16:26.openssl
Modified:
stable/9/crypto/openssl/crypto/bn/bn_print.c
stable/9/crypto/openssl/crypto/dsa/dsa_ossl.c
stable/9/crypto/openssl/crypto/mdc2/mdc2dgst.c
stable/9/crypto/openssl/ssl/d1_both.c
stable/9/crypto/openssl/ssl/d1_clnt.c
stable/9/crypto/openssl/ssl/d1_lib.c
stable/9/crypto/openssl/ssl/d1_pkt.c
stable/9/crypto/openssl/ssl/d1_srvr.c
stable/9/crypto/openssl/ssl/s3_clnt.c
stable/9/crypto/openssl/ssl/s3_srvr.c
stable/9/crypto/openssl/ssl/ssl.h
stable/9/crypto/openssl/ssl/ssl_err.c
stable/9/crypto/openssl/ssl/ssl_locl.h
stable/9/crypto/openssl/ssl/ssl_sess.c
stable/9/crypto/openssl/ssl/t1_lib.c
Modified: stable/9/crypto/openssl/crypto/bn/bn_print.c
==============================================================================
--- stable/9/crypto/openssl/crypto/bn/bn_print.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/crypto/bn/bn_print.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -111,6 +111,7 @@ char *BN_bn2dec(const BIGNUM *a)
char *p;
BIGNUM *t = NULL;
BN_ULONG *bn_data = NULL, *lp;
+ int bn_data_num;
/*-
* get an upper bound for the length of the decimal integer
@@ -120,8 +121,8 @@ char *BN_bn2dec(const BIGNUM *a)
*/
i = BN_num_bits(a) * 3;
num = (i / 10 + i / 1000 + 1) + 1;
- bn_data =
- (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
+ bn_data_num = num / BN_DEC_NUM + 1;
+ bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG));
buf = (char *)OPENSSL_malloc(num + 3);
if ((buf == NULL) || (bn_data == NULL)) {
BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE);
@@ -143,7 +144,11 @@ char *BN_bn2dec(const BIGNUM *a)
i = 0;
while (!BN_is_zero(t)) {
*lp = BN_div_word(t, BN_DEC_CONV);
+ if (*lp == (BN_ULONG)-1)
+ goto err;
lp++;
+ if (lp - bn_data >= bn_data_num)
+ goto err;
}
lp--;
/*
Modified: stable/9/crypto/openssl/crypto/dsa/dsa_ossl.c
==============================================================================
--- stable/9/crypto/openssl/crypto/dsa/dsa_ossl.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/crypto/dsa/dsa_ossl.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -235,11 +235,13 @@ static int dsa_sign_setup(DSA *dsa, BN_C
do
if (!BN_rand_range(&k, dsa->q))
goto err;
- while (BN_is_zero(&k)) ;
+ while (BN_is_zero(&k));
+
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) {
BN_set_flags(&k, BN_FLG_CONSTTIME);
}
+
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
CRYPTO_LOCK_DSA, dsa->p, ctx))
@@ -252,6 +254,8 @@ static int dsa_sign_setup(DSA *dsa, BN_C
if (!BN_copy(&kq, &k))
goto err;
+ BN_set_flags(&kq, BN_FLG_CONSTTIME);
+
/*
* We do not want timing information to leak the length of k, so we
* compute g^k using an equivalent exponent of fixed length. (This
@@ -270,6 +274,7 @@ static int dsa_sign_setup(DSA *dsa, BN_C
} else {
K = &k;
}
+
DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, K, dsa->p, ctx,
dsa->method_mont_p);
if (!BN_mod(r, r, dsa->q, ctx))
Modified: stable/9/crypto/openssl/crypto/mdc2/mdc2dgst.c
==============================================================================
--- stable/9/crypto/openssl/crypto/mdc2/mdc2dgst.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/crypto/mdc2/mdc2dgst.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -94,7 +94,7 @@ int MDC2_Update(MDC2_CTX *c, const unsig
i = c->num;
if (i != 0) {
- if (i + len < MDC2_BLOCK) {
+ if (len < MDC2_BLOCK - i) {
/* partial block */
memcpy(&(c->data[i]), in, len);
c->num += (int)len;
Modified: stable/9/crypto/openssl/ssl/d1_both.c
==============================================================================
--- stable/9/crypto/openssl/ssl/d1_both.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/d1_both.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -543,11 +543,23 @@ static int dtls1_retrieve_buffered_fragm
int al;
*ok = 0;
- item = pqueue_peek(s->d1->buffered_messages);
- if (item == NULL)
- return 0;
+ do {
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.seq < s->d1->handshake_read_seq) {
+ /* This is a stale message that has been buffered so clear it */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = NULL;
+ frag = NULL;
+ }
+ } while (item == NULL);
- frag = (hm_fragment *)item->data;
/* Don't return if reassembly still in progress */
if (frag->reassembly != NULL)
@@ -1335,18 +1347,6 @@ dtls1_retransmit_message(SSL *s, unsigne
return ret;
}
-/* call this function when the buffered messages are no longer needed */
-void dtls1_clear_record_buffer(SSL *s)
-{
- pitem *item;
-
- for (item = pqueue_pop(s->d1->sent_messages);
- item != NULL; item = pqueue_pop(s->d1->sent_messages)) {
- dtls1_hm_fragment_free((hm_fragment *)item->data);
- pitem_free(item);
- }
-}
-
unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p,
unsigned char mt, unsigned long len,
unsigned long frag_off,
Modified: stable/9/crypto/openssl/ssl/d1_clnt.c
==============================================================================
--- stable/9/crypto/openssl/ssl/d1_clnt.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/d1_clnt.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -564,6 +564,7 @@ int dtls1_connect(SSL *s)
/* done with handshaking */
s->d1->handshake_read_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
Modified: stable/9/crypto/openssl/ssl/d1_lib.c
==============================================================================
--- stable/9/crypto/openssl/ssl/d1_lib.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/d1_lib.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -155,7 +155,6 @@ int dtls1_new(SSL *s)
static void dtls1_clear_queues(SSL *s)
{
pitem *item = NULL;
- hm_fragment *frag = NULL;
DTLS1_RECORD_DATA *rdata;
while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
@@ -176,12 +175,36 @@ static void dtls1_clear_queues(SSL *s)
pitem_free(item);
}
+ while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ dtls1_clear_received_buffer(s);
+ dtls1_clear_sent_buffer(s);
+}
+
+void dtls1_clear_received_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
+
while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
frag = (hm_fragment *)item->data;
OPENSSL_free(frag->fragment);
OPENSSL_free(frag);
pitem_free(item);
}
+}
+
+void dtls1_clear_sent_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
frag = (hm_fragment *)item->data;
@@ -189,17 +212,9 @@ static void dtls1_clear_queues(SSL *s)
OPENSSL_free(frag);
pitem_free(item);
}
-
- while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
- rdata = (DTLS1_RECORD_DATA *)item->data;
- if (rdata->rbuf.buf) {
- OPENSSL_free(rdata->rbuf.buf);
- }
- OPENSSL_free(item->data);
- pitem_free(item);
- }
}
+
void dtls1_free(SSL *s)
{
ssl3_free(s);
@@ -431,7 +446,7 @@ void dtls1_stop_timer(SSL *s)
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&(s->d1->next_timeout));
/* Clear retransmission buffer */
- dtls1_clear_record_buffer(s);
+ dtls1_clear_sent_buffer(s);
}
int dtls1_check_timeout_num(SSL *s)
Modified: stable/9/crypto/openssl/ssl/d1_pkt.c
==============================================================================
--- stable/9/crypto/openssl/ssl/d1_pkt.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/d1_pkt.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -124,8 +124,7 @@
static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
int len, int peek);
-static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap,
- PQ_64BIT * seq_num);
+static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
unsigned int *is_next_epoch);
@@ -135,7 +134,7 @@ static int dtls1_record_needs_buffering(
unsigned long *offset);
#endif
static int dtls1_buffer_record(SSL *s, record_pqueue *q, PQ_64BIT * priority);
-static int dtls1_process_record(SSL *s);
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
#if PQ_64BIT_IS_INTEGER
static PQ_64BIT bytes_to_long_long(unsigned char *bytes, PQ_64BIT * num);
#endif
@@ -248,20 +247,66 @@ static int dtls1_retrieve_buffered_recor
static int dtls1_process_buffered_records(SSL *s)
{
pitem *item;
+ SSL3_BUFFER *rb;
+ SSL3_RECORD *rr;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+ int replayok = 1;
item = pqueue_peek(s->d1->unprocessed_rcds.q);
if (item) {
/* Check if epoch is current. */
if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
- return (1); /* Nothing to do. */
+ return 1; /* Nothing to do. */
+
+ rr = &s->s3->rrec;
+ rb = &s->s3->rbuf;
+
+ if (rb->left > 0) {
+ /*
+ * We've still got data from the current packet to read. There could
+ * be a record from the new epoch in it - so don't overwrite it
+ * with the unprocessed records yet (we'll do it when we've
+ * finished reading the current packet).
+ */
+ return 1;
+ }
+
/* Process all the records. */
while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
dtls1_get_unprocessed_record(s);
- if (!dtls1_process_record(s))
- return (0);
- dtls1_buffer_record(s, &(s->d1->processed_rcds),
- &s->s3->rrec.seq_num);
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ /*
+ * Should not happen. This will only ever be NULL when the
+ * current record is from a different epoch. But that cannot
+ * be the case because we already checked the epoch above
+ */
+ SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ {
+ /*
+ * Check whether this is a repeat, or aged record. We did this
+ * check once already when we first received the record - but
+ * we might have updated the window since then due to
+ * records we subsequently processed.
+ */
+ replayok = dtls1_record_replay_check(s, bitmap);
+ }
+
+ if (!replayok || !dtls1_process_record(s, bitmap)) {
+ /* dump this record */
+ rr->length = 0;
+ s->packet_length = 0;
+ continue;
+ }
+
+ if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
+ &s->s3->rrec.seq_num) < 0)
+ return 0;
}
}
@@ -272,7 +317,7 @@ static int dtls1_process_buffered_record
s->d1->processed_rcds.epoch = s->d1->r_epoch;
s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
- return (1);
+ return 1;
}
#if 0
@@ -319,7 +364,7 @@ static int dtls1_get_buffered_record(SSL
#endif
-static int dtls1_process_record(SSL *s)
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
{
int i, al;
int enc_err;
@@ -478,8 +523,10 @@ static int dtls1_process_record(SSL *s)
/* we have pulled in a full packet so zero things */
s->packet_length = 0;
- dtls1_record_bitmap_update(s, &(s->d1->bitmap)); /* Mark receipt of
- * record. */
+
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+
return (1);
f_err:
@@ -510,6 +557,7 @@ int dtls1_get_record(SSL *s)
rr = &(s->s3->rrec);
+ again:
/*
* The epoch may have changed. If so, process all the pending records.
* This is a non-blocking operation.
@@ -521,7 +569,6 @@ int dtls1_get_record(SSL *s)
return 1;
/* get something from the wire */
- again:
/* check if we have the header */
if ((s->rstate != SSL_ST_READ_BODY) ||
(s->packet_length < DTLS1_RT_HEADER_LENGTH)) {
@@ -620,7 +667,7 @@ int dtls1_get_record(SSL *s)
if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
s->packet_length > DTLS1_RT_HEADER_LENGTH &&
s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) &&
- !dtls1_record_replay_check(s, bitmap, &(rr->seq_num))) {
+ !dtls1_record_replay_check(s, bitmap)) {
rr->length = 0;
s->packet_length = 0; /* dump this record */
goto again; /* get another record */
@@ -638,14 +685,16 @@ int dtls1_get_record(SSL *s)
*/
if (is_next_epoch) {
if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) {
- dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), &rr->seq_num);
+ if (dtls1_buffer_record
+ (s, &(s->d1->unprocessed_rcds), &rr->seq_num) < 0)
+ return -1;
}
rr->length = 0;
s->packet_length = 0;
goto again;
}
- if (!dtls1_process_record(s)) {
+ if (!dtls1_process_record(s, bitmap)) {
rr->length = 0;
s->packet_length = 0; /* dump this record */
goto again; /* get another record */
@@ -1514,8 +1563,7 @@ int do_dtls1_write(SSL *s, int type, con
return -1;
}
-static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap,
- PQ_64BIT * seq_num)
+static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
{
#if PQ_64BIT_IS_INTEGER
PQ_64BIT mask = 0x0000000000000001L;
@@ -1530,7 +1578,7 @@ static int dtls1_record_replay_check(SSL
if (pq_64bit_gt(&rcd_num, &(bitmap->max_seq_num)) ||
pq_64bit_eq(&rcd_num, &(bitmap->max_seq_num))) {
- pq_64bit_assign(seq_num, &rcd_num);
+ pq_64bit_assign(&s->s3->rrec.seq_num, &rcd_num);
pq_64bit_free(&rcd_num);
pq_64bit_free(&tmp);
return 1; /* this record is new */
@@ -1561,7 +1609,7 @@ static int dtls1_record_replay_check(SSL
return 0; /* record previously received */
#endif
- pq_64bit_assign(seq_num, &rcd_num);
+ pq_64bit_assign(&s->s3->rrec.seq_num, &rcd_num);
pq_64bit_free(&rcd_num);
pq_64bit_free(&tmp);
return 1;
@@ -1687,8 +1735,13 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SS
if (rr->epoch == s->d1->r_epoch)
return &s->d1->bitmap;
- /* Only HM and ALERT messages can be from the next epoch */
+ /*
+ * Only HM and ALERT messages can be from the next epoch and only if we
+ * have already processed all of the unprocessed records from the last
+ * epoch
+ */
else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
+ s->d1->unprocessed_rcds.epoch != s->d1->r_epoch &&
(rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
*is_next_epoch = 1;
return &s->d1->next_bitmap;
@@ -1776,6 +1829,12 @@ void dtls1_reset_seq_numbers(SSL *s, int
memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
pq_64bit_init(&(s->d1->next_bitmap.map));
pq_64bit_init(&(s->d1->next_bitmap.max_seq_num));
+
+ /*
+ * We must not use any buffered messages received from the previous
+ * epoch
+ */
+ dtls1_clear_received_buffer(s);
} else {
seq = s->s3->write_sequence;
memcpy(s->d1->last_write_sequence, seq,
Modified: stable/9/crypto/openssl/ssl/d1_srvr.c
==============================================================================
--- stable/9/crypto/openssl/ssl/d1_srvr.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/d1_srvr.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -242,7 +242,7 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SW_HELLO_REQ_B:
s->shutdown = 0;
- dtls1_clear_record_buffer(s);
+ dtls1_clear_sent_buffer(s);
dtls1_start_timer(s);
ret = dtls1_send_hello_request(s);
if (ret <= 0)
@@ -648,6 +648,7 @@ int dtls1_accept(SSL *s)
/* next message is server hello */
s->d1->handshake_write_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
Modified: stable/9/crypto/openssl/ssl/s3_clnt.c
==============================================================================
--- stable/9/crypto/openssl/ssl/s3_clnt.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/s3_clnt.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -931,6 +931,12 @@ int ssl3_get_server_certificate(SSL *s)
goto f_err;
}
for (nc = 0; nc < llen;) {
+ if (nc + 3 > llen) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
n2l3(p, l);
if ((l + nc + 3) > llen) {
al = SSL_AD_DECODE_ERROR;
@@ -1627,6 +1633,11 @@ int ssl3_get_certificate_request(SSL *s)
}
for (nc = 0; nc < llen;) {
+ if (nc + 2 > llen) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG);
+ goto err;
+ }
n2s(p, l);
if ((l + nc + 2) > llen) {
if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
Modified: stable/9/crypto/openssl/ssl/s3_srvr.c
==============================================================================
--- stable/9/crypto/openssl/ssl/s3_srvr.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/s3_srvr.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -819,7 +819,7 @@ int ssl3_get_client_hello(SSL *s)
session_length = *(p + SSL3_RANDOM_SIZE);
- if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
+ if (SSL3_RANDOM_SIZE + session_length + 1 >= (d + n) - p) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -837,7 +837,7 @@ int ssl3_get_client_hello(SSL *s)
/* get the session-id */
j = *(p++);
- if (p + j > d + n) {
+ if ((d + n) - p < j) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -874,14 +874,14 @@ int ssl3_get_client_hello(SSL *s)
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
/* cookie stuff */
- if (p + 1 > d + n) {
+ if ((d + n) - p < 1) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
cookie_len = *(p++);
- if (p + cookie_len > d + n) {
+ if ((d + n ) - p < cookie_len) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -927,7 +927,7 @@ int ssl3_get_client_hello(SSL *s)
p += cookie_len;
}
- if (p + 2 > d + n) {
+ if ((d + n ) - p < 2) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -941,7 +941,7 @@ int ssl3_get_client_hello(SSL *s)
}
/* i bytes of cipher data + 1 byte for compression length later */
- if ((p + i + 1) > (d + n)) {
+ if ((d + n) - p < i + 1) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
@@ -1007,7 +1007,7 @@ int ssl3_get_client_hello(SSL *s)
/* compression */
i = *(p++);
- if ((p + i) > (d + n)) {
+ if ((d + n) - p < i) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
@@ -1029,7 +1029,7 @@ int ssl3_get_client_hello(SSL *s)
#ifndef OPENSSL_NO_TLSEXT
/* TLS extensions */
if (s->version >= SSL3_VERSION) {
- if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) {
+ if (!ssl_parse_clienthello_tlsext(s, &p, d + n, &al)) {
/* 'al' set by ssl_parse_clienthello_tlsext */
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
goto f_err;
@@ -2526,6 +2526,12 @@ int ssl3_get_client_certificate(SSL *s)
goto f_err;
}
for (nc = 0; nc < llen;) {
+ if (nc + 3 > llen) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
n2l3(p, l);
if ((l + nc + 3) > llen) {
al = SSL_AD_DECODE_ERROR;
Modified: stable/9/crypto/openssl/ssl/ssl.h
==============================================================================
--- stable/9/crypto/openssl/ssl/ssl.h Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/ssl.h Fri Sep 23 07:44:10 2016 (r306229)
@@ -1803,6 +1803,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_DTLS1_HANDLE_TIMEOUT 282
# define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 277
+# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424
# define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256
# define SSL_F_DTLS1_PROCESS_RECORD 257
# define SSL_F_DTLS1_READ_BYTES 258
Modified: stable/9/crypto/openssl/ssl/ssl_err.c
==============================================================================
--- stable/9/crypto/openssl/ssl/ssl_err.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/ssl_err.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -1,6 +1,6 @@
/* ssl/ssl_err.c */
/* ====================================================================
- * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2016 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
@@ -92,6 +92,8 @@ static ERR_STRING_DATA SSL_str_functs[]
{ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT), "DTLS1_HANDLE_TIMEOUT"},
{ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"},
{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"},
+ {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS),
+ "DTLS1_PROCESS_BUFFERED_RECORDS"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),
"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"},
Modified: stable/9/crypto/openssl/ssl/ssl_locl.h
==============================================================================
--- stable/9/crypto/openssl/ssl/ssl_locl.h Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/ssl_locl.h Fri Sep 23 07:44:10 2016 (r306229)
@@ -910,7 +910,8 @@ int dtls1_retransmit_message(SSL *s, uns
unsigned long frag_off, int *found);
int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
int dtls1_retransmit_buffered_messages(SSL *s);
-void dtls1_clear_record_buffer(SSL *s);
+void dtls1_clear_received_buffer(SSL *s);
+void dtls1_clear_sent_buffer(SSL *s);
void dtls1_get_message_header(unsigned char *data,
struct hm_header_st *msg_hdr);
void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
@@ -1022,7 +1023,7 @@ unsigned char *ssl_add_clienthello_tlsex
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p,
unsigned char *limit);
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data,
- unsigned char *d, int n, int *al);
+ unsigned char *limit, int *al);
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data,
unsigned char *d, int n, int *al);
int ssl_prepare_clienthello_tlsext(SSL *s);
Modified: stable/9/crypto/openssl/ssl/ssl_sess.c
==============================================================================
--- stable/9/crypto/openssl/ssl/ssl_sess.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/ssl_sess.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -384,7 +384,7 @@ int ssl_get_prev_session(SSL *s, unsigne
if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
goto err;
- if (session_id + len > limit) {
+ if (limit - session_id < len) {
fatal = 1;
goto err;
}
Modified: stable/9/crypto/openssl/ssl/t1_lib.c
==============================================================================
--- stable/9/crypto/openssl/ssl/t1_lib.c Fri Sep 23 07:41:23 2016 (r306228)
+++ stable/9/crypto/openssl/ssl/t1_lib.c Fri Sep 23 07:44:10 2016 (r306229)
@@ -357,7 +357,7 @@ unsigned char *ssl_add_serverhello_tlsex
* 10.8..10.8.3 (which don't work).
*/
static void ssl_check_for_safari(SSL *s, const unsigned char *data,
- const unsigned char *d, int n)
+ const unsigned char *limit)
{
unsigned short type, size;
static const unsigned char kSafariExtensionsBlock[] = {
@@ -386,11 +386,11 @@ static void ssl_check_for_safari(SSL *s,
0x02, 0x03, /* SHA-1/ECDSA */
};
- if (data >= (d + n - 2))
+ if (limit - data <= 2)
return;
data += 2;
- if (data > (d + n - 4))
+ if (limit - data < 4)
return;
n2s(data, type);
n2s(data, size);
@@ -398,7 +398,7 @@ static void ssl_check_for_safari(SSL *s,
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > d + n)
+ if (limit - data < size)
return;
data += size;
@@ -406,7 +406,7 @@ static void ssl_check_for_safari(SSL *s,
const size_t len1 = sizeof(kSafariExtensionsBlock);
const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
- if (data + len1 + len2 != d + n)
+ if (limit - data != (int)(len1 + len2))
return;
if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
return;
@@ -415,7 +415,7 @@ static void ssl_check_for_safari(SSL *s,
} else {
const size_t len = sizeof(kSafariExtensionsBlock);
- if (data + len != d + n)
+ if (limit - data != (int)(len))
return;
if (memcmp(data, kSafariExtensionsBlock, len) != 0)
return;
@@ -425,8 +425,8 @@ static void ssl_check_for_safari(SSL *s,
}
# endif /* !OPENSSL_NO_EC */
-int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
- int n, int *al)
+int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
+ unsigned char *limit, int *al)
{
unsigned short type;
unsigned short size;
@@ -439,24 +439,26 @@ int ssl_parse_clienthello_tlsext(SSL *s,
# ifndef OPENSSL_NO_EC
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
- ssl_check_for_safari(s, data, d, n);
+ ssl_check_for_safari(s, data, limit);
# endif /* !OPENSSL_NO_EC */
- if (data >= (d + n - 2))
+ if (data == limit)
goto ri_check;
+ if (limit - data < 2)
+ goto err;
+
n2s(data, len);
- if (data > (d + n - len))
- goto ri_check;
+ if (limit - data != len)
+ goto err;
- while (data <= (d + n - 4)) {
+ while (limit - data >= 4) {
n2s(data, type);
n2s(data, size);
- if (data + size > (d + n))
- goto ri_check;
-
+ if (limit - data < size)
+ goto err;
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 0, type, data, size, s->tlsext_debug_arg);
/*-
@@ -580,6 +582,23 @@ int ssl_parse_clienthello_tlsext(SSL *s,
*al = SSL_AD_DECODE_ERROR;
return 0;
}
+
+ /*
+ * We remove any OCSP_RESPIDs from a previous handshake
+ * to prevent unbounded memory growth - CVE-2016-6304
+ */
+ sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids,
+ OCSP_RESPID_free);
+ if (dsize > 0) {
+ s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null();
+ if (s->tlsext_ocsp_ids == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else {
+ s->tlsext_ocsp_ids = NULL;
+ }
+
while (dsize > 0) {
OCSP_RESPID *id;
int idsize;
@@ -606,13 +625,6 @@ int ssl_parse_clienthello_tlsext(SSL *s,
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- if (!s->tlsext_ocsp_ids
- && !(s->tlsext_ocsp_ids =
- sk_OCSP_RESPID_new_null())) {
- OCSP_RESPID_free(id);
- *al = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) {
OCSP_RESPID_free(id);
*al = SSL_AD_INTERNAL_ERROR;
@@ -672,6 +684,10 @@ int ssl_parse_clienthello_tlsext(SSL *s,
}
return 1;
+
+err:
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
}
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
@@ -684,20 +700,20 @@ int ssl_parse_serverhello_tlsext(SSL *s,
int tlsext_servername = 0;
int renegotiate_seen = 0;
- if (data >= (d + n - 2))
+ if ((d + n) - data <= 2)
goto ri_check;
n2s(data, length);
- if (data + length != d + n) {
+ if ((d + n) - data != length) {
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- while (data <= (d + n - 4)) {
+ while ((d + n) - data >= 4) {
n2s(data, type);
n2s(data, size);
- if (data + size > (d + n))
+ if ((d + n) - data < size)
goto ri_check;
if (s->tlsext_debug_cb)
@@ -960,29 +976,33 @@ int tls1_process_ticket(SSL *s, unsigned
/* Skip past DTLS cookie */
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
i = *(p++);
- p += i;
- if (p >= limit)
+
+ if (limit - p <= i)
return -1;
+
+ p += i;
}
/* Skip past cipher list */
n2s(p, i);
- p += i;
- if (p >= limit)
+ if (limit - p <= i)
return -1;
+ p += i;
+
/* Skip past compression algorithm list */
i = *(p++);
- p += i;
- if (p > limit)
+ if (limit - p < i)
return -1;
+ p += i;
+
/* Now at start of extensions */
- if ((p + 2) >= limit)
+ if (limit - p <= 2)
return 1;
n2s(p, i);
- while ((p + 4) <= limit) {
+ while (limit - p >= 4) {
unsigned short type, size;
n2s(p, type);
n2s(p, size);
- if (p + size > limit)
+ if (limit - p < size)
return 1;
if (type == TLSEXT_TYPE_session_ticket) {
/*
@@ -1012,9 +1032,7 @@ static int tls_decrypt_ticket(SSL *s, co
HMAC_CTX hctx;
EVP_CIPHER_CTX ctx;
SSL_CTX *tctx = s->initial_ctx;
- /* Need at least keyname + iv + some encrypted data */
- if (eticklen < 48)
- goto tickerr;
+
/* Initialize session ticket encryption and HMAC contexts */
HMAC_CTX_init(&hctx);
EVP_CIPHER_CTX_init(&ctx);
@@ -1042,6 +1060,13 @@ static int tls_decrypt_ticket(SSL *s, co
* checks on ticket.
*/
mlen = HMAC_size(&hctx);
+ /* Sanity check ticket length: must exceed keyname + IV + HMAC */
+ if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) {
+ HMAC_CTX_cleanup(&hctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return 2;
+ }
+
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
HMAC_Update(&hctx, etick, eticklen);
More information about the svn-src-stable-9
mailing list