From owner-svn-doc-head@FreeBSD.ORG Thu Mar 19 17:48:03 2015 Return-Path: Delivered-To: svn-doc-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 6F0D6D34; Thu, 19 Mar 2015 17:48:03 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 57937875; Thu, 19 Mar 2015 17:48:03 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t2JHm3v5076714; Thu, 19 Mar 2015 17:48:03 GMT (envelope-from delphij@FreeBSD.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t2JHm2Yq076705; Thu, 19 Mar 2015 17:48:02 GMT (envelope-from delphij@FreeBSD.org) Message-Id: <201503191748.t2JHm2Yq076705@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: delphij set sender to delphij@FreeBSD.org using -f From: Xin LI Date: Thu, 19 Mar 2015 17:48:02 +0000 (UTC) To: doc-committers@freebsd.org, svn-doc-all@freebsd.org, svn-doc-head@freebsd.org Subject: svn commit: r46358 - in head/share: security/advisories security/patches/SA-15:06 xml X-SVN-Group: doc-head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-doc-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the doc tree for head List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Mar 2015 17:48:03 -0000 Author: delphij Date: Thu Mar 19 17:48:01 2015 New Revision: 46358 URL: https://svnweb.freebsd.org/changeset/doc/46358 Log: Add SA-15:06.openssl. Added: head/share/security/advisories/FreeBSD-SA-15:06.openssl.asc (contents, props changed) head/share/security/patches/SA-15:06/ head/share/security/patches/SA-15:06/openssl-0.9.8.patch (contents, props changed) head/share/security/patches/SA-15:06/openssl-0.9.8.patch.asc (contents, props changed) head/share/security/patches/SA-15:06/openssl-1.0.1.patch (contents, props changed) head/share/security/patches/SA-15:06/openssl-1.0.1.patch.asc (contents, props changed) Modified: head/share/xml/advisories.xml Added: head/share/security/advisories/FreeBSD-SA-15:06.openssl.asc ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/security/advisories/FreeBSD-SA-15:06.openssl.asc Thu Mar 19 17:48:01 2015 (r46358) @@ -0,0 +1,197 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-15:06.openssl Security Advisory + The FreeBSD Project + +Topic: Multiple OpenSSL vulnerabilities + +Category: contrib +Module: openssl +Announced: 2015-03-19 +Affects: All supported versions of FreeBSD. +Corrected: 2015-03-19 17:40:43 UTC (stable/10, 10.1-STABLE) + 2015-03-19 17:42:38 UTC (releng/10.1, 10.1-RELEASE-p7) + 2015-03-19 17:40:43 UTC (stable/9, 9.3-STABLE) + 2015-03-19 17:42:38 UTC (releng/9.3, 9.3-RELEASE-p11) + 2015-03-19 17:40:43 UTC (stable/8, 8.4-STABLE) + 2015-03-19 17:42:38 UTC (releng/8.4, 8.4-RELEASE-p25) +CVE Name: CVE-2015-0209, CVE-2015-0286, CVE-2015-0287, CVE-2015-0288, + CVE-2015-0289, CVE-2015-0293 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit . + +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. + +Abstract Syntax Notation One (ASN.1) is a standard and notation that +describes rules and structures for representing, encoding, transmitting, +and decoding data in telecommunications and computer networking, which +enables representation of objects that are independent of machine-specific +encoding technique. + +II. Problem Description + +A malformed elliptic curve private key file could cause a use-after-free +condition in the d2i_ECPrivateKey function. [CVE-2015-0209] + +An attempt to compare ASN.1 boolean types will cause the ASN1_TYPE_cmp +function to crash with an invalid read. [CVE-2015-0286] + +Reusing a structure in ASN.1 parsing may allow an attacker to cause memory +corruption via an invalid write. [CVE-2015-0287] + +The function X509_to_X509_REQ will crash with a NULL pointer dereference if +the certificate key is invalid. [CVE-2015-0288] + +The PKCS#7 parsing code does not handle missing outer ContentInfo correctly. +[CVE-2015-0289] + +A malicious client can trigger an OPENSSL_assert in servers that both support +SSLv2 and enable export cipher suites by sending a specially crafted SSLv2 +CLIENT-MASTER-KEY message. [CVE-2015-0293] + +III. Impact + +A malformed elliptic curve private key file can cause server daemons using +OpenSSL to crash, resulting in a Denial of Service. [CVE-2015-0209] + +A remote attacker who is able to send specifically crafted certificates +may be able to crash an OpenSSL client or server. [CVE-2015-0286] + +An attacker who can cause invalid writes with applications that parse +structures containing CHOICE or ANY DEFINED BY components and reusing +the structures may be able to cause them to crash. Such reuse is believed +to be rare. OpenSSL clients and servers are not affected. [CVE-2015-0287] + +An attacker may be able to crash applications that create a new certificate +request with subject name the same as in an existing, specifically crafted +certificate. This usage is rare in practice. [CVE-2015-0288] + +An attacker may be able to crash applications that verify PKCS#7 signatures, +decrypt PKCS#7 data or otherwise parse PKCS#7 structures with specifically +crafted certificates. [CVE-2015-0289] + +A malicious client can trigger an OPENSSL_assert in servers that both support +SSLv2 and enable export cipher suites by sending a carefully crafted SSLv2 +CLIENT-MASTER-KEY message, resulting in a Denial of Service. [CVE-2015-0293] + +Note that two issues in the original OpenSSL advisory, CVE-2015-0204 and +CVE-2015-0292, were already addressed by FreeBSD-SA-15:01.openssl and +FreeBSD-EN-15:02.openssl. + +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. + +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 + +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 8.4 and FreeBSD 9.3] +# fetch https://security.FreeBSD.org/patches/SA-15:06/openssl-0.9.8.patch +# fetch https://security.FreeBSD.org/patches/SA-15:06/openssl-0.9.8.patch.asc +# gpg --verify openssl-0.9.8.patch.asc + +[FreeBSD 10.1] +# fetch https://security.FreeBSD.org/patches/SA-15:06/openssl-1.0.1.patch +# fetch https://security.FreeBSD.org/patches/SA-15:06/openssl-1.0.1.patch.asc +# gpg --verify openssl-1.0.1.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 . + +Restart all deamons using 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/8/ r280266 +releng/8.4/ r280268 +stable/9/ r280266 +releng/9.3/ r280268 +stable/10/ r280266 +releng/10.1/ r280268 +- ------------------------------------------------------------------------- + +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: + + + +VII. References + + + + + + + + + + + + + + + +The latest revision of this advisory is available at + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.1.2 (FreeBSD) + +iQIcBAEBCgAGBQJVCwr1AAoJEO1n7NZdz2rnayEP/0w3Pba5k/1G0mJ1T9APNAns +hhXm0YuR/rNJ1XBooWEOctrijlsVChcIt8KvJCU9apOZWjDvm/nvaQ077GCi5RSp +jhQBs8MLVfXzwMbJ0/uBpp6ChF8uafk5O+gr8ulb2jG6VIaLkGOWPYv61aRYSGxy +R7+6FxD8M0lLbGOQGETy1HxKzeWztA2p0ILORNAsi+bF8GSJpxGhSxqDDi4+ic/C +3oEw0zT/E6DhxJovOPebKq0eGcRbv7ETqDmtNQdqbOddV+0FY1E+nHtrAo6B/Kln +rL+meBJHmLeEREROFk4OvCynuROUJGmXJGKwjN3uOVM05qcEZS4NkVhFNrxt6S5H +t3wQ02SesbA3pbmce5OuXmlJgdL57DVlMb5sQjkqPeoJ6pn6Rz7VLSgLNfXDUSxs +x/Lgx0+qLQUubMud7zT97UIvZmDqFTWXfJu5S/0Qt8BPFunmoNJttJ5Cr+brzEtu +5RLjcvkC1giVCpSXS96QbeT67uqSkMZa8gtII8bA77HBGA0Ky8AOwTAXbCiUovuH +sLwsI8KUC3lsKUh7eyLsSm2+wRHn0e6dZ1PE0JRazCnCRboTvMWK2d4R7ANdrwsq +CgtCWLRz6vbB9J4XTNupcEoZGhIA4RuOBqx43eQmaRw1HoV3vn85QP94oL5jzXBd +UQg3YfrXHDlxCsqEzN7o +=wi0T +-----END PGP SIGNATURE----- Added: head/share/security/patches/SA-15:06/openssl-0.9.8.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/security/patches/SA-15:06/openssl-0.9.8.patch Thu Mar 19 17:48:01 2015 (r46358) @@ -0,0 +1,387 @@ +Index: crypto/openssl/crypto/asn1/a_type.c +=================================================================== +--- crypto/openssl/crypto/asn1/a_type.c (revision 280181) ++++ crypto/openssl/crypto/asn1/a_type.c (working copy) +@@ -121,6 +121,9 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_T + case V_ASN1_OBJECT: + result = OBJ_cmp(a->value.object, b->value.object); + break; ++ case V_ASN1_BOOLEAN: ++ result = a->value.boolean - b->value.boolean; ++ break; + case V_ASN1_NULL: + result = 0; /* They do not have content. */ + break; +Index: crypto/openssl/crypto/asn1/tasn_dec.c +=================================================================== +--- crypto/openssl/crypto/asn1/tasn_dec.c (revision 280181) ++++ crypto/openssl/crypto/asn1/tasn_dec.c (working copy) +@@ -125,16 +125,23 @@ unsigned long ASN1_tag2bit(int tag) + + ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, const ASN1_ITEM *it) +- { ++{ + ASN1_TLC c; + ASN1_VALUE *ptmpval = NULL; +- if (!pval) +- pval = &ptmpval; + c.valid = 0; +- if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) +- return *pval; ++ if (pval && *pval && it->itype == ASN1_ITYPE_PRIMITIVE) ++ ptmpval = *pval; ++ ++ if (ASN1_item_ex_d2i(&ptmpval, in, len, it, -1, 0, 0, &c) > 0) { ++ if (pval && it->itype != ASN1_ITYPE_PRIMITIVE) { ++ if (*pval) ++ ASN1_item_free(*pval, it); ++ *pval = ptmpval; ++ } ++ return ptmpval; ++ } + return NULL; +- } ++} + + int ASN1_template_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, const ASN1_TEMPLATE *tt) +@@ -309,13 +316,20 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsi + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it)) + goto auxerr; + +- /* Allocate structure */ +- if (!*pval && !ASN1_item_ex_new(pval, it)) +- { ++ if (*pval) { ++ /* Free up and zero CHOICE value if initialised */ ++ i = asn1_get_choice_selector(pval, it); ++ if ((i >= 0) && (i < it->tcount)) { ++ tt = it->templates + i; ++ pchptr = asn1_get_field_ptr(pval, tt); ++ ASN1_template_free(pchptr, tt); ++ asn1_set_choice_selector(pval, -1, it); ++ } ++ } else if (!ASN1_item_ex_new(pval, it)) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, + ERR_R_NESTED_ASN1_ERROR); + goto err; +- } ++ } + /* CHOICE type, try each possibility in turn */ + p = *in; + for (i = 0, tt=it->templates; i < it->tcount; i++, tt++) +@@ -405,6 +419,17 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsi + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it)) + goto auxerr; + ++ /* Free up and zero any ADB found */ ++ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { ++ if (tt->flags & ASN1_TFLG_ADB_MASK) { ++ const ASN1_TEMPLATE *seqtt; ++ ASN1_VALUE **pseqval; ++ seqtt = asn1_do_adb(pval, tt, 1); ++ pseqval = asn1_get_field_ptr(pval, seqtt); ++ ASN1_template_free(pseqval, seqtt); ++ } ++ } ++ + /* Get each field entry */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) + { +Index: crypto/openssl/crypto/pkcs7/pk7_doit.c +=================================================================== +--- crypto/openssl/crypto/pkcs7/pk7_doit.c (revision 280181) ++++ crypto/openssl/crypto/pkcs7/pk7_doit.c (working copy) +@@ -151,6 +151,25 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) + EVP_PKEY *pkey; + ASN1_OCTET_STRING *os=NULL; + ++ if (p7 == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); ++ return NULL; ++ } ++ /* ++ * The content field in the PKCS7 ContentInfo is optional, but that really ++ * only applies to inner content (precisely, detached signatures). ++ * ++ * When reading content, missing outer content is therefore treated as an ++ * error. ++ * ++ * When creating content, PKCS7_content_new() must be called before ++ * calling this method, so a NULL p7->d is always an error. ++ */ ++ if (p7->d.ptr == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); ++ return NULL; ++ } ++ + i=OBJ_obj2nid(p7->type); + p7->state=PKCS7_S_HEADER; + +@@ -344,6 +363,16 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, B + STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; + PKCS7_RECIP_INFO *ri=NULL; + ++ if (p7 == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); ++ return NULL; ++ } ++ ++ if (p7->d.ptr == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); ++ return NULL; ++ } ++ + i=OBJ_obj2nid(p7->type); + p7->state=PKCS7_S_HEADER; + +@@ -637,6 +666,16 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; + ASN1_OCTET_STRING *os=NULL; + ++ if (p7 == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); ++ return 0; ++ } ++ ++ if (p7->d.ptr == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); ++ return 0; ++ } ++ + EVP_MD_CTX_init(&ctx_tmp); + i=OBJ_obj2nid(p7->type); + p7->state=PKCS7_S_HEADER; +@@ -668,6 +707,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + /* If detached data then the content is excluded */ + if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { + M_ASN1_OCTET_STRING_free(os); ++ os = NULL; + p7->d.sign->contents->d.data = NULL; + } + break; +@@ -678,6 +718,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) + { + M_ASN1_OCTET_STRING_free(os); ++ os = NULL; + p7->d.digest->contents->d.data = NULL; + } + break; +@@ -813,8 +854,13 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); + } + +- if (!PKCS7_is_detached(p7)) +- { ++ if (!PKCS7_is_detached(p7)) { ++ /* ++ * NOTE(emilia): I think we only reach os == NULL here because detached ++ * digested data support is broken. ++ */ ++ if (os == NULL) ++ goto err; + btmp=BIO_find_type(bio,BIO_TYPE_MEM); + if (btmp == NULL) + { +@@ -849,6 +895,16 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_ + STACK_OF(X509) *cert; + X509 *x509; + ++ if (p7 == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); ++ return 0; ++ } ++ ++ if (p7->d.ptr == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); ++ return 0; ++ } ++ + if (PKCS7_type_is_signed(p7)) + { + cert=p7->d.sign->cert; +Index: crypto/openssl/crypto/pkcs7/pk7_lib.c +=================================================================== +--- crypto/openssl/crypto/pkcs7/pk7_lib.c (revision 280181) ++++ crypto/openssl/crypto/pkcs7/pk7_lib.c (working copy) +@@ -70,6 +70,7 @@ long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, cha + + switch (cmd) + { ++ /* NOTE(emilia): does not support detached digested data. */ + case PKCS7_OP_SET_DETACHED_SIGNATURE: + if (nid == NID_pkcs7_signed) + { +@@ -473,6 +474,8 @@ int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) + + STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) + { ++ if (p7 == NULL || p7->d.ptr == NULL) ++ return NULL; + if (PKCS7_type_is_signed(p7)) + { + return(p7->d.sign->signer_info); +Index: crypto/openssl/doc/crypto/d2i_X509.pod +=================================================================== +--- crypto/openssl/doc/crypto/d2i_X509.pod (revision 280181) ++++ crypto/openssl/doc/crypto/d2i_X509.pod (working copy) +@@ -199,6 +199,12 @@ B<*px> is valid is broken and some parts of the re + persist if they are not present in the new one. As a result the use + of this "reuse" behaviour is strongly discouraged. + ++Current versions of OpenSSL will not modify B<*px> if an error occurs. ++If parsing succeeds then B<*px> is freed (if it is not NULL) and then ++set to the value of the newly decoded structure. As a result B<*px> ++B be allocated on the stack or an attempt will be made to ++free an invalid pointer. ++ + i2d_X509() will not return an error in many versions of OpenSSL, + if mandatory fields are not initialized due to a programming error + then the encoded structure may contain invalid data or omit the +@@ -210,7 +216,9 @@ always succeed. + + d2i_X509(), d2i_X509_bio() and d2i_X509_fp() return a valid B structure + or B if an error occurs. The error code that can be obtained by +-L. ++L. If the "reuse" capability has been used ++with a valid X509 structure being passed in via B then the object is not ++modified in the event of error. + + i2d_X509() returns the number of bytes successfully encoded or a negative + value if an error occurs. The error code can be obtained by +Index: crypto/openssl/ssl/s2_lib.c +=================================================================== +--- crypto/openssl/ssl/s2_lib.c (revision 280181) ++++ crypto/openssl/ssl/s2_lib.c (working copy) +@@ -410,7 +410,7 @@ int ssl2_generate_key_material(SSL *s) + + OPENSSL_assert(s->session->master_key_length >= 0 + && s->session->master_key_length +- < (int)sizeof(s->session->master_key)); ++ <= (int)sizeof(s->session->master_key)); + EVP_DigestUpdate(&ctx,s->session->master_key,s->session->master_key_length); + EVP_DigestUpdate(&ctx,&c,1); + c++; +Index: crypto/openssl/ssl/s2_srvr.c +=================================================================== +--- crypto/openssl/ssl/s2_srvr.c (revision 280181) ++++ crypto/openssl/ssl/s2_srvr.c (working copy) +@@ -446,9 +446,6 @@ static int get_client_master_key(SSL *s) + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY); + return(-1); + } +- i=ssl_rsa_private_decrypt(s->cert,s->s2->tmp.enc, +- &(p[s->s2->tmp.clear]),&(p[s->s2->tmp.clear]), +- (s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING); + + is_export=SSL_C_IS_EXPORT(s->session->cipher); + +@@ -467,23 +464,61 @@ static int get_client_master_key(SSL *s) + else + ek=5; + ++ /* ++ * The format of the CLIENT-MASTER-KEY message is ++ * 1 byte message type ++ * 3 bytes cipher ++ * 2-byte clear key length (stored in s->s2->tmp.clear) ++ * 2-byte encrypted key length (stored in s->s2->tmp.enc) ++ * 2-byte key args length (IV etc) ++ * clear key ++ * encrypted key ++ * key args ++ * ++ * If the cipher is an export cipher, then the encrypted key bytes ++ * are a fixed portion of the total key (5 or 8 bytes). The size of ++ * this portion is in |ek|. If the cipher is not an export cipher, ++ * then the entire key material is encrypted (i.e., clear key length ++ * must be zero). ++ */ ++ if ((!is_export && s->s2->tmp.clear != 0) || ++ (is_export && s->s2->tmp.clear + ek != EVP_CIPHER_key_length(c))) { ++ ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); ++ SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_LENGTH); ++ return -1; ++ } ++ /* ++ * The encrypted blob must decrypt to the encrypted portion of the key. ++ * Decryption can't be expanding, so if we don't have enough encrypted ++ * bytes to fit the key in the buffer, stop now. ++ */ ++ if ((is_export && s->s2->tmp.enc < ek) || ++ (!is_export && s->s2->tmp.enc < EVP_CIPHER_key_length(c))) { ++ ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); ++ SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_LENGTH_TOO_SHORT); ++ return -1; ++ } ++ ++ i = ssl_rsa_private_decrypt(s->cert, s->s2->tmp.enc, ++ &(p[s->s2->tmp.clear]), ++ &(p[s->s2->tmp.clear]), ++ (s->s2->ssl2_rollback) ? RSA_SSLV23_PADDING : ++ RSA_PKCS1_PADDING); ++ + /* bad decrypt */ + #if 1 + /* If a bad decrypt, continue with protocol but with a + * random master secret (Bleichenbacher attack) */ +- if ((i < 0) || +- ((!is_export && (i != EVP_CIPHER_key_length(c))) +- || (is_export && ((i != ek) || (s->s2->tmp.clear+(unsigned int)i != +- (unsigned int)EVP_CIPHER_key_length(c)))))) +- { ++ if ((i < 0) || ((!is_export && i != EVP_CIPHER_key_length(c)) ++ || (is_export && i != ek))) { + ERR_clear_error(); + if (is_export) + i=ek; + else + i=EVP_CIPHER_key_length(c); +- if (RAND_pseudo_bytes(p,i) <= 0) ++ if (RAND_pseudo_bytes(&p[s->s2->tmp.clear], i) <= 0) + return 0; +- } ++ } + #else + if (i < 0) + { +@@ -505,7 +540,8 @@ static int get_client_master_key(SSL *s) + } + #endif + +- if (is_export) i+=s->s2->tmp.clear; ++ if (is_export) ++ i = EVP_CIPHER_key_length(c); + + if (i > SSL_MAX_MASTER_KEY_LENGTH) + { +Index: secure/lib/libcrypto/man/d2i_X509.3 +=================================================================== +--- secure/lib/libcrypto/man/d2i_X509.3 (revision 280181) ++++ secure/lib/libcrypto/man/d2i_X509.3 (working copy) +@@ -342,6 +342,12 @@ In some versions of OpenSSL the \*(L"reuse\*(R" be + persist if they are not present in the new one. As a result the use + of this \*(L"reuse\*(R" behaviour is strongly discouraged. + .PP ++Current versions of OpenSSL will not modify \fB*px\fR if an error occurs. ++If parsing succeeds then \fB*px\fR is freed (if it is not \s-1NULL\s0) and then ++set to the value of the newly decoded structure. As a result \fB*px\fR ++\&\fBmust not\fR be allocated on the stack or an attempt will be made to ++free an invalid pointer. ++.PP + \&\fIi2d_X509()\fR will not return an error in many versions of OpenSSL, + if mandatory fields are not initialized due to a programming error + then the encoded structure may contain invalid data or omit the +@@ -352,7 +358,9 @@ always succeed. + .IX Header "RETURN VALUES" + \&\fId2i_X509()\fR, \fId2i_X509_bio()\fR and \fId2i_X509_fp()\fR return a valid \fBX509\fR structure + or \fB\s-1NULL\s0\fR if an error occurs. The error code that can be obtained by +-\&\fIERR_get_error\fR\|(3). ++\&\fIERR_get_error\fR\|(3). If the \*(L"reuse\*(R" capability has been used ++with a valid X509 structure being passed in via \fBpx\fR then the object is not ++modified in the event of error. + .PP + \&\fIi2d_X509()\fR returns the number of bytes successfully encoded or a negative + value if an error occurs. The error code can be obtained by Added: head/share/security/patches/SA-15:06/openssl-0.9.8.patch.asc ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/security/patches/SA-15:06/openssl-0.9.8.patch.asc Thu Mar 19 17:48:01 2015 (r46358) @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.1.2 (FreeBSD) + +iQIcBAABCgAGBQJVCwsCAAoJEO1n7NZdz2rnWy4P+QGq5XsN4+SQb4B66MJeemw8 +5ogrKICDpYb5QciOxqaF/99XxheKvIFRQkc8Av/VMJrMrx7JJ2HKdMUD+ZrzlNYs +kAMEKBsgS4wj8bACWYCRN8zhztOVLNwzKSNPjjFQZOiQ7cDYI9U27Jj/uPb27/KJ +fSPQCoYCN47xrbWBuxbeJFqdSk3f9xSp3ZVMRkCUfMvme6LDdenqcZkGm6vE0128 +T3b9KHmk2RgwHklkrhiuR8u+27TjkgqL3KGgF2iKR28rkplgoupGpo/grp0kQQZU +u9AQQOQV7QrDkVdOVVEpo76z+qaZX8x/z3JPuxDcMxACa1SqKdGXYXlrEcn8e7xD +IAFAQRBMUnlr3WzxSGAFd2B2m8F0/7t2FPCKoqI2QzLmnte2zLUlpk5s5Ystx5ea +Y2sxgMC+19PfJZg+nlG5fj4sWRZVQqZ98Nob7e7naZySbC/G7W9VqhhwQm7f0yXI +dLjzBilVwJ7/6/EeXhms6N4IExULBx5sNKMyXJAWT7yhP2L9DOxffiyLLDM/WQV1 +IBWeDFTZs0rJtwurafU82zO1RWSLp8MmnAI3v8AeqUFzXUyWK6HhBQtXjBAOK+6j +6v49GPC4DKUUXVPu5K72pXQDv0KcCkRBS80EML+wHBe0NaMPWhwDf1KNL4p1uTOT +ueRwW6tDMa+DWPjUMqxN +=0rs2 +-----END PGP SIGNATURE----- Added: head/share/security/patches/SA-15:06/openssl-1.0.1.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/security/patches/SA-15:06/openssl-1.0.1.patch Thu Mar 19 17:48:01 2015 (r46358) @@ -0,0 +1,428 @@ +Index: crypto/openssl/crypto/asn1/a_type.c +=================================================================== +--- crypto/openssl/crypto/asn1/a_type.c (revision 280181) ++++ crypto/openssl/crypto/asn1/a_type.c (working copy) +@@ -124,6 +124,9 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_T + case V_ASN1_OBJECT: + result = OBJ_cmp(a->value.object, b->value.object); + break; ++ case V_ASN1_BOOLEAN: ++ result = a->value.boolean - b->value.boolean; ++ break; + case V_ASN1_NULL: + result = 0; /* They do not have content. */ + break; +Index: crypto/openssl/crypto/asn1/tasn_dec.c +=================================================================== +--- crypto/openssl/crypto/asn1/tasn_dec.c (revision 280181) ++++ crypto/openssl/crypto/asn1/tasn_dec.c (working copy) +@@ -127,16 +127,22 @@ unsigned long ASN1_tag2bit(int tag) + + ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, const ASN1_ITEM *it) +- { ++{ + ASN1_TLC c; + ASN1_VALUE *ptmpval = NULL; +- if (!pval) +- pval = &ptmpval; + asn1_tlc_clear_nc(&c); +- if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) +- return *pval; ++ if (pval && *pval && it->itype == ASN1_ITYPE_PRIMITIVE) ++ ptmpval = *pval; ++ if (ASN1_item_ex_d2i(&ptmpval, in, len, it, -1, 0, 0, &c) > 0) { ++ if (pval && it->itype != ASN1_ITYPE_PRIMITIVE) { ++ if (*pval) ++ ASN1_item_free(*pval, it); ++ *pval = ptmpval; ++ } ++ return ptmpval; ++ } + return NULL; +- } ++} + + int ASN1_template_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, const ASN1_TEMPLATE *tt) +@@ -311,13 +317,20 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsi + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) + goto auxerr; + +- /* Allocate structure */ +- if (!*pval && !ASN1_item_ex_new(pval, it)) +- { ++ if (*pval) { ++ /* Free up and zero CHOICE value if initialised */ ++ i = asn1_get_choice_selector(pval, it); ++ if ((i >= 0) && (i < it->tcount)) { ++ tt = it->templates + i; ++ pchptr = asn1_get_field_ptr(pval, tt); ++ ASN1_template_free(pchptr, tt); ++ asn1_set_choice_selector(pval, -1, it); ++ } ++ } else if (!ASN1_item_ex_new(pval, it)) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, + ERR_R_NESTED_ASN1_ERROR); + goto err; +- } ++ } + /* CHOICE type, try each possibility in turn */ + p = *in; + for (i = 0, tt=it->templates; i < it->tcount; i++, tt++) +@@ -407,6 +420,17 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsi + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) + goto auxerr; + ++ /* Free up and zero any ADB found */ ++ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { ++ if (tt->flags & ASN1_TFLG_ADB_MASK) { ++ const ASN1_TEMPLATE *seqtt; ++ ASN1_VALUE **pseqval; ++ seqtt = asn1_do_adb(pval, tt, 1); ++ pseqval = asn1_get_field_ptr(pval, seqtt); ++ ASN1_template_free(pseqval, seqtt); ++ } ++ } ++ + /* Get each field entry */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) + { +Index: crypto/openssl/crypto/pkcs7/pk7_doit.c +=================================================================== +--- crypto/openssl/crypto/pkcs7/pk7_doit.c (revision 280181) ++++ crypto/openssl/crypto/pkcs7/pk7_doit.c (working copy) +@@ -272,6 +272,25 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) + PKCS7_RECIP_INFO *ri=NULL; + ASN1_OCTET_STRING *os=NULL; + ++ if (p7 == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); ++ return NULL; ++ } ++ /* ++ * The content field in the PKCS7 ContentInfo is optional, but that really ++ * only applies to inner content (precisely, detached signatures). ++ * ++ * When reading content, missing outer content is therefore treated as an ++ * error. ++ * ++ * When creating content, PKCS7_content_new() must be called before ++ * calling this method, so a NULL p7->d is always an error. ++ */ ++ if (p7->d.ptr == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); ++ return NULL; ++ } ++ + i=OBJ_obj2nid(p7->type); + p7->state=PKCS7_S_HEADER; + +@@ -433,6 +452,16 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, B + unsigned char *ek = NULL, *tkey = NULL; + int eklen = 0, tkeylen = 0; + ++ if (p7 == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); ++ return NULL; ++ } ++ ++ if (p7->d.ptr == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); ++ return NULL; ++ } ++ + i=OBJ_obj2nid(p7->type); + p7->state=PKCS7_S_HEADER; + +@@ -752,6 +781,16 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; + ASN1_OCTET_STRING *os=NULL; + ++ if (p7 == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); ++ return 0; ++ } ++ ++ if (p7->d.ptr == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); ++ return 0; ++ } ++ + EVP_MD_CTX_init(&ctx_tmp); + i=OBJ_obj2nid(p7->type); + p7->state=PKCS7_S_HEADER; +@@ -796,6 +835,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + /* If detached data then the content is excluded */ + if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { + M_ASN1_OCTET_STRING_free(os); ++ os = NULL; + p7->d.sign->contents->d.data = NULL; + } + break; +@@ -806,6 +846,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) + { + M_ASN1_OCTET_STRING_free(os); ++ os = NULL; + p7->d.digest->contents->d.data = NULL; + } + break; +@@ -866,8 +907,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + } + } + } +- else if (i == NID_pkcs7_digest) +- { ++ else if (i == NID_pkcs7_digest) { + unsigned char md_data[EVP_MAX_MD_SIZE]; + unsigned int md_len; + if (!PKCS7_find_digest(&mdc, bio, +@@ -878,24 +918,31 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) + M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); + } + +- if (!PKCS7_is_detached(p7) && !(os->flags & ASN1_STRING_FLAG_NDEF)) +- { +- char *cont; +- long contlen; +- btmp=BIO_find_type(bio,BIO_TYPE_MEM); +- if (btmp == NULL) +- { +- PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); +- goto err; ++ if (!PKCS7_is_detached(p7)) { ++ /* ++ * NOTE(emilia): I think we only reach os == NULL here because detached ++ * digested data support is broken. ++ */ ++ if (os == NULL) ++ goto err; ++ if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { ++ char *cont; ++ long contlen; ++ btmp = BIO_find_type(bio, BIO_TYPE_MEM); ++ if (btmp == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); ++ goto err; + } +- contlen = BIO_get_mem_data(btmp, &cont); +- /* Mark the BIO read only then we can use its copy of the data +- * instead of making an extra copy. +- */ +- BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); +- BIO_set_mem_eof_return(btmp, 0); +- ASN1_STRING_set0(os, (unsigned char *)cont, contlen); ++ contlen = BIO_get_mem_data(btmp, &cont); ++ /* ++ * Mark the BIO read only then we can use its copy of the data ++ * instead of making an extra copy. ++ */ ++ BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); ++ BIO_set_mem_eof_return(btmp, 0); ++ ASN1_STRING_set0(os, (unsigned char *)cont, contlen); + } ++ } + ret=1; + err: + EVP_MD_CTX_cleanup(&ctx_tmp); +@@ -971,6 +1018,16 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_ + STACK_OF(X509) *cert; + X509 *x509; + ++ if (p7 == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); ++ return 0; ++ } ++ ++ if (p7->d.ptr == NULL) { ++ PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); ++ return 0; ++ } ++ + if (PKCS7_type_is_signed(p7)) + { + cert=p7->d.sign->cert; +Index: crypto/openssl/crypto/pkcs7/pk7_lib.c +=================================================================== +--- crypto/openssl/crypto/pkcs7/pk7_lib.c (revision 280181) ++++ crypto/openssl/crypto/pkcs7/pk7_lib.c (working copy) +@@ -71,6 +71,7 @@ long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, cha + + switch (cmd) + { ++ /* NOTE(emilia): does not support detached digested data. */ + case PKCS7_OP_SET_DETACHED_SIGNATURE: + if (nid == NID_pkcs7_signed) + { +@@ -459,6 +460,8 @@ int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) + + STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) + { ++ if (p7 == NULL || p7->d.ptr == NULL) ++ return NULL; + if (PKCS7_type_is_signed(p7)) + { + return(p7->d.sign->signer_info); +Index: crypto/openssl/doc/crypto/d2i_X509.pod +=================================================================== +--- crypto/openssl/doc/crypto/d2i_X509.pod (revision 280181) ++++ crypto/openssl/doc/crypto/d2i_X509.pod (working copy) +@@ -199,6 +199,12 @@ B<*px> is valid is broken and some parts of the re + persist if they are not present in the new one. As a result the use + of this "reuse" behaviour is strongly discouraged. + ++Current versions of OpenSSL will not modify B<*px> if an error occurs. ++If parsing succeeds then B<*px> is freed (if it is not NULL) and then ++set to the value of the newly decoded structure. As a result B<*px> ++B be allocated on the stack or an attempt will be made to ++free an invalid pointer. ++ + i2d_X509() will not return an error in many versions of OpenSSL, + if mandatory fields are not initialized due to a programming error + then the encoded structure may contain invalid data or omit the +@@ -210,7 +216,9 @@ always succeed. + + d2i_X509(), d2i_X509_bio() and d2i_X509_fp() return a valid B structure + or B if an error occurs. The error code that can be obtained by +-L. ++L. If the "reuse" capability has been used ++with a valid X509 structure being passed in via B then the object is not ++modified in the event of error. + + i2d_X509() returns the number of bytes successfully encoded or a negative + value if an error occurs. The error code can be obtained by +Index: crypto/openssl/ssl/s2_lib.c +=================================================================== +--- crypto/openssl/ssl/s2_lib.c (revision 280181) ++++ crypto/openssl/ssl/s2_lib.c (working copy) +@@ -488,7 +488,7 @@ int ssl2_generate_key_material(SSL *s) + + OPENSSL_assert(s->session->master_key_length >= 0 + && s->session->master_key_length +- < (int)sizeof(s->session->master_key)); ++ <= (int)sizeof(s->session->master_key)); + EVP_DigestUpdate(&ctx,s->session->master_key,s->session->master_key_length); + EVP_DigestUpdate(&ctx,&c,1); + c++; +Index: crypto/openssl/ssl/s2_srvr.c +=================================================================== +--- crypto/openssl/ssl/s2_srvr.c (revision 280181) ++++ crypto/openssl/ssl/s2_srvr.c (working copy) +@@ -454,9 +454,6 @@ static int get_client_master_key(SSL *s) + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY); + return(-1); + } +- i=ssl_rsa_private_decrypt(s->cert,s->s2->tmp.enc, +- &(p[s->s2->tmp.clear]),&(p[s->s2->tmp.clear]), +- (s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING); + + is_export=SSL_C_IS_EXPORT(s->session->cipher); + +@@ -475,23 +472,61 @@ static int get_client_master_key(SSL *s) + else + ek=5; + ++ /* ++ * The format of the CLIENT-MASTER-KEY message is ++ * 1 byte message type ++ * 3 bytes cipher ++ * 2-byte clear key length (stored in s->s2->tmp.clear) ++ * 2-byte encrypted key length (stored in s->s2->tmp.enc) ++ * 2-byte key args length (IV etc) ++ * clear key ++ * encrypted key ++ * key args ++ * ++ * If the cipher is an export cipher, then the encrypted key bytes ++ * are a fixed portion of the total key (5 or 8 bytes). The size of ++ * this portion is in |ek|. If the cipher is not an export cipher, ++ * then the entire key material is encrypted (i.e., clear key length ++ * must be zero). ++ */ ++ if ((!is_export && s->s2->tmp.clear != 0) || ++ (is_export && s->s2->tmp.clear + ek != EVP_CIPHER_key_length(c))) { ++ ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); ++ SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_LENGTH); ++ return -1; ++ } ++ /* ++ * The encrypted blob must decrypt to the encrypted portion of the key. ++ * Decryption can't be expanding, so if we don't have enough encrypted ++ * bytes to fit the key in the buffer, stop now. ++ */ ++ if ((is_export && s->s2->tmp.enc < ek) || ++ (!is_export && s->s2->tmp.enc < EVP_CIPHER_key_length(c))) { ++ ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); ++ SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_LENGTH_TOO_SHORT); ++ return -1; ++ } ++ ++ i = ssl_rsa_private_decrypt(s->cert, s->s2->tmp.enc, ++ &(p[s->s2->tmp.clear]), ++ &(p[s->s2->tmp.clear]), ++ (s->s2->ssl2_rollback) ? RSA_SSLV23_PADDING : ++ RSA_PKCS1_PADDING); ++ + /* bad decrypt */ + #if 1 + /* If a bad decrypt, continue with protocol but with a + * random master secret (Bleichenbacher attack) */ +- if ((i < 0) || +- ((!is_export && (i != EVP_CIPHER_key_length(c))) +- || (is_export && ((i != ek) || (s->s2->tmp.clear+(unsigned int)i != +- (unsigned int)EVP_CIPHER_key_length(c)))))) +- { ++ if ((i < 0) || ((!is_export && i != EVP_CIPHER_key_length(c)) ++ || (is_export && i != ek))) { + ERR_clear_error(); + if (is_export) + i=ek; + else + i=EVP_CIPHER_key_length(c); +- if (RAND_pseudo_bytes(p,i) <= 0) ++ if (RAND_pseudo_bytes(&p[s->s2->tmp.clear], i) <= 0) + return 0; +- } ++ } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***