Add SA-14:18.openssl.

This commit is contained in:
Xin LI 2014-09-09 10:29:20 +00:00
parent 3a9013aadd
commit 957bbade8e
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=45570
8 changed files with 1781 additions and 0 deletions

View file

@ -0,0 +1,193 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
=============================================================================
FreeBSD-SA-14:18.openssl Security Advisory
The FreeBSD Project
Topic: OpenSSL multiple vulnerabilities
Category: contrib
Module: openssl
Announced: 2014-09-09
Affects: All supported versions of FreeBSD.
Corrected: 2014-08-07 21:04:42 UTC (stable/10, 10.0-STABLE)
2014-09-09 10:09:46 UTC (releng/10.0, 10.0-RELEASE-p8)
2014-08-07 21:06:34 UTC (stable/9, 9.3-STABLE)
2014-09-09 10:13:46 UTC (releng/9.3, 9.3-RELEASE-p1)
2014-09-09 10:13:46 UTC (releng/9.2, 9.2-RELEASE-p11)
2014-09-09 10:13:46 UTC (releng/9.1, 9.1-RELEASE-p18)
2014-08-07 21:06:34 UTC (stable/8, 8.4-STABLE)
2014-09-09 10:13:46 UTC (releng/8.4, 8.4-RELEASE-p15)
CVE Name: CVE-2014-3506, CVE-2014-3507, CVE-2014-3508, CVE-2014-3510,
CVE-2014-3509, CVE-2014-3511, CVE-2014-3512, CVE-2014-5139
For general information regarding FreeBSD Security Advisories,
including descriptions of the fields above, security branches, and the
following sections, please visit <URL:http://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
The receipt of a specifically crafted DTLS handshake message may cause OpenSSL
to consume large amounts of memory. [CVE-2014-3506]
The receipt of a specifically crafted DTLS packet could cause OpenSSL to leak
memory. [CVE-2014-3507]
A flaw in OBJ_obj2txt may cause pretty printing functions such as
X509_name_oneline, X509_name_print_ex et al. to leak some information from
the stack. [CVE-2014-3508]
OpenSSL DTLS clients enabling anonymous (EC)DH ciphersuites are subject to
a denial of service attack. [CVE-2014-3510]
The following problems affect FreeBSD 10.0-RELEASE and later:
If a multithreaded client connects to a malicious server using a resumed
session and the server sends an ec point format extension it could write
up to 255 bytes to freed memory. [CVE-2014-3509]
A flaw in the OpenSSL SSL/TLS server code causes the server to negotiate
TLS 1.0 instead of higher protocol versions when the ClientHello message
is badly fragmented. [CVE-2014-3511]
A malicious client or server can send invalid SRP parameters and overrun
an internal buffer. [CVE-2014-3512]
A malicious server can crash the client with a NULL pointer dereference by
specifying a SRP ciphersuite even though it was not properly negotiated
with the client. [CVE-2014-5139]
III. Impact
A remote attacker may be able to cause a denial of service (application
crash, large memory consumption), obtain additional information,
cause protocol downgrade. Additionally, a remote attacker may be able
to run arbitrary code on a vulnerable system if the application has been
set up for SRP.
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 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.0]
# fetch http://security.FreeBSD.org/patches/SA-14:18/openssl-10.0.patch
# fetch http://security.FreeBSD.org/patches/SA-14:18/openssl-10.0.patch.asc
# gpg --verify openssl-10.0.patch.asc
[FreeBSD 9.3]
# fetch http://security.FreeBSD.org/patches/SA-14:18/openssl-9.3.patch
# fetch http://security.FreeBSD.org/patches/SA-14:18/openssl-9.3.patch.asc
# gpg --verify openssl-9.3.patch.asc
[FreeBSD 9.2, 9.1, 8.4]
# fetch http://security.FreeBSD.org/patches/SA-14:18/openssl-9.patch
# fetch http://security.FreeBSD.org/patches/SA-14:18/openssl-9.patch.asc
# gpg --verify openssl-9.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:http://www.FreeBSD.org/handbook/makeworld.html>.
Restart all deamons using the library, or reboot the system.
3) 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
VI. Correction details
The following list contains the correction revision numbers for each
affected branch.
Branch/path Revision
- -------------------------------------------------------------------------
stable/8/ r269687
releng/8.4/ r271305
stable/9/ r269687
releng/9.1/ r271305
releng/9.2/ r271305
releng/9.3/ r271305
stable/10/ r269686
releng/10.0/ r271304
- -------------------------------------------------------------------------
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:http://svnweb.freebsd.org/base?view=revision&revision=NNNNNN>
VII. References
<URL:https://www.openssl.org/news/secadv_20140806.txt>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3506>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3507>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3508>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3509>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3510>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3511>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3512>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-5139>
The latest revision of this advisory is available at
<URL:http://security.FreeBSD.org/advisories/FreeBSD-SA-14:18.openssl.asc>
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCgAGBQJUDtUBAAoJEO1n7NZdz2rnOUoP/jNoEEPVt1RoVPQoOQc6vno5
2HXcCDsu0ql3kCNIIZ7E6TddfduzV04EMzBrIgulg7eXft+Lnx6HlEgJOo7QLImc
aWLWxjcbyby6wrbYOc+FLK11yx9/uZJF0VCdSeyzhy0EFD3tOZPsDMXKZmG7FRkg
6A7ENJU25Mx8V1myzHw/VfDwAHCtXHliFVVE0CUku55pYnlhMeetu/wuB6KYbmgV
1WUamiHEGl4Dh4Up7nGHYYm32kqZLaE+cf1Ovc2VGT98ZyXmCgDB4+8kkA/HZxxp
DRgQlojeQhahee5MmzD+wMJXlq6dekoo+JVf22+Nb+oNmlKT6/UxtUhCwW11MLUV
rnOMr3u1JCNvBc+3KroSmtFeEtqh7jx3Ag4w8lS5mJO+wX1/lilbsFxSS/9G65fy
LqHUQSxkuDJ1bNzPfKreBPyUmQlG5t/3DonIDCF9r3sefDN+kxqe1+RwjdNRM0ov
V7OH/AW1NBQtV/F/h0tKCcskvcJo9Q+inAohheLPnWkFj7F2tLNt5TAxsGy7WvFZ
MuQSAXpZkdh7OkhAhBM3Xk+EOv7Qk7zZL5HJ1Lpm6kfJ8wSb4etoUV7oELaDMBz8
+9r+Vr9GtjSsec2a4tjNIixZKV9bzEhgKP5gsWD/JewhAzF+0bYNa9snOWxzpAYb
j+eW9IT7pEAJK9DtIsDd
=f4To
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,726 @@
Index: crypto/openssl/crypto/asn1/a_object.c
===================================================================
--- crypto/openssl/crypto/asn1/a_object.c (revision 270128)
+++ crypto/openssl/crypto/asn1/a_object.c (working copy)
@@ -283,6 +283,7 @@ err:
ASN1err(ASN1_F_D2I_ASN1_OBJECT,i);
return(NULL);
}
+
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long len)
{
@@ -289,12 +290,23 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, cons
ASN1_OBJECT *ret=NULL;
const unsigned char *p;
unsigned char *data;
- int i;
- /* Sanity check OID encoding: can't have leading 0x80 in
- * subidentifiers, see: X.690 8.19.2
+ int i, length;
+
+ /* Sanity check OID encoding.
+ * Need at least one content octet.
+ * MSB must be clear in the last octet.
+ * can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
*/
- for (i = 0, p = *pp; i < len; i++, p++)
+ if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
+ p[len - 1] & 0x80)
{
+ ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
+ return NULL;
+ }
+ /* Now 0 < len <= INT_MAX, so the cast is safe. */
+ length = (int)len;
+ for (i = 0; i < length; i++, p++)
+ {
if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
{
ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
@@ -316,23 +328,23 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, cons
data = (unsigned char *)ret->data;
ret->data = NULL;
/* once detached we can change it */
- if ((data == NULL) || (ret->length < len))
+ if ((data == NULL) || (ret->length < length))
{
ret->length=0;
if (data != NULL) OPENSSL_free(data);
- data=(unsigned char *)OPENSSL_malloc(len ? (int)len : 1);
+ data=(unsigned char *)OPENSSL_malloc(length);
if (data == NULL)
{ i=ERR_R_MALLOC_FAILURE; goto err; }
ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
}
- memcpy(data,p,(int)len);
+ memcpy(data,p,length);
/* reattach data to object, after which it remains const */
ret->data =data;
- ret->length=(int)len;
+ ret->length=length;
ret->sn=NULL;
ret->ln=NULL;
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
- p+=len;
+ p+=length;
if (a != NULL) (*a)=ret;
*pp=p;
Index: crypto/openssl/crypto/objects/obj_dat.c
===================================================================
--- crypto/openssl/crypto/objects/obj_dat.c (revision 270128)
+++ crypto/openssl/crypto/objects/obj_dat.c (working copy)
@@ -471,12 +471,13 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
const unsigned char *p;
char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
- if ((a == NULL) || (a->data == NULL)) {
- buf[0]='\0';
+ /* Ensure that, at every state, |buf| is NUL-terminated. */
+ if (buf && buf_len > 0)
+ buf[0] = '\0';
+
+ if ((a == NULL) || (a->data == NULL))
return(0);
- }
-
if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
{
const char *s;
@@ -554,9 +555,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
i=(int)(l/40);
l-=(long)(i*40);
}
- if (buf && (buf_len > 0))
+ if (buf && (buf_len > 1))
{
*buf++ = i + '0';
+ *buf = '\0';
buf_len--;
}
n++;
@@ -571,9 +573,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
i = strlen(bndec);
if (buf)
{
- if (buf_len > 0)
+ if (buf_len > 1)
{
*buf++ = '.';
+ *buf = '\0';
buf_len--;
}
BUF_strlcpy(buf,bndec,buf_len);
@@ -807,4 +810,3 @@ err:
OPENSSL_free(buf);
return(ok);
}
-
Index: crypto/openssl/crypto/srp/srp_lib.c
===================================================================
--- crypto/openssl/crypto/srp/srp_lib.c (revision 270128)
+++ crypto/openssl/crypto/srp/srp_lib.c (working copy)
@@ -85,6 +85,9 @@ static BIGNUM *srp_Calc_k(BIGNUM *N, BIGNUM *g)
int longg ;
int longN = BN_num_bytes(N);
+ if (BN_ucmp(g, N) >= 0)
+ return NULL;
+
if ((tmp = OPENSSL_malloc(longN)) == NULL)
return NULL;
BN_bn2bin(N,tmp) ;
@@ -117,6 +120,9 @@ BIGNUM *SRP_Calc_u(BIGNUM *A, BIGNUM *B, BIGNUM *N
if ((A == NULL) ||(B == NULL) || (N == NULL))
return NULL;
+ if (BN_ucmp(A, N) >= 0 || BN_ucmp(B, N) >= 0)
+ return NULL;
+
longN= BN_num_bytes(N);
if ((cAB = OPENSSL_malloc(2*longN)) == NULL)
Index: crypto/openssl/ssl/d1_both.c
===================================================================
--- crypto/openssl/ssl/d1_both.c (revision 270128)
+++ crypto/openssl/ssl/d1_both.c (working copy)
@@ -586,30 +586,33 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max,
return 0;
}
+/* dtls1_max_handshake_message_len returns the maximum number of bytes
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
+ * be greater if the maximum certificate list size requires it. */
+static unsigned long dtls1_max_handshake_message_len(const SSL *s)
+ {
+ unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (max_len < (unsigned long)s->max_cert_list)
+ return s->max_cert_list;
+ return max_len;
+ }
static int
-dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+dtls1_reassemble_fragment(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
{
hm_fragment *frag = NULL;
pitem *item = NULL;
int i = -1, is_complete;
unsigned char seq64be[8];
- unsigned long frag_len = msg_hdr->frag_len, max_len;
+ unsigned long frag_len = msg_hdr->frag_len;
- if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
+ if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
+ msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
goto err;
- /* Determine maximum allowed message size. Depends on (user set)
- * maximum certificate length, but 16k is minimum.
- */
- if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
- max_len = s->max_cert_list;
- else
- max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (frag_len == 0)
+ return DTLS1_HM_FRAGMENT_RETRY;
- if ((msg_hdr->frag_off+frag_len) > max_len)
- goto err;
-
/* Try to find item in queue */
memset(seq64be,0,sizeof(seq64be));
seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
@@ -638,7 +641,8 @@ static int
/* If message is already reassembled, this must be a
- * retransmit and can be dropped.
+ * retransmit and can be dropped. In this case item != NULL and so frag
+ * does not need to be freed.
*/
if (frag->reassembly == NULL)
{
@@ -658,7 +662,9 @@ static int
/* read the body of the fragment (header has already been read */
i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
frag->fragment + msg_hdr->frag_off,frag_len,0);
- if (i<=0 || (unsigned long)i!=frag_len)
+ if ((unsigned long)i!=frag_len)
+ i=-1;
+ if (i<=0)
goto err;
RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
@@ -675,10 +681,6 @@ static int
if (item == NULL)
{
- memset(seq64be,0,sizeof(seq64be));
- seq64be[6] = (unsigned char)(msg_hdr->seq>>8);
- seq64be[7] = (unsigned char)(msg_hdr->seq);
-
item = pitem_new(seq64be, frag);
if (item == NULL)
{
@@ -686,14 +688,18 @@ static int
i = -1;
}
- pqueue_insert(s->d1->buffered_messages, item);
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /* pqueue_insert fails iff a duplicate item is inserted.
+ * However, |item| cannot be a duplicate. If it were,
+ * |pqueue_find|, above, would have returned it and control
+ * would never have reached this branch. */
+ OPENSSL_assert(item != NULL);
}
return DTLS1_HM_FRAGMENT_RETRY;
err:
- if (frag != NULL) dtls1_hm_fragment_free(frag);
- if (item != NULL) OPENSSL_free(item);
+ if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
*ok = 0;
return i;
}
@@ -700,7 +706,7 @@ err:
static int
-dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
{
int i=-1;
hm_fragment *frag = NULL;
@@ -720,7 +726,7 @@ static int
/* If we already have an entry and this one is a fragment,
* don't discard it and rather try to reassemble it.
*/
- if (item != NULL && frag_len < msg_hdr->msg_len)
+ if (item != NULL && frag_len != msg_hdr->msg_len)
item = NULL;
/* Discard the message if sequence number was already there, is
@@ -745,9 +751,12 @@ static int
}
else
{
- if (frag_len && frag_len < msg_hdr->msg_len)
+ if (frag_len != msg_hdr->msg_len)
return dtls1_reassemble_fragment(s, msg_hdr, ok);
+ if (frag_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
frag = dtls1_hm_fragment_new(frag_len, 0);
if ( frag == NULL)
goto err;
@@ -759,26 +768,31 @@ static int
/* read the body of the fragment (header has already been read */
i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
frag->fragment,frag_len,0);
- if (i<=0 || (unsigned long)i!=frag_len)
+ if ((unsigned long)i!=frag_len)
+ i = -1;
+ if (i<=0)
goto err;
}
- memset(seq64be,0,sizeof(seq64be));
- seq64be[6] = (unsigned char)(msg_hdr->seq>>8);
- seq64be[7] = (unsigned char)(msg_hdr->seq);
-
item = pitem_new(seq64be, frag);
if ( item == NULL)
goto err;
- pqueue_insert(s->d1->buffered_messages, item);
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /* pqueue_insert fails iff a duplicate item is inserted.
+ * However, |item| cannot be a duplicate. If it were,
+ * |pqueue_find|, above, would have returned it. Then, either
+ * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
+ * to NULL and it will have been processed with
+ * |dtls1_reassemble_fragment|, above, or the record will have
+ * been discarded. */
+ OPENSSL_assert(item != NULL);
}
return DTLS1_HM_FRAGMENT_RETRY;
err:
- if ( frag != NULL) dtls1_hm_fragment_free(frag);
- if ( item != NULL) OPENSSL_free(item);
+ if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
*ok = 0;
return i;
}
Index: crypto/openssl/ssl/d1_clnt.c
===================================================================
--- crypto/openssl/ssl/d1_clnt.c (revision 270128)
+++ crypto/openssl/ssl/d1_clnt.c (working copy)
@@ -982,6 +982,13 @@ int dtls1_send_client_key_exchange(SSL *s)
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+ if (s->session->sess_cert == NULL)
+ {
+ /* We should always have a server certificate with SSL_kRSA. */
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_rsa_tmp != NULL)
rsa=s->session->sess_cert->peer_rsa_tmp;
else
@@ -1172,6 +1179,13 @@ int dtls1_send_client_key_exchange(SSL *s)
{
DH *dh_srvr,*dh_clnt;
+ if (s->session->sess_cert == NULL)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_dh_tmp != NULL)
dh_srvr=s->session->sess_cert->peer_dh_tmp;
else
@@ -1231,6 +1245,13 @@ int dtls1_send_client_key_exchange(SSL *s)
int ecdh_clnt_cert = 0;
int field_size = 0;
+ if (s->session->sess_cert == NULL)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
/* Did we send out the client's
* ECDH share for use in premaster
* computation as part of client certificate?
@@ -1706,5 +1727,3 @@ int dtls1_send_client_certificate(SSL *s)
/* SSL3_ST_CW_CERT_D */
return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
}
-
-
Index: crypto/openssl/ssl/s23_srvr.c
===================================================================
--- crypto/openssl/ssl/s23_srvr.c (revision 270128)
+++ crypto/openssl/ssl/s23_srvr.c (working copy)
@@ -348,16 +348,12 @@ int ssl23_get_client_hello(SSL *s)
* Client Hello message, this would be difficult, and we'd have
* to read more records to find out.
* No known SSL 3.0 client fragments ClientHello like this,
- * so we simply assume TLS 1.0 to avoid protocol version downgrade
- * attacks. */
+ * so we simply reject such connections to avoid
+ * protocol version downgrade attacks. */
if (p[3] == 0 && p[4] < 6)
{
-#if 0
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL);
goto err;
-#else
- v[1] = TLS1_VERSION_MINOR;
-#endif
}
/* if major version number > 3 set minor to a value
* which will use the highest version 3 we support.
@@ -364,7 +360,7 @@ int ssl23_get_client_hello(SSL *s)
* If TLS 2.0 ever appears we will need to revise
* this....
*/
- else if (p[9] > SSL3_VERSION_MAJOR)
+ if (p[9] > SSL3_VERSION_MAJOR)
v[1]=0xff;
else
v[1]=p[10]; /* minor version according to client_version */
@@ -444,6 +440,18 @@ int ssl23_get_client_hello(SSL *s)
v[0] = p[3]; /* == SSL3_VERSION_MAJOR */
v[1] = p[4];
+ /* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
+ * header is sent directly on the wire, not wrapped as a TLS
+ * record. It's format is:
+ * Byte Content
+ * 0-1 msg_length
+ * 2 msg_type
+ * 3-4 version
+ * 5-6 cipher_spec_length
+ * 7-8 session_id_length
+ * 9-10 challenge_length
+ * ... ...
+ */
n=((p[0]&0x7f)<<8)|p[1];
if (n > (1024*4))
{
@@ -450,8 +458,16 @@ int ssl23_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE);
goto err;
}
+ if (n < 9)
+ {
+ SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
+ goto err;
+ }
j=ssl23_read_bytes(s,n+2);
+ /* We previously read 11 bytes, so if j > 0, we must have
+ * j == n+2 == s->packet_length. We have at least 11 valid
+ * packet bytes. */
if (j <= 0) return(j);
ssl3_finish_mac(s, s->packet+2, s->packet_length-2);
Index: crypto/openssl/ssl/s3_clnt.c
===================================================================
--- crypto/openssl/ssl/s3_clnt.c (revision 270128)
+++ crypto/openssl/ssl/s3_clnt.c (working copy)
@@ -953,6 +953,15 @@ int ssl3_get_server_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
goto f_err;
}
+#ifndef OPENSSL_NO_SRP
+ if (((c->algorithm_mkey & SSL_kSRP) || (c->algorithm_auth & SSL_aSRP)) &&
+ !(s->srp_ctx.srp_Mask & SSL_kSRP))
+ {
+ al=SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
+#endif /* OPENSSL_NO_SRP */
p+=ssl_put_cipher_by_char(s,NULL,NULL);
sk=ssl_get_ciphers_by_id(s);
@@ -1459,6 +1468,12 @@ int ssl3_get_key_exchange(SSL *s)
p+=i;
n-=param_len;
+ if (!srp_verify_server_param(s, &al))
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS);
+ goto f_err;
+ }
+
/* We must check if there is a certificate */
#ifndef OPENSSL_NO_RSA
if (alg_a & SSL_aRSA)
@@ -2252,6 +2267,13 @@ int ssl3_send_client_key_exchange(SSL *s)
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+ if (s->session->sess_cert == NULL)
+ {
+ /* We should always have a server certificate with SSL_kRSA. */
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_rsa_tmp != NULL)
rsa=s->session->sess_cert->peer_rsa_tmp;
else
Index: crypto/openssl/ssl/s3_lib.c
===================================================================
--- crypto/openssl/ssl/s3_lib.c (revision 270128)
+++ crypto/openssl/ssl/s3_lib.c (working copy)
@@ -2426,7 +2426,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
SSL_kSRP,
- SSL_aNULL,
+ SSL_aSRP,
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
@@ -2474,7 +2474,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA,
TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA,
SSL_kSRP,
- SSL_aNULL,
+ SSL_aSRP,
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
@@ -2522,7 +2522,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA,
TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA,
SSL_kSRP,
- SSL_aNULL,
+ SSL_aSRP,
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
Index: crypto/openssl/ssl/s3_srvr.c
===================================================================
--- crypto/openssl/ssl/s3_srvr.c (revision 270128)
+++ crypto/openssl/ssl/s3_srvr.c (working copy)
@@ -2798,6 +2798,13 @@ int ssl3_get_client_key_exchange(SSL *s)
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB);
goto err;
}
+ if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0
+ || BN_is_zero(s->srp_ctx.A))
+ {
+ al=SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS);
+ goto f_err;
+ }
if (s->session->srp_username != NULL)
OPENSSL_free(s->session->srp_username);
s->session->srp_username = BUF_strdup(s->srp_ctx.login);
Index: crypto/openssl/ssl/ssl.h
===================================================================
--- crypto/openssl/ssl/ssl.h (revision 270128)
+++ crypto/openssl/ssl/ssl.h (working copy)
@@ -264,6 +264,7 @@ extern "C" {
#define SSL_TXT_aGOST94 "aGOST94"
#define SSL_TXT_aGOST01 "aGOST01"
#define SSL_TXT_aGOST "aGOST"
+#define SSL_TXT_aSRP "aSRP"
#define SSL_TXT_DSS "DSS"
#define SSL_TXT_DH "DH"
@@ -2309,6 +2310,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_BAD_SRP_B_LENGTH 348
#define SSL_R_BAD_SRP_G_LENGTH 349
#define SSL_R_BAD_SRP_N_LENGTH 350
+#define SSL_R_BAD_SRP_PARAMETERS 371
#define SSL_R_BAD_SRP_S_LENGTH 351
#define SSL_R_BAD_SRTP_MKI_VALUE 352
#define SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST 353
Index: crypto/openssl/ssl/ssl_ciph.c
===================================================================
--- crypto/openssl/ssl/ssl_ciph.c (revision 270128)
+++ crypto/openssl/ssl/ssl_ciph.c (working copy)
@@ -270,6 +270,7 @@ static const SSL_CIPHER cipher_aliases[]={
{0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0},
{0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0},
{0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0},
+ {0,SSL_TXT_aSRP,0, 0,SSL_aSRP, 0,0,0,0,0,0,0},
/* aliases combining key exchange and server authentication */
{0,SSL_TXT_EDH,0, SSL_kEDH,~SSL_aNULL,0,0,0,0,0,0,0},
@@ -1628,6 +1629,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cip
case SSL_aPSK:
au="PSK";
break;
+ case SSL_aSRP:
+ au="SRP";
+ break;
default:
au="unknown";
break;
Index: crypto/openssl/ssl/ssl_err.c
===================================================================
--- crypto/openssl/ssl/ssl_err.c (revision 270128)
+++ crypto/openssl/ssl/ssl_err.c (working copy)
@@ -329,6 +329,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_BAD_SRP_B_LENGTH) ,"bad srp b length"},
{ERR_REASON(SSL_R_BAD_SRP_G_LENGTH) ,"bad srp g length"},
{ERR_REASON(SSL_R_BAD_SRP_N_LENGTH) ,"bad srp n length"},
+{ERR_REASON(SSL_R_BAD_SRP_PARAMETERS) ,"bad srp parameters"},
{ERR_REASON(SSL_R_BAD_SRP_S_LENGTH) ,"bad srp s length"},
{ERR_REASON(SSL_R_BAD_SRTP_MKI_VALUE) ,"bad srtp mki value"},
{ERR_REASON(SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST),"bad srtp protection profile list"},
Index: crypto/openssl/ssl/ssl_lib.c
===================================================================
--- crypto/openssl/ssl/ssl_lib.c (revision 270128)
+++ crypto/openssl/ssl/ssl_lib.c (working copy)
@@ -1402,6 +1402,11 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_C
s->psk_client_callback == NULL)
continue;
#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (((c->algorithm_mkey & SSL_kSRP) || (c->algorithm_auth & SSL_aSRP)) &&
+ !(s->srp_ctx.srp_Mask & SSL_kSRP))
+ continue;
+#endif /* OPENSSL_NO_SRP */
j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
p+=j;
}
Index: crypto/openssl/ssl/ssl_locl.h
===================================================================
--- crypto/openssl/ssl/ssl_locl.h (revision 270128)
+++ crypto/openssl/ssl/ssl_locl.h (working copy)
@@ -311,6 +311,7 @@
#define SSL_aPSK 0x00000080L /* PSK auth */
#define SSL_aGOST94 0x00000100L /* GOST R 34.10-94 signature auth */
#define SSL_aGOST01 0x00000200L /* GOST R 34.10-2001 signature auth */
+#define SSL_aSRP 0x00000400L /* SRP auth */
/* Bits for algorithm_enc (symmetric encryption) */
@@ -1173,4 +1174,6 @@ void tls_fips_digest_extra(
const EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *mac_ctx,
const unsigned char *data, size_t data_len, size_t orig_len);
+int srp_verify_server_param(SSL *s, int *al);
+
#endif
Index: crypto/openssl/ssl/t1_lib.c
===================================================================
--- crypto/openssl/ssl/t1_lib.c (revision 270128)
+++ crypto/openssl/ssl/t1_lib.c (working copy)
@@ -1446,15 +1446,18 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
- s->session->tlsext_ecpointformatlist_length = 0;
- if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
- if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+ if (!s->hit)
{
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
+ s->session->tlsext_ecpointformatlist_length = 0;
+ if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
+ if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+ memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
}
- s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
#if 0
fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
sdata = s->session->tlsext_ecpointformatlist;
Index: crypto/openssl/ssl/tls_srp.c
===================================================================
--- crypto/openssl/ssl/tls_srp.c (revision 270128)
+++ crypto/openssl/ssl/tls_srp.c (working copy)
@@ -408,17 +408,47 @@ err:
return ret;
}
+int srp_verify_server_param(SSL *s, int *al)
+ {
+ SRP_CTX *srp = &s->srp_ctx;
+ /* Sanity check parameters: we can quickly check B % N == 0
+ * by checking B != 0 since B < N
+ */
+ if (BN_ucmp(srp->g, srp->N) >=0 || BN_ucmp(srp->B, srp->N) >= 0
+ || BN_is_zero(srp->B))
+ {
+ *al = SSL3_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ if (BN_num_bits(srp->N) < srp->strength)
+ {
+ *al = TLS1_AD_INSUFFICIENT_SECURITY;
+ return 0;
+ }
+
+ if (srp->SRP_verify_param_callback)
+ {
+ if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0)
+ {
+ *al = TLS1_AD_INSUFFICIENT_SECURITY;
+ return 0;
+ }
+ }
+ else if(!SRP_check_known_gN_param(srp->g, srp->N))
+ {
+ *al = TLS1_AD_INSUFFICIENT_SECURITY;
+ return 0;
+ }
+
+ return 1;
+ }
+
+
int SRP_Calc_A_param(SSL *s)
{
unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
- if (BN_num_bits(s->srp_ctx.N) < s->srp_ctx.strength)
- return -1;
-
- if (s->srp_ctx.SRP_verify_param_callback ==NULL &&
- !SRP_check_known_gN_param(s->srp_ctx.g,s->srp_ctx.N))
- return -1 ;
-
RAND_bytes(rnd, sizeof(rnd));
s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
OPENSSL_cleanse(rnd, sizeof(rnd));
@@ -426,10 +456,6 @@ int SRP_Calc_A_param(SSL *s)
if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a,s->srp_ctx.N,s->srp_ctx.g)))
return -1;
- /* We can have a callback to verify SRP param!! */
- if (s->srp_ctx.SRP_verify_param_callback !=NULL)
- return s->srp_ctx.SRP_verify_param_callback(s,s->srp_ctx.SRP_cb_arg);
-
return 1;
}

View file

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIcBAABCgAGBQJUDtUYAAoJEO1n7NZdz2rnWKsQAKLQ01Ut/9n/ue0eeqEo6O8e
6UUudGR3KoiWIfsPhczMNxjMy/5JUjpf9aeP5hy5mQQ2YRDPyL7QAIjL4aHiXfpx
JI9inrSs8bR8SbehYCP90GFGBG6TpoXN0dXXPG8WKddXNXt/85rHmqnll7YzT+rR
aJ4W1PAS0nwnXgTtG4S0GftU2muGA3Xk8xG8w5aJ2KEhamDQv4MPdttv5vW8Q4/K
BL5bLUCpfzjBO3b47woQsZ57KZWhBoWB8H0bUvIFsLS+J0nWG2QaodJfzFjabuPb
mcBTnv4YWCTFrX7D4UfcbKWPeCd/eS90If8OJ3Chpb2xpFVRhV0wDwhzVuQSU5dO
kSsiPhxdzIiv8bVzQuAw5rTEoMkkM4zAaYR+oHulVBpH+TfVjfTbB2s5y7KZ0O4N
VsIKQMX38rdUhLa4Enswa+kZGUHox1OM5aL1Sw9ZrSX4xRKYWrOD0xxL1VhDV73z
K0zXxupthhxPZn0rIu56ChswyJs0W1tsWGfiSoCHjIMA5o3/lBWwDzkj5l4oj0Oy
v6zDU5dKvzzztPxIfAQX2xN7qrR9Ts5CfQA01fKA15kzZ5FwHnibBiHYBglglXQe
h9e3Dy0blYIqAehZu4QDrwNJ73peGcNty0pFFn/2BthrqtxqBI+CISnmTqDop/7S
pKDF2NeO9llYq61Pxpf6
=Htnr
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,401 @@
Index: crypto/openssl/crypto/asn1/a_object.c
===================================================================
--- crypto/openssl/crypto/asn1/a_object.c (revision 270128)
+++ crypto/openssl/crypto/asn1/a_object.c (working copy)
@@ -285,17 +285,29 @@ err:
ASN1_OBJECT_free(ret);
return(NULL);
}
+
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long len)
{
ASN1_OBJECT *ret=NULL;
const unsigned char *p;
- int i;
- /* Sanity check OID encoding: can't have leading 0x80 in
- * subidentifiers, see: X.690 8.19.2
+ int i, length;
+
+ /* Sanity check OID encoding.
+ * Need at least one content octet.
+ * MSB must be clear in the last octet.
+ * can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
*/
- for (i = 0, p = *pp; i < len; i++, p++)
+ if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
+ p[len - 1] & 0x80)
{
+ ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
+ return NULL;
+ }
+ /* Now 0 < len <= INT_MAX, so the cast is safe. */
+ length = (int)len;
+ for (i = 0; i < length; i++, p++)
+ {
if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
{
ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
@@ -313,20 +325,20 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, cons
else ret=(*a);
p= *pp;
- if ((ret->data == NULL) || (ret->length < len))
+ if ((ret->data == NULL) || (ret->length < length))
{
if (ret->data != NULL) OPENSSL_free(ret->data);
- ret->data=(unsigned char *)OPENSSL_malloc(len ? (int)len : 1);
+ ret->data=(unsigned char *)OPENSSL_malloc(length);
ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
if (ret->data == NULL)
{ i=ERR_R_MALLOC_FAILURE; goto err; }
}
- memcpy(ret->data,p,(int)len);
- ret->length=(int)len;
+ memcpy(ret->data,p,length);
+ ret->length=length;
ret->sn=NULL;
ret->ln=NULL;
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
- p+=len;
+ p+=length;
if (a != NULL) (*a)=ret;
*pp=p;
Index: crypto/openssl/crypto/objects/obj_dat.c
===================================================================
--- crypto/openssl/crypto/objects/obj_dat.c (revision 270128)
+++ crypto/openssl/crypto/objects/obj_dat.c (working copy)
@@ -444,12 +444,13 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
unsigned char *p;
char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
- if ((a == NULL) || (a->data == NULL)) {
- buf[0]='\0';
+ /* Ensure that, at every state, |buf| is NUL-terminated. */
+ if (buf && buf_len > 0)
+ buf[0] = '\0';
+
+ if ((a == NULL) || (a->data == NULL))
return(0);
- }
-
if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
{
const char *s;
@@ -527,9 +528,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
i=(int)(l/40);
l-=(long)(i*40);
}
- if (buf && (buf_len > 0))
+ if (buf && (buf_len > 1))
{
*buf++ = i + '0';
+ *buf = '\0';
buf_len--;
}
n++;
@@ -544,9 +546,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
i = strlen(bndec);
if (buf)
{
- if (buf_len > 0)
+ if (buf_len > 1)
{
*buf++ = '.';
+ *buf = '\0';
buf_len--;
}
BUF_strlcpy(buf,bndec,buf_len);
@@ -786,4 +789,3 @@ err:
OPENSSL_free(buf);
return(ok);
}
-
Index: crypto/openssl/ssl/d1_both.c
===================================================================
--- crypto/openssl/ssl/d1_both.c (revision 270128)
+++ crypto/openssl/ssl/d1_both.c (working copy)
@@ -581,30 +581,33 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max,
return 0;
}
+/* dtls1_max_handshake_message_len returns the maximum number of bytes
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
+ * be greater if the maximum certificate list size requires it. */
+static unsigned long dtls1_max_handshake_message_len(const SSL *s)
+ {
+ unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (max_len < (unsigned long)s->max_cert_list)
+ return s->max_cert_list;
+ return max_len;
+ }
static int
-dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+dtls1_reassemble_fragment(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
{
hm_fragment *frag = NULL;
pitem *item = NULL;
int i = -1, is_complete;
PQ_64BIT seq64;
- unsigned long frag_len = msg_hdr->frag_len, max_len;
+ unsigned long frag_len = msg_hdr->frag_len;
- if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
+ if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
+ msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
goto err;
- /* Determine maximum allowed message size. Depends on (user set)
- * maximum certificate length, but 16k is minimum.
- */
- if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
- max_len = s->max_cert_list;
- else
- max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (frag_len == 0)
+ return DTLS1_HM_FRAGMENT_RETRY;
- if ((msg_hdr->frag_off+frag_len) > max_len)
- goto err;
-
/* Try to find item in queue */
pq_64bit_init(&seq64);
pq_64bit_assign_word(&seq64, msg_hdr->seq);
@@ -633,7 +636,8 @@ static int
/* If message is already reassembled, this must be a
- * retransmit and can be dropped.
+ * retransmit and can be dropped. In this case item != NULL and so frag
+ * does not need to be freed.
*/
if (frag->reassembly == NULL)
{
@@ -653,7 +657,9 @@ static int
/* read the body of the fragment (header has already been read */
i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
frag->fragment + msg_hdr->frag_off,frag_len,0);
- if (i<=0 || (unsigned long)i!=frag_len)
+ if ((unsigned long)i!=frag_len)
+ i=-1;
+ if (i<=0)
goto err;
RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
@@ -681,14 +687,18 @@ static int
goto err;
}
- pqueue_insert(s->d1->buffered_messages, item);
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /* pqueue_insert fails iff a duplicate item is inserted.
+ * However, |item| cannot be a duplicate. If it were,
+ * |pqueue_find|, above, would have returned it and control
+ * would never have reached this branch. */
+ OPENSSL_assert(item != NULL);
}
return DTLS1_HM_FRAGMENT_RETRY;
err:
- if (frag != NULL) dtls1_hm_fragment_free(frag);
- if (item != NULL) OPENSSL_free(item);
+ if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
*ok = 0;
return i;
}
@@ -695,7 +705,7 @@ err:
static int
-dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
{
int i=-1;
hm_fragment *frag = NULL;
@@ -715,7 +725,7 @@ static int
/* If we already have an entry and this one is a fragment,
* don't discard it and rather try to reassemble it.
*/
- if (item != NULL && frag_len < msg_hdr->msg_len)
+ if (item != NULL && frag_len != msg_hdr->msg_len)
item = NULL;
/* Discard the message if sequence number was already there, is
@@ -740,9 +750,12 @@ static int
}
else
{
- if (frag_len && frag_len < msg_hdr->msg_len)
+ if (frag_len != msg_hdr->msg_len)
return dtls1_reassemble_fragment(s, msg_hdr, ok);
+ if (frag_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
frag = dtls1_hm_fragment_new(frag_len, 0);
if ( frag == NULL)
goto err;
@@ -754,7 +767,9 @@ static int
/* read the body of the fragment (header has already been read) */
i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
frag->fragment,frag_len,0);
- if (i<=0 || (unsigned long)i!=frag_len)
+ if ((unsigned long)i!=frag_len)
+ i = -1;
+ if (i<=0)
goto err;
}
@@ -766,14 +781,21 @@ static int
if ( item == NULL)
goto err;
- pqueue_insert(s->d1->buffered_messages, item);
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /* pqueue_insert fails iff a duplicate item is inserted.
+ * However, |item| cannot be a duplicate. If it were,
+ * |pqueue_find|, above, would have returned it. Then, either
+ * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
+ * to NULL and it will have been processed with
+ * |dtls1_reassemble_fragment|, above, or the record will have
+ * been discarded. */
+ OPENSSL_assert(item != NULL);
}
return DTLS1_HM_FRAGMENT_RETRY;
err:
- if ( frag != NULL) dtls1_hm_fragment_free(frag);
- if ( item != NULL) OPENSSL_free(item);
+ if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
*ok = 0;
return i;
}
Index: crypto/openssl/ssl/d1_clnt.c
===================================================================
--- crypto/openssl/ssl/d1_clnt.c (revision 270128)
+++ crypto/openssl/ssl/d1_clnt.c (working copy)
@@ -796,6 +796,13 @@ int dtls1_send_client_key_exchange(SSL *s)
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+ if (s->session->sess_cert == NULL)
+ {
+ /* We should always have a server certificate with SSL_kRSA. */
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_rsa_tmp != NULL)
rsa=s->session->sess_cert->peer_rsa_tmp;
else
@@ -986,6 +993,13 @@ int dtls1_send_client_key_exchange(SSL *s)
{
DH *dh_srvr,*dh_clnt;
+ if (s->session->sess_cert == NULL)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_dh_tmp != NULL)
dh_srvr=s->session->sess_cert->peer_dh_tmp;
else
@@ -1226,5 +1240,3 @@ int dtls1_send_client_certificate(SSL *s)
/* SSL3_ST_CW_CERT_D */
return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
}
-
-
Index: crypto/openssl/ssl/s23_srvr.c
===================================================================
--- crypto/openssl/ssl/s23_srvr.c (revision 270128)
+++ crypto/openssl/ssl/s23_srvr.c (working copy)
@@ -328,16 +328,12 @@ int ssl23_get_client_hello(SSL *s)
* Client Hello message, this would be difficult, and we'd have
* to read more records to find out.
* No known SSL 3.0 client fragments ClientHello like this,
- * so we simply assume TLS 1.0 to avoid protocol version downgrade
- * attacks. */
+ * so we simply reject such connections to avoid
+ * protocol version downgrade attacks. */
if (p[3] == 0 && p[4] < 6)
{
-#if 0
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL);
goto err;
-#else
- v[1] = TLS1_VERSION_MINOR;
-#endif
}
/* if major version number > 3 set minor to a value
* which will use the highest version 3 we support.
@@ -344,7 +340,7 @@ int ssl23_get_client_hello(SSL *s)
* If TLS 2.0 ever appears we will need to revise
* this....
*/
- else if (p[9] > SSL3_VERSION_MAJOR)
+ if (p[9] > SSL3_VERSION_MAJOR)
v[1]=0xff;
else
v[1]=p[10]; /* minor version according to client_version */
@@ -412,6 +408,18 @@ int ssl23_get_client_hello(SSL *s)
v[0] = p[3]; /* == SSL3_VERSION_MAJOR */
v[1] = p[4];
+ /* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
+ * header is sent directly on the wire, not wrapped as a TLS
+ * record. It's format is:
+ * Byte Content
+ * 0-1 msg_length
+ * 2 msg_type
+ * 3-4 version
+ * 5-6 cipher_spec_length
+ * 7-8 session_id_length
+ * 9-10 challenge_length
+ * ... ...
+ */
n=((p[0]&0x7f)<<8)|p[1];
if (n > (1024*4))
{
@@ -418,8 +426,16 @@ int ssl23_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE);
goto err;
}
+ if (n < 9)
+ {
+ SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
+ goto err;
+ }
j=ssl23_read_bytes(s,n+2);
+ /* We previously read 11 bytes, so if j > 0, we must have
+ * j == n+2 == s->packet_length. We have at least 11 valid
+ * packet bytes. */
if (j <= 0) return(j);
ssl3_finish_mac(s, s->packet+2, s->packet_length-2);
Index: crypto/openssl/ssl/s3_clnt.c
===================================================================
--- crypto/openssl/ssl/s3_clnt.c (revision 270128)
+++ crypto/openssl/ssl/s3_clnt.c (working copy)
@@ -1915,6 +1915,13 @@ int ssl3_send_client_key_exchange(SSL *s)
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+ if (s->session->sess_cert == NULL)
+ {
+ /* We should always have a server certificate with SSL_kRSA. */
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_rsa_tmp != NULL)
rsa=s->session->sess_cert->peer_rsa_tmp;
else

View file

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIcBAABCgAGBQJUDtUYAAoJEO1n7NZdz2rnvhsP/itSB1eJrlPYWDBAJZTGSqiE
GKQbQ/9/mhlU+j+Apgmnx5KskzvrXHXED/bE5xOQG9Empy/XoayMI5lpvLxm0+80
itYgDFImCuxA7PbU3rE7+dw7dK2dirvzWCF3UsHc6TVpmXaU0e1Je/512oeJBzUd
WY++JmZxuLYj3zPrsyCbNp5sk/FrVhracqHkiKtFU/AhLKt5xMtkmGyFdMy/03Kn
G5ft5xttqE37pmo2bBs5yImS+4/3x7e9orxWfrH7pFWqMwVKIrRoqrC8qviwf5rG
o5eRQllBDWi+Nf7X7LtvUvnCNEv+YATrswqcbL7T6dqXYJM/qluANGFna7qMsloP
Lqyqt2xoz9apmGzFI3D/RuXN15w66cemA+HgvDdgoPb56sJDvoOfRNdAk6fljuOr
WDh2On8WSndTltNAmb4uZ3ZxnErTbpQoRAUDDenbUlmSc3saJPuiE++7yEZgXC8z
z0rYwD6fa+a+2jsc+zYxgTEiATi79QlTOa4IMh6fwGvoC3n7bn+RBXSELaAo9Sb5
XPpUAayFEYiTbaQlrjhi8ldMEHt+1sBU6jhHRd5aUgTsVe70HGBNoeNJx40OTq2I
zj0u/zBj2a/tgRIE2s2kwsqiYfNyWerlX5UYurWm4836TQ1UgSStuQ5FfbmGQPFC
IuZ0Y08m6UXccrBF16oK
=PvtV
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,401 @@
Index: crypto/openssl/crypto/asn1/a_object.c
===================================================================
--- crypto/openssl/crypto/asn1/a_object.c (revision 270128)
+++ crypto/openssl/crypto/asn1/a_object.c (working copy)
@@ -285,17 +285,29 @@ err:
ASN1_OBJECT_free(ret);
return(NULL);
}
+
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long len)
{
ASN1_OBJECT *ret=NULL;
const unsigned char *p;
- int i;
- /* Sanity check OID encoding: can't have leading 0x80 in
- * subidentifiers, see: X.690 8.19.2
+ int i, length;
+
+ /* Sanity check OID encoding.
+ * Need at least one content octet.
+ * MSB must be clear in the last octet.
+ * can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
*/
- for (i = 0, p = *pp; i < len; i++, p++)
+ if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
+ p[len - 1] & 0x80)
{
+ ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
+ return NULL;
+ }
+ /* Now 0 < len <= INT_MAX, so the cast is safe. */
+ length = (int)len;
+ for (i = 0; i < length; i++, p++)
+ {
if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
{
ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
@@ -313,20 +325,20 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, cons
else ret=(*a);
p= *pp;
- if ((ret->data == NULL) || (ret->length < len))
+ if ((ret->data == NULL) || (ret->length < length))
{
if (ret->data != NULL) OPENSSL_free(ret->data);
- ret->data=(unsigned char *)OPENSSL_malloc(len ? (int)len : 1);
+ ret->data=(unsigned char *)OPENSSL_malloc(length);
ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
if (ret->data == NULL)
{ i=ERR_R_MALLOC_FAILURE; goto err; }
}
- memcpy(ret->data,p,(int)len);
- ret->length=(int)len;
+ memcpy(ret->data,p,length);
+ ret->length=length;
ret->sn=NULL;
ret->ln=NULL;
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
- p+=len;
+ p+=length;
if (a != NULL) (*a)=ret;
*pp=p;
Index: crypto/openssl/crypto/objects/obj_dat.c
===================================================================
--- crypto/openssl/crypto/objects/obj_dat.c (revision 270128)
+++ crypto/openssl/crypto/objects/obj_dat.c (working copy)
@@ -444,12 +444,13 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
unsigned char *p;
char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
- if ((a == NULL) || (a->data == NULL)) {
- buf[0]='\0';
+ /* Ensure that, at every state, |buf| is NUL-terminated. */
+ if (buf && buf_len > 0)
+ buf[0] = '\0';
+
+ if ((a == NULL) || (a->data == NULL))
return(0);
- }
-
if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
{
const char *s;
@@ -527,9 +528,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
i=(int)(l/40);
l-=(long)(i*40);
}
- if (buf && (buf_len > 0))
+ if (buf && (buf_len > 1))
{
*buf++ = i + '0';
+ *buf = '\0';
buf_len--;
}
n++;
@@ -544,9 +546,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
i = strlen(bndec);
if (buf)
{
- if (buf_len > 0)
+ if (buf_len > 1)
{
*buf++ = '.';
+ *buf = '\0';
buf_len--;
}
BUF_strlcpy(buf,bndec,buf_len);
@@ -786,4 +789,3 @@ err:
OPENSSL_free(buf);
return(ok);
}
-
Index: crypto/openssl/ssl/d1_both.c
===================================================================
--- crypto/openssl/ssl/d1_both.c (revision 270128)
+++ crypto/openssl/ssl/d1_both.c (working copy)
@@ -580,30 +580,33 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max,
return 0;
}
+/* dtls1_max_handshake_message_len returns the maximum number of bytes
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
+ * be greater if the maximum certificate list size requires it. */
+static unsigned long dtls1_max_handshake_message_len(const SSL *s)
+ {
+ unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (max_len < (unsigned long)s->max_cert_list)
+ return s->max_cert_list;
+ return max_len;
+ }
static int
-dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+dtls1_reassemble_fragment(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
{
hm_fragment *frag = NULL;
pitem *item = NULL;
int i = -1, is_complete;
PQ_64BIT seq64;
- unsigned long frag_len = msg_hdr->frag_len, max_len;
+ unsigned long frag_len = msg_hdr->frag_len;
- if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
+ if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
+ msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
goto err;
- /* Determine maximum allowed message size. Depends on (user set)
- * maximum certificate length, but 16k is minimum.
- */
- if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
- max_len = s->max_cert_list;
- else
- max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (frag_len == 0)
+ return DTLS1_HM_FRAGMENT_RETRY;
- if ((msg_hdr->frag_off+frag_len) > max_len)
- goto err;
-
/* Try to find item in queue */
pq_64bit_init(&seq64);
pq_64bit_assign_word(&seq64, msg_hdr->seq);
@@ -632,7 +635,8 @@ static int
/* If message is already reassembled, this must be a
- * retransmit and can be dropped.
+ * retransmit and can be dropped. In this case item != NULL and so frag
+ * does not need to be freed.
*/
if (frag->reassembly == NULL)
{
@@ -652,7 +656,9 @@ static int
/* read the body of the fragment (header has already been read */
i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
frag->fragment + msg_hdr->frag_off,frag_len,0);
- if (i<=0 || (unsigned long)i!=frag_len)
+ if ((unsigned long)i!=frag_len)
+ i=-1;
+ if (i<=0)
goto err;
RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
@@ -680,14 +686,18 @@ static int
i = -1;
}
- pqueue_insert(s->d1->buffered_messages, item);
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /* pqueue_insert fails iff a duplicate item is inserted.
+ * However, |item| cannot be a duplicate. If it were,
+ * |pqueue_find|, above, would have returned it and control
+ * would never have reached this branch. */
+ OPENSSL_assert(item != NULL);
}
return DTLS1_HM_FRAGMENT_RETRY;
err:
- if (frag != NULL) dtls1_hm_fragment_free(frag);
- if (item != NULL) OPENSSL_free(item);
+ if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
*ok = 0;
return i;
}
@@ -694,7 +704,7 @@ err:
static int
-dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
{
int i=-1;
hm_fragment *frag = NULL;
@@ -714,7 +724,7 @@ static int
/* If we already have an entry and this one is a fragment,
* don't discard it and rather try to reassemble it.
*/
- if (item != NULL && frag_len < msg_hdr->msg_len)
+ if (item != NULL && frag_len != msg_hdr->msg_len)
item = NULL;
/* Discard the message if sequence number was already there, is
@@ -739,9 +749,12 @@ static int
}
else
{
- if (frag_len && frag_len < msg_hdr->msg_len)
+ if (frag_len != msg_hdr->msg_len)
return dtls1_reassemble_fragment(s, msg_hdr, ok);
+ if (frag_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
frag = dtls1_hm_fragment_new(frag_len, 0);
if ( frag == NULL)
goto err;
@@ -753,7 +766,9 @@ static int
/* read the body of the fragment (header has already been read) */
i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
frag->fragment,frag_len,0);
- if (i<=0 || (unsigned long)i!=frag_len)
+ if ((unsigned long)i!=frag_len)
+ i = -1;
+ if (i<=0)
goto err;
}
@@ -765,14 +780,21 @@ static int
if ( item == NULL)
goto err;
- pqueue_insert(s->d1->buffered_messages, item);
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /* pqueue_insert fails iff a duplicate item is inserted.
+ * However, |item| cannot be a duplicate. If it were,
+ * |pqueue_find|, above, would have returned it. Then, either
+ * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
+ * to NULL and it will have been processed with
+ * |dtls1_reassemble_fragment|, above, or the record will have
+ * been discarded. */
+ OPENSSL_assert(item != NULL);
}
return DTLS1_HM_FRAGMENT_RETRY;
err:
- if ( frag != NULL) dtls1_hm_fragment_free(frag);
- if ( item != NULL) OPENSSL_free(item);
+ if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
*ok = 0;
return i;
}
Index: crypto/openssl/ssl/d1_clnt.c
===================================================================
--- crypto/openssl/ssl/d1_clnt.c (revision 270128)
+++ crypto/openssl/ssl/d1_clnt.c (working copy)
@@ -796,6 +796,13 @@ int dtls1_send_client_key_exchange(SSL *s)
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+ if (s->session->sess_cert == NULL)
+ {
+ /* We should always have a server certificate with SSL_kRSA. */
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_rsa_tmp != NULL)
rsa=s->session->sess_cert->peer_rsa_tmp;
else
@@ -986,6 +993,13 @@ int dtls1_send_client_key_exchange(SSL *s)
{
DH *dh_srvr,*dh_clnt;
+ if (s->session->sess_cert == NULL)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_dh_tmp != NULL)
dh_srvr=s->session->sess_cert->peer_dh_tmp;
else
@@ -1226,5 +1240,3 @@ int dtls1_send_client_certificate(SSL *s)
/* SSL3_ST_CW_CERT_D */
return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
}
-
-
Index: crypto/openssl/ssl/s23_srvr.c
===================================================================
--- crypto/openssl/ssl/s23_srvr.c (revision 270128)
+++ crypto/openssl/ssl/s23_srvr.c (working copy)
@@ -328,16 +328,12 @@ int ssl23_get_client_hello(SSL *s)
* Client Hello message, this would be difficult, and we'd have
* to read more records to find out.
* No known SSL 3.0 client fragments ClientHello like this,
- * so we simply assume TLS 1.0 to avoid protocol version downgrade
- * attacks. */
+ * so we simply reject such connections to avoid
+ * protocol version downgrade attacks. */
if (p[3] == 0 && p[4] < 6)
{
-#if 0
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL);
goto err;
-#else
- v[1] = TLS1_VERSION_MINOR;
-#endif
}
/* if major version number > 3 set minor to a value
* which will use the highest version 3 we support.
@@ -344,7 +340,7 @@ int ssl23_get_client_hello(SSL *s)
* If TLS 2.0 ever appears we will need to revise
* this....
*/
- else if (p[9] > SSL3_VERSION_MAJOR)
+ if (p[9] > SSL3_VERSION_MAJOR)
v[1]=0xff;
else
v[1]=p[10]; /* minor version according to client_version */
@@ -412,6 +408,18 @@ int ssl23_get_client_hello(SSL *s)
v[0] = p[3]; /* == SSL3_VERSION_MAJOR */
v[1] = p[4];
+ /* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
+ * header is sent directly on the wire, not wrapped as a TLS
+ * record. It's format is:
+ * Byte Content
+ * 0-1 msg_length
+ * 2 msg_type
+ * 3-4 version
+ * 5-6 cipher_spec_length
+ * 7-8 session_id_length
+ * 9-10 challenge_length
+ * ... ...
+ */
n=((p[0]&0x7f)<<8)|p[1];
if (n > (1024*4))
{
@@ -418,8 +426,16 @@ int ssl23_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE);
goto err;
}
+ if (n < 9)
+ {
+ SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
+ goto err;
+ }
j=ssl23_read_bytes(s,n+2);
+ /* We previously read 11 bytes, so if j > 0, we must have
+ * j == n+2 == s->packet_length. We have at least 11 valid
+ * packet bytes. */
if (j <= 0) return(j);
ssl3_finish_mac(s, s->packet+2, s->packet_length-2);
Index: crypto/openssl/ssl/s3_clnt.c
===================================================================
--- crypto/openssl/ssl/s3_clnt.c (revision 270128)
+++ crypto/openssl/ssl/s3_clnt.c (working copy)
@@ -1913,6 +1913,13 @@ int ssl3_send_client_key_exchange(SSL *s)
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+ if (s->session->sess_cert == NULL)
+ {
+ /* We should always have a server certificate with SSL_kRSA. */
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_rsa_tmp != NULL)
rsa=s->session->sess_cert->peer_rsa_tmp;
else

View file

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIcBAABCgAGBQJUDtUZAAoJEO1n7NZdz2rn128QAI08gk8rXMOUHij9jg2M7wiT
oVFb78eWEuSSYsOnnMkfH2LJA7kQ7tYeGarrzPSeni7WInp47JGmchqpe+agzVAW
+KUAQjXDpMiIQ02txxoq593Q9wDu8jL8gXrOcqEKqagebNI34zizy27eCESyGPbD
e1RpSL/vHx+CmIh/+u4wPuX9aDSZzzNahPZopGPmkMnoVgEbD6DqNgeOVUbKsyOS
5Dlfj0gFEmi4moTsNFodps91xPRQD5gp+5xxqlLI9jyJDLDnz61cMkAjKXUjNtZF
XXTEcMlOB/z0HJdQARchxbKuxc1O9JrDu0AOZLTBeVGBL++Snnb6ZAl8aIS5A9qt
QWhVkEBDXyFP4NBLNkhxGSVG5x33gx/c1rWZxsUCXKOAhUx037UuoFUw3V2sBhkD
XP+QNhRTlPiODuq53Cz2cYiSmSQnQRR2Lxja9sFwVYqXc93HvGWXP8zX3AL1jD15
ldl1FAtbGax3T9FIi6lkBO6LBEu/FRv8ujqJzfK286NgyKPWyYfaZ5frVg/t9ODj
Tx85C/3QLU6H+cXfhr6MytX1x8DloD3KI1Ivxl0MkefgviHWWtaqngIyT1G9gGQp
cHmac2T/9CkeTvVXXwh4EPM+JR50cq4YM9cMGA2s4RMiYz9Sh0W7Xiweo8Jlo6Eq
rIEKAcXFcuFUEeRodAeU
=pVJD
-----END PGP SIGNATURE-----

View file

@ -7,6 +7,18 @@
<year>
<name>2014</name>
<month>
<name>9</name>
<day>
<name>9</name>
<advisory>
<name>FreeBSD-SA-14:18.openssl</name>
</advisory>
</day>
</month>
<month>
<name>7</name>