Date: Fri, 23 Sep 2016 07:59:16 +0000 (UTC) From: Xin LI <delphij@FreeBSD.org> To: doc-committers@freebsd.org, svn-doc-all@freebsd.org, svn-doc-head@freebsd.org Subject: svn commit: r49422 - in head/share: security/advisories security/patches/SA-16:26 xml Message-ID: <201609230759.u8N7xGWI038564@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: delphij Date: Fri Sep 23 07:59:16 2016 New Revision: 49422 URL: https://svnweb.freebsd.org/changeset/doc/49422 Log: Add SA-16:26. Added: head/share/security/advisories/FreeBSD-SA-16:26.openssl.asc (contents, props changed) head/share/security/patches/SA-16:26/ head/share/security/patches/SA-16:26/openssl-10.2.patch (contents, props changed) head/share/security/patches/SA-16:26/openssl-10.2.patch.asc (contents, props changed) head/share/security/patches/SA-16:26/openssl-10.3.patch (contents, props changed) head/share/security/patches/SA-16:26/openssl-10.3.patch.asc (contents, props changed) head/share/security/patches/SA-16:26/openssl-9.3.patch (contents, props changed) head/share/security/patches/SA-16:26/openssl-9.3.patch.asc (contents, props changed) Modified: head/share/xml/advisories.xml Added: head/share/security/advisories/FreeBSD-SA-16:26.openssl.asc ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/security/advisories/FreeBSD-SA-16:26.openssl.asc Fri Sep 23 07:59:16 2016 (r49422) @@ -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----- Added: head/share/security/patches/SA-16:26/openssl-10.2.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/security/patches/SA-16:26/openssl-10.2.patch Fri Sep 23 07:59:16 2016 (r49422) @@ -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; + } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609230759.u8N7xGWI038564>