Add SA-15:06.openssl.

This commit is contained in:
Xin LI 2015-03-19 17:48:01 +00:00
parent 37328bd4fd
commit 0c2ac51c94
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=46358
6 changed files with 1058 additions and 0 deletions

View file

@ -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 <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.
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 <URL:https://www.FreeBSD.org/handbook/makeworld.html>.
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:
<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN>
VII. References
<URL:https://www.openssl.org/news/secadv_20150319.txt>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-0209>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-0286>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-0287>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-0288>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-0289>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-0293>
The latest revision of this advisory is available at
<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-15:06.openssl.asc>
-----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-----

View file

@ -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<must not> 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<X509> structure
or B<NULL> if an error occurs. The error code that can be obtained by
-L<ERR_get_error(3)|ERR_get_error(3)>.
+L<ERR_get_error(3)|ERR_get_error(3)>. If the "reuse" capability has been used
+with a valid X509 structure being passed in via B<px> 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

View file

@ -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-----

View file

@ -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<must not> 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<X509> structure
or B<NULL> if an error occurs. The error code that can be obtained by
-L<ERR_get_error(3)|ERR_get_error(3)>.
+L<ERR_get_error(3)|ERR_get_error(3)>. If the "reuse" capability has been used
+with a valid X509 structure being passed in via B<px> 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;
- }
+ }
#else
if (i < 0)
{
@@ -513,7 +548,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

View file

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.1.2 (FreeBSD)
iQIcBAABCgAGBQJVCwsCAAoJEO1n7NZdz2rnYK0P/2grEYCuwKfz0hPaXpbahiD/
JZnpuyHg9BdRXGcBMboZoNUCx0DRfUVbvB3kD+sYxLvkA6TtlNSNQ6d5K3QUjBYk
VqIrhy5hSAQ6aIBuquLnYHmQk94LnDkxTV9rFsJwOLOY/Kou2qZTbbR6qpJ73o3/
vAuGcNGH4XFTltGPZNtXz1a7hQ/zaXJkfQKoSl7pd/tRybRce+UxSZOMs3LNjnxS
p3NQ5S/1jYc50uiLQhoAtac2kHzQox9l9DO2mX/R3tKV6XmCg5zj9B3p8dXce2fd
ik5wh1I4z9f7VFLnqwFOPz2fNBCL+B/TUi0mOvjm36huE8TGCok0Vfd1hhSUyPBh
3EAXScgAW/lMEe6wwsGaqCDUO1caVrn7S0cDNzQKj1T6EEEvVpbwLpN3tfODq2u0
fqq+K8/rugN0gl+6gdkpzXSUejNMWUGBk8lq5WhIkgNXIwfkzU3v9PqP7S66lL+m
S17SelupFLzbfDuQEiMoLT9KF/JHv40JIay3oh2NPUUB1JW8Ls3ZxHmXLRGGrIYx
jmTz3hnVSwuX+VyaXwVZHHFId39lyLth37672xVyO4+zzk5zBTQTdV+/ZjqPtpZb
0TYzrUofp+iEyIZfsm1roAlpvn2xjZ5iqGy6oTb+LK8cnCKiMXz9/3E5ZUSflD0X
U4gZKwpwe6opyyGLsUre
=v+Oh
-----END PGP SIGNATURE-----

View file

@ -7,6 +7,18 @@
<year>
<name>2015</name>
<month>
<name>3</name>
<day>
<name>19</name>
<advisory>
<name>FreeBSD-SA-15:06.openssl</name>
</advisory>
</day>
</month>
<month>
<name>2</name>