aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/openssl/ssl.h1
-rw-r--r--ssl/record/rec_layer_d1.c49
-rw-r--r--ssl/record/record_locl.h2
-rw-r--r--ssl/record/ssl3_record.c17
-rw-r--r--ssl/ssl_err.c2
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"},