Blob Blame History Raw
diff -up openssl-fips-0.9.8e/ssl/d1_pkt.c.dtls-fixes2 openssl-fips-0.9.8e/ssl/d1_pkt.c
--- openssl-fips-0.9.8e/ssl/d1_pkt.c.dtls-fixes2	2012-01-16 11:00:34.242797904 +0100
+++ openssl-fips-0.9.8e/ssl/d1_pkt.c	2012-01-18 15:45:25.144865068 +0100
@@ -134,7 +134,7 @@ static int dtls1_record_needs_buffering(
 	unsigned short *priority, unsigned long *offset);
 #endif
 static int dtls1_buffer_record(SSL *s, record_pqueue *q,
-	PQ_64BIT priority);
+	PQ_64BIT *priority);
 static int dtls1_process_record(SSL *s);
 #if PQ_64BIT_IS_INTEGER
 static PQ_64BIT bytes_to_long_long(unsigned char *bytes, PQ_64BIT *num);
@@ -156,13 +156,16 @@ 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);
     }
 
 
 static int
-dtls1_buffer_record(SSL *s, record_pqueue *queue, PQ_64BIT priority)
+dtls1_buffer_record(SSL *s, record_pqueue *queue, PQ_64BIT *priority)
 {
     DTLS1_RECORD_DATA *rdata;
 	pitem *item;
@@ -172,7 +175,7 @@ dtls1_buffer_record(SSL *s, record_pqueu
 		return 0;
 		
 	rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
-	item = pitem_new(priority, rdata);
+	item = pitem_new(*priority, rdata);
 	if (rdata == NULL || item == NULL)
 		{
 		if (rdata != NULL) OPENSSL_free(rdata);
@@ -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. */
@@ -267,7 +267,7 @@ dtls1_process_buffered_records(SSL *s)
             if ( ! dtls1_process_record(s))
                 return(0);
             dtls1_buffer_record(s, &(s->d1->processed_rcds), 
-                s->s3->rrec.seq_num);
+                &s->s3->rrec.seq_num);
             }
         }
 
@@ -328,13 +328,15 @@ 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;
     SSL3_RECORD *rr;
 	unsigned int mac_size;
 	unsigned char md[EVP_MAX_MD_SIZE];
+	int decryption_failed_or_bad_record_mac = 0;
+	unsigned char *mac = NULL;
 
 
 	rr= &(s->s3->rrec);
@@ -369,12 +371,10 @@ dtls1_process_record(SSL *s)
 	enc_err = s->method->ssl3_enc->enc(s,0);
 	if (enc_err <= 0)
 		{
-		if (enc_err == 0)
-			/* SSLerr() and ssl3_send_alert() have been called */
-			goto err;
-
-		/* otherwise enc_err == -1 */
-		goto decryption_failed_or_bad_record_mac;
+		/* To minimize information leaked via timing, we will always
+		 * perform all computations before discarding the message.
+		 */
+		decryption_failed_or_bad_record_mac = 1;
 		}
 
 #ifdef TLS_DEBUG
@@ -400,28 +400,32 @@ 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;
+			decryption_failed_or_bad_record_mac = 1;
 #endif			
 			}
 		/* check the MAC for rr->input (it's in mac_size bytes at the tail) */
-		if (rr->length < mac_size)
+		if (rr->length >= mac_size)
 			{
-#if 0 /* OK only for stream ciphers */
-			al=SSL_AD_DECODE_ERROR;
-			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT);
-			goto f_err;
-#else
-			goto decryption_failed_or_bad_record_mac;
-#endif
+			rr->length -= mac_size;
+			mac = &rr->data[rr->length];
 			}
-		rr->length-=mac_size;
-		i=s->method->ssl3_enc->mac(s,md,0);
-		if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0)
+		else
+			rr->length = 0;
+		s->method->ssl3_enc->mac(s,md,0);
+		if (mac == NULL || memcmp(md, mac, mac_size) != 0)
 			{
-			goto decryption_failed_or_bad_record_mac;
+			decryption_failed_or_bad_record_mac = 1;
 			}
 		}
 
+	if (decryption_failed_or_bad_record_mac)
+		{
+		/* decryption failed, silently discard message */
+		rr->length = 0;
+		s->packet_length = 0;
+		goto err;
+		}
+
 	/* r->length is now just compressed */
 	if (s->expand != NULL)
 		{
@@ -460,14 +464,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:
@@ -486,22 +482,19 @@ err:
 /* used only by dtls1_read_bytes */
 int dtls1_get_record(SSL *s)
 	{
-	int ssl_major,ssl_minor,al;
+	int ssl_major,ssl_minor;
 	int i,n;
 	SSL3_RECORD *rr;
-	SSL_SESSION *sess;
-	unsigned char *p;
+	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))
@@ -517,7 +510,12 @@ again:
 		/* read timeout is handled by dtls1_read_bytes */
 		if (n <= 0) return(n); /* error or non-blocking */
 
-		OPENSSL_assert(s->packet_length == DTLS1_RT_HEADER_LENGTH);
+		/* this packet contained a partial record, dump it */
+		if (s->packet_length != DTLS1_RT_HEADER_LENGTH)
+			{
+			s->packet_length = 0;
+			goto again;
+			}
 
 		s->rstate=SSL_ST_READ_BODY;
 
@@ -542,27 +540,28 @@ again:
 			{
 			if (version != s->version && version != DTLS1_BAD_VER)
 				{
-				SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
-				/* Send back error using their
-				 * version number :-) */
-				s->version=version;
-				al=SSL_AD_PROTOCOL_VERSION;
-				goto f_err;
+				/* unexpected version, silently discard */
+				rr->length = 0;
+				s->packet_length = 0;
+				goto again;
 				}
 			}
 
 		if ((version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
 		    (version & 0xff00) != (DTLS1_BAD_VER & 0xff00))
 			{
-			SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
-			goto err;
+			/* wrong version, silently discard record */
+			rr->length = 0;
+			s->packet_length = 0;
+			goto again;
 			}
 
 		if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
 			{
-			al=SSL_AD_RECORD_OVERFLOW;
-			SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
-			goto f_err;
+			/* record too long, silently discard it */
+			rr->length = 0;
+			s->packet_length = 0;
+			goto again;
 			}
 
 		s->client_version = version;
@@ -581,6 +580,7 @@ again:
 		/* this packet contained a partial record, dump it */
 		if ( n != i)
 			{
+			rr->length = 0;
 			s->packet_length = 0;
 			goto again;
 			}
@@ -594,6 +594,7 @@ again:
 	bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
 	if ( bitmap == NULL)
         {
+	rr->length = 0;
         s->packet_length = 0;  /* dump this record */
         goto again;   /* get another record */
 		}
@@ -601,6 +602,7 @@ again:
 	/* check whether this is a repeat, or aged record */
 	if ( ! dtls1_record_replay_check(s, bitmap, &(rr->seq_num)))
 		{
+		rr->length = 0;
 		s->packet_length=0; /* dump this record */
 		goto again;     /* get another record */
 		}
@@ -615,21 +617,22 @@ again:
     if (is_next_epoch)
         {
         dtls1_record_bitmap_update(s, bitmap);
-        dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num);
+        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);
 
-f_err:
-	ssl3_send_alert(s,SSL3_AL_FATAL,al);
-err:
-	return(0);
 	}
 
 /* Return up to 'len' payload bytes received in 'type' records.