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.