Add SA-16:26.
This commit is contained in:
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
259
share/security/advisories/FreeBSD-SA-16:26.openssl.asc
Normal file
259
share/security/advisories/FreeBSD-SA-16:26.openssl.asc
Normal 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-----
|
||||
847
share/security/patches/SA-16:26/openssl-10.2.patch
Normal file
847
share/security/patches/SA-16:26/openssl-10.2.patch
Normal 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);
|
||||
17
share/security/patches/SA-16:26/openssl-10.2.patch.asc
Normal file
17
share/security/patches/SA-16:26/openssl-10.2.patch.asc
Normal 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-----
|
||||
787
share/security/patches/SA-16:26/openssl-10.3.patch
Normal file
787
share/security/patches/SA-16:26/openssl-10.3.patch
Normal 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
|
||||
17
share/security/patches/SA-16:26/openssl-10.3.patch.asc
Normal file
17
share/security/patches/SA-16:26/openssl-10.3.patch.asc
Normal 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-----
|
||||
874
share/security/patches/SA-16:26/openssl-9.3.patch
Normal file
874
share/security/patches/SA-16:26/openssl-9.3.patch
Normal 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);
|
||||
17
share/security/patches/SA-16:26/openssl-9.3.patch.asc
Normal file
17
share/security/patches/SA-16:26/openssl-9.3.patch.asc
Normal 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-----
|
||||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue