diff options
| author | Simon L. B. Nielsen <simon@FreeBSD.org> | 2010-11-21 22:45:18 +0000 | 
|---|---|---|
| committer | Simon L. B. Nielsen <simon@FreeBSD.org> | 2010-11-21 22:45:18 +0000 | 
| commit | f2c43d19b91f8847c1dfd87721254b44f963d9a2 (patch) | |
| tree | 4710d37952455e247de95eedf55ea05ee4df9f69 /ssl | |
| parent | 0cedaa6c89235ed396068f2ebf546c9a909439e1 (diff) | |
Diffstat (limited to 'ssl')
| -rw-r--r-- | ssl/d1_both.c | 320 | ||||
| -rw-r--r-- | ssl/d1_clnt.c | 3 | ||||
| -rw-r--r-- | ssl/d1_enc.c | 6 | ||||
| -rw-r--r-- | ssl/d1_lib.c | 10 | ||||
| -rw-r--r-- | ssl/d1_pkt.c | 60 | ||||
| -rw-r--r-- | ssl/dtls1.h | 1 | ||||
| -rw-r--r-- | ssl/s23_clnt.c | 5 | ||||
| -rw-r--r-- | ssl/s23_lib.c | 8 | ||||
| -rw-r--r-- | ssl/s2_srvr.c | 2 | ||||
| -rw-r--r-- | ssl/s3_both.c | 2 | ||||
| -rw-r--r-- | ssl/s3_clnt.c | 4 | ||||
| -rw-r--r-- | ssl/s3_enc.c | 3 | ||||
| -rw-r--r-- | ssl/ssl_algs.c | 8 | ||||
| -rw-r--r-- | ssl/ssl_asn1.c | 3 | ||||
| -rw-r--r-- | ssl/ssl_cert.c | 2 | ||||
| -rw-r--r-- | ssl/ssl_ciph.c | 6 | ||||
| -rw-r--r-- | ssl/ssl_lib.c | 6 | ||||
| -rw-r--r-- | ssl/ssltest.c | 3 | ||||
| -rw-r--r-- | ssl/t1_enc.c | 18 | ||||
| -rw-r--r-- | ssl/t1_lib.c | 27 | 
20 files changed, 328 insertions, 169 deletions
diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 0a5c08d71395..920fb1ff2493 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -123,6 +123,37 @@  #include <openssl/evp.h>  #include <openssl/x509.h> +#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8) + +#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \ +			if ((end) - (start) <= 8) { \ +				long ii; \ +				for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \ +			} else { \ +				long ii; \ +				bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \ +				for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \ +				bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \ +			} } + +#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \ +			long ii; \ +			OPENSSL_assert((msg_len) > 0); \ +			is_complete = 1; \ +			if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \ +			if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \ +				if (bitmask[ii] != 0xff) { is_complete = 0; break; } } + +#if 0 +#define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \ +			long ii; \ +			printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \ +			printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \ +			printf("\n"); } +#endif + +static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; +static unsigned char bitmask_end_values[]   = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};  /* XDTLS:  figure out the right values */  static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; @@ -140,10 +171,11 @@ static long dtls1_get_message_fragment(SSL *s, int st1, int stn,  	long max, int *ok);  static hm_fragment * -dtls1_hm_fragment_new(unsigned long frag_len) +dtls1_hm_fragment_new(unsigned long frag_len, int reassembly)  	{  	hm_fragment *frag = NULL;  	unsigned char *buf = NULL; +	unsigned char *bitmask = NULL;  	frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));  	if ( frag == NULL) @@ -162,6 +194,21 @@ dtls1_hm_fragment_new(unsigned long frag_len)  	/* zero length fragment gets zero frag->fragment */  	frag->fragment = buf; +	/* Initialize reassembly bitmask if necessary */ +	if (reassembly) +		{ +		bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len)); +		if (bitmask == NULL) +			{ +			if (buf != NULL) OPENSSL_free(buf); +			OPENSSL_free(frag); +			return NULL; +			} +		memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len)); +		} + +	frag->reassembly = bitmask; +  	return frag;  	} @@ -169,6 +216,7 @@ static void  dtls1_hm_fragment_free(hm_fragment *frag)  	{  	if (frag->fragment) OPENSSL_free(frag->fragment); +	if (frag->reassembly) OPENSSL_free(frag->reassembly);  	OPENSSL_free(frag);  	} @@ -363,6 +411,8 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)  	{  	int i, al;  	struct hm_header_st *msg_hdr; +	unsigned char *p; +	unsigned long msg_len;  	/* s3->tmp is used to store messages that are unexpected, caused  	 * by the absence of an optional handshake message */ @@ -382,76 +432,55 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)  		}  	msg_hdr = &s->d1->r_msg_hdr; -	do -		{ -		if ( msg_hdr->frag_off == 0) -			{ -			/* s->d1->r_message_header.msg_len = 0; */ -			memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); -			} +	memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); -		i = dtls1_get_message_fragment(s, st1, stn, max, ok); -		if ( i == DTLS1_HM_BAD_FRAGMENT || -			i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */ -			continue; -		else if ( i <= 0 && !*ok) -			return i; +again: +	i = dtls1_get_message_fragment(s, st1, stn, max, ok); +	if ( i == DTLS1_HM_BAD_FRAGMENT || +		i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */ +		goto again; +	else if ( i <= 0 && !*ok) +		return i; -		/* Note that s->init_sum is used as a counter summing -		 * up fragments' lengths: as soon as they sum up to -		 * handshake packet length, we assume we have got all -		 * the fragments. Overlapping fragments would cause -		 * premature termination, so we don't expect overlaps. -		 * Well, handling overlaps would require something more -		 * drastic. Indeed, as it is now there is no way to -		 * tell if out-of-order fragment from the middle was -		 * the last. '>=' is the best/least we can do to control -		 * the potential damage caused by malformed overlaps. */ -		if ((unsigned int)s->init_num >= msg_hdr->msg_len) -			{ -			unsigned char *p = (unsigned char *)s->init_buf->data; -			unsigned long msg_len = msg_hdr->msg_len; - -			/* reconstruct message header as if it was -			 * sent in single fragment */ -			*(p++) = msg_hdr->type; -			l2n3(msg_len,p); -			s2n (msg_hdr->seq,p); -			l2n3(0,p); -			l2n3(msg_len,p); -			if (s->client_version != DTLS1_BAD_VER) -				p       -= DTLS1_HM_HEADER_LENGTH, -				msg_len += DTLS1_HM_HEADER_LENGTH; - -			ssl3_finish_mac(s, p, msg_len); -			if (s->msg_callback) -				s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, -					p, msg_len, -					s, s->msg_callback_arg); - -			memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); - -			s->d1->handshake_read_seq++; -			/* we just read a handshake message from the other side: -			 * this means that we don't need to retransmit of the -			 * buffered messages.   -			 * XDTLS: may be able clear out this -			 * buffer a little sooner (i.e if an out-of-order -			 * handshake message/record is received at the record -			 * layer.   -			 * XDTLS: exception is that the server needs to -			 * know that change cipher spec and finished messages -			 * have been received by the client before clearing this -			 * buffer.  this can simply be done by waiting for the -			 * first data  segment, but is there a better way?  */ -			dtls1_clear_record_buffer(s); - -			s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; -			return s->init_num; -			} -		else -			msg_hdr->frag_off = i; -		} while(1) ; +	p = (unsigned char *)s->init_buf->data; +	msg_len = msg_hdr->msg_len; + +	/* reconstruct message header */ +	*(p++) = msg_hdr->type; +	l2n3(msg_len,p); +	s2n (msg_hdr->seq,p); +	l2n3(0,p); +	l2n3(msg_len,p); +	if (s->version != DTLS1_BAD_VER) { +		p       -= DTLS1_HM_HEADER_LENGTH; +		msg_len += DTLS1_HM_HEADER_LENGTH; +	} + +	ssl3_finish_mac(s, p, msg_len); +	if (s->msg_callback) +		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, +			p, msg_len, +			s, s->msg_callback_arg); + +	memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); + +	s->d1->handshake_read_seq++; +	/* we just read a handshake message from the other side: +	 * this means that we don't need to retransmit of the +	 * buffered messages.   +	 * XDTLS: may be able clear out this +	 * buffer a little sooner (i.e if an out-of-order +	 * handshake message/record is received at the record +	 * layer.   +	 * XDTLS: exception is that the server needs to +	 * know that change cipher spec and finished messages +	 * have been received by the client before clearing this +	 * buffer.  this can simply be done by waiting for the +	 * first data  segment, but is there a better way?  */ +	dtls1_clear_record_buffer(s); + +	s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; +	return s->init_num;  f_err:  	ssl3_send_alert(s,SSL3_AL_FATAL,al); @@ -527,6 +556,10 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)  		return 0;  	frag = (hm_fragment *)item->data; +	 +	/* Don't return if reassembly still in progress */ +	if (frag->reassembly != NULL) +		return 0;  	if ( s->d1->handshake_read_seq == frag->msg_header.seq)  		{ @@ -562,6 +595,109 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)  static int +dtls1_reassemble_fragment(SSL *s, 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; + +	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len) +		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 ((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); +	item = pqueue_find(s->d1->buffered_messages, seq64); +	pq_64bit_free(&seq64); + +	if (item == NULL) +		{ +		frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1); +		if ( frag == NULL) +			goto err; +		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); +		frag->msg_header.frag_len = frag->msg_header.msg_len; +		frag->msg_header.frag_off = 0; +		} +	else +		frag = (hm_fragment*) item->data; + +	/* If message is already reassembled, this must be a +	 * retransmit and can be dropped. +	 */ +	if (frag->reassembly == NULL) +		{ +		unsigned char devnull [256]; + +		while (frag_len) +			{ +			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, +				devnull, +				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0); +			if (i<=0) goto err; +			frag_len -= i; +			} +		return DTLS1_HM_FRAGMENT_RETRY; +		} + +	/* 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) +		goto err; + +	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off, +	                    (long)(msg_hdr->frag_off + frag_len)); + +	RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len, +	                           is_complete); + +	if (is_complete) +		{ +		OPENSSL_free(frag->reassembly); +		frag->reassembly = NULL; +		} + +	if (item == NULL) +		{ +		pq_64bit_init(&seq64); +		pq_64bit_assign_word(&seq64, msg_hdr->seq); +		item = pitem_new(seq64, frag); +		pq_64bit_free(&seq64); + +		if (item == NULL) +			{ +			goto err; +			i = -1; +			} + +		pqueue_insert(s->d1->buffered_messages, item); +		} + +	return DTLS1_HM_FRAGMENT_RETRY; + +err: +	if (frag != NULL) dtls1_hm_fragment_free(frag); +	if (item != NULL) OPENSSL_free(item); +	*ok = 0; +	return i; +	} + + +static int  dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)  {  	int i=-1; @@ -578,7 +714,13 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)  	pq_64bit_assign_word(&seq64, msg_hdr->seq);  	item = pqueue_find(s->d1->buffered_messages, seq64);  	pq_64bit_free(&seq64); -	 + +	/* 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) +		item = NULL; +  	/* Discard the message if sequence number was already there, is  	 * too far in the future, already in the queue or if we received  	 * a FINISHED before the SERVER_HELLO, which then must be a stale @@ -599,20 +741,25 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)  			frag_len -= i;  			}  		} +	else +		{ +		if (frag_len && frag_len < msg_hdr->msg_len) +			return dtls1_reassemble_fragment(s, msg_hdr, ok); -	if (frag_len) -	{ -		frag = dtls1_hm_fragment_new(frag_len); +		frag = dtls1_hm_fragment_new(frag_len, 0);  		if ( frag == NULL)  			goto err;  		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); -		/* 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) -			goto err; +		if (frag_len) +			{ +			/* 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) +				goto err; +			}  		pq_64bit_init(&seq64);  		pq_64bit_assign_word(&seq64, msg_hdr->seq); @@ -623,7 +770,7 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)  			goto err;  		pqueue_insert(s->d1->buffered_messages, item); -	} +		}  	return DTLS1_HM_FRAGMENT_RETRY; @@ -639,14 +786,14 @@ static long  dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)  	{  	unsigned char wire[DTLS1_HM_HEADER_LENGTH]; -	unsigned long l, frag_off, frag_len; +	unsigned long len, frag_off, frag_len;  	int i,al;  	struct hm_header_st msg_hdr;  	/* see if we have the required fragment already */  	if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)  		{ -		if (*ok)	s->init_num += frag_len; +		if (*ok)	s->init_num = frag_len;  		return frag_len;  		} @@ -671,10 +818,13 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)  	if ( msg_hdr.seq != s->d1->handshake_read_seq)  		return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); -	l = msg_hdr.msg_len; +	len = msg_hdr.msg_len;  	frag_off = msg_hdr.frag_off;  	frag_len = msg_hdr.frag_len; +	if (frag_len && frag_len < len) +		return dtls1_reassemble_fragment(s, &msg_hdr, ok); +  	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&  		wire[0] == SSL3_MT_HELLO_REQUEST)  		{ @@ -734,7 +884,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)  	 * s->init_buf->data, but as a counter summing up fragments'  	 * lengths: as soon as they sum up to handshake packet  	 * length, we assume we have got all the fragments. */ -	s->init_num += frag_len; +	s->init_num = frag_len;  	return frag_len;  f_err: @@ -888,6 +1038,8 @@ unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)    			}  		X509_verify_cert(&xs_ctx); +		/* Don't leave errors in the queue */ +		ERR_clear_error();  		for (i=0; i < sk_X509_num(xs_ctx.chain); i++)    			{  			x = sk_X509_value(xs_ctx.chain, i); @@ -1010,7 +1162,7 @@ dtls1_buffer_message(SSL *s, int is_ccs)  	 * been serialized */  	OPENSSL_assert(s->init_off == 0); -	frag = dtls1_hm_fragment_new(s->init_num); +	frag = dtls1_hm_fragment_new(s->init_num, 0);  	memcpy(frag->fragment, s->init_buf->data, s->init_num); diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c index 223d11627948..0aa77ee51d50 100644 --- a/ssl/d1_clnt.c +++ b/ssl/d1_clnt.c @@ -144,7 +144,7 @@ IMPLEMENT_dtls1_meth_func(DTLSv1_client_method,  int dtls1_connect(SSL *s)  	{  	BUF_MEM *buf=NULL; -	unsigned long Time=(unsigned long)time(NULL),l; +	unsigned long Time=(unsigned long)time(NULL);  	void (*cb)(const SSL *ssl,int type,int val)=NULL;  	int ret= -1;  	int new_state,state,skip=0;; @@ -374,7 +374,6 @@ int dtls1_connect(SSL *s)  			dtls1_start_timer(s);  			ret=dtls1_send_client_key_exchange(s);  			if (ret <= 0) goto end; -			l=s->s3->tmp.new_cipher->algorithms;  			/* EAY EAY EAY need to check for DH fix cert  			 * sent back */  			/* For TLS, cert_req is set to 2, so a cert chain diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c index 3dfa5adba3f9..4a6c9090314d 100644 --- a/ssl/d1_enc.c +++ b/ssl/d1_enc.c @@ -131,13 +131,11 @@ int dtls1_enc(SSL *s, int send)  	SSL3_RECORD *rec;  	EVP_CIPHER_CTX *ds;  	unsigned long l; -	int bs,i,ii,j,k,n=0; +	int bs,i,ii,j,k;  	const EVP_CIPHER *enc;  	if (send)  		{ -		if (s->write_hash != NULL) -			n=EVP_MD_size(s->write_hash);  		ds=s->enc_write_ctx;  		rec= &(s->s3->wrec);  		if (s->enc_write_ctx == NULL) @@ -158,8 +156,6 @@ int dtls1_enc(SSL *s, int send)  		}  	else  		{ -		if (s->read_hash != NULL) -			n=EVP_MD_size(s->read_hash);  		ds=s->enc_read_ctx;  		rec= &(s->s3->rrec);  		if (s->enc_read_ctx == NULL) diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 63bfbacc8216..54e16403e6e5 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -305,6 +305,16 @@ struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft)  		timeleft->tv_usec += 1000000;  		} +	/* If remaining time is less than 15 ms, set it to 0 +	 * to prevent issues because of small devergences with +	 * socket timeouts. +	 */ +	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) +		{ +		memset(timeleft, 0, sizeof(struct timeval)); +		} +	 +  	return timeleft;  	} diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index ca2d73f02ef5..3f19077af111 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -156,6 +156,9 @@ dtls1_copy_record(SSL *s, pitem *item)      s->packet_length = rdata->packet_length;      memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));      memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD)); +	 +	/* Set proper sequence number for mac calculation */ +	memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);      return(1);      } @@ -253,9 +256,6 @@ dtls1_process_buffered_records(SSL *s)      item = pqueue_peek(s->d1->unprocessed_rcds.q);      if (item)          { -        DTLS1_RECORD_DATA *rdata; -        rdata = (DTLS1_RECORD_DATA *)item->data; -                  /* Check if epoch is current. */          if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)              return(1);  /* Nothing to do. */ @@ -328,7 +328,7 @@ dtls1_get_buffered_record(SSL *s)  static int  dtls1_process_record(SSL *s)  { -    int i,al; +    int al;  	int clear=0;      int enc_err;  	SSL_SESSION *sess; @@ -374,7 +374,7 @@ dtls1_process_record(SSL *s)  			goto err;  		/* otherwise enc_err == -1 */ -		goto decryption_failed_or_bad_record_mac; +		goto err;  		}  #ifdef TLS_DEBUG @@ -400,7 +400,7 @@ if (	(sess == NULL) ||  			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG);  			goto f_err;  #else -			goto decryption_failed_or_bad_record_mac; +			goto err;  #endif			  			}  		/* check the MAC for rr->input (it's in mac_size bytes at the tail) */ @@ -411,14 +411,14 @@ if (	(sess == NULL) ||  			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT);  			goto f_err;  #else -			goto decryption_failed_or_bad_record_mac; +			goto err;  #endif  			}  		rr->length-=mac_size; -		i=s->method->ssl3_enc->mac(s,md,0); +		s->method->ssl3_enc->mac(s,md,0);  		if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0)  			{ -			goto decryption_failed_or_bad_record_mac; +			goto err;  			}  		} @@ -460,14 +460,6 @@ if (	(sess == NULL) ||      dtls1_record_bitmap_update(s, &(s->d1->bitmap));/* Mark receipt of record. */      return(1); -decryption_failed_or_bad_record_mac: -	/* Separate 'decryption_failed' alert was introduced with TLS 1.0, -	 * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption -	 * failure is directly visible from the ciphertext anyway, -	 * we should not reveal which kind of error occured -- this -	 * might become visible to an attacker (e.g. via logfile) */ -	al=SSL_AD_BAD_RECORD_MAC; -	SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);  f_err:  	ssl3_send_alert(s,SSL3_AL_FATAL,al);  err: @@ -489,19 +481,16 @@ int dtls1_get_record(SSL *s)  	int ssl_major,ssl_minor;  	int i,n;  	SSL3_RECORD *rr; -	SSL_SESSION *sess;  	unsigned char *p = NULL;  	unsigned short version;  	DTLS1_BITMAP *bitmap;  	unsigned int is_next_epoch;  	rr= &(s->s3->rrec); -	sess=s->session;      /* The epoch may have changed.  If so, process all the       * pending records.  This is a non-blocking operation. */ -    if ( ! dtls1_process_buffered_records(s)) -        return 0; +    dtls1_process_buffered_records(s);  	/* if we're renegotiating, then there may be buffered records */  	if (dtls1_get_processed_record(s)) @@ -624,21 +613,26 @@ again:  	/* just read a 0 length packet */  	if (rr->length == 0) goto again; -    /* If this record is from the next epoch (either HM or ALERT), buffer it -     * since it cannot be processed at this time. -     * Records from the next epoch are marked as received even though they are  -     * not processed, so as to prevent any potential resource DoS attack */ -    if (is_next_epoch) -        { -        dtls1_record_bitmap_update(s, bitmap); -        dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), &rr->seq_num); -	rr->length = 0; +	/* If this record is from the next epoch (either HM or ALERT), +	 * and a handshake is currently in progress, buffer it since it +	 * cannot be processed at this time. */ +	if (is_next_epoch) +		{ +		if (SSL_in_init(s) || s->in_handshake) +			{ +			dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), &rr->seq_num); +			} +		rr->length = 0;          s->packet_length = 0;          goto again;          } -    if ( ! dtls1_process_record(s)) -        return(0); +    if (!dtls1_process_record(s)) +		{ +		rr->length = 0; +		s->packet_length=0; /* dump this record */ +		goto again;     /* get another record */ +		}  	dtls1_clear_timeouts(s);  /* done waiting */  	return(1); @@ -766,7 +760,7 @@ start:  		 * buffer the application data for later processing rather  		 * than dropping the connection.  		 */ -		dtls1_buffer_record(s, &(s->d1->buffered_app_data), 0); +		dtls1_buffer_record(s, &(s->d1->buffered_app_data), &rr->seq_num);  		rr->length = 0;  		goto start;  		} diff --git a/ssl/dtls1.h b/ssl/dtls1.h index a8ce51ac3e34..697ff6e31593 100644 --- a/ssl/dtls1.h +++ b/ssl/dtls1.h @@ -165,6 +165,7 @@ typedef struct hm_fragment_st  	{  	struct hm_header_st msg_header;  	unsigned char *fragment; +	unsigned char *reassembly;  	} hm_fragment;  typedef struct dtls1_state_st diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index de0238935a2f..c6b9142c909c 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -369,7 +369,9 @@ static int ssl23_client_hello(SSL *s)  				}  			s2n(i,p);  			p+=i; - +#ifdef OPENSSL_NO_COMP +			*(p++)=1; +#else  			/* COMPRESSION */  			if (s->ctx->comp_methods == NULL)  				j=0; @@ -381,6 +383,7 @@ static int ssl23_client_hello(SSL *s)  				comp=sk_SSL_COMP_value(s->ctx->comp_methods,i);  				*(p++)=comp->id;  				} +#endif  			*(p++)=0; /* Add the NULL method */  #ifndef OPENSSL_NO_TLSEXT  			if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) diff --git a/ssl/s23_lib.c b/ssl/s23_lib.c index fc2981308d55..0b82777b2ae6 100644 --- a/ssl/s23_lib.c +++ b/ssl/s23_lib.c @@ -97,14 +97,8 @@ SSL_CIPHER *ssl23_get_cipher(unsigned int u)   * available */  SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p)  	{ -	SSL_CIPHER c,*cp; -	unsigned long id; -	int n; +	SSL_CIPHER *cp; -	n=ssl3_num_ciphers(); -	id=0x03000000|((unsigned long)p[0]<<16L)| -		((unsigned long)p[1]<<8L)|(unsigned long)p[2]; -	c.id=id;  	cp=ssl3_get_cipher_by_char(p);  #ifndef OPENSSL_NO_SSL2  	if (cp == NULL) diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c index 01d62fad1165..eeffe2549248 100644 --- a/ssl/s2_srvr.c +++ b/ssl/s2_srvr.c @@ -697,7 +697,6 @@ static int server_hello(SSL *s)  	{  	unsigned char *p,*d;  	int n,hit; -	STACK_OF(SSL_CIPHER) *sk;  	p=(unsigned char *)s->init_buf->data;  	if (s->state == SSL2_ST_SEND_SERVER_HELLO_A) @@ -778,7 +777,6 @@ static int server_hello(SSL *s)  			/* lets send out the ciphers we like in the  			 * prefered order */ -			sk= s->session->ciphers;  			n=ssl_cipher_list_to_bytes(s,s->session->ciphers,d,0);  			d+=n;  			s2n(n,p);		/* add cipher length */ diff --git a/ssl/s3_both.c b/ssl/s3_both.c index 7f462250c7a2..869a25d47642 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -354,6 +354,8 @@ unsigned long ssl3_output_cert_chain(SSL *s, X509 *x)  				return(0);  				}  			X509_verify_cert(&xs_ctx); +			/* Don't leave errors in the queue */ +			ERR_clear_error();  			for (i=0; i < sk_X509_num(xs_ctx.chain); i++)  				{  				x = sk_X509_value(xs_ctx.chain, i); diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index e5138b6e5eee..f0995b96acea 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -166,7 +166,7 @@ IMPLEMENT_ssl3_meth_func(SSLv3_client_method,  int ssl3_connect(SSL *s)  	{  	BUF_MEM *buf=NULL; -	unsigned long Time=(unsigned long)time(NULL),l; +	unsigned long Time=(unsigned long)time(NULL);  	void (*cb)(const SSL *ssl,int type,int val)=NULL;  	int ret= -1;  	int new_state,state,skip=0; @@ -360,7 +360,6 @@ int ssl3_connect(SSL *s)  		case SSL3_ST_CW_KEY_EXCH_B:  			ret=ssl3_send_client_key_exchange(s);  			if (ret <= 0) goto end; -			l=s->s3->tmp.new_cipher->algorithms;  			/* EAY EAY EAY need to check for DH fix cert  			 * sent back */  			/* For TLS, cert_req is set to 2, so a cert chain @@ -1377,6 +1376,7 @@ int ssl3_get_key_exchange(SSL *s)  		s->session->sess_cert->peer_ecdh_tmp=ecdh;  		ecdh=NULL;  		BN_CTX_free(bn_ctx); +		bn_ctx = NULL;  		EC_POINT_free(srvr_ecpoint);  		srvr_ecpoint = NULL;  		} diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 06e54666b277..1539a4ce1c54 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -191,7 +191,7 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)  int ssl3_change_cipher_state(SSL *s, int which)  	{ -	unsigned char *p,*key_block,*mac_secret; +	unsigned char *p,*mac_secret;  	unsigned char exp_key[EVP_MAX_KEY_LENGTH];  	unsigned char exp_iv[EVP_MAX_IV_LENGTH];  	unsigned char *ms,*key,*iv,*er1,*er2; @@ -214,7 +214,6 @@ int ssl3_change_cipher_state(SSL *s, int which)  	else  		comp=s->s3->tmp.new_compression->method;  #endif -	key_block=s->s3->tmp.key_block;  	if (which & SSL3_CC_READ)  		{ diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c index 2d9077e30337..6488cdfa9c61 100644 --- a/ssl/ssl_algs.c +++ b/ssl/ssl_algs.c @@ -102,6 +102,14 @@ int SSL_library_init(void)  	EVP_add_digest_alias(SN_sha1,"ssl3-sha1");  	EVP_add_digest_alias(SN_sha1WithRSAEncryption,SN_sha1WithRSA);  #endif +#ifndef OPENSSL_NO_SHA256 +	EVP_add_digest(EVP_sha224()); +	EVP_add_digest(EVP_sha256()); +#endif +#ifndef OPENSSL_NO_SHA512 +	EVP_add_digest(EVP_sha384()); +	EVP_add_digest(EVP_sha512()); +#endif  #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_DSA)  	EVP_add_digest(EVP_dss1()); /* DSA with sha1 */  	EVP_add_digest_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2); diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c index d82e47a14eb6..df8ec82ebf3a 100644 --- a/ssl/ssl_asn1.c +++ b/ssl/ssl_asn1.c @@ -297,7 +297,7 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)  SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,  	     long length)  	{ -	int version,ssl_version=0,i; +	int ssl_version=0,i;  	long id;  	ASN1_INTEGER ai,*aip;  	ASN1_OCTET_STRING os,*osp; @@ -311,7 +311,6 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,  	ai.data=NULL; ai.length=0;  	M_ASN1_D2I_get_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER); -	version=(int)ASN1_INTEGER_get(aip);  	if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; }  	/* we don't care about the version right now :-) */ diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 16fda5d8bffe..361cd9c978ee 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -753,6 +753,8 @@ int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,  			sk_X509_NAME_push(stack,xn);  		} +	ERR_clear_error(); +  	if (0)  		{  err: diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 5e2d436da39a..a34680ee8502 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -777,7 +777,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,  		CIPHER_ORDER **tail_p, SSL_CIPHER **ca_list)  	{  	unsigned long algorithms, mask, algo_strength, mask_strength; -	const char *l, *start, *buf; +	const char *l, *buf;  	int j, multi, found, rule, retval, ok, buflen;  	unsigned long cipher_id = 0, ssl_version = 0;  	char ch; @@ -809,7 +809,6 @@ static int ssl_cipher_process_rulestr(const char *rule_str,  		algorithms = mask = algo_strength = mask_strength = 0; -		start=l;  		for (;;)  			{  			ch = *l; @@ -1100,7 +1099,7 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)  	int is_export,pkl,kl;  	const char *ver,*exp_str;  	const char *kx,*au,*enc,*mac; -	unsigned long alg,alg2,alg_s; +	unsigned long alg,alg2;  #ifdef KSSL_DEBUG  	static const char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s AL=%lx\n";  #else @@ -1108,7 +1107,6 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)  #endif /* KSSL_DEBUG */  	alg=cipher->algorithms; -	alg_s=cipher->algo_strength;  	alg2=cipher->algorithm2;  	is_export=SSL_C_IS_EXPORT(cipher); diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 15650da5e720..b6b8e6038aa6 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1940,15 +1940,13 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs)  /* THIS NEEDS CLEANING UP */  X509 *ssl_get_server_send_cert(SSL *s)  	{ -	unsigned long alg,mask,kalg; +	unsigned long alg,kalg;  	CERT *c; -	int i,is_export; +	int i;  	c=s->cert;  	ssl_set_cert_masks(c, s->s3->tmp.new_cipher);  	alg=s->s3->tmp.new_cipher->algorithms; -	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); -	mask=is_export?c->export_mask:c->mask;  	kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK);  	if (kalg & SSL_kECDH) diff --git a/ssl/ssltest.c b/ssl/ssltest.c index b09c542087ba..310e0677e90a 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -1351,7 +1351,6 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)  	BIO *c_bio=NULL;  	BIO *s_bio=NULL;  	int c_r,c_w,s_r,s_w; -	int c_want,s_want;  	int i,j;  	int done=0;  	int c_write,s_write; @@ -1386,8 +1385,6 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)  	c_r=0; s_r=1;  	c_w=1; s_w=0; -	c_want=W_WRITE; -	s_want=0;  	c_write=1,s_write=0;  	/* We can always do writes */ diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index dab6e4485b78..34830988fca8 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -125,7 +125,7 @@ static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,  			int sec_len, unsigned char *seed, int seed_len,  			unsigned char *out, int olen)  	{ -	int chunk,n; +	int chunk;  	unsigned int j;  	HMAC_CTX ctx;  	HMAC_CTX ctx_tmp; @@ -143,7 +143,6 @@ static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,  	HMAC_Update(&ctx,seed,seed_len);  	HMAC_Final(&ctx,A1,&A1_len); -	n=0;  	for (;;)  		{  		HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */ @@ -227,14 +226,14 @@ static void tls1_generate_key_block(SSL *s, unsigned char *km,  int tls1_change_cipher_state(SSL *s, int which)  	{  	static const unsigned char empty[]=""; -	unsigned char *p,*key_block,*mac_secret; +	unsigned char *p,*mac_secret;  	unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+  		SSL3_RANDOM_SIZE*2];  	unsigned char tmp1[EVP_MAX_KEY_LENGTH];  	unsigned char tmp2[EVP_MAX_KEY_LENGTH];  	unsigned char iv1[EVP_MAX_IV_LENGTH*2];  	unsigned char iv2[EVP_MAX_IV_LENGTH*2]; -	unsigned char *ms,*key,*iv,*er1,*er2; +	unsigned char *ms,*key,*iv;  	int client_write;  	EVP_CIPHER_CTX *dd;  	const EVP_CIPHER *c; @@ -251,9 +250,10 @@ int tls1_change_cipher_state(SSL *s, int which)  #ifndef OPENSSL_NO_COMP  	comp=s->s3->tmp.new_compression;  #endif -	key_block=s->s3->tmp.key_block;  #ifdef KSSL_DEBUG +	key_block=s->s3->tmp.key_block; +  	printf("tls1_change_cipher_state(which= %d) w/\n", which);  	printf("\talg= %ld, comp= %p\n", s->s3->tmp.new_cipher->algorithms,                  (void *)comp); @@ -348,8 +348,6 @@ int tls1_change_cipher_state(SSL *s, int which)  	               cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;  	/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */  	k=EVP_CIPHER_iv_length(c); -	er1= &(s->s3->client_random[0]); -	er2= &(s->s3->server_random[0]);  	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||  		(which == SSL3_CHANGE_CIPHER_SERVER_READ))  		{ @@ -535,13 +533,11 @@ int tls1_enc(SSL *s, int send)  	SSL3_RECORD *rec;  	EVP_CIPHER_CTX *ds;  	unsigned long l; -	int bs,i,ii,j,k,n=0; +	int bs,i,ii,j,k;  	const EVP_CIPHER *enc;  	if (send)  		{ -		if (s->write_hash != NULL) -			n=EVP_MD_size(s->write_hash);  		ds=s->enc_write_ctx;  		rec= &(s->s3->wrec);  		if (s->enc_write_ctx == NULL) @@ -551,8 +547,6 @@ int tls1_enc(SSL *s, int send)  		}  	else  		{ -		if (s->read_hash != NULL) -			n=EVP_MD_size(s->read_hash);  		ds=s->enc_read_ctx;  		rec= &(s->s3->rrec);  		if (s->enc_read_ctx == NULL) diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 8b5311277015..0cc8320e1789 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -432,14 +432,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in  				switch (servname_type)  					{  				case TLSEXT_NAMETYPE_host_name: -					if (s->session->tlsext_hostname == NULL) +					if (!s->hit)  						{ -						if (len > TLSEXT_MAXLEN_host_name ||  -							((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL)) +						if(s->session->tlsext_hostname) +							{ +							*al = SSL_AD_DECODE_ERROR; +							return 0; +							} +						if (len > TLSEXT_MAXLEN_host_name)  							{  							*al = TLS1_AD_UNRECOGNIZED_NAME;  							return 0;  							} +						if ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL) +							{ +							*al = TLS1_AD_INTERNAL_ERROR; +							return 0; +							}  						memcpy(s->session->tlsext_hostname, sdata, len);  						s->session->tlsext_hostname[len]='\0';  						if (strlen(s->session->tlsext_hostname) != len) { @@ -452,7 +461,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in  						}  					else  -						s->servername_done = strlen(s->session->tlsext_hostname) == len  +						s->servername_done = s->session->tlsext_hostname +							&& strlen(s->session->tlsext_hostname) == len   							&& strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;  					break; @@ -601,9 +611,9 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in  int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)  	{ +	unsigned short length;  	unsigned short type;  	unsigned short size; -	unsigned short len;    	unsigned char *data = *p;  	int tlsext_servername = 0;  	int renegotiate_seen = 0; @@ -611,7 +621,12 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in  	if (data >= (d+n-2))  		goto ri_check; -	n2s(data,len); +	n2s(data,length); +	if (data+length != d+n) +		{ +		*al = SSL_AD_DECODE_ERROR; +		return 0; +		}  	while(data <= (d+n-4))  		{  | 
