Add SA-16:26.

This commit is contained in:
Xin LI 2016-09-23 07:59:16 +00:00
parent e0fa548c05
commit f9fe83c1ad
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=49422
8 changed files with 2830 additions and 0 deletions

View file

@ -0,0 +1,259 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
=============================================================================
FreeBSD-SA-16:26.openssl Security Advisory
The FreeBSD Project
Topic: Multiple OpenSSL vulnerabilities
Category: contrib
Module: openssl
Announced: 2016-09-23
Credits: OpenSSL Project
Affects: All supported versions of FreeBSD.
Corrected: 2016-09-22 14:57:48 UTC (stable/11, 11.0-STABLE)
2016-09-22 15:55:27 UTC (releng/11.0, 11.0-RELEASE)
2016-09-22 15:05:38 UTC (stable/10, 10.3-STABLE)
2016-09-23 07:48:34 UTC (releng/10.3, 10.3-RELEASE-p8)
2016-09-23 07:48:34 UTC (releng/10.2, 10.2-RELEASE-p21)
2016-09-23 07:48:34 UTC (releng/10.1, 10.1-RELEASE-p38)
2016-09-23 07:44:10 UTC (stable/9, 9.3-STABLE)
2016-09-23 07:48:34 UTC (releng/9.3, 9.3-RELEASE-p46)
CVE Name: CVE-2016-2177, CVE-2016-2178, CVE-2016-2179, CVE-2016-2180,
CVE-2016-2181, CVE-2016-2182, CVE-2016-6302, CVE-2016-6303,
CVE-2016-6304, CVE-2016-6306
For general information regarding FreeBSD Security Advisories,
including descriptions of the fields above, security branches, and the
following sections, please visit <URL:https://security.FreeBSD.org/>.
I. Background
FreeBSD includes software from the OpenSSL Project. The OpenSSL Project is
a collaborative effort to develop a robust, commercial-grade, full-featured
Open Source toolkit implementing the Secure Sockets Layer (SSL v2/v3)
and Transport Layer Security (TLS v1) protocols as well as a full-strength
general purpose cryptography library.
II. Problem Description
A malicious client can send an excessively large OCSP Status Request extension.
If that client continually requests renegotiation, sending a large OCSP Status
Request extension each time, then there will be unbounded memory growth on the
server. [CVE-2016-6304]
An overflow can occur in MDC2_Update() either if called directly or through
the EVP_DigestUpdate() function using MDC2. If an attacker is able to supply
very large amounts of input data after a previous call to EVP_EncryptUpdate()
with a partial block then a length check can overflow resulting in a heap
corruption. [CVE-2016-6303]
If a server uses SHA512 for TLS session ticket HMAC it is vulnerable to a
DoS attack where a malformed ticket will result in an OOB read which will
ultimately crash. [CVE-2016-6302]
The function BN_bn2dec() does not check the return value of BN_div_word().
This can cause an OOB write if an application uses this function with an
overly large BIGNUM. This could be a problem if an overly large certificate
or CRL is printed out from an untrusted source. TLS is not affected because
record limits will reject an oversized certificate before it is parsed.
[CVE-2016-2182]
The function TS_OBJ_print_bio() misuses OBJ_obj2txt(): the return value is
the total length the OID text representation would use and not the amount
of data written. This will result in OOB reads when large OIDs are presented.
[CVE-2016-2180]
Some calculations of limits in OpenSSL have used undefined pointer arithmetic.
This could cause problems with some malloc implementations. [CVE-2016-2177]
Operations in the DSA signing algorithm should run in constant time in order to
avoid side channel attacks. A flaw in the OpenSSL DSA implementation means that
a non-constant time codepath is followed for certain operations. [CVE-2016-2178]
In a DTLS connection where handshake messages are delivered out-of-order those
messages that OpenSSL is not yet ready to process will be buffered for later
use. Under certain circumstances, a flaw in the logic means that those messages
do not get removed from the buffer even though the handshake has been completed.
An attacker could force up to approx. 15 messages to remain in the buffer when
they are no longer required. These messages will be cleared when the DTLS
connection is closed. The default maximum size for a message is 100k. Therefore
the attacker could force an additional 1500k to be consumed per connection.
[CVE-2016-2179]
A flaw in the DTLS replay attack protection mechanism means that records that
arrive for future epochs update the replay protection "window" before the MAC
for the record has been validated. This could be exploited by an attacker by
sending a record for the next epoch (which does not have to decrypt or have a
valid MAC), with a very large sequence number. This means that all subsequent
legitimate packets are dropped causing a denial of service for a specific
DTLS connection. [CVE-2016-2181]
In OpenSSL 1.0.2 and earlier some missing message length checks can result in
OOB reads of up to 2 bytes beyond an allocated buffer. There is a theoretical
DoS risk but this has not been observed in practice on common platforms.
[CVE-2016-6306]
III. Impact
A remote attacker can cause OpenSSL server, regardless whether OCSP is supported,
to have unbounded memory growth, and eventually lead to a Denial of Service.
[CVE-2016-6304]
If an attacker is able to supply very large amounts of input data after a previous
call to EVP_EncryptUpdate() with a partial block then a length check can overflow
resulting in a heap corruption. [CVE-2016-6303]
An attacker who can send a malformed ticket to the server can cause an OOB read
which will ultimately lead to a crash, resulting in a Denial of Service.
[CVE-2016-6302]
A local attacker can cause an application that parses overly large certificate or
CRL to crash. TLS is not affected. [CVE-2016-2182]
A local attacker who can create a specially-crafted time stamp file and pass it
through the "ts" command of openssl(1) can cause it to crash. This functionality
is not used by the SSL/TLS implementation. [CVE-2016-2180]
Some OpenSSL code is questionable to integer overflow, which may lead to heap
corruption. [CVE-2016-2177]
An attacker may recover the private DSA key by conducting timing attack.
[CVE-2016-2178]
A remote attacker may cause a DTLS server to exhaust memory, resulting in a
Denial of Service. [CVE-2016-2179]
A remote attacker who can send DTLS records can cause the server to drop all
subsequent packets for a specific connection. [CVE-2016-2181]
A remote attacker can, in theory, cause OOB reads if the server enabled client
authentication. [CVE-2016-6306]
IV. Workaround
No workaround is available.
V. Solution
Perform one of the following:
1) Upgrade your vulnerable system to a supported FreeBSD stable or
release / security branch (releng) dated after the correction date.
Restart all daemons that use the library, or reboot the system.
2) To update your vulnerable system via a binary patch:
Systems running a RELEASE version of FreeBSD on the i386 or amd64
platforms can be updated via the freebsd-update(8) utility:
# freebsd-update fetch
# freebsd-update install
Restart all daemons that use the library, or reboot the system.
3) To update your vulnerable system via a source code patch:
The following patches have been verified to apply to the applicable
FreeBSD release branches.
a) Download the relevant patch from the location below, and verify the
detached PGP signature using your PGP utility.
[FreeBSD 10.3]
# fetch https://security.FreeBSD.org/patches/SA-16:26/openssl-10.3.patch
# fetch https://security.FreeBSD.org/patches/SA-16:26/openssl-10.3.patch.asc
# gpg --verify openssl-10.3.patch.asc
[FreeBSD 10.1 and 10.2]
# fetch https://security.FreeBSD.org/patches/SA-16:26/openssl-10.2.patch
# fetch https://security.FreeBSD.org/patches/SA-16:26/openssl-10.2.patch.as
# gpg --verify openssl-10.2.patch.asc
[FreeBSD 9.3]
# fetch https://security.FreeBSD.org/patches/SA-16:26/openssl-9.3.patch
# fetch https://security.FreeBSD.org/patches/SA-16:26/openssl-9.3.patch.as
# gpg --verify openssl-9.3.patch.asc
b) Apply the patch. Execute the following commands as root:
# cd /usr/src
# patch < /path/to/patch
c) Recompile the operating system using buildworld and installworld as
described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>.
Restart all daemons that use the library, or reboot the system.
VI. Correction details
The following list contains the correction revision numbers for each
affected branch.
Branch/path Revision
- -------------------------------------------------------------------------
stable/9/ r306229
releng/9.3/ r206230
stable/10/ r306196
releng/10.1/ r206230
releng/10.2/ r206230
releng/10.3/ r206230
stable/11/ r306195
releng/11.0/ r306198
- -------------------------------------------------------------------------
To see which files were modified by a particular revision, run the
following command, replacing NNNNNN with the revision number, on a
machine with Subversion installed:
# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base
Or visit the following URL, replacing NNNNNN with the revision number:
<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN>
VII. References
<URL:https://www.openssl.org/news/secadv/20160922.txt>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2177>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2178>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2179>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2180>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2181>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2182>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6302>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6303>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6304>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6306>
The latest revision of this advisory is available at
<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-16:26.openssl.asc>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.1.13 (FreeBSD)
iQIcBAEBCgAGBQJX5N+CAAoJEO1n7NZdz2rnRZEP/2/fe1c3tLZZAPguwphI7NFK
DoGODy5Uj/pMdMv2ZvSJaNFKX5bo4ph2mCtA3rxFhFX4PEDaRoZc4BIlN470qdDe
soBV0mJEHC8r0z8cw6WYbh4wbd2yYy2x95LFi3g/04udctGQyxWmEzkzjzT8SqxU
EMoZYZuYQTvr8paQGiUizLu61AFDM2sZhU8yW4euxxiIREbFTO8rC7DMAk3mKfNk
Og1NN6uVK7+AgxZRJtfrKPftdwGPfKPQKgR731goAghQihThNNDvQ8OdDwj8Mlh1
KI8u+GaVKUTfgS2Ra9a291nEqV0EHZkY3zSpp4LeCY93gpFQeEhS5M/32oFheP4+
qNQZdvDzKVBKT1NTzgDbMN++56/h0FDa9NkIQbZI9TwkOTbLeGNMWtC46Ngza3tz
avlSxxckCwelvmZcjntU3MakdWQhIgMRFvOzVDgfL+erUi3kot0+kgiXq+cn0UEa
ZHOCJWIzAh/PJGPNOJl71Ji3qb6iUJx31HmVLxyoofbfKmNsg72/ROqUgBLCYO3s
kW77yMNYEBAzdxeep8oNwMat9bZbxnhvAbr2v934SIndLQ5FtDJ/OdiCq3oXMbyE
uLFTjqGaTur7z26bibT72l4OEy7Qkt5G1EqefxTGHpY0UQhjQQVFWjwbFYq9RT40
60v4DC15ArshCN6tuyWt
=8wR6
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,847 @@
--- crypto/openssl/crypto/bn/bn_print.c.orig
+++ crypto/openssl/crypto/bn/bn_print.c
@@ -111,6 +111,7 @@
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 @@
*/
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 @@
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--;
/*
--- crypto/openssl/crypto/dsa/dsa_ossl.c.orig
+++ crypto/openssl/crypto/dsa/dsa_ossl.c
@@ -247,11 +247,13 @@
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))
@@ -264,6 +266,8 @@
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
@@ -282,6 +286,7 @@
} 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))
--- crypto/openssl/crypto/mdc2/mdc2dgst.c.orig
+++ crypto/openssl/crypto/mdc2/mdc2dgst.c
@@ -91,7 +91,7 @@
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;
--- crypto/openssl/crypto/ts/ts_lib.c.orig
+++ crypto/openssl/crypto/ts/ts_lib.c
@@ -90,9 +90,8 @@
{
char obj_txt[128];
- int len = OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
- BIO_write(bio, obj_txt, len);
- BIO_write(bio, "\n", 1);
+ OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
+ BIO_printf(bio, "%s\n", obj_txt);
return 1;
}
--- crypto/openssl/ssl/d1_both.c.orig
+++ crypto/openssl/ssl/d1_both.c
@@ -586,12 +586,24 @@
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;
+ 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);
+
+
/* Don't return if reassembly still in progress */
if (frag->reassembly != NULL)
return 0;
@@ -1388,18 +1400,6 @@
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,
--- crypto/openssl/ssl/d1_clnt.c.orig
+++ crypto/openssl/ssl/d1_clnt.c
@@ -740,6 +740,7 @@
/* done with handshaking */
s->d1->handshake_read_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
--- crypto/openssl/ssl/d1_lib.c.orig
+++ crypto/openssl/ssl/d1_lib.c
@@ -144,7 +144,6 @@
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) {
@@ -165,28 +164,44 @@
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;
dtls1_hm_fragment_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;
dtls1_hm_fragment_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);
@@ -420,7 +435,7 @@
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)
--- crypto/openssl/ssl/d1_pkt.c.orig
+++ crypto/openssl/ssl/d1_pkt.c
@@ -194,7 +194,7 @@
#endif
static int dtls1_buffer_record(SSL *s, record_pqueue *q,
unsigned char *priority);
-static int dtls1_process_record(SSL *s);
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
/* copy buffered record into SSL structure */
static int dtls1_copy_record(SSL *s, pitem *item)
@@ -319,21 +319,70 @@
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);
+ 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;
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
+#endif
+ {
+ /*
+ * 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 -1;
+ return 0;
}
}
@@ -344,7 +393,7 @@
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
@@ -391,7 +440,7 @@
#endif
-static int dtls1_process_record(SSL *s)
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
{
int i, al;
int enc_err;
@@ -551,6 +600,10 @@
/* we have pulled in a full packet so zero things */
s->packet_length = 0;
+
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+
return (1);
f_err:
@@ -581,11 +634,12 @@
rr = &(s->s3->rrec);
+ again:
/*
* The epoch may have changed. If so, process all the pending records.
* This is a non-blocking operation.
*/
- if (dtls1_process_buffered_records(s) < 0)
+ if (!dtls1_process_buffered_records(s))
return -1;
/* if we're renegotiating, then there may be buffered records */
@@ -593,7 +647,6 @@
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)) {
@@ -717,8 +770,6 @@
if (dtls1_buffer_record
(s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0)
return -1;
- /* Mark receipt of record. */
- dtls1_record_bitmap_update(s, bitmap);
}
rr->length = 0;
s->packet_length = 0;
@@ -725,12 +776,11 @@
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 */
}
- dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
return (1);
@@ -1814,8 +1864,13 @@
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;
@@ -1894,6 +1949,12 @@
s->d1->r_epoch++;
memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+
+ /*
+ * 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,
--- crypto/openssl/ssl/d1_srvr.c.orig
+++ crypto/openssl/ssl/d1_srvr.c
@@ -282,7 +282,7 @@
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)
@@ -845,6 +845,7 @@
/* 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; */
--- crypto/openssl/ssl/s3_clnt.c.orig
+++ crypto/openssl/ssl/s3_clnt.c
@@ -1143,6 +1143,12 @@
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;
@@ -2046,6 +2052,11 @@
}
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))
--- crypto/openssl/ssl/s3_srvr.c.orig
+++ crypto/openssl/ssl/s3_srvr.c
@@ -1041,7 +1041,7 @@
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;
@@ -1059,7 +1059,7 @@
/* 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;
@@ -1109,7 +1109,7 @@
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;
@@ -1116,7 +1116,7 @@
}
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;
@@ -1162,7 +1162,7 @@
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;
@@ -1176,7 +1176,7 @@
}
/* 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);
@@ -1242,7 +1242,7 @@
/* 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);
@@ -1264,7 +1264,7 @@
#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;
@@ -3218,6 +3218,12 @@
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;
--- crypto/openssl/ssl/ssl.h.orig
+++ crypto/openssl/ssl/ssl.h
@@ -2256,6 +2256,7 @@
# define SSL_F_DTLS1_HEARTBEAT 305
# define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288
+# 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
--- crypto/openssl/ssl/ssl_err.c.orig
+++ crypto/openssl/ssl/ssl_err.c
@@ -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
@@ -93,6 +93,8 @@
{ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "DTLS1_HEARTBEAT"},
{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"},
--- crypto/openssl/ssl/ssl_locl.h.orig
+++ crypto/openssl/ssl/ssl_locl.h
@@ -1025,7 +1025,8 @@
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);
@@ -1154,7 +1155,7 @@
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
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);
--- crypto/openssl/ssl/ssl_sess.c.orig
+++ crypto/openssl/ssl/ssl_sess.c
@@ -605,7 +605,7 @@
if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH)
goto err;
- if (session_id + len > limit) {
+ if (limit - session_id < len) {
fatal = 1;
goto err;
}
--- crypto/openssl/ssl/t1_lib.c.orig
+++ crypto/openssl/ssl/t1_lib.c
@@ -913,7 +913,7 @@
* 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[] = {
@@ -942,11 +942,11 @@
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);
@@ -954,7 +954,7 @@
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > d + n)
+ if (limit - data < size)
return;
data += size;
@@ -962,7 +962,7 @@
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;
@@ -971,7 +971,7 @@
} 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;
@@ -981,8 +981,8 @@
}
# 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;
@@ -1004,7 +1004,7 @@
# 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 */
# ifndef OPENSSL_NO_SRP
@@ -1016,22 +1016,22 @@
s->srtp_profile = NULL;
- if (data == d + n)
+ if (data == limit)
goto ri_check;
- if (data > (d + n - 2))
+ if (limit - data < 2)
goto err;
n2s(data, len);
- if (data > (d + n - len))
+ 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))
+ if (limit - data < size)
goto err;
# if 0
fprintf(stderr, "Received extension type %d size %d\n", type, size);
@@ -1284,6 +1284,23 @@
size -= 2;
if (dsize > size)
goto err;
+
+ /*
+ * 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;
@@ -1303,13 +1320,6 @@
OCSP_RESPID_free(id);
goto err;
}
- 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;
@@ -1396,7 +1406,7 @@
}
/* Spurious data on the end */
- if (data != d + n)
+ if (data != limit)
goto err;
*p = data;
@@ -1460,20 +1470,20 @@
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
# endif
- 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)
@@ -2181,29 +2191,33 @@
/* Skip past DTLS cookie */
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
i = *(p++);
+
+ if (limit - p <= i)
+ return -1;
+
p += i;
- if (p >= limit)
- return -1;
}
/* Skip past cipher list */
n2s(p, i);
+ if (limit - p <= i)
+ return -1;
p += i;
- if (p >= limit)
- return -1;
+
/* Skip past compression algorithm list */
i = *(p++);
+ if (limit - p < i)
+ return -1;
p += i;
- if (p > limit)
- return -1;
+
/* Now at start of extensions */
- if ((p + 2) >= limit)
+ if (limit - p <= 2)
return 0;
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 0;
if (type == TLSEXT_TYPE_session_ticket) {
int r;
@@ -2271,9 +2285,7 @@
HMAC_CTX hctx;
EVP_CIPHER_CTX ctx;
SSL_CTX *tctx = s->initial_ctx;
- /* Need at least keyname + iv + some encrypted data */
- if (eticklen < 48)
- return 2;
+
/* Initialize session ticket encryption and HMAC contexts */
HMAC_CTX_init(&hctx);
EVP_CIPHER_CTX_init(&ctx);
@@ -2305,6 +2317,13 @@
EVP_CIPHER_CTX_cleanup(&ctx);
return -1;
}
+ /* 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);

View file

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.1.13 (FreeBSD)
iQIcBAABCgAGBQJX5N+TAAoJEO1n7NZdz2rnYz0QAIYPSotTtGp8zb4bV3kKEMGQ
JwA9KgNSiZRaMrV/65lX0FWXzCnaL4wBh0yPNHzrQYCYFl7QpDr1ouTlUONZ25g2
JgnosFFpvREHq47lhJPnF/vCQ74YJVALeqmBr+duCPOIeJyV8HuqIaVzqamXgug9
OLKH4gqEvx+mIX+A17zAGHcF3JxiWJMrlsSXWWwGIq3bcjcPQyO9DcnBPQIpklb5
toyufSlAXkC42v9d85+W1O5IKqYSMNMCQjnF2Xh2i3uQ8ytOJaDPamLd6BRbxWv4
nz2cE+6M1k7i4jHNP3UU4ny6aUtuOjFXmSGVseAucOdT/3sdvzuvW6SZfql7HdQc
+tRnSJ5ZJy6O6R0i8KytexpjjtmJGn78qT+rEUkCUqFueVj5MKL2yZRVez8pepdW
++TrkZkrBr4BYxPZvMaLvaYov+PlPpVuVs31SJq8LGH1tQ4Fc03Wtg2wYYi0bgYx
/blhPxnlU0KyFKqUD4fqCYur7FvExUW9HR6/Sqt5c2gi5n8S+eNJHxvuLOyex5ZV
lsxho3OMIolEGSAfpsl15XwsctvraBaoIURcfocyU+Li0voLJ5YIMoBE5U7RNsAg
G7L/zxLjFDB0ddjpt6R+Ygt4M2UhCVUswkswJUxDPRQMne2hbEkfxyFtOSw4cZBm
WmhDsNoDgeMuY2/oBBsI
=439E
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,787 @@
--- crypto/openssl/crypto/bn/bn_print.c.orig
+++ crypto/openssl/crypto/bn/bn_print.c
@@ -111,6 +111,7 @@
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 @@
*/
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 @@
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--;
/*
--- crypto/openssl/crypto/dsa/dsa_ossl.c.orig
+++ crypto/openssl/crypto/dsa/dsa_ossl.c
@@ -247,11 +247,13 @@
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))
@@ -264,6 +266,8 @@
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
@@ -282,6 +286,7 @@
} 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))
--- crypto/openssl/crypto/mdc2/mdc2dgst.c.orig
+++ crypto/openssl/crypto/mdc2/mdc2dgst.c
@@ -91,7 +91,7 @@
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;
--- crypto/openssl/crypto/ts/ts_lib.c.orig
+++ crypto/openssl/crypto/ts/ts_lib.c
@@ -90,9 +90,8 @@
{
char obj_txt[128];
- int len = OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
- BIO_write(bio, obj_txt, len);
- BIO_write(bio, "\n", 1);
+ OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
+ BIO_printf(bio, "%s\n", obj_txt);
return 1;
}
--- crypto/openssl/ssl/d1_both.c.orig
+++ crypto/openssl/ssl/d1_both.c
@@ -614,12 +614,24 @@
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;
+ 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);
+
+
/* Don't return if reassembly still in progress */
if (frag->reassembly != NULL)
return 0;
@@ -1416,18 +1428,6 @@
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,
--- crypto/openssl/ssl/d1_clnt.c.orig
+++ crypto/openssl/ssl/d1_clnt.c
@@ -751,6 +751,7 @@
/* done with handshaking */
s->d1->handshake_read_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
--- crypto/openssl/ssl/d1_lib.c.orig
+++ crypto/openssl/ssl/d1_lib.c
@@ -144,7 +144,6 @@
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) {
@@ -165,28 +164,44 @@
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;
dtls1_hm_fragment_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;
dtls1_hm_fragment_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);
@@ -420,7 +435,7 @@
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)
--- crypto/openssl/ssl/d1_pkt.c.orig
+++ crypto/openssl/ssl/d1_pkt.c
@@ -194,7 +194,7 @@
#endif
static int dtls1_buffer_record(SSL *s, record_pqueue *q,
unsigned char *priority);
-static int dtls1_process_record(SSL *s);
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
/* copy buffered record into SSL structure */
static int dtls1_copy_record(SSL *s, pitem *item)
@@ -319,21 +319,70 @@
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);
+ 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;
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
+#endif
+ {
+ /*
+ * 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 -1;
+ return 0;
}
}
@@ -344,7 +393,7 @@
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
@@ -391,7 +440,7 @@
#endif
-static int dtls1_process_record(SSL *s)
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
{
int i, al;
int enc_err;
@@ -551,6 +600,10 @@
/* we have pulled in a full packet so zero things */
s->packet_length = 0;
+
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+
return (1);
f_err:
@@ -581,11 +634,12 @@
rr = &(s->s3->rrec);
+ again:
/*
* The epoch may have changed. If so, process all the pending records.
* This is a non-blocking operation.
*/
- if (dtls1_process_buffered_records(s) < 0)
+ if (!dtls1_process_buffered_records(s))
return -1;
/* if we're renegotiating, then there may be buffered records */
@@ -593,7 +647,6 @@
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)) {
@@ -717,8 +770,6 @@
if (dtls1_buffer_record
(s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0)
return -1;
- /* Mark receipt of record. */
- dtls1_record_bitmap_update(s, bitmap);
}
rr->length = 0;
s->packet_length = 0;
@@ -725,12 +776,11 @@
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 */
}
- dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
return (1);
@@ -1814,8 +1864,13 @@
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;
@@ -1894,6 +1949,12 @@
s->d1->r_epoch++;
memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+
+ /*
+ * 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,
--- crypto/openssl/ssl/d1_srvr.c.orig
+++ crypto/openssl/ssl/d1_srvr.c
@@ -295,7 +295,7 @@
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)
@@ -866,6 +866,7 @@
/* 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; */
--- crypto/openssl/ssl/s3_clnt.c.orig
+++ crypto/openssl/ssl/s3_clnt.c
@@ -1143,6 +1143,12 @@
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;
@@ -2072,6 +2078,11 @@
}
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))
--- crypto/openssl/ssl/s3_srvr.c.orig
+++ crypto/openssl/ssl/s3_srvr.c
@@ -1040,7 +1040,7 @@
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;
@@ -1058,7 +1058,7 @@
/* 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;
@@ -1114,7 +1114,7 @@
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;
@@ -1121,7 +1121,7 @@
}
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;
@@ -1166,7 +1166,7 @@
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;
@@ -1180,7 +1180,7 @@
}
/* 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);
@@ -1246,7 +1246,7 @@
/* 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);
@@ -3237,6 +3237,12 @@
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;
--- crypto/openssl/ssl/ssl.h.orig
+++ crypto/openssl/ssl/ssl.h
@@ -2256,6 +2256,7 @@
# define SSL_F_DTLS1_HEARTBEAT 305
# define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288
+# 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
--- crypto/openssl/ssl/ssl_err.c.orig
+++ crypto/openssl/ssl/ssl_err.c
@@ -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
@@ -93,6 +93,8 @@
{ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "DTLS1_HEARTBEAT"},
{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"},
--- crypto/openssl/ssl/ssl_locl.h.orig
+++ crypto/openssl/ssl/ssl_locl.h
@@ -1025,7 +1025,8 @@
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);
--- crypto/openssl/ssl/ssl_sess.c.orig
+++ crypto/openssl/ssl/ssl_sess.c
@@ -602,7 +602,7 @@
int r;
#endif
- if (session_id + len > limit) {
+ if (limit - session_id < len) {
fatal = 1;
goto err;
}
--- crypto/openssl/ssl/t1_lib.c.orig
+++ crypto/openssl/ssl/t1_lib.c
@@ -942,11 +942,11 @@
0x02, 0x03, /* SHA-1/ECDSA */
};
- if (data >= (limit - 2))
+ if (limit - data <= 2)
return;
data += 2;
- if (data > (limit - 4))
+ if (limit - data < 4)
return;
n2s(data, type);
n2s(data, size);
@@ -954,7 +954,7 @@
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > limit)
+ if (limit - data < size)
return;
data += size;
@@ -962,7 +962,7 @@
const size_t len1 = sizeof(kSafariExtensionsBlock);
const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
- if (data + len1 + len2 != limit)
+ if (limit - data != (int)(len1 + len2))
return;
if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
return;
@@ -971,7 +971,7 @@
} else {
const size_t len = sizeof(kSafariExtensionsBlock);
- if (data + len != limit)
+ if (limit - data != (int)(len))
return;
if (memcmp(data, kSafariExtensionsBlock, len) != 0)
return;
@@ -1019,19 +1019,19 @@
if (data == limit)
goto ri_check;
- if (data > (limit - 2))
+ if (limit - data < 2)
goto err;
n2s(data, len);
- if (data + len != limit)
+ if (limit - data != len)
goto err;
- while (data <= (limit - 4)) {
+ while (limit - data >= 4) {
n2s(data, type);
n2s(data, size);
- if (data + size > (limit))
+ if (limit - data < size)
goto err;
# if 0
fprintf(stderr, "Received extension type %d size %d\n", type, size);
@@ -1284,6 +1284,23 @@
size -= 2;
if (dsize > size)
goto err;
+
+ /*
+ * 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;
@@ -1303,13 +1320,6 @@
OCSP_RESPID_free(id);
goto err;
}
- 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;
@@ -1460,20 +1470,20 @@
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
# endif
- 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)
@@ -2179,29 +2189,33 @@
/* Skip past DTLS cookie */
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
i = *(p++);
+
+ if (limit - p <= i)
+ return -1;
+
p += i;
- if (p >= limit)
- return -1;
}
/* Skip past cipher list */
n2s(p, i);
+ if (limit - p <= i)
+ return -1;
p += i;
- if (p >= limit)
- return -1;
+
/* Skip past compression algorithm list */
i = *(p++);
+ if (limit - p < i)
+ return -1;
p += i;
- if (p > limit)
- return -1;
+
/* Now at start of extensions */
- if ((p + 2) >= limit)
+ if (limit - p <= 2)
return 0;
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 0;
if (type == TLSEXT_TYPE_session_ticket) {
int r;
@@ -2269,9 +2283,7 @@
HMAC_CTX hctx;
EVP_CIPHER_CTX ctx;
SSL_CTX *tctx = s->initial_ctx;
- /* Need at least keyname + iv + some encrypted data */
- if (eticklen < 48)
- return 2;
+
/* Initialize session ticket encryption and HMAC contexts */
HMAC_CTX_init(&hctx);
EVP_CIPHER_CTX_init(&ctx);
@@ -2305,6 +2317,13 @@
if (mlen < 0) {
goto err;
}
+ /* 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 */
if (HMAC_Update(&hctx, etick, eticklen) <= 0

View file

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.1.13 (FreeBSD)
iQIcBAABCgAGBQJX5N+WAAoJEO1n7NZdz2rnV3cP/0GDkFZT2nyXygWCgHnkA+jt
ga3bDirYeWr0n9VMM3RyruiO0O7TKwIypaJ9Zkyp5c4HpAhEVHp3df89/ZhmknDx
N04qmqVOSkPPSenqxF+4+eIe5/u4bN1Xp2NS61S6ksXxXXUa3TkXUqGzIv05ppBC
C5cti4VYFpQJZgWSLYvk12V6qylkBRfas+enhA6vTl3hBLBXvzXX8QpDSZE48bsf
a+QxrBwVzVXBVgWQwnJgluERKNnCClZHsloWRB7mnAUMVkReft3t/DXp+VFgue+B
wE9G0dXVtjMCkrMl7eyQNdKlp1yu+VrjvdNwBJR9FOVDk18gc2QshGBn7KMOUlLN
C4V6cf6P8PNL4PRn7D6PhDuoSWJgc1PTzZ71PQA94OBnlGC9IMB3Ts8g6REdpFqR
WIpyDRxFBXGNdZt3jKXa/zlwPen7GX8jg1JSiD/YrihtS2EymR1SvEZTZpLevYAB
g8ENV89GTAX/lQMiOX9BUJKSf4Saxh1C1F3ilhlaWkthMzwb13Ult8Pee/PYKJQf
X5I803QEjxhp8ZFDyPM1zp1vMGq9c/o696BQuzgNTmG+sW/ucAn/U+FmXNm8Q16D
j20LNHyOpcGbTEi6aEGt2xsLWREzuhTsNEG69vXzWMeGg0rqwf63KmxnIqZY0RUU
wbjYFMqoWZkEM0T55Qw5
=4wyK
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,874 @@
--- crypto/openssl/crypto/bn/bn_print.c.orig
+++ crypto/openssl/crypto/bn/bn_print.c
@@ -111,6 +111,7 @@
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 @@
*/
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 @@
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--;
/*
--- crypto/openssl/crypto/dsa/dsa_ossl.c.orig
+++ crypto/openssl/crypto/dsa/dsa_ossl.c
@@ -235,11 +235,13 @@
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 @@
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 @@
} 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))
--- crypto/openssl/crypto/mdc2/mdc2dgst.c.orig
+++ crypto/openssl/crypto/mdc2/mdc2dgst.c
@@ -94,7 +94,7 @@
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;
--- crypto/openssl/ssl/d1_both.c.orig
+++ crypto/openssl/ssl/d1_both.c
@@ -543,12 +543,24 @@
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;
+ 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);
+
+
/* Don't return if reassembly still in progress */
if (frag->reassembly != NULL)
return 0;
@@ -1335,18 +1347,6 @@
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,
--- crypto/openssl/ssl/d1_clnt.c.orig
+++ crypto/openssl/ssl/d1_clnt.c
@@ -564,6 +564,7 @@
/* done with handshaking */
s->d1->handshake_read_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
--- crypto/openssl/ssl/d1_lib.c.orig
+++ crypto/openssl/ssl/d1_lib.c
@@ -155,7 +155,6 @@
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,6 +175,24 @@
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);
@@ -182,7 +199,13 @@
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;
OPENSSL_free(frag->fragment);
@@ -189,17 +212,9 @@
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 @@
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)
--- crypto/openssl/ssl/d1_pkt.c.orig
+++ crypto/openssl/ssl/d1_pkt.c
@@ -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 @@
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_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 @@
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 @@
#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 @@
/* 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 @@
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 @@
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 @@
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,7 +685,9 @@
*/
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;
@@ -645,7 +694,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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,
--- crypto/openssl/ssl/d1_srvr.c.orig
+++ crypto/openssl/ssl/d1_srvr.c
@@ -242,7 +242,7 @@
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 @@
/* 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; */
--- crypto/openssl/ssl/s3_clnt.c.orig
+++ crypto/openssl/ssl/s3_clnt.c
@@ -931,6 +931,12 @@
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 @@
}
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))
--- crypto/openssl/ssl/s3_srvr.c.orig
+++ crypto/openssl/ssl/s3_srvr.c
@@ -819,7 +819,7 @@
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 @@
/* 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,7 +874,7 @@
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;
@@ -881,7 +881,7 @@
}
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 @@
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 @@
}
/* 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 @@
/* 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 @@
#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 @@
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;
--- crypto/openssl/ssl/ssl.h.orig
+++ crypto/openssl/ssl/ssl.h
@@ -1803,6 +1803,7 @@
# 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
--- crypto/openssl/ssl/ssl_err.c.orig
+++ crypto/openssl/ssl/ssl_err.c
@@ -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 @@
{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"},
--- crypto/openssl/ssl/ssl_locl.h.orig
+++ crypto/openssl/ssl/ssl_locl.h
@@ -910,7 +910,8 @@
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_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);
--- crypto/openssl/ssl/ssl_sess.c.orig
+++ crypto/openssl/ssl/ssl_sess.c
@@ -384,7 +384,7 @@
if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
goto err;
- if (session_id + len > limit) {
+ if (limit - session_id < len) {
fatal = 1;
goto err;
}
--- crypto/openssl/ssl/t1_lib.c.orig
+++ crypto/openssl/ssl/t1_lib.c
@@ -357,7 +357,7 @@
* 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 @@
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 @@
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > d + n)
+ if (limit - data < size)
return;
data += size;
@@ -406,7 +406,7 @@
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 @@
} 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 @@
}
# 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 @@
# 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 @@
*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 @@
*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 @@
}
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 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 @@
/* Skip past DTLS cookie */
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
i = *(p++);
+
+ if (limit - p <= i)
+ return -1;
+
p += i;
- if (p >= limit)
- return -1;
}
/* Skip past cipher list */
n2s(p, i);
+ if (limit - p <= i)
+ return -1;
p += i;
- if (p >= limit)
- return -1;
+
/* Skip past compression algorithm list */
i = *(p++);
+ if (limit - p < i)
+ return -1;
p += i;
- if (p > limit)
- return -1;
+
/* 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 @@
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 @@
* 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);

View file

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.1.13 (FreeBSD)
iQIcBAABCgAGBQJX5N+aAAoJEO1n7NZdz2rn/ecQAJl2+FSzL5P7Mhe00mhKAYsm
TtJHi1LFDpQYg6QRQvDzaJw1cJVrsmRw8eK5PQZvY18lWknGmTHp2XwdqsOVY5aQ
CAELzKjratPnQoI6x5zeHKUQsD4M/jjX3kBlk2UkiZ0iV99tMu1oUrDNOAZh8jCa
935p8mhIUn0SGdb/O87QiJNHyn+3AGw3RQfz9wCtFA3w0KVKdQpYxSrcgGHgavvT
gbe+22eWoaWN1HWvs8lqYAMRm1J7Wkmv6T9pyi7B/EKTj1mrQgOM2u4UJ8HiwRNH
R12viCQ4g0rSHAieAMTmfCcmini5QGtrGHgmXH10q/j+mlJ1n6fcURpSJ0BsLZ45
YmRCmHrsZlLOxtfPK7DWPrl3SzoWQZn3jaIGQlE+5SvYN2g5bJPQ7lvCJ8LGzV5V
Y0RF+2vvqXAV3AJy86zZGMoRu5YytVQR5EG9WIGmQYW9ShrbfFyZhBey0rZjxqWW
DhROzfhJiMwBSUxJUlqfKccmE9lDAZr2WnRDlJPhwX6fua6qLYZDqxSfLIzlLneJ
7xBGYAz33yqg780fNmqgQ0Z1ALJV4J3HFkFC4YEaf4z3oEGidAvKz3G2bHu/7lSs
BXfbEbotPaIcpJ6u+pS140AoADapFPoqYGam+7w28ZqpjS2Xx4FpSyXDruI8NO+O
kHFZbbFBQgsnB4A96Tsy
=BDuv
-----END PGP SIGNATURE-----

View file

@ -7,6 +7,18 @@
<year>
<name>2016</name>
<month>
<name>9</name>
<day>
<name>23</name>
<advisory>
<name>FreeBSD-SA-16:26.openssl</name>
</advisory>
</day>
</month>
<month>
<name>7</name>