saprasad / rpms / openssl

Forked from rpms/openssl 3 years ago
Clone
53a15b4
Fix DTLS implementation to be RFC 4347 compliant. This makes the new client
53a15b4
incompatible with the old openssl DTLS servers. However the older openssl client
53a15b4
will still be able to connect to the new server code. This change also
53a15b4
resolves buffer overrun when out-of-order fragments are received during
53a15b4
the handshake.
53a15b4
CVE-2007-4995
53a15b4
diff -up openssl-0.9.8b/ssl/dtls1.h.dtls-fixes openssl-0.9.8b/ssl/dtls1.h
53a15b4
--- openssl-0.9.8b/ssl/dtls1.h.dtls-fixes	2007-10-08 17:55:22.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/dtls1.h	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -67,9 +67,8 @@
53a15b4
 extern "C" {
53a15b4
 #endif
53a15b4
 
53a15b4
-#define DTLS1_VERSION			0x0100
53a15b4
-#define DTLS1_VERSION_MAJOR		0x01
53a15b4
-#define DTLS1_VERSION_MINOR		0x00
53a15b4
+#define DTLS1_VERSION			0xFEFF
53a15b4
+#define DTLS1_BAD_VER			0x0100
53a15b4
 
53a15b4
 #define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE    110
53a15b4
 
53a15b4
@@ -83,7 +82,7 @@ extern "C" {
53a15b4
 #define DTLS1_HM_BAD_FRAGMENT                   -2
53a15b4
 #define DTLS1_HM_FRAGMENT_RETRY                 -3
53a15b4
 
53a15b4
-#define DTLS1_CCS_HEADER_LENGTH                  3
53a15b4
+#define DTLS1_CCS_HEADER_LENGTH                  1
53a15b4
 
53a15b4
 #define DTLS1_AL_HEADER_LENGTH                   7
53a15b4
 
53a15b4
diff -up openssl-0.9.8b/ssl/d1_lib.c.dtls-fixes openssl-0.9.8b/ssl/d1_lib.c
53a15b4
--- openssl-0.9.8b/ssl/d1_lib.c.dtls-fixes	2005-08-08 21:26:35.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/d1_lib.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -188,3 +188,23 @@ void dtls1_clear(SSL *s)
53a15b4
 	ssl3_clear(s);
53a15b4
 	s->version=DTLS1_VERSION;
53a15b4
 	}
53a15b4
+
53a15b4
+/*
53a15b4
+ * As it's impossible to use stream ciphers in "datagram" mode, this
53a15b4
+ * simple filter is designed to disengage them in DTLS. Unfortunately
53a15b4
+ * there is no universal way to identify stream SSL_CIPHER, so we have
53a15b4
+ * to explicitly list their SSL_* codes. Currently RC4 is the only one
53a15b4
+ * available, but if new ones emerge, they will have to be added...
53a15b4
+ */
53a15b4
+SSL_CIPHER *dtls1_get_cipher(unsigned int u)
53a15b4
+	{
53a15b4
+	SSL_CIPHER *ciph = ssl3_get_cipher(u);
53a15b4
+
53a15b4
+	if (ciph != NULL)
53a15b4
+		{
53a15b4
+		if ((ciph->algorithms&SSL_ENC_MASK) == SSL_RC4)
53a15b4
+			return NULL;
53a15b4
+		}
53a15b4
+
53a15b4
+	return ciph;
53a15b4
+	}
53a15b4
diff -up openssl-0.9.8b/ssl/d1_srvr.c.dtls-fixes openssl-0.9.8b/ssl/d1_srvr.c
53a15b4
--- openssl-0.9.8b/ssl/d1_srvr.c.dtls-fixes	2005-12-05 18:32:19.000000000 +0100
53a15b4
+++ openssl-0.9.8b/ssl/d1_srvr.c	2007-10-10 14:21:49.000000000 +0200
53a15b4
@@ -285,6 +285,10 @@ int dtls1_accept(SSL *s)
53a15b4
 			s->d1->send_cookie = 0;
53a15b4
 			s->state=SSL3_ST_SW_FLUSH;
53a15b4
 			s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
53a15b4
+
53a15b4
+			/* HelloVerifyRequests resets Finished MAC */
53a15b4
+			if (s->client_version != DTLS1_BAD_VER)
53a15b4
+				ssl3_init_finished_mac(s);
53a15b4
 			break;
53a15b4
 			
53a15b4
 		case SSL3_ST_SW_SRVR_HELLO_A:
53a15b4
@@ -620,10 +624,13 @@ int dtls1_send_hello_verify_request(SSL 
53a15b4
 		buf = (unsigned char *)s->init_buf->data;
53a15b4
 
53a15b4
 		msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]);
53a15b4
-		*(p++) = s->version >> 8;
53a15b4
-		*(p++) = s->version & 0xFF;
53a15b4
+		if (s->client_version == DTLS1_BAD_VER)
53a15b4
+			*(p++) = DTLS1_BAD_VER>>8,
53a15b4
+			*(p++) = DTLS1_BAD_VER&0xff;
53a15b4
+		else
53a15b4
+			*(p++) = s->version >> 8,
53a15b4
+			*(p++) = s->version & 0xFF;
53a15b4
 
53a15b4
-		*(p++) = (unsigned char) s->d1->cookie_len;
53a15b4
         if ( s->ctx->app_gen_cookie_cb != NULL &&
53a15b4
             s->ctx->app_gen_cookie_cb(s, s->d1->cookie, 
53a15b4
                 &(s->d1->cookie_len)) == 0)
53a15b4
@@ -634,6 +641,7 @@ int dtls1_send_hello_verify_request(SSL 
53a15b4
         /* else the cookie is assumed to have 
53a15b4
          * been initialized by the application */
53a15b4
 
53a15b4
+		*(p++) = (unsigned char) s->d1->cookie_len;
53a15b4
 		memcpy(p, s->d1->cookie, s->d1->cookie_len);
53a15b4
 		p += s->d1->cookie_len;
53a15b4
 		msg_len = p - msg;
53a15b4
@@ -672,8 +680,12 @@ int dtls1_send_server_hello(SSL *s)
53a15b4
 		/* Do the message type and length last */
53a15b4
 		d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
53a15b4
 
53a15b4
-		*(p++)=s->version>>8;
53a15b4
-		*(p++)=s->version&0xff;
53a15b4
+		if (s->client_version == DTLS1_BAD_VER)
53a15b4
+			*(p++)=DTLS1_BAD_VER>>8,
53a15b4
+			*(p++)=DTLS1_BAD_VER&0xff;
53a15b4
+		else
53a15b4
+			*(p++)=s->version>>8,
53a15b4
+			*(p++)=s->version&0xff;
53a15b4
 
53a15b4
 		/* Random stuff */
53a15b4
 		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
53a15b4
@@ -1009,6 +1021,7 @@ int dtls1_send_certificate_request(SSL *
53a15b4
 	STACK_OF(X509_NAME) *sk=NULL;
53a15b4
 	X509_NAME *name;
53a15b4
 	BUF_MEM *buf;
53a15b4
+	unsigned int msg_len;
53a15b4
 
53a15b4
 	if (s->state == SSL3_ST_SW_CERT_REQ_A)
53a15b4
 		{
53a15b4
@@ -1086,6 +1099,10 @@ int dtls1_send_certificate_request(SSL *
53a15b4
 #endif
53a15b4
 
53a15b4
 		/* XDTLS:  set message header ? */
53a15b4
+		msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH;
53a15b4
+		dtls1_set_message_header(s, (void *)s->init_buf->data,
53a15b4
+			SSL3_MT_CERTIFICATE_REQUEST, msg_len, 0, msg_len);
53a15b4
+
53a15b4
 		/* buffer the message to handle re-xmits */
53a15b4
 		dtls1_buffer_message(s, 0);
53a15b4
 
53a15b4
diff -up openssl-0.9.8b/ssl/s3_srvr.c.dtls-fixes openssl-0.9.8b/ssl/s3_srvr.c
53a15b4
--- openssl-0.9.8b/ssl/s3_srvr.c.dtls-fixes	2007-10-08 17:55:22.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/s3_srvr.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -679,9 +679,9 @@ int ssl3_get_client_hello(SSL *s)
53a15b4
 	 */
53a15b4
 	if (s->state == SSL3_ST_SR_CLNT_HELLO_A)
53a15b4
 		{
53a15b4
-		s->first_packet=1;
53a15b4
 		s->state=SSL3_ST_SR_CLNT_HELLO_B;
53a15b4
 		}
53a15b4
+	s->first_packet=1;
53a15b4
 	n=s->method->ssl_get_message(s,
53a15b4
 		SSL3_ST_SR_CLNT_HELLO_B,
53a15b4
 		SSL3_ST_SR_CLNT_HELLO_C,
53a15b4
@@ -690,6 +690,7 @@ int ssl3_get_client_hello(SSL *s)
53a15b4
 		&ok;;
53a15b4
 
53a15b4
 	if (!ok) return((int)n);
53a15b4
+	s->first_packet=0;
53a15b4
 	d=p=(unsigned char *)s->init_msg;
53a15b4
 
53a15b4
 	/* use version from inside client hello, not from record header
53a15b4
@@ -697,7 +698,8 @@ int ssl3_get_client_hello(SSL *s)
53a15b4
 	s->client_version=(((int)p[0])<<8)|(int)p[1];
53a15b4
 	p+=2;
53a15b4
 
53a15b4
-	if (s->client_version < s->version)
53a15b4
+	if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
53a15b4
+	    (s->version != DTLS1_VERSION && s->client_version < s->version))
53a15b4
 		{
53a15b4
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
53a15b4
 		if ((s->client_version>>8) == SSL3_VERSION_MAJOR) 
53a15b4
@@ -748,7 +750,7 @@ int ssl3_get_client_hello(SSL *s)
53a15b4
 
53a15b4
 	p+=j;
53a15b4
 
53a15b4
-	if (SSL_version(s) == DTLS1_VERSION)
53a15b4
+	if (s->version == DTLS1_VERSION)
53a15b4
 		{
53a15b4
 		/* cookie stuff */
53a15b4
 		cookie_len = *(p++);
53a15b4
@@ -1709,8 +1711,9 @@ int ssl3_get_client_key_exchange(SSL *s)
53a15b4
 			rsa=pkey->pkey.rsa;
53a15b4
 			}
53a15b4
 
53a15b4
-		/* TLS */
53a15b4
-		if (s->version > SSL3_VERSION)
53a15b4
+		/* TLS and [incidentally] DTLS, including pre-0.9.8f */
53a15b4
+		if (s->version > SSL3_VERSION &&
53a15b4
+		    s->client_version != DTLS1_BAD_VER)
53a15b4
 			{
53a15b4
 			n2s(p,i);
53a15b4
 			if (n != i+2)
53a15b4
diff -up openssl-0.9.8b/ssl/ssl_locl.h.dtls-fixes openssl-0.9.8b/ssl/ssl_locl.h
53a15b4
--- openssl-0.9.8b/ssl/ssl_locl.h.dtls-fixes	2007-10-08 17:55:22.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/ssl_locl.h	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -677,7 +677,7 @@ SSL_METHOD *func_name(void)  \
53a15b4
 		ssl3_put_cipher_by_char, \
53a15b4
 		ssl3_pending, \
53a15b4
 		ssl3_num_ciphers, \
53a15b4
-		ssl3_get_cipher, \
53a15b4
+		dtls1_get_cipher, \
53a15b4
 		s_get_meth, \
53a15b4
 		dtls1_default_timeout, \
53a15b4
 		&DTLSv1_enc_data, \
53a15b4
@@ -842,6 +842,8 @@ void dtls1_get_message_header(unsigned c
53a15b4
 void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
53a15b4
 void dtls1_reset_seq_numbers(SSL *s, int rw);
53a15b4
 long dtls1_default_timeout(void);
53a15b4
+SSL_CIPHER *dtls1_get_cipher(unsigned int u);
53a15b4
+
53a15b4
 
53a15b4
 
53a15b4
 /* some client-only functions */
53a15b4
diff -up openssl-0.9.8b/ssl/t1_enc.c.dtls-fixes openssl-0.9.8b/ssl/t1_enc.c
53a15b4
--- openssl-0.9.8b/ssl/t1_enc.c.dtls-fixes	2007-10-08 17:55:22.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/t1_enc.c	2007-10-10 14:24:52.000000000 +0200
53a15b4
@@ -737,15 +737,35 @@ int tls1_mac(SSL *ssl, unsigned char *md
53a15b4
 	md_size=EVP_MD_size(hash);
53a15b4
 
53a15b4
 	buf[0]=rec->type;
53a15b4
-	buf[1]=TLS1_VERSION_MAJOR;
53a15b4
-	buf[2]=TLS1_VERSION_MINOR;
53a15b4
+	if (ssl->version == DTLS1_VERSION && ssl->client_version == DTLS1_BAD_VER)
53a15b4
+		{
53a15b4
+		buf[1]=TLS1_VERSION_MAJOR;
53a15b4
+		buf[2]=TLS1_VERSION_MINOR;
53a15b4
+		}
53a15b4
+	else	{
53a15b4
+		buf[1]=(unsigned char)(ssl->version>>8);
53a15b4
+		buf[2]=(unsigned char)(ssl->version);
53a15b4
+		}
53a15b4
+
53a15b4
 	buf[3]=rec->length>>8;
53a15b4
 	buf[4]=rec->length&0xff;
53a15b4
 
53a15b4
 	/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
53a15b4
 	HMAC_CTX_init(&hmac);
53a15b4
 	HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL);
53a15b4
-	HMAC_Update(&hmac,seq,8);
53a15b4
+
53a15b4
+	if (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER)
53a15b4
+		{
53a15b4
+		unsigned char dtlsseq[8],*p=dtlsseq;
53a15b4
+
53a15b4
+		s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
53a15b4
+		memcpy (p,&seq[2],6);
53a15b4
+
53a15b4
+		HMAC_Update(&hmac,dtlsseq,8);
53a15b4
+		}
53a15b4
+	else
53a15b4
+		HMAC_Update(&hmac,seq,8);
53a15b4
+
53a15b4
 	HMAC_Update(&hmac,buf,5);
53a15b4
 	HMAC_Update(&hmac,rec->input,rec->length);
53a15b4
 	HMAC_Final(&hmac,md,&md_size);
53a15b4
@@ -762,8 +782,8 @@ printf("rec=");
53a15b4
 {unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
53a15b4
 #endif
53a15b4
 
53a15b4
-    if ( SSL_version(ssl) != DTLS1_VERSION)
53a15b4
-	    {
53a15b4
+	if ( SSL_version(ssl) != DTLS1_VERSION)
53a15b4
+		{
53a15b4
 		for (i=7; i>=0; i--)
53a15b4
 			{
53a15b4
 			++seq[i];
53a15b4
diff -up openssl-0.9.8b/ssl/ssl.h.dtls-fixes openssl-0.9.8b/ssl/ssl.h
53a15b4
--- openssl-0.9.8b/ssl/ssl.h.dtls-fixes	2007-10-08 17:55:22.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/ssl.h	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -315,7 +315,7 @@ extern "C" {
53a15b4
 /* The following cipher list is used by default.
53a15b4
  * It also is substituted when an application-defined cipher list string
53a15b4
  * starts with 'DEFAULT'. */
53a15b4
-#define SSL_DEFAULT_CIPHER_LIST	"ALL:!ADH:+RC4:@STRENGTH" /* low priority for RC4 */
53a15b4
+#define SSL_DEFAULT_CIPHER_LIST	"AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" /* low priority for RC4 */
53a15b4
 
53a15b4
 /* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
53a15b4
 #define SSL_SENT_SHUTDOWN	1
53a15b4
@@ -1551,6 +1551,7 @@ void ERR_load_SSL_strings(void);
53a15b4
 #define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT		 253
53a15b4
 #define SSL_F_DTLS1_GET_RECORD				 254
53a15b4
 #define SSL_F_DTLS1_OUTPUT_CERT_CHAIN			 255
53a15b4
+#define SSL_F_DTLS1_PREPROCESS_FRAGMENT			 277
53a15b4
 #define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE		 256
53a15b4
 #define SSL_F_DTLS1_PROCESS_RECORD			 257
53a15b4
 #define SSL_F_DTLS1_READ_BYTES				 258
53a15b4
diff -up openssl-0.9.8b/ssl/d1_pkt.c.dtls-fixes openssl-0.9.8b/ssl/d1_pkt.c
53a15b4
--- openssl-0.9.8b/ssl/d1_pkt.c.dtls-fixes	2006-02-08 20:16:32.000000000 +0100
53a15b4
+++ openssl-0.9.8b/ssl/d1_pkt.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -120,6 +120,7 @@
53a15b4
 #include <openssl/evp.h>
53a15b4
 #include <openssl/buffer.h>
53a15b4
 #include <openssl/pqueue.h>
53a15b4
+#include <openssl/rand.h>
53a15b4
 
53a15b4
 static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, 
53a15b4
 	int len, int peek);
53a15b4
@@ -486,9 +487,9 @@ int dtls1_get_record(SSL *s)
53a15b4
 	SSL3_RECORD *rr;
53a15b4
 	SSL_SESSION *sess;
53a15b4
 	unsigned char *p;
53a15b4
-	short version;
53a15b4
+	unsigned short version;
53a15b4
 	DTLS1_BITMAP *bitmap;
53a15b4
-    unsigned int is_next_epoch;
53a15b4
+	unsigned int is_next_epoch;
53a15b4
 
53a15b4
 	rr= &(s->s3->rrec);
53a15b4
 	sess=s->session;
53a15b4
@@ -524,7 +525,7 @@ again:
53a15b4
 		ssl_minor= *(p++);
53a15b4
 		version=(ssl_major<<8)|ssl_minor;
53a15b4
 
53a15b4
-        /* sequence number is 64 bits, with top 2 bytes = epoch */ 
53a15b4
+		/* sequence number is 64 bits, with top 2 bytes = epoch */ 
53a15b4
 		n2s(p,rr->epoch);
53a15b4
 
53a15b4
 		memcpy(&(s->s3->read_sequence[2]), p, 6);
53a15b4
@@ -533,13 +534,9 @@ again:
53a15b4
 		n2s(p,rr->length);
53a15b4
 
53a15b4
 		/* Lets check version */
53a15b4
-		if (s->first_packet)
53a15b4
+		if (!s->first_packet)
53a15b4
 			{
53a15b4
-			s->first_packet=0;
53a15b4
-			}
53a15b4
-		else
53a15b4
-			{
53a15b4
-			if (version != s->version)
53a15b4
+			if (version != s->version && version != DTLS1_BAD_VER)
53a15b4
 				{
53a15b4
 				SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
53a15b4
 				/* Send back error using their
53a15b4
@@ -550,7 +547,8 @@ again:
53a15b4
 				}
53a15b4
 			}
53a15b4
 
53a15b4
-		if ((version & 0xff00) != (DTLS1_VERSION & 0xff00))
53a15b4
+		if ((version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
53a15b4
+		    (version & 0xff00) != (DTLS1_BAD_VER & 0xff00))
53a15b4
 			{
53a15b4
 			SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
53a15b4
 			goto err;
53a15b4
@@ -796,8 +794,14 @@ start:
53a15b4
 			dest = s->d1->alert_fragment;
53a15b4
 			dest_len = &s->d1->alert_fragment_len;
53a15b4
 			}
53a15b4
-		else	/* else it's a CCS message */
53a15b4
-			OPENSSL_assert(rr->type == SSL3_RT_CHANGE_CIPHER_SPEC);
53a15b4
+                /* else it's a CCS message, or it's wrong */
53a15b4
+                else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
53a15b4
+                        {
53a15b4
+                          /* Not certain if this is the right error handling */
53a15b4
+                          al=SSL_AD_UNEXPECTED_MESSAGE;
53a15b4
+                          SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
53a15b4
+                          goto f_err;
53a15b4
+                        }
53a15b4
 
53a15b4
 
53a15b4
 		if (dest_maxlen > 0)
53a15b4
@@ -971,47 +975,40 @@ start:
53a15b4
 		}
53a15b4
 
53a15b4
 	if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
53a15b4
-        {
53a15b4
-        struct ccs_header_st ccs_hdr;
53a15b4
+		{
53a15b4
+		struct ccs_header_st ccs_hdr;
53a15b4
 
53a15b4
 		dtls1_get_ccs_header(rr->data, &ccs_hdr);
53a15b4
 
53a15b4
-		if ( ccs_hdr.seq == s->d1->handshake_read_seq)
53a15b4
+		/* 'Change Cipher Spec' is just a single byte, so we know
53a15b4
+		 * exactly what the record payload has to look like */
53a15b4
+		/* XDTLS: check that epoch is consistent */
53a15b4
+		if (	(s->client_version == DTLS1_BAD_VER && rr->length != 3) ||
53a15b4
+			(s->client_version != DTLS1_BAD_VER && rr->length != DTLS1_CCS_HEADER_LENGTH) || 
53a15b4
+			(rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
53a15b4
 			{
53a15b4
-			/* 'Change Cipher Spec' is just a single byte, so we know
53a15b4
-			 * exactly what the record payload has to look like */
53a15b4
-			/* XDTLS: check that epoch is consistent */
53a15b4
-			if (	(rr->length != DTLS1_CCS_HEADER_LENGTH) || 
53a15b4
-				(rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
53a15b4
-				{
53a15b4
-				i=SSL_AD_ILLEGAL_PARAMETER;
53a15b4
-				SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
53a15b4
-				goto err;
53a15b4
-				}
53a15b4
-			
53a15b4
-			rr->length=0;
53a15b4
-			
53a15b4
-			if (s->msg_callback)
53a15b4
-				s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, 
53a15b4
-					rr->data, 1, s, s->msg_callback_arg);
53a15b4
-			
53a15b4
-			s->s3->change_cipher_spec=1;
53a15b4
-			if (!ssl3_do_change_cipher_spec(s))
53a15b4
-				goto err;
53a15b4
-			
53a15b4
-			/* do this whenever CCS is processed */
53a15b4
-			dtls1_reset_seq_numbers(s, SSL3_CC_READ);
53a15b4
-			
53a15b4
-			/* handshake read seq is reset upon handshake completion */
53a15b4
-			s->d1->handshake_read_seq++;
53a15b4
-			
53a15b4
-			goto start;
53a15b4
-			}
53a15b4
-		else
53a15b4
-			{
53a15b4
-			rr->length = 0;
53a15b4
-			goto start;
53a15b4
+			i=SSL_AD_ILLEGAL_PARAMETER;
53a15b4
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
53a15b4
+			goto err;
53a15b4
 			}
53a15b4
+
53a15b4
+		rr->length=0;
53a15b4
+
53a15b4
+		if (s->msg_callback)
53a15b4
+			s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, 
53a15b4
+				rr->data, 1, s, s->msg_callback_arg);
53a15b4
+
53a15b4
+		s->s3->change_cipher_spec=1;
53a15b4
+		if (!ssl3_do_change_cipher_spec(s))
53a15b4
+			goto err;
53a15b4
+
53a15b4
+		/* do this whenever CCS is processed */
53a15b4
+		dtls1_reset_seq_numbers(s, SSL3_CC_READ);
53a15b4
+
53a15b4
+		/* handshake read seq is reset upon handshake completion */
53a15b4
+		s->d1->handshake_read_seq++;
53a15b4
+
53a15b4
+		goto start;
53a15b4
 		}
53a15b4
 
53a15b4
 	/* Unexpected handshake message (Client Hello, or protocol violation) */
53a15b4
@@ -1339,8 +1336,12 @@ int do_dtls1_write(SSL *s, int type, con
53a15b4
 	*(p++)=type&0xff;
53a15b4
 	wr->type=type;
53a15b4
 
53a15b4
-	*(p++)=(s->version>>8);
53a15b4
-	*(p++)=s->version&0xff;
53a15b4
+	if (s->client_version == DTLS1_BAD_VER)
53a15b4
+		*(p++) = DTLS1_BAD_VER>>8,
53a15b4
+		*(p++) = DTLS1_BAD_VER&0xff;
53a15b4
+	else
53a15b4
+		*(p++)=(s->version>>8),
53a15b4
+		*(p++)=s->version&0xff;
53a15b4
 
53a15b4
 	/* field where we are to write out packet epoch, seq num and len */
53a15b4
 	pseq=p; 
53a15b4
@@ -1395,8 +1396,14 @@ int do_dtls1_write(SSL *s, int type, con
53a15b4
 
53a15b4
 
53a15b4
 	/* ssl3_enc can only have an error on read */
53a15b4
-	wr->length += bs;  /* bs != 0 in case of CBC.  The enc fn provides
53a15b4
-						* the randomness */ 
53a15b4
+	if (bs)	/* bs != 0 in case of CBC */
53a15b4
+		{
53a15b4
+		RAND_pseudo_bytes(p,bs);
53a15b4
+		/* master IV and last CBC residue stand for
53a15b4
+		 * the rest of randomness */
53a15b4
+		wr->length += bs;
53a15b4
+		}
53a15b4
+
53a15b4
 	s->method->ssl3_enc->enc(s,1);
53a15b4
 
53a15b4
 	/* record length after mac and block padding */
53a15b4
diff -up openssl-0.9.8b/ssl/ssl_err.c.dtls-fixes openssl-0.9.8b/ssl/ssl_err.c
53a15b4
--- openssl-0.9.8b/ssl/ssl_err.c.dtls-fixes	2006-01-08 22:52:46.000000000 +0100
53a15b4
+++ openssl-0.9.8b/ssl/ssl_err.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -87,6 +87,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
53a15b4
 {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT),	"DTLS1_GET_MESSAGE_FRAGMENT"},
53a15b4
 {ERR_FUNC(SSL_F_DTLS1_GET_RECORD),	"DTLS1_GET_RECORD"},
53a15b4
 {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN),	"DTLS1_OUTPUT_CERT_CHAIN"},
53a15b4
+{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT),	"DTLS1_PREPROCESS_FRAGMENT"},
53a15b4
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),	"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
53a15b4
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD),	"DTLS1_PROCESS_RECORD"},
53a15b4
 {ERR_FUNC(SSL_F_DTLS1_READ_BYTES),	"DTLS1_READ_BYTES"},
53a15b4
diff -up openssl-0.9.8b/ssl/s3_pkt.c.dtls-fixes openssl-0.9.8b/ssl/s3_pkt.c
53a15b4
--- openssl-0.9.8b/ssl/s3_pkt.c.dtls-fixes	2005-10-01 01:38:20.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/s3_pkt.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -277,11 +277,7 @@ again:
53a15b4
 		n2s(p,rr->length);
53a15b4
 
53a15b4
 		/* Lets check version */
53a15b4
-		if (s->first_packet)
53a15b4
-			{
53a15b4
-			s->first_packet=0;
53a15b4
-			}
53a15b4
-		else
53a15b4
+		if (!s->first_packet)
53a15b4
 			{
53a15b4
 			if (version != s->version)
53a15b4
 				{
53a15b4
diff -up openssl-0.9.8b/ssl/s23_srvr.c.dtls-fixes openssl-0.9.8b/ssl/s23_srvr.c
53a15b4
--- openssl-0.9.8b/ssl/s23_srvr.c.dtls-fixes	2005-12-05 18:32:19.000000000 +0100
53a15b4
+++ openssl-0.9.8b/ssl/s23_srvr.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -565,7 +565,6 @@ int ssl23_get_client_hello(SSL *s)
53a15b4
 	s->init_num=0;
53a15b4
 
53a15b4
 	if (buf != buf_space) OPENSSL_free(buf);
53a15b4
-	s->first_packet=1;
53a15b4
 	return(SSL_accept(s));
53a15b4
 err:
53a15b4
 	if (buf != buf_space) OPENSSL_free(buf);
53a15b4
diff -up openssl-0.9.8b/ssl/s23_clnt.c.dtls-fixes openssl-0.9.8b/ssl/s23_clnt.c
53a15b4
--- openssl-0.9.8b/ssl/s23_clnt.c.dtls-fixes	2005-12-05 18:32:19.000000000 +0100
53a15b4
+++ openssl-0.9.8b/ssl/s23_clnt.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -574,7 +574,6 @@ static int ssl23_get_server_hello(SSL *s
53a15b4
 	if (!ssl_get_new_session(s,0))
53a15b4
 		goto err;
53a15b4
 
53a15b4
-	s->first_packet=1;
53a15b4
 	return(SSL_connect(s));
53a15b4
 err:
53a15b4
 	return(-1);
53a15b4
diff -up openssl-0.9.8b/ssl/s3_lib.c.dtls-fixes openssl-0.9.8b/ssl/s3_lib.c
53a15b4
--- openssl-0.9.8b/ssl/s3_lib.c.dtls-fixes	2006-01-15 08:14:38.000000000 +0100
53a15b4
+++ openssl-0.9.8b/ssl/s3_lib.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -903,7 +903,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]
53a15b4
 	},
53a15b4
 
53a15b4
 #if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES
53a15b4
-	/* New TLS Export CipherSuites */
53a15b4
+	/* New TLS Export CipherSuites from expired ID */
53a15b4
+#if 0
53a15b4
 	/* Cipher 60 */
53a15b4
 	    {
53a15b4
 	    1,
53a15b4
@@ -930,6 +931,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]
53a15b4
 	    SSL_ALL_CIPHERS,
53a15b4
 	    SSL_ALL_STRENGTHS,
53a15b4
 	    },
53a15b4
+#endif
53a15b4
 	/* Cipher 62 */
53a15b4
 	    {
53a15b4
 	    1,
53a15b4
diff -up openssl-0.9.8b/ssl/s2_lib.c.dtls-fixes openssl-0.9.8b/ssl/s2_lib.c
53a15b4
--- openssl-0.9.8b/ssl/s2_lib.c.dtls-fixes	2005-08-27 14:05:23.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/s2_lib.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -178,7 +178,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl2_ciphers[]
53a15b4
 	SSL_ALL_STRENGTHS,
53a15b4
 	},
53a15b4
 /* RC4_64_WITH_MD5 */
53a15b4
-#if 1
53a15b4
+#if 0
53a15b4
 	{
53a15b4
 	1,
53a15b4
 	SSL2_TXT_RC4_64_WITH_MD5,
53a15b4
diff -up openssl-0.9.8b/ssl/d1_both.c.dtls-fixes openssl-0.9.8b/ssl/d1_both.c
53a15b4
--- openssl-0.9.8b/ssl/d1_both.c.dtls-fixes	2005-08-29 01:20:52.000000000 +0200
53a15b4
+++ openssl-0.9.8b/ssl/d1_both.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -138,38 +138,40 @@ static void dtls1_set_message_header_int
53a15b4
 	unsigned long frag_len);
53a15b4
 static int dtls1_retransmit_buffered_messages(SSL *s);
53a15b4
 static long dtls1_get_message_fragment(SSL *s, int st1, int stn, 
53a15b4
-    long max, int *ok);
53a15b4
-static void dtls1_process_handshake_fragment(SSL *s, int frag_len);
53a15b4
+	long max, int *ok);
53a15b4
 
53a15b4
 static hm_fragment *
53a15b4
 dtls1_hm_fragment_new(unsigned long frag_len)
53a15b4
-    {
53a15b4
-    hm_fragment *frag = NULL;
53a15b4
-    unsigned char *buf = NULL;
53a15b4
+	{
53a15b4
+	hm_fragment *frag = NULL;
53a15b4
+	unsigned char *buf = NULL;
53a15b4
 
53a15b4
-    frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
53a15b4
-    if ( frag == NULL)
53a15b4
-        return NULL;
53a15b4
+	frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
53a15b4
+	if ( frag == NULL)
53a15b4
+		return NULL;
53a15b4
 
53a15b4
-    buf = (unsigned char *)OPENSSL_malloc(frag_len 
53a15b4
-        + DTLS1_HM_HEADER_LENGTH);
53a15b4
-    if ( buf == NULL)
53a15b4
-        {
53a15b4
-        OPENSSL_free(frag);
53a15b4
-        return NULL;
53a15b4
-        }
53a15b4
-    
53a15b4
-    frag->fragment = buf;
53a15b4
+	if (frag_len)
53a15b4
+		{
53a15b4
+		buf = (unsigned char *)OPENSSL_malloc(frag_len);
53a15b4
+		if ( buf == NULL)
53a15b4
+			{
53a15b4
+			OPENSSL_free(frag);
53a15b4
+			return NULL;
53a15b4
+			}
53a15b4
+		}
53a15b4
 
53a15b4
-    return frag;
53a15b4
-    }
53a15b4
+	/* zero length fragment gets zero frag->fragment */
53a15b4
+	frag->fragment = buf;
53a15b4
+
53a15b4
+	return frag;
53a15b4
+	}
53a15b4
 
53a15b4
 static void
53a15b4
 dtls1_hm_fragment_free(hm_fragment *frag)
53a15b4
-    {
53a15b4
-    OPENSSL_free(frag->fragment);
53a15b4
-    OPENSSL_free(frag);
53a15b4
-    }
53a15b4
+	{
53a15b4
+	if (frag->fragment) OPENSSL_free(frag->fragment);
53a15b4
+	OPENSSL_free(frag);
53a15b4
+	}
53a15b4
 
53a15b4
 /* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
53a15b4
 int dtls1_do_write(SSL *s, int type)
53a15b4
@@ -180,7 +182,7 @@ int dtls1_do_write(SSL *s, int type)
53a15b4
 
53a15b4
 	/* AHA!  Figure out the MTU, and stick to the right size */
53a15b4
 	if ( ! (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
53a15b4
-        {
53a15b4
+		{
53a15b4
 		s->d1->mtu = 
53a15b4
 			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
53a15b4
 
53a15b4
@@ -207,7 +209,7 @@ int dtls1_do_write(SSL *s, int type)
53a15b4
 		mtu = curr_mtu;
53a15b4
 	else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0)
53a15b4
 		return ret;
53a15b4
-		
53a15b4
+
53a15b4
 	if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu)
53a15b4
 		{
53a15b4
 		ret = BIO_flush(SSL_get_wbio(s));
53a15b4
@@ -254,11 +256,11 @@ int dtls1_do_write(SSL *s, int type)
53a15b4
 				s->init_off -= DTLS1_HM_HEADER_LENGTH;
53a15b4
 				s->init_num += DTLS1_HM_HEADER_LENGTH;
53a15b4
 
53a15b4
-                /* write atleast DTLS1_HM_HEADER_LENGTH bytes */
53a15b4
+				/* write atleast DTLS1_HM_HEADER_LENGTH bytes */
53a15b4
 				if ( len <= DTLS1_HM_HEADER_LENGTH)  
53a15b4
 					len += DTLS1_HM_HEADER_LENGTH;
53a15b4
 				}
53a15b4
-			
53a15b4
+
53a15b4
 			dtls1_fix_message_header(s, frag_off, 
53a15b4
 				len - DTLS1_HM_HEADER_LENGTH);
53a15b4
 
53a15b4
@@ -286,18 +288,40 @@ int dtls1_do_write(SSL *s, int type)
53a15b4
 			}
53a15b4
 		else
53a15b4
 			{
53a15b4
-			
53a15b4
+
53a15b4
 			/* bad if this assert fails, only part of the handshake
53a15b4
 			 * message got sent.  but why would this happen? */
53a15b4
-			OPENSSL_assert(len == (unsigned int)ret); 
53a15b4
-			
53a15b4
+			OPENSSL_assert(len == (unsigned int)ret);
53a15b4
+
53a15b4
 			if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
53a15b4
+				{
53a15b4
 				/* should not be done for 'Hello Request's, but in that case
53a15b4
 				 * we'll ignore the result anyway */
53a15b4
-				ssl3_finish_mac(s, 
53a15b4
-					(unsigned char *)&s->init_buf->data[s->init_off + 
53a15b4
-						DTLS1_HM_HEADER_LENGTH], ret - DTLS1_HM_HEADER_LENGTH);
53a15b4
-			
53a15b4
+				unsigned char *p = &s->init_buf->data[s->init_off];
53a15b4
+				const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
53a15b4
+				int len;
53a15b4
+
53a15b4
+				if (frag_off == 0 && s->client_version != DTLS1_BAD_VER)
53a15b4
+					{
53a15b4
+					/* reconstruct message header is if it
53a15b4
+					 * is being sent in single fragment */
53a15b4
+					*p++ = msg_hdr->type;
53a15b4
+					l2n3(msg_hdr->msg_len,p);
53a15b4
+					s2n (msg_hdr->seq,p);
53a15b4
+					l2n3(0,p);
53a15b4
+					l2n3(msg_hdr->msg_len,p);
53a15b4
+					p  -= DTLS1_HM_HEADER_LENGTH;
53a15b4
+					len = ret;
53a15b4
+					}
53a15b4
+				else
53a15b4
+					{
53a15b4
+					p  += DTLS1_HM_HEADER_LENGTH;
53a15b4
+					len = ret - DTLS1_HM_HEADER_LENGTH;
53a15b4
+					}
53a15b4
+
53a15b4
+				ssl3_finish_mac(s, p, len);
53a15b4
+				}
53a15b4
+
53a15b4
 			if (ret == s->init_num)
53a15b4
 				{
53a15b4
 				if (s->msg_callback)
53a15b4
@@ -307,7 +331,7 @@ int dtls1_do_write(SSL *s, int type)
53a15b4
 
53a15b4
 				s->init_off = 0;  /* done writing this message */
53a15b4
 				s->init_num = 0;
53a15b4
-				
53a15b4
+
53a15b4
 				return(1);
53a15b4
 				}
53a15b4
 			s->init_off+=ret;
53a15b4
@@ -327,6 +351,7 @@ int dtls1_do_write(SSL *s, int type)
53a15b4
 long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
53a15b4
 	{
53a15b4
 	int i, al;
53a15b4
+	struct hm_header_st *msg_hdr;
53a15b4
 
53a15b4
 	/* s3->tmp is used to store messages that are unexpected, caused
53a15b4
 	 * by the absence of an optional handshake message */
53a15b4
@@ -344,25 +369,56 @@ long dtls1_get_message(SSL *s, int st1, 
53a15b4
 		s->init_num = (int)s->s3->tmp.message_size;
53a15b4
 		return s->init_num;
53a15b4
 		}
53a15b4
-	
53a15b4
+
53a15b4
+	msg_hdr = &s->d1->r_msg_hdr;
53a15b4
 	do
53a15b4
 		{
53a15b4
-		if ( s->d1->r_msg_hdr.frag_off == 0)
53a15b4
+		if ( msg_hdr->frag_off == 0)
53a15b4
 			{
53a15b4
 			/* s->d1->r_message_header.msg_len = 0; */
53a15b4
-			memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st));
53a15b4
+			memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
53a15b4
 			}
53a15b4
 
53a15b4
 		i = dtls1_get_message_fragment(s, st1, stn, max, ok);
53a15b4
 		if ( i == DTLS1_HM_BAD_FRAGMENT ||
53a15b4
-            i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
53a15b4
+			i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
53a15b4
 			continue;
53a15b4
 		else if ( i <= 0 && !*ok)
53a15b4
 			return i;
53a15b4
 
53a15b4
-		if (s->d1->r_msg_hdr.msg_len == (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH)
53a15b4
+		/* Note that s->init_sum is used as a counter summing
53a15b4
+		 * up fragments' lengths: as soon as they sum up to
53a15b4
+		 * handshake packet length, we assume we have got all
53a15b4
+		 * the fragments. Overlapping fragments would cause
53a15b4
+		 * premature termination, so we don't expect overlaps.
53a15b4
+		 * Well, handling overlaps would require something more
53a15b4
+		 * drastic. Indeed, as it is now there is no way to
53a15b4
+		 * tell if out-of-order fragment from the middle was
53a15b4
+		 * the last. '>=' is the best/least we can do to control
53a15b4
+		 * the potential damage caused by malformed overlaps. */
53a15b4
+		if ((unsigned int)s->init_num >= msg_hdr->msg_len)
53a15b4
 			{
53a15b4
-			memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st));
53a15b4
+			unsigned char *p = s->init_buf->data;
53a15b4
+			unsigned long msg_len = msg_hdr->msg_len;
53a15b4
+
53a15b4
+			/* reconstruct message header as if it was
53a15b4
+			 * sent in single fragment */
53a15b4
+			*(p++) = msg_hdr->type;
53a15b4
+			l2n3(msg_len,p);
53a15b4
+			s2n (msg_hdr->seq,p);
53a15b4
+			l2n3(0,p);
53a15b4
+			l2n3(msg_len,p);
53a15b4
+			if (s->client_version != DTLS1_BAD_VER)
53a15b4
+				p       -= DTLS1_HM_HEADER_LENGTH,
53a15b4
+				msg_len += DTLS1_HM_HEADER_LENGTH;
53a15b4
+
53a15b4
+			ssl3_finish_mac(s, p, msg_len);
53a15b4
+			if (s->msg_callback)
53a15b4
+				s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
53a15b4
+					p, msg_len,
53a15b4
+					s, s->msg_callback_arg);
53a15b4
+
53a15b4
+			memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
53a15b4
 
53a15b4
 			s->d1->handshake_read_seq++;
53a15b4
 			/* we just read a handshake message from the other side:
53a15b4
@@ -379,11 +435,11 @@ long dtls1_get_message(SSL *s, int st1, 
53a15b4
 			 * first data  segment, but is there a better way?  */
53a15b4
 			dtls1_clear_record_buffer(s);
53a15b4
 
53a15b4
-            s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
53a15b4
-			return s->init_num - DTLS1_HM_HEADER_LENGTH;
53a15b4
+			s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
53a15b4
+			return s->init_num;
53a15b4
 			}
53a15b4
 		else
53a15b4
-			s->d1->r_msg_hdr.frag_off = i;
53a15b4
+			msg_hdr->frag_off = i;
53a15b4
 		} while(1) ;
53a15b4
 
53a15b4
 f_err:
53a15b4
@@ -393,161 +449,183 @@ f_err:
53a15b4
 	}
53a15b4
 
53a15b4
 
53a15b4
-static int
53a15b4
-dtls1_retrieve_buffered_fragment(SSL *s, unsigned long *copied)
53a15b4
-    {
53a15b4
-    /* (0) check whether the desired fragment is available
53a15b4
-     * if so:
53a15b4
-     * (1) copy over the fragment to s->init_buf->data[]
53a15b4
-     * (2) update s->init_num
53a15b4
-     */
53a15b4
-    pitem *item;
53a15b4
-    hm_fragment *frag;
53a15b4
-    unsigned long overlap;
53a15b4
-    unsigned char *p;
53a15b4
-
53a15b4
-    item = pqueue_peek(s->d1->buffered_messages);
53a15b4
-    if ( item == NULL)
53a15b4
-        return 0;
53a15b4
+static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max)
53a15b4
+	{
53a15b4
+	size_t frag_off,frag_len,msg_len;
53a15b4
 
53a15b4
-    frag = (hm_fragment *)item->data;
53a15b4
-    
53a15b4
-    if ( s->d1->handshake_read_seq == frag->msg_header.seq &&
53a15b4
-        frag->msg_header.frag_off <= (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH)
53a15b4
-        {
53a15b4
-        pqueue_pop(s->d1->buffered_messages);
53a15b4
-        overlap = s->init_num - DTLS1_HM_HEADER_LENGTH 
53a15b4
-            - frag->msg_header.frag_off;
53a15b4
-
53a15b4
-        p = frag->fragment;
53a15b4
-
53a15b4
-        memcpy(&s->init_buf->data[s->init_num],
53a15b4
-            p + DTLS1_HM_HEADER_LENGTH + overlap,
53a15b4
-            frag->msg_header.frag_len - overlap);
53a15b4
-    
53a15b4
-        OPENSSL_free(frag->fragment);
53a15b4
-        OPENSSL_free(frag);
53a15b4
-        pitem_free(item);
53a15b4
+	msg_len  = msg_hdr->msg_len;
53a15b4
+	frag_off = msg_hdr->frag_off;
53a15b4
+	frag_len = msg_hdr->frag_len;
53a15b4
 
53a15b4
-        *copied = frag->msg_header.frag_len - overlap;
53a15b4
-        return *copied;
53a15b4
-        }
53a15b4
-    else
53a15b4
-        return 0;
53a15b4
-    }
53a15b4
+	/* sanity checking */
53a15b4
+	if ( (frag_off+frag_len) > msg_len)
53a15b4
+		{
53a15b4
+		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
53a15b4
+		return SSL_AD_ILLEGAL_PARAMETER;
53a15b4
+		}
53a15b4
 
53a15b4
+	if ( (frag_off+frag_len) > (unsigned long)max)
53a15b4
+		{
53a15b4
+		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
53a15b4
+		return SSL_AD_ILLEGAL_PARAMETER;
53a15b4
+		}
53a15b4
 
53a15b4
-static int
53a15b4
-dtls1_buffer_handshake_fragment(SSL *s, struct hm_header_st* msg_hdr)
53a15b4
-{
53a15b4
-    hm_fragment *frag = NULL;
53a15b4
-    pitem *item = NULL;
53a15b4
-	PQ_64BIT seq64;
53a15b4
+	if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
53a15b4
+		{
53a15b4
+		/* msg_len is limited to 2^24, but is effectively checked
53a15b4
+		 * against max above */
53a15b4
+		if (!BUF_MEM_grow_clean(s->init_buf,(int)msg_len+DTLS1_HM_HEADER_LENGTH))
53a15b4
+			{
53a15b4
+			SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB);
53a15b4
+			return SSL_AD_INTERNAL_ERROR;
53a15b4
+			}
53a15b4
 
53a15b4
-    frag = dtls1_hm_fragment_new(msg_hdr->frag_len);
53a15b4
-    if ( frag == NULL)
53a15b4
-        goto err;
53a15b4
+		s->s3->tmp.message_size  = msg_len;
53a15b4
+		s->d1->r_msg_hdr.msg_len = msg_len;
53a15b4
+		s->s3->tmp.message_type  = msg_hdr->type;
53a15b4
+		s->d1->r_msg_hdr.type    = msg_hdr->type;
53a15b4
+		s->d1->r_msg_hdr.seq     = msg_hdr->seq;
53a15b4
+		}
53a15b4
+	else if (msg_len != s->d1->r_msg_hdr.msg_len)
53a15b4
+		{
53a15b4
+		/* They must be playing with us! BTW, failure to enforce
53a15b4
+		 * upper limit would open possibility for buffer overrun. */
53a15b4
+		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
53a15b4
+		return SSL_AD_ILLEGAL_PARAMETER;
53a15b4
+		}
53a15b4
 
53a15b4
-    memcpy(frag->fragment, &(s->init_buf->data[s->init_num]),
53a15b4
-        msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH);
53a15b4
+	return 0; /* no error */
53a15b4
+	}
53a15b4
 
53a15b4
-    memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
53a15b4
 
53a15b4
-    pq_64bit_init(&seq64);
53a15b4
-    pq_64bit_assign_word(&seq64, msg_hdr->seq);
53a15b4
+static int
53a15b4
+dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
53a15b4
+	{
53a15b4
+	/* (0) check whether the desired fragment is available
53a15b4
+	 * if so:
53a15b4
+	 * (1) copy over the fragment to s->init_buf->data[]
53a15b4
+	 * (2) update s->init_num
53a15b4
+	 */
53a15b4
+	pitem *item;
53a15b4
+	hm_fragment *frag;
53a15b4
+	int al;
53a15b4
 
53a15b4
-    item = pitem_new(seq64, frag);
53a15b4
-    if ( item == NULL)
53a15b4
-        goto err;
53a15b4
+	*ok = 0;
53a15b4
+	item = pqueue_peek(s->d1->buffered_messages);
53a15b4
+	if ( item == NULL)
53a15b4
+		return 0;
53a15b4
 
53a15b4
-    pq_64bit_free(&seq64);
53a15b4
+	frag = (hm_fragment *)item->data;
53a15b4
 
53a15b4
-    pqueue_insert(s->d1->buffered_messages, item);
53a15b4
-    return 1;
53a15b4
+	if ( s->d1->handshake_read_seq == frag->msg_header.seq)
53a15b4
+		{
53a15b4
+		pqueue_pop(s->d1->buffered_messages);
53a15b4
 
53a15b4
-err:
53a15b4
-    if ( frag != NULL) dtls1_hm_fragment_free(frag);
53a15b4
-    if ( item != NULL) OPENSSL_free(item);
53a15b4
-    return 0;
53a15b4
-}
53a15b4
+		al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
53a15b4
 
53a15b4
+		if (al==0) /* no alert */
53a15b4
+			{
53a15b4
+			unsigned char *p = s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
53a15b4
+			memcpy(&p[frag->msg_header.frag_off],
53a15b4
+				frag->fragment,frag->msg_header.frag_len);
53a15b4
+			}
53a15b4
 
53a15b4
-static void
53a15b4
-dtls1_process_handshake_fragment(SSL *s, int frag_len)
53a15b4
-    {
53a15b4
-    unsigned char *p;
53a15b4
+		dtls1_hm_fragment_free(frag);
53a15b4
+		pitem_free(item);
53a15b4
 
53a15b4
-    p = (unsigned char *)s->init_buf->data;
53a15b4
+		if (al==0)
53a15b4
+			{
53a15b4
+			*ok = 1;
53a15b4
+			return frag->msg_header.frag_len;
53a15b4
+			}
53a15b4
 
53a15b4
-	ssl3_finish_mac(s, &p[s->init_num - frag_len], frag_len);
53a15b4
-    }
53a15b4
+		ssl3_send_alert(s,SSL3_AL_FATAL,al);
53a15b4
+		s->init_num = 0;
53a15b4
+		*ok = 0;
53a15b4
+		return -1;
53a15b4
+		}
53a15b4
+	else
53a15b4
+		return 0;
53a15b4
+	}
53a15b4
 
53a15b4
 
53a15b4
 static int
53a15b4
-dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st *msg_hdr, int *ok)
53a15b4
-    {
53a15b4
-    int i;
53a15b4
-    unsigned char *p;
53a15b4
-
53a15b4
-    /* make sure there's enough room to read this fragment */
53a15b4
-    if ( (int)msg_hdr->frag_len && !BUF_MEM_grow_clean(s->init_buf, 
53a15b4
-             (int)msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH + s->init_num))
53a15b4
-        {
53a15b4
-        SSLerr(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE,ERR_R_BUF_LIB);
53a15b4
-        goto err;
53a15b4
-        }
53a15b4
+dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
53a15b4
+{
53a15b4
+	int i=-1;
53a15b4
+	hm_fragment *frag = NULL;
53a15b4
+	pitem *item = NULL;
53a15b4
+	PQ_64BIT seq64;
53a15b4
+	unsigned long frag_len = msg_hdr->frag_len;
53a15b4
 
53a15b4
-    p = (unsigned char *)s->init_buf->data;
53a15b4
+	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
53a15b4
+		goto err;
53a15b4
 
53a15b4
-    /* read the body of the fragment (header has already been read */
53a15b4
-    if ( msg_hdr->frag_len > 0)
53a15b4
+	if (msg_hdr->seq <= s->d1->handshake_read_seq)
53a15b4
 		{
53a15b4
-		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
53a15b4
-            &p[s->init_num], 
53a15b4
-            msg_hdr->frag_len,0);
53a15b4
-		if (i <= 0)
53a15b4
+		unsigned char devnull [256];
53a15b4
+
53a15b4
+		while (frag_len)
53a15b4
 			{
53a15b4
-			*ok = 0;
53a15b4
-			return i;
53a15b4
+			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
53a15b4
+				devnull,
53a15b4
+				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
53a15b4
+			if (i<=0) goto err;
53a15b4
+			frag_len -= i;
53a15b4
 			}
53a15b4
 		}
53a15b4
 
53a15b4
-    if ( msg_hdr->seq > s->d1->handshake_read_seq)
53a15b4
-        dtls1_buffer_handshake_fragment(s, msg_hdr);
53a15b4
-    else
53a15b4
-        OPENSSL_assert(msg_hdr->seq < s->d1->handshake_read_seq);
53a15b4
+	frag = dtls1_hm_fragment_new(frag_len);
53a15b4
+	if ( frag == NULL)
53a15b4
+		goto err;
53a15b4
+
53a15b4
+	memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
53a15b4
+
53a15b4
+	if (frag_len)
53a15b4
+		{
53a15b4
+		/* read the body of the fragment (header has already been read */
53a15b4
+		i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
53a15b4
+			frag->fragment,frag_len,0);
53a15b4
+		if (i<=0 || i!=frag_len)
53a15b4
+			goto err;
53a15b4
+		}
53a15b4
+
53a15b4
+	pq_64bit_init(&seq64);
53a15b4
+	pq_64bit_assign_word(&seq64, msg_hdr->seq);
53a15b4
+
53a15b4
+	item = pitem_new(seq64, frag);
53a15b4
+	pq_64bit_free(&seq64);
53a15b4
+	if ( item == NULL)
53a15b4
+		goto err;
53a15b4
+
53a15b4
+	pqueue_insert(s->d1->buffered_messages, item);
53a15b4
+	return DTLS1_HM_FRAGMENT_RETRY;
53a15b4
 
53a15b4
-    return DTLS1_HM_FRAGMENT_RETRY;
53a15b4
 err:
53a15b4
-    *ok = 0;
53a15b4
-    return -1;
53a15b4
-    }
53a15b4
+	if ( frag != NULL) dtls1_hm_fragment_free(frag);
53a15b4
+	if ( item != NULL) OPENSSL_free(item);
53a15b4
+	*ok = 0;
53a15b4
+	return i;
53a15b4
+	}
53a15b4
 
53a15b4
 
53a15b4
 static long
53a15b4
 dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
53a15b4
 	{
53a15b4
-	unsigned char *p;
53a15b4
+	unsigned char wire[DTLS1_HM_HEADER_LENGTH];
53a15b4
 	unsigned long l, frag_off, frag_len;
53a15b4
 	int i,al;
53a15b4
 	struct hm_header_st msg_hdr;
53a15b4
-    unsigned long overlap;
53a15b4
-    
53a15b4
-    /* see if we have the required fragment already */
53a15b4
-    if (dtls1_retrieve_buffered_fragment(s, &l))
53a15b4
-    {
53a15b4
-        /* compute MAC, remove fragment headers */
53a15b4
-        dtls1_process_handshake_fragment(s, l);
53a15b4
-        s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
53a15b4
-        s->state = stn;
53a15b4
-        return 1;
53a15b4
-    }
53a15b4
 
53a15b4
-    /* get a handshake fragment from the record layer */
53a15b4
-	p = (unsigned char *)s->init_buf->data;
53a15b4
+	/* see if we have the required fragment already */
53a15b4
+	if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)
53a15b4
+		{
53a15b4
+		if (*ok)	s->init_num += frag_len;
53a15b4
+		return frag_len;
53a15b4
+		}
53a15b4
 
53a15b4
-    /* read handshake message header */
53a15b4
-	i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],
53a15b4
+	/* read handshake message header */
53a15b4
+	i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire,
53a15b4
 		DTLS1_HM_HEADER_LENGTH, 0);
53a15b4
 	if (i <= 0) 	/* nbio, or an error */
53a15b4
 		{
53a15b4
@@ -555,130 +633,61 @@ dtls1_get_message_fragment(SSL *s, int s
53a15b4
 		*ok = 0;
53a15b4
 		return i;
53a15b4
 		}
53a15b4
-
53a15b4
 	OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH);
53a15b4
 
53a15b4
-	p += s->init_num;
53a15b4
-    /* parse the message fragment header */
53a15b4
-    
53a15b4
-    dtls1_get_message_header(p, &msg_hdr);
53a15b4
+	/* parse the message fragment header */
53a15b4
+	dtls1_get_message_header(wire, &msg_hdr);
53a15b4
 
53a15b4
-    /* 
53a15b4
-     * if this is a future (or stale) message it gets buffered
53a15b4
-     * (or dropped)--no further processing at this time 
53a15b4
-     */
53a15b4
-    if ( msg_hdr.seq != s->d1->handshake_read_seq)
53a15b4
-        return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
53a15b4
+	/* 
53a15b4
+	 * if this is a future (or stale) message it gets buffered
53a15b4
+	 * (or dropped)--no further processing at this time 
53a15b4
+	 */
53a15b4
+	if ( msg_hdr.seq != s->d1->handshake_read_seq)
53a15b4
+		return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
53a15b4
 
53a15b4
-    l = msg_hdr.msg_len;
53a15b4
-    frag_off = msg_hdr.frag_off;
53a15b4
+	l = msg_hdr.msg_len;
53a15b4
+	frag_off = msg_hdr.frag_off;
53a15b4
 	frag_len = msg_hdr.frag_len;
53a15b4
 
53a15b4
-    /* sanity checking */
53a15b4
-    if ( frag_off + frag_len > l)
53a15b4
-        {
53a15b4
-        al=SSL_AD_ILLEGAL_PARAMETER;
53a15b4
-        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
53a15b4
-        goto f_err;
53a15b4
-        }
53a15b4
-
53a15b4
 	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
53a15b4
-        p[0] == SSL3_MT_HELLO_REQUEST)
53a15b4
-        {
53a15b4
-        /* The server may always send 'Hello Request' messages --
53a15b4
-         * we are doing a handshake anyway now, so ignore them
53a15b4
-         * if their format is correct. Does not count for
53a15b4
-         * 'Finished' MAC. */
53a15b4
-        if (p[1] == 0 && p[2] == 0 &&p[3] == 0)
53a15b4
-            {
53a15b4
-            if (s->msg_callback)
53a15b4
-                s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
53a15b4
-                    p, DTLS1_HM_HEADER_LENGTH, s, 
53a15b4
-                    s->msg_callback_arg);
53a15b4
-            
53a15b4
-            s->init_num = 0;
53a15b4
-            return dtls1_get_message_fragment(s, st1, stn,
53a15b4
-                max, ok);
53a15b4
-            }
53a15b4
-        else /* Incorrectly formated Hello request */
53a15b4
-            {
53a15b4
-            al=SSL_AD_UNEXPECTED_MESSAGE;
53a15b4
-            SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
53a15b4
-            goto f_err;
53a15b4
-            }
53a15b4
-        }
53a15b4
-
53a15b4
-    /* XDTLS: do a sanity check on the fragment */
53a15b4
-
53a15b4
-    s->init_num += i;
53a15b4
-
53a15b4
-	if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
53a15b4
+		wire[0] == SSL3_MT_HELLO_REQUEST)
53a15b4
 		{
53a15b4
-		/* BUF_MEM_grow takes an 'int' parameter */
53a15b4
-		if (l > (INT_MAX-DTLS1_HM_HEADER_LENGTH)) 
53a15b4
+		/* The server may always send 'Hello Request' messages --
53a15b4
+		 * we are doing a handshake anyway now, so ignore them
53a15b4
+		 * if their format is correct. Does not count for
53a15b4
+		 * 'Finished' MAC. */
53a15b4
+		if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0)
53a15b4
 			{
53a15b4
-			al=SSL_AD_ILLEGAL_PARAMETER;
53a15b4
-			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
53a15b4
-			goto f_err;
53a15b4
-			}
53a15b4
-		if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l
53a15b4
-			+ DTLS1_HM_HEADER_LENGTH))
53a15b4
-			{
53a15b4
-			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB);
53a15b4
-			goto err;
53a15b4
+			if (s->msg_callback)
53a15b4
+				s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
53a15b4
+					wire, DTLS1_HM_HEADER_LENGTH, s, 
53a15b4
+					s->msg_callback_arg);
53a15b4
+			
53a15b4
+			s->init_num = 0;
53a15b4
+			return dtls1_get_message_fragment(s, st1, stn,
53a15b4
+				max, ok);
53a15b4
 			}
53a15b4
-        /* Only do this test when we're reading the expected message.
53a15b4
-         * Stale messages will be dropped and future messages will be buffered */
53a15b4
-        if ( l > (unsigned long)max)
53a15b4
+		else /* Incorrectly formated Hello request */
53a15b4
 			{
53a15b4
-			al=SSL_AD_ILLEGAL_PARAMETER;
53a15b4
-			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
53a15b4
+			al=SSL_AD_UNEXPECTED_MESSAGE;
53a15b4
+			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
53a15b4
 			goto f_err;
53a15b4
 			}
53a15b4
-
53a15b4
-		s->s3->tmp.message_size=l;
53a15b4
 		}
53a15b4
 
53a15b4
-    if ( frag_len > (unsigned long)max)
53a15b4
-        {
53a15b4
-        al=SSL_AD_ILLEGAL_PARAMETER;
53a15b4
-        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
53a15b4
-        goto f_err;
53a15b4
-        }
53a15b4
-    if ( frag_len + s->init_num > (INT_MAX - DTLS1_HM_HEADER_LENGTH))
53a15b4
-        {
53a15b4
-        al=SSL_AD_ILLEGAL_PARAMETER;
53a15b4
-        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
53a15b4
-        goto f_err;
53a15b4
-        }
53a15b4
-
53a15b4
-    if ( frag_len & !BUF_MEM_grow_clean(s->init_buf, (int)frag_len 
53a15b4
-             + DTLS1_HM_HEADER_LENGTH + s->init_num))
53a15b4
-        {
53a15b4
-        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB);
53a15b4
-        goto err;
53a15b4
-        }
53a15b4
-
53a15b4
-	if ( s->d1->r_msg_hdr.frag_off == 0)
53a15b4
-		{
53a15b4
-		s->s3->tmp.message_type = msg_hdr.type;
53a15b4
-		s->d1->r_msg_hdr.type = msg_hdr.type;
53a15b4
-		s->d1->r_msg_hdr.msg_len = l;
53a15b4
-		/* s->d1->r_msg_hdr.seq = seq_num; */
53a15b4
-		}
53a15b4
+	if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max)))
53a15b4
+		goto f_err;
53a15b4
 
53a15b4
 	/* XDTLS:  ressurect this when restart is in place */
53a15b4
 	s->state=stn;
53a15b4
-	
53a15b4
-	/* next state (stn) */
53a15b4
-	p = (unsigned char *)s->init_buf->data;
53a15b4
 
53a15b4
 	if ( frag_len > 0)
53a15b4
 		{
53a15b4
+		unsigned char *p=s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
53a15b4
+
53a15b4
 		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
53a15b4
-            &p[s->init_num], 
53a15b4
-            frag_len,0);
53a15b4
-        /* XDTLS:  fix this--message fragments cannot span multiple packets */
53a15b4
+			&p[frag_off],frag_len,0);
53a15b4
+		/* XDTLS:  fix this--message fragments cannot span multiple packets */
53a15b4
 		if (i <= 0)
53a15b4
 			{
53a15b4
 			s->rwstate=SSL_READING;
53a15b4
@@ -689,70 +698,23 @@ dtls1_get_message_fragment(SSL *s, int s
53a15b4
 	else
53a15b4
 		i = 0;
53a15b4
 
53a15b4
-    /* XDTLS:  an incorrectly formatted fragment should cause the 
53a15b4
-     * handshake to fail */
53a15b4
+	/* XDTLS:  an incorrectly formatted fragment should cause the 
53a15b4
+	 * handshake to fail */
53a15b4
 	OPENSSL_assert(i == (int)frag_len);
53a15b4
 
53a15b4
-#if 0
53a15b4
-    /* Successfully read a fragment.
53a15b4
-     * It may be (1) out of order, or
53a15b4
-     *           (2) it's a repeat, in which case we dump it
53a15b4
-     *           (3) the one we are expecting next (maybe with overlap)
53a15b4
-     * If it is next one, it may overlap with previously read bytes
53a15b4
-     */
53a15b4
+	*ok = 1;
53a15b4
 
53a15b4
-    /* case (1): buffer the future fragment 
53a15b4
-     * (we can treat fragments from a future message the same
53a15b4
-     * as future fragments from the message being currently read, since
53a15b4
-     * they are sematically simply out of order.
53a15b4
-     */
53a15b4
-    if ( msg_hdr.seq > s->d1->handshake_read_seq ||
53a15b4
-        frag_off > s->init_num - DTLS1_HM_HEADER_LENGTH)
53a15b4
-    {
53a15b4
-        dtls1_buffer_handshake_fragment(s, &msg_hdr);
53a15b4
-        return DTLS1_HM_FRAGMENT_RETRY;
53a15b4
-    }
53a15b4
-
53a15b4
-    /* case (2):  drop the entire fragment, and try again */
53a15b4
-    if ( msg_hdr.seq < s->d1->handshake_read_seq ||
53a15b4
-        frag_off + frag_len < s->init_num - DTLS1_HM_HEADER_LENGTH)
53a15b4
-        {
53a15b4
-        s->init_num -= DTLS1_HM_HEADER_LENGTH;
53a15b4
-        return DTLS1_HM_FRAGMENT_RETRY;
53a15b4
-        }
53a15b4
-#endif
53a15b4
-
53a15b4
-    /* case (3): received a immediately useful fragment.  Determine the 
53a15b4
-     * possible overlap and copy the fragment.
53a15b4
-     */
53a15b4
-    overlap = (s->init_num - DTLS1_HM_HEADER_LENGTH) - frag_off;
53a15b4
-        
53a15b4
-    /* retain the header for the first fragment */
53a15b4
-    if ( s->init_num > DTLS1_HM_HEADER_LENGTH)
53a15b4
-        {
53a15b4
-        memmove(&(s->init_buf->data[s->init_num]),
53a15b4
-            &(s->init_buf->data[s->init_num + DTLS1_HM_HEADER_LENGTH + overlap]),
53a15b4
-            frag_len - overlap);
53a15b4
-
53a15b4
-        s->init_num += frag_len - overlap;
53a15b4
-        }
53a15b4
-    else
53a15b4
-        s->init_num += frag_len;
53a15b4
-
53a15b4
-    dtls1_process_handshake_fragment(s, frag_len - overlap);
53a15b4
-
53a15b4
-	if (s->msg_callback)
53a15b4
-		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, 
53a15b4
-			(size_t)s->init_num, s, 
53a15b4
-			s->msg_callback_arg);
53a15b4
-	*ok=1;
53a15b4
-
53a15b4
-	return s->init_num;
53a15b4
+	/* Note that s->init_num is *not* used as current offset in
53a15b4
+	 * s->init_buf->data, but as a counter summing up fragments'
53a15b4
+	 * lengths: as soon as they sum up to handshake packet
53a15b4
+	 * length, we assume we have got all the fragments. */
53a15b4
+	s->init_num += frag_len;
53a15b4
+	return frag_len;
53a15b4
 
53a15b4
 f_err:
53a15b4
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
53a15b4
-    s->init_num = 0;
53a15b4
-err:
53a15b4
+	s->init_num = 0;
53a15b4
+
53a15b4
 	*ok=0;
53a15b4
 	return(-1);
53a15b4
 	}
53a15b4
@@ -790,7 +752,7 @@ int dtls1_send_finished(SSL *s, int a, i
53a15b4
 
53a15b4
 		/* buffer the message to handle re-xmits */
53a15b4
 		dtls1_buffer_message(s, 0);
53a15b4
-		
53a15b4
+
53a15b4
 		s->state=b;
53a15b4
 		}
53a15b4
 
53a15b4
@@ -816,9 +778,14 @@ int dtls1_send_change_cipher_spec(SSL *s
53a15b4
 		*p++=SSL3_MT_CCS;
53a15b4
 		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
53a15b4
 		s->d1->next_handshake_write_seq++;
53a15b4
-		s2n(s->d1->handshake_write_seq,p);
53a15b4
-
53a15b4
 		s->init_num=DTLS1_CCS_HEADER_LENGTH;
53a15b4
+
53a15b4
+		if (s->client_version == DTLS1_BAD_VER)
53a15b4
+			{
53a15b4
+			s2n(s->d1->handshake_write_seq,p);
53a15b4
+			s->init_num+=2;
53a15b4
+			}
53a15b4
+
53a15b4
 		s->init_off=0;
53a15b4
 
53a15b4
 		dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, 
53a15b4
@@ -1056,7 +1023,7 @@ dtls1_buffer_message(SSL *s, int is_ccs)
53a15b4
     if ( is_ccs)
53a15b4
         {
53a15b4
         OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
53a15b4
-            DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num);
53a15b4
+            DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num);
53a15b4
         }
53a15b4
     else
53a15b4
         {
53a15b4
@@ -1259,5 +1226,4 @@ dtls1_get_ccs_header(unsigned char *data
53a15b4
     memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
53a15b4
     
53a15b4
     ccs_hdr->type = *(data++);
53a15b4
-    n2s(data, ccs_hdr->seq);
53a15b4
 }
53a15b4
diff -up openssl-0.9.8b/ssl/d1_clnt.c.dtls-fixes openssl-0.9.8b/ssl/d1_clnt.c
53a15b4
--- openssl-0.9.8b/ssl/d1_clnt.c.dtls-fixes	2005-12-05 18:32:19.000000000 +0100
53a15b4
+++ openssl-0.9.8b/ssl/d1_clnt.c	2007-10-08 17:55:22.000000000 +0200
53a15b4
@@ -214,17 +214,21 @@ int dtls1_connect(SSL *s)
53a15b4
 
53a15b4
 			/* don't push the buffering BIO quite yet */
53a15b4
 
53a15b4
-			ssl3_init_finished_mac(s);
53a15b4
-
53a15b4
 			s->state=SSL3_ST_CW_CLNT_HELLO_A;
53a15b4
 			s->ctx->stats.sess_connect++;
53a15b4
 			s->init_num=0;
53a15b4
+			/* mark client_random uninitialized */
53a15b4
+			memset(s->s3->client_random,0,sizeof(s->s3->client_random));
53a15b4
 			break;
53a15b4
 
53a15b4
 		case SSL3_ST_CW_CLNT_HELLO_A:
53a15b4
 		case SSL3_ST_CW_CLNT_HELLO_B:
53a15b4
 
53a15b4
 			s->shutdown=0;
53a15b4
+
53a15b4
+			/* every DTLS ClientHello resets Finished MAC */
53a15b4
+			ssl3_init_finished_mac(s);
53a15b4
+
53a15b4
 			ret=dtls1_client_hello(s);
53a15b4
 			if (ret <= 0) goto end;
53a15b4
 
53a15b4
@@ -422,6 +426,9 @@ int dtls1_connect(SSL *s)
53a15b4
 				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
53a15b4
 				}
53a15b4
 			s->init_num=0;
53a15b4
+			/* mark client_random uninitialized */
53a15b4
+			memset (s->s3->client_random,0,sizeof(s->s3->client_random));
53a15b4
+
53a15b4
 			break;
53a15b4
 
53a15b4
 		case SSL3_ST_CR_FINISHED_A:
53a15b4
@@ -544,9 +551,15 @@ int dtls1_client_hello(SSL *s)
53a15b4
 		/* else use the pre-loaded session */
53a15b4
 
53a15b4
 		p=s->s3->client_random;
53a15b4
-		Time=(unsigned long)time(NULL);			/* Time */
53a15b4
-		l2n(Time,p);
53a15b4
-		RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
53a15b4
+		/* if client_random is initialized, reuse it, we are
53a15b4
+		 * required to use same upon reply to HelloVerify */
53a15b4
+		for (i=0;p[i]=='\0' && i<sizeof(s->s3->client_random);i++) ;
53a15b4
+		if (i==sizeof(s->s3->client_random))
53a15b4
+			{
53a15b4
+			Time=(unsigned long)time(NULL);	/* Time */
53a15b4
+			l2n(Time,p);
53a15b4
+			RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4);
53a15b4
+			}
53a15b4
 
53a15b4
 		/* Do the message type and length last */
53a15b4
 		d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);