Module Name:    src
Committed By:   msaitoh
Date:           Wed Aug 27 13:29:56 UTC 2014

Modified Files:
        src/crypto/dist/openssl/crypto/asn1 [netbsd-5]: a_object.c asn1.h
            asn1_err.c
        src/crypto/dist/openssl/crypto/objects [netbsd-5]: obj_dat.c
        src/crypto/dist/openssl/ssl [netbsd-5]: d1_both.c s23_srvr.c s3_clnt.c
            t1_lib.c

Log Message:
Pull up following revision(s) (requested by spz in ticket #1918):
        crypto/dist/openssl/crypto/asn1/a_object.c      patch
        crypto/dist/openssl/crypto/asn1/asn1.h          patch
        crypto/dist/openssl/crypto/asn1/asn1_err.c      patch
        crypto/dist/openssl/crypto/objects/obj_dat.c    patch
        crypto/dist/openssl/ssl/d1_both.c               patch
        crypto/dist/openssl/ssl/s23_srvr.c              patch
        crypto/dist/openssl/ssl/s3_clnt.c               patch
        crypto/dist/openssl/ssl/t1_lib.c                patch

Patches for the following vulnerabilities:
Information leak in pretty printing functions (CVE-2014-3508)
Double Free when processing DTLS packets (CVE-2014-3505)
DTLS memory exhaustion (CVE-2014-3506)
DTLS memory leak from zero-length fragments (CVE-2014-3507)
OpenSSL DTLS anonymous EC(DH) denial of service (CVE-2014-3510)
Race condition in ssl_parse_serverhello_tlsext (CVE-2014-3509)
OpenSSL TLS protocol downgrade attack (CVE-2014-3511)

backported from the recent 1.0.1i OpenSSL release.


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.7 -r1.1.1.7.4.1 \
    src/crypto/dist/openssl/crypto/asn1/a_object.c
cvs rdiff -u -r1.9.4.1 -r1.9.4.2 src/crypto/dist/openssl/crypto/asn1/asn1.h
cvs rdiff -u -r1.1.1.8.4.1 -r1.1.1.8.4.2 \
    src/crypto/dist/openssl/crypto/asn1/asn1_err.c
cvs rdiff -u -r1.10 -r1.10.4.1 \
    src/crypto/dist/openssl/crypto/objects/obj_dat.c
cvs rdiff -u -r1.3.4.3 -r1.3.4.4 src/crypto/dist/openssl/ssl/d1_both.c
cvs rdiff -u -r1.6 -r1.6.4.1 src/crypto/dist/openssl/ssl/s23_srvr.c
cvs rdiff -u -r1.12.4.4 -r1.12.4.5 src/crypto/dist/openssl/ssl/s3_clnt.c
cvs rdiff -u -r1.2.4.3 -r1.2.4.4 src/crypto/dist/openssl/ssl/t1_lib.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/crypto/dist/openssl/crypto/asn1/a_object.c
diff -u src/crypto/dist/openssl/crypto/asn1/a_object.c:1.1.1.7 src/crypto/dist/openssl/crypto/asn1/a_object.c:1.1.1.7.4.1
--- src/crypto/dist/openssl/crypto/asn1/a_object.c:1.1.1.7	Fri May  9 21:34:16 2008
+++ src/crypto/dist/openssl/crypto/asn1/a_object.c	Wed Aug 27 13:29:56 2014
@@ -95,7 +95,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, 
 	if (num == 0)
 		return(0);
 	else if (num == -1)
-		num=strlen(buf);
+		num=(int)strlen(buf);
 
 	p=buf;
 	c= *(p++);
@@ -239,7 +239,7 @@ int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT
 
 	if ((a == NULL) || (a->data == NULL))
 		return(BIO_write(bp,"NULL",4));
-	i=i2t_ASN1_OBJECT(buf,sizeof buf,a);
+	i=i2t_ASN1_OBJECT(buf,(int)sizeof buf,a);
 	if (i > (int)(sizeof(buf) - 1))
 		{
 		p = OPENSSL_malloc(i + 1);
@@ -289,7 +289,21 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT
 	ASN1_OBJECT *ret=NULL;
 	const unsigned char *p;
 	unsigned char *data;
-	int i;
+	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
+	 */
+	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;
 
 	/* only the ASN1_OBJECTs from the 'table' will have values
 	 * for ->sn or ->ln */
@@ -300,28 +314,27 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT
 		}
 	else	ret=(*a);
 
-	p= *pp;
 	/* detach data from object */
 	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: src/crypto/dist/openssl/crypto/asn1/asn1.h
diff -u src/crypto/dist/openssl/crypto/asn1/asn1.h:1.9.4.1 src/crypto/dist/openssl/crypto/asn1/asn1.h:1.9.4.2
--- src/crypto/dist/openssl/crypto/asn1/asn1.h:1.9.4.1	Mon Mar 30 16:29:38 2009
+++ src/crypto/dist/openssl/crypto/asn1/asn1.h	Wed Aug 27 13:29:56 2014
@@ -1314,6 +1314,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_INVALID_MIME_TYPE			 205
 #define ASN1_R_INVALID_MODIFIER				 186
 #define ASN1_R_INVALID_NUMBER				 187
+#define ASN1_R_INVALID_OBJECT_ENCODING                   216
 #define ASN1_R_INVALID_SEPARATOR			 131
 #define ASN1_R_INVALID_TIME_FORMAT			 132
 #define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH		 133

Index: src/crypto/dist/openssl/crypto/asn1/asn1_err.c
diff -u src/crypto/dist/openssl/crypto/asn1/asn1_err.c:1.1.1.8.4.1 src/crypto/dist/openssl/crypto/asn1/asn1_err.c:1.1.1.8.4.2
--- src/crypto/dist/openssl/crypto/asn1/asn1_err.c:1.1.1.8.4.1	Mon Mar 30 16:29:38 2009
+++ src/crypto/dist/openssl/crypto/asn1/asn1_err.c	Wed Aug 27 13:29:56 2014
@@ -245,6 +245,7 @@ static ERR_STRING_DATA ASN1_str_reasons[
 {ERR_REASON(ASN1_R_INVALID_MIME_TYPE)    ,"invalid mime type"},
 {ERR_REASON(ASN1_R_INVALID_MODIFIER)     ,"invalid modifier"},
 {ERR_REASON(ASN1_R_INVALID_NUMBER)       ,"invalid number"},
+{ERR_REASON(ASN1_R_INVALID_OBJECT_ENCODING),"invalid object encoding"},
 {ERR_REASON(ASN1_R_INVALID_SEPARATOR)    ,"invalid separator"},
 {ERR_REASON(ASN1_R_INVALID_TIME_FORMAT)  ,"invalid time format"},
 {ERR_REASON(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH),"invalid universalstring length"},

Index: src/crypto/dist/openssl/crypto/objects/obj_dat.c
diff -u src/crypto/dist/openssl/crypto/objects/obj_dat.c:1.10 src/crypto/dist/openssl/crypto/objects/obj_dat.c:1.10.4.1
--- src/crypto/dist/openssl/crypto/objects/obj_dat.c:1.10	Fri May  9 21:49:41 2008
+++ src/crypto/dist/openssl/crypto/objects/obj_dat.c	Wed Aug 27 13:29:56 2014
@@ -464,8 +464,11 @@ int OBJ_obj2txt(char *buf, int buf_len, 
 	const unsigned char *p;
 	char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
 
-	if ((a == NULL) || (a->data == NULL)) {
+	/* 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);
 	}
 
@@ -544,9 +547,10 @@ int OBJ_obj2txt(char *buf, int buf_len, 
 				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++;
@@ -561,9 +565,10 @@ int OBJ_obj2txt(char *buf, int buf_len, 
 			i = strlen(bndec);
 			if (buf)
 				{
-				if (buf_len > 0)
+				if (buf_len > 1)
 					{
 					*buf++ = '.';
+					*buf = '\0';
 					buf_len--;
 					}
 				BUF_strlcpy(buf,bndec,buf_len);

Index: src/crypto/dist/openssl/ssl/d1_both.c
diff -u src/crypto/dist/openssl/ssl/d1_both.c:1.3.4.3 src/crypto/dist/openssl/ssl/d1_both.c:1.3.4.4
--- src/crypto/dist/openssl/ssl/d1_both.c:1.3.4.3	Fri Jun  6 06:36:44 2014
+++ src/crypto/dist/openssl/ssl/d1_both.c	Wed Aug 27 13:29:56 2014
@@ -549,6 +549,17 @@ dtls1_retrieve_buffered_fragment(SSL *s,
 	}
 
 
+/* 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_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
 {
@@ -558,7 +569,8 @@ dtls1_process_out_of_seq_message(SSL *s,
 	unsigned char seq64be[8];
 	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;
 
 	/* Try to find item in queue, to prevent duplicate entries */
@@ -585,6 +597,8 @@ dtls1_process_out_of_seq_message(SSL *s,
 			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 				devnull,
 				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
+			if ((unsigned long)i!=frag_len)
+				i = -1;
 			if (i<=0) goto err;
 			frag_len -= i;
 			}
@@ -592,6 +606,9 @@ dtls1_process_out_of_seq_message(SSL *s,
 
 	if (frag_len)
 	{
+		if (frag_len > dtls1_max_handshake_message_len(s))
+			goto err;
+
 		frag = dtls1_hm_fragment_new(frag_len);
 		if ( frag == NULL)
 			goto err;
@@ -604,6 +621,9 @@ dtls1_process_out_of_seq_message(SSL *s,
 		if (i<=0 || (unsigned long)i!=frag_len)
 			goto err;
 
+		if (frag_len == 0)
+			return DTLS1_HM_FRAGMENT_RETRY;
+
 		memset(seq64be,0,sizeof(seq64be));
 		seq64be[6] = (unsigned char)(msg_hdr->seq>>8);
 		seq64be[7] = (unsigned char)(msg_hdr->seq);
@@ -612,14 +632,18 @@ dtls1_process_out_of_seq_message(SSL *s,
 		if ( item == NULL)
 			goto err;
 
-		pqueue_insert(s->d1->buffered_messages, item);
+		item = pqueue_insert(s->d1->buffered_messages, item);
+		/* pqueue_insert fails if 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;
 	}
@@ -704,6 +728,8 @@ dtls1_get_message_fragment(SSL *s, int s
 		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 			&p[frag_off],frag_len,0);
 		/* XDTLS:  fix this--message fragments cannot span multiple packets */
+		if ((unsigned long)i!=frag_len)
+			i=-1;
 		if (i <= 0)
 			{
 			s->rwstate=SSL_READING;

Index: src/crypto/dist/openssl/ssl/s23_srvr.c
diff -u src/crypto/dist/openssl/ssl/s23_srvr.c:1.6 src/crypto/dist/openssl/ssl/s23_srvr.c:1.6.4.1
--- src/crypto/dist/openssl/ssl/s23_srvr.c:1.6	Fri May  9 21:49:42 2008
+++ src/crypto/dist/openssl/ssl/s23_srvr.c	Wed Aug 27 13:29:56 2014
@@ -332,13 +332,11 @@ int ssl23_get_client_hello(SSL *s)
 			 * 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 (p[9] > SSL3_VERSION_MAJOR)
+				v[1]=0xff;
 			else
 				v[1]=p[10]; /* minor version according to client_version */
 			if (v[1] >= TLS1_VERSION_MINOR)
@@ -396,14 +394,34 @@ 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))
 			{
 			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: src/crypto/dist/openssl/ssl/s3_clnt.c
diff -u src/crypto/dist/openssl/ssl/s3_clnt.c:1.12.4.4 src/crypto/dist/openssl/ssl/s3_clnt.c:1.12.4.5
--- src/crypto/dist/openssl/ssl/s3_clnt.c:1.12.4.4	Fri Jun  6 06:36:44 2014
+++ src/crypto/dist/openssl/ssl/s3_clnt.c	Wed Aug 27 13:29:56 2014
@@ -1956,6 +1956,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: src/crypto/dist/openssl/ssl/t1_lib.c
diff -u src/crypto/dist/openssl/ssl/t1_lib.c:1.2.4.3 src/crypto/dist/openssl/ssl/t1_lib.c:1.2.4.4
--- src/crypto/dist/openssl/ssl/t1_lib.c:1.2.4.3	Wed Feb 16 21:00:23 2011
+++ src/crypto/dist/openssl/ssl/t1_lib.c	Wed Aug 27 13:29:56 2014
@@ -937,6 +937,7 @@ int ssl_parse_serverhello_tlsext(SSL *s,
 				*al = TLS1_AD_DECODE_ERROR;
 				return 0;
 				}
+			if (!s->hit) {
 			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)
@@ -946,6 +947,7 @@ int ssl_parse_serverhello_tlsext(SSL *s,
 				}
 			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;

Reply via email to