diff options
-rw-r--r-- | include/openssl/ssl.h | 1 | ||||
-rw-r--r-- | ssl/record/rec_layer_d1.c | 49 | ||||
-rw-r--r-- | ssl/record/record_locl.h | 2 | ||||
-rw-r--r-- | ssl/record/ssl3_record.c | 17 | ||||
-rw-r--r-- | ssl/ssl_err.c | 2 |
5 files changed, 57 insertions, 14 deletions
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index a7732ff512..4f23c9f804 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2066,6 +2066,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 318 # define SSL_F_DTLS1_HEARTBEAT 305 # define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288 +# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 423 # define SSL_F_DTLS1_PROCESS_RECORD 257 # define SSL_F_DTLS1_READ_BYTES 258 # define SSL_F_DTLS1_READ_FAILED 339 diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c index 0f7881ecd0..be6aac719f 100644 --- a/ssl/record/rec_layer_d1.c +++ b/ssl/record/rec_layer_d1.c @@ -230,12 +230,18 @@ int dtls1_process_buffered_records(SSL *s) { pitem *item; SSL3_BUFFER *rb; + SSL3_RECORD *rr; + DTLS1_BITMAP *bitmap; + unsigned int is_next_epoch; + int replayok = 1; item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q); if (item) { /* Check if epoch is current. */ if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch) - return (1); /* Nothing to do. */ + return 1; /* Nothing to do. */ + + rr = RECORD_LAYER_get_rrec(&s->rlayer); rb = RECORD_LAYER_get_rbuf(&s->rlayer); @@ -252,12 +258,41 @@ int dtls1_process_buffered_records(SSL *s) /* Process all the records. */ while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) { dtls1_get_unprocessed_record(s); - if (!dtls1_process_record(s)) - return (0); + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) { + /* + * Should not happen. This will only ever be NULL when the + * current record is from a different epoch. But that cannot + * be the case because we already checked the epoch above + */ + SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, + ERR_R_INTERNAL_ERROR); + return 0; + } +#ifndef OPENSSL_NO_SCTP + /* Only do replay check if no SCTP bio */ + if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) +#endif + { + /* + * Check whether this is a repeat, or aged record. We did this + * check once already when we first received the record - but + * we might have updated the window since then due to + * records we subsequently processed. + */ + replayok = dtls1_record_replay_check(s, bitmap); + } + + if (!replayok || !dtls1_process_record(s, bitmap)) { + /* dump this record */ + rr->length = 0; + RECORD_LAYER_reset_packet_length(&s->rlayer); + continue; + } + if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), - SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < - 0) - return -1; + SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) + return 0; } } @@ -268,7 +303,7 @@ int dtls1_process_buffered_records(SSL *s) s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch; s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1; - return (1); + return 1; } /*- diff --git a/ssl/record/record_locl.h b/ssl/record/record_locl.h index 3b9a700d9f..52e59e46d5 100644 --- a/ssl/record/record_locl.h +++ b/ssl/record/record_locl.h @@ -110,5 +110,5 @@ __owur int ssl3_cbc_remove_padding(SSL3_RECORD *rec, __owur int tls1_cbc_remove_padding(const SSL *s, SSL3_RECORD *rec, unsigned block_size, unsigned mac_size); -int dtls1_process_record(SSL *s); +int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap); __owur int dtls1_get_record(SSL *s); diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index c99d5e4416..32a97aff08 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -1273,7 +1273,7 @@ void ssl3_cbc_copy_mac(unsigned char *out, #endif } -int dtls1_process_record(SSL *s) +int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap) { int i, al; int enc_err; @@ -1429,6 +1429,10 @@ int dtls1_process_record(SSL *s) /* we have pulled in a full packet so zero things */ RECORD_LAYER_reset_packet_length(&s->rlayer); + + /* Mark receipt of record. */ + dtls1_record_bitmap_update(s, bitmap); + return (1); f_err: @@ -1472,7 +1476,7 @@ int dtls1_get_record(SSL *s) * The epoch may have changed. If so, process all the pending records. * This is a non-blocking operation. */ - if (dtls1_process_buffered_records(s) < 0) + if (!dtls1_process_buffered_records(s)) return -1; /* if we're renegotiating, then there may be buffered records */ @@ -1580,6 +1584,10 @@ int dtls1_get_record(SSL *s) if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) { #endif /* Check whether this is a repeat, or aged record. */ + /* + * TODO: Does it make sense to have replay protection in epoch 0 where + * we have no integrity negotiated yet? + */ if (!dtls1_record_replay_check(s, bitmap)) { rr->length = 0; RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */ @@ -1604,20 +1612,17 @@ int dtls1_get_record(SSL *s) (s, &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)), rr->seq_num) < 0) return -1; - /* Mark receipt of record. */ - dtls1_record_bitmap_update(s, bitmap); } rr->length = 0; RECORD_LAYER_reset_packet_length(&s->rlayer); goto again; } - if (!dtls1_process_record(s)) { + if (!dtls1_process_record(s, bitmap)) { rr->length = 0; RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */ goto again; /* get another record */ } - dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */ return (1); diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 9644fd2466..1fddda612a 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -32,6 +32,8 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_DTLS1_CHECK_TIMEOUT_NUM), "dtls1_check_timeout_num"}, {ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "dtls1_heartbeat"}, {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "dtls1_preprocess_fragment"}, + {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS), + "dtls1_process_buffered_records"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "dtls1_process_record"}, {ERR_FUNC(SSL_F_DTLS1_READ_BYTES), "dtls1_read_bytes"}, {ERR_FUNC(SSL_F_DTLS1_READ_FAILED), "dtls1_read_failed"}, |