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;