|
|
c4366c |
diff -up openssl-fips-0.9.8e/ssl/d1_pkt.c.dtls-fixes2 openssl-fips-0.9.8e/ssl/d1_pkt.c
|
|
|
c4366c |
--- openssl-fips-0.9.8e/ssl/d1_pkt.c.dtls-fixes2 2012-01-16 11:00:34.242797904 +0100
|
|
|
c4366c |
+++ openssl-fips-0.9.8e/ssl/d1_pkt.c 2012-01-18 15:45:25.144865068 +0100
|
|
|
c4366c |
@@ -134,7 +134,7 @@ static int dtls1_record_needs_buffering(
|
|
|
c4366c |
unsigned short *priority, unsigned long *offset);
|
|
|
c4366c |
#endif
|
|
|
c4366c |
static int dtls1_buffer_record(SSL *s, record_pqueue *q,
|
|
|
c4366c |
- PQ_64BIT priority);
|
|
|
c4366c |
+ PQ_64BIT *priority);
|
|
|
c4366c |
static int dtls1_process_record(SSL *s);
|
|
|
c4366c |
#if PQ_64BIT_IS_INTEGER
|
|
|
c4366c |
static PQ_64BIT bytes_to_long_long(unsigned char *bytes, PQ_64BIT *num);
|
|
|
c4366c |
@@ -156,13 +156,16 @@ dtls1_copy_record(SSL *s, pitem *item)
|
|
|
c4366c |
s->packet_length = rdata->packet_length;
|
|
|
c4366c |
memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
|
|
|
c4366c |
memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
|
|
|
c4366c |
+
|
|
|
c4366c |
+ /* Set proper sequence number for mac calculation */
|
|
|
c4366c |
+ memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);
|
|
|
c4366c |
|
|
|
c4366c |
return(1);
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
|
|
|
c4366c |
static int
|
|
|
c4366c |
-dtls1_buffer_record(SSL *s, record_pqueue *queue, PQ_64BIT priority)
|
|
|
c4366c |
+dtls1_buffer_record(SSL *s, record_pqueue *queue, PQ_64BIT *priority)
|
|
|
c4366c |
{
|
|
|
c4366c |
DTLS1_RECORD_DATA *rdata;
|
|
|
c4366c |
pitem *item;
|
|
|
c4366c |
@@ -172,7 +175,7 @@ dtls1_buffer_record(SSL *s, record_pqueu
|
|
|
c4366c |
return 0;
|
|
|
c4366c |
|
|
|
c4366c |
rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
|
|
|
c4366c |
- item = pitem_new(priority, rdata);
|
|
|
c4366c |
+ item = pitem_new(*priority, rdata);
|
|
|
c4366c |
if (rdata == NULL || item == NULL)
|
|
|
c4366c |
{
|
|
|
c4366c |
if (rdata != NULL) OPENSSL_free(rdata);
|
|
|
c4366c |
@@ -253,9 +256,6 @@ dtls1_process_buffered_records(SSL *s)
|
|
|
c4366c |
item = pqueue_peek(s->d1->unprocessed_rcds.q);
|
|
|
c4366c |
if (item)
|
|
|
c4366c |
{
|
|
|
c4366c |
- DTLS1_RECORD_DATA *rdata;
|
|
|
c4366c |
- rdata = (DTLS1_RECORD_DATA *)item->data;
|
|
|
c4366c |
-
|
|
|
c4366c |
/* Check if epoch is current. */
|
|
|
c4366c |
if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
|
|
|
c4366c |
return(1); /* Nothing to do. */
|
|
|
c4366c |
@@ -267,7 +267,7 @@ dtls1_process_buffered_records(SSL *s)
|
|
|
c4366c |
if ( ! dtls1_process_record(s))
|
|
|
c4366c |
return(0);
|
|
|
c4366c |
dtls1_buffer_record(s, &(s->d1->processed_rcds),
|
|
|
c4366c |
- s->s3->rrec.seq_num);
|
|
|
c4366c |
+ &s->s3->rrec.seq_num);
|
|
|
c4366c |
}
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
@@ -328,13 +328,15 @@ dtls1_get_buffered_record(SSL *s)
|
|
|
c4366c |
static int
|
|
|
c4366c |
dtls1_process_record(SSL *s)
|
|
|
c4366c |
{
|
|
|
c4366c |
- int i,al;
|
|
|
c4366c |
+ int al;
|
|
|
c4366c |
int clear=0;
|
|
|
c4366c |
int enc_err;
|
|
|
c4366c |
SSL_SESSION *sess;
|
|
|
c4366c |
SSL3_RECORD *rr;
|
|
|
c4366c |
unsigned int mac_size;
|
|
|
c4366c |
unsigned char md[EVP_MAX_MD_SIZE];
|
|
|
c4366c |
+ int decryption_failed_or_bad_record_mac = 0;
|
|
|
c4366c |
+ unsigned char *mac = NULL;
|
|
|
c4366c |
|
|
|
c4366c |
|
|
|
c4366c |
rr= &(s->s3->rrec);
|
|
|
c4366c |
@@ -369,12 +371,10 @@ dtls1_process_record(SSL *s)
|
|
|
c4366c |
enc_err = s->method->ssl3_enc->enc(s,0);
|
|
|
c4366c |
if (enc_err <= 0)
|
|
|
c4366c |
{
|
|
|
c4366c |
- if (enc_err == 0)
|
|
|
c4366c |
- /* SSLerr() and ssl3_send_alert() have been called */
|
|
|
c4366c |
- goto err;
|
|
|
c4366c |
-
|
|
|
c4366c |
- /* otherwise enc_err == -1 */
|
|
|
c4366c |
- goto decryption_failed_or_bad_record_mac;
|
|
|
c4366c |
+ /* To minimize information leaked via timing, we will always
|
|
|
c4366c |
+ * perform all computations before discarding the message.
|
|
|
c4366c |
+ */
|
|
|
c4366c |
+ decryption_failed_or_bad_record_mac = 1;
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
#ifdef TLS_DEBUG
|
|
|
c4366c |
@@ -400,28 +400,32 @@ if ( (sess == NULL) ||
|
|
|
c4366c |
SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG);
|
|
|
c4366c |
goto f_err;
|
|
|
c4366c |
#else
|
|
|
c4366c |
- goto decryption_failed_or_bad_record_mac;
|
|
|
c4366c |
+ decryption_failed_or_bad_record_mac = 1;
|
|
|
c4366c |
#endif
|
|
|
c4366c |
}
|
|
|
c4366c |
/* check the MAC for rr->input (it's in mac_size bytes at the tail) */
|
|
|
c4366c |
- if (rr->length < mac_size)
|
|
|
c4366c |
+ if (rr->length >= mac_size)
|
|
|
c4366c |
{
|
|
|
c4366c |
-#if 0 /* OK only for stream ciphers */
|
|
|
c4366c |
- al=SSL_AD_DECODE_ERROR;
|
|
|
c4366c |
- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT);
|
|
|
c4366c |
- goto f_err;
|
|
|
c4366c |
-#else
|
|
|
c4366c |
- goto decryption_failed_or_bad_record_mac;
|
|
|
c4366c |
-#endif
|
|
|
c4366c |
+ rr->length -= mac_size;
|
|
|
c4366c |
+ mac = &rr->data[rr->length];
|
|
|
c4366c |
}
|
|
|
c4366c |
- rr->length-=mac_size;
|
|
|
c4366c |
- i=s->method->ssl3_enc->mac(s,md,0);
|
|
|
c4366c |
- if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0)
|
|
|
c4366c |
+ else
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
+ s->method->ssl3_enc->mac(s,md,0);
|
|
|
c4366c |
+ if (mac == NULL || memcmp(md, mac, mac_size) != 0)
|
|
|
c4366c |
{
|
|
|
c4366c |
- goto decryption_failed_or_bad_record_mac;
|
|
|
c4366c |
+ decryption_failed_or_bad_record_mac = 1;
|
|
|
c4366c |
}
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
+ if (decryption_failed_or_bad_record_mac)
|
|
|
c4366c |
+ {
|
|
|
c4366c |
+ /* decryption failed, silently discard message */
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
+ s->packet_length = 0;
|
|
|
c4366c |
+ goto err;
|
|
|
c4366c |
+ }
|
|
|
c4366c |
+
|
|
|
c4366c |
/* r->length is now just compressed */
|
|
|
c4366c |
if (s->expand != NULL)
|
|
|
c4366c |
{
|
|
|
c4366c |
@@ -460,14 +464,6 @@ if ( (sess == NULL) ||
|
|
|
c4366c |
dtls1_record_bitmap_update(s, &(s->d1->bitmap));/* Mark receipt of record. */
|
|
|
c4366c |
return(1);
|
|
|
c4366c |
|
|
|
c4366c |
-decryption_failed_or_bad_record_mac:
|
|
|
c4366c |
- /* Separate 'decryption_failed' alert was introduced with TLS 1.0,
|
|
|
c4366c |
- * SSL 3.0 only has 'bad_record_mac'. But unless a decryption
|
|
|
c4366c |
- * failure is directly visible from the ciphertext anyway,
|
|
|
c4366c |
- * we should not reveal which kind of error occured -- this
|
|
|
c4366c |
- * might become visible to an attacker (e.g. via logfile) */
|
|
|
c4366c |
- al=SSL_AD_BAD_RECORD_MAC;
|
|
|
c4366c |
- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
|
|
|
c4366c |
f_err:
|
|
|
c4366c |
ssl3_send_alert(s,SSL3_AL_FATAL,al);
|
|
|
c4366c |
err:
|
|
|
c4366c |
@@ -486,22 +482,19 @@ err:
|
|
|
c4366c |
/* used only by dtls1_read_bytes */
|
|
|
c4366c |
int dtls1_get_record(SSL *s)
|
|
|
c4366c |
{
|
|
|
c4366c |
- int ssl_major,ssl_minor,al;
|
|
|
c4366c |
+ int ssl_major,ssl_minor;
|
|
|
c4366c |
int i,n;
|
|
|
c4366c |
SSL3_RECORD *rr;
|
|
|
c4366c |
- SSL_SESSION *sess;
|
|
|
c4366c |
- unsigned char *p;
|
|
|
c4366c |
+ unsigned char *p = NULL;
|
|
|
c4366c |
unsigned short version;
|
|
|
c4366c |
DTLS1_BITMAP *bitmap;
|
|
|
c4366c |
unsigned int is_next_epoch;
|
|
|
c4366c |
|
|
|
c4366c |
rr= &(s->s3->rrec);
|
|
|
c4366c |
- sess=s->session;
|
|
|
c4366c |
|
|
|
c4366c |
/* The epoch may have changed. If so, process all the
|
|
|
c4366c |
* pending records. This is a non-blocking operation. */
|
|
|
c4366c |
- if ( ! dtls1_process_buffered_records(s))
|
|
|
c4366c |
- return 0;
|
|
|
c4366c |
+ dtls1_process_buffered_records(s);
|
|
|
c4366c |
|
|
|
c4366c |
/* if we're renegotiating, then there may be buffered records */
|
|
|
c4366c |
if (dtls1_get_processed_record(s))
|
|
|
c4366c |
@@ -517,7 +510,12 @@ again:
|
|
|
c4366c |
/* read timeout is handled by dtls1_read_bytes */
|
|
|
c4366c |
if (n <= 0) return(n); /* error or non-blocking */
|
|
|
c4366c |
|
|
|
c4366c |
- OPENSSL_assert(s->packet_length == DTLS1_RT_HEADER_LENGTH);
|
|
|
c4366c |
+ /* this packet contained a partial record, dump it */
|
|
|
c4366c |
+ if (s->packet_length != DTLS1_RT_HEADER_LENGTH)
|
|
|
c4366c |
+ {
|
|
|
c4366c |
+ s->packet_length = 0;
|
|
|
c4366c |
+ goto again;
|
|
|
c4366c |
+ }
|
|
|
c4366c |
|
|
|
c4366c |
s->rstate=SSL_ST_READ_BODY;
|
|
|
c4366c |
|
|
|
c4366c |
@@ -542,27 +540,28 @@ again:
|
|
|
c4366c |
{
|
|
|
c4366c |
if (version != s->version && version != DTLS1_BAD_VER)
|
|
|
c4366c |
{
|
|
|
c4366c |
- SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
|
|
|
c4366c |
- /* Send back error using their
|
|
|
c4366c |
- * version number :-) */
|
|
|
c4366c |
- s->version=version;
|
|
|
c4366c |
- al=SSL_AD_PROTOCOL_VERSION;
|
|
|
c4366c |
- goto f_err;
|
|
|
c4366c |
+ /* unexpected version, silently discard */
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
+ s->packet_length = 0;
|
|
|
c4366c |
+ goto again;
|
|
|
c4366c |
}
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
if ((version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
|
|
|
c4366c |
(version & 0xff00) != (DTLS1_BAD_VER & 0xff00))
|
|
|
c4366c |
{
|
|
|
c4366c |
- SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
|
|
|
c4366c |
- goto err;
|
|
|
c4366c |
+ /* wrong version, silently discard record */
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
+ s->packet_length = 0;
|
|
|
c4366c |
+ goto again;
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
|
|
|
c4366c |
{
|
|
|
c4366c |
- al=SSL_AD_RECORD_OVERFLOW;
|
|
|
c4366c |
- SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
|
|
|
c4366c |
- goto f_err;
|
|
|
c4366c |
+ /* record too long, silently discard it */
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
+ s->packet_length = 0;
|
|
|
c4366c |
+ goto again;
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
s->client_version = version;
|
|
|
c4366c |
@@ -581,6 +580,7 @@ again:
|
|
|
c4366c |
/* this packet contained a partial record, dump it */
|
|
|
c4366c |
if ( n != i)
|
|
|
c4366c |
{
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
s->packet_length = 0;
|
|
|
c4366c |
goto again;
|
|
|
c4366c |
}
|
|
|
c4366c |
@@ -594,6 +594,7 @@ again:
|
|
|
c4366c |
bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
|
|
|
c4366c |
if ( bitmap == NULL)
|
|
|
c4366c |
{
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
s->packet_length = 0; /* dump this record */
|
|
|
c4366c |
goto again; /* get another record */
|
|
|
c4366c |
}
|
|
|
c4366c |
@@ -601,6 +602,7 @@ again:
|
|
|
c4366c |
/* check whether this is a repeat, or aged record */
|
|
|
c4366c |
if ( ! dtls1_record_replay_check(s, bitmap, &(rr->seq_num)))
|
|
|
c4366c |
{
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
s->packet_length=0; /* dump this record */
|
|
|
c4366c |
goto again; /* get another record */
|
|
|
c4366c |
}
|
|
|
c4366c |
@@ -615,21 +617,22 @@ again:
|
|
|
c4366c |
if (is_next_epoch)
|
|
|
c4366c |
{
|
|
|
c4366c |
dtls1_record_bitmap_update(s, bitmap);
|
|
|
c4366c |
- dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num);
|
|
|
c4366c |
+ dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), &rr->seq_num);
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
s->packet_length = 0;
|
|
|
c4366c |
goto again;
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
- if ( ! dtls1_process_record(s))
|
|
|
c4366c |
- return(0);
|
|
|
c4366c |
+ if (!dtls1_process_record(s))
|
|
|
c4366c |
+ {
|
|
|
c4366c |
+ rr->length = 0;
|
|
|
c4366c |
+ s->packet_length=0; /* dump this record */
|
|
|
c4366c |
+ goto again; /* get another record */
|
|
|
c4366c |
+ }
|
|
|
c4366c |
|
|
|
c4366c |
dtls1_clear_timeouts(s); /* done waiting */
|
|
|
c4366c |
return(1);
|
|
|
c4366c |
|
|
|
c4366c |
-f_err:
|
|
|
c4366c |
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
|
|
|
c4366c |
-err:
|
|
|
c4366c |
- return(0);
|
|
|
c4366c |
}
|
|
|
c4366c |
|
|
|
c4366c |
/* Return up to 'len' payload bytes received in 'type' records.
|