diff --git a/ssl/d1_both.cc b/ssl/d1_both.cc index b910b96d9..1a68d93bd 100644 --- a/ssl/d1_both.cc +++ b/ssl/d1_both.cc @@ -624,16 +624,14 @@ static enum seal_result_t seal_next_message(SSL *ssl, uint8_t *out, assert(ssl->d1->outgoing_written < ssl->d1->outgoing_messages_len); assert(msg == &ssl->d1->outgoing_messages[ssl->d1->outgoing_written]); - enum dtls1_use_epoch_t use_epoch = dtls1_use_current_epoch; - if (ssl->d1->w_epoch >= 1 && msg->epoch == ssl->d1->w_epoch - 1) { - use_epoch = dtls1_use_previous_epoch; - } else if (msg->epoch != ssl->d1->w_epoch) { + if (msg->epoch != ssl->d1->w_epoch && + (ssl->d1->w_epoch == 0 || msg->epoch != ssl->d1->w_epoch - 1)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return seal_error; } - size_t overhead = dtls_max_seal_overhead(ssl, use_epoch); - size_t prefix = dtls_seal_prefix_len(ssl, use_epoch); + size_t overhead = dtls_max_seal_overhead(ssl, msg->epoch); + size_t prefix = dtls_seal_prefix_len(ssl, msg->epoch); if (msg->is_ccs) { // Check there is room for the ChangeCipherSpec. @@ -644,7 +642,7 @@ static enum seal_result_t seal_next_message(SSL *ssl, uint8_t *out, if (!dtls_seal_record(ssl, out, out_len, max_out, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec, - sizeof(kChangeCipherSpec), use_epoch)) { + sizeof(kChangeCipherSpec), msg->epoch)) { return seal_error; } @@ -697,7 +695,7 @@ static enum seal_result_t seal_next_message(SSL *ssl, uint8_t *out, MakeSpan(frag, frag_len)); if (!dtls_seal_record(ssl, out, out_len, max_out, SSL3_RT_HANDSHAKE, - out + prefix, frag_len, use_epoch)) { + out + prefix, frag_len, msg->epoch)) { return seal_error; } diff --git a/ssl/d1_pkt.cc b/ssl/d1_pkt.cc index b86615626..da898b499 100644 --- a/ssl/d1_pkt.cc +++ b/ssl/d1_pkt.cc @@ -208,7 +208,7 @@ int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, } int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, in, - dtls1_use_current_epoch); + ssl->d1->w_epoch); if (ret <= 0) { return ret; } @@ -217,7 +217,7 @@ int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, } int dtls1_write_record(SSL *ssl, int type, Span in, - enum dtls1_use_epoch_t use_epoch) { + uint16_t epoch) { SSLBuffer *buf = &ssl->s3->write_buffer; assert(in.size() <= SSL3_RT_MAX_PLAIN_LENGTH); // There should never be a pending write buffer in DTLS. One can't write half @@ -235,7 +235,7 @@ int dtls1_write_record(SSL *ssl, int type, Span in, in.size() + SSL_max_seal_overhead(ssl)) || !dtls_seal_record(ssl, buf->remaining().data(), &ciphertext_len, buf->remaining().size(), type, in.data(), in.size(), - use_epoch)) { + epoch)) { buf->Clear(); return -1; } @@ -250,7 +250,7 @@ int dtls1_write_record(SSL *ssl, int type, Span in, int dtls1_dispatch_alert(SSL *ssl) { int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, ssl->s3->send_alert, - dtls1_use_current_epoch); + ssl->d1->w_epoch); if (ret <= 0) { return ret; } diff --git a/ssl/dtls_record.cc b/ssl/dtls_record.cc index 068864fae..6551aa45d 100644 --- a/ssl/dtls_record.cc +++ b/ssl/dtls_record.cc @@ -258,29 +258,30 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, } static const SSLAEADContext *get_write_aead(const SSL *ssl, - enum dtls1_use_epoch_t use_epoch) { - if (use_epoch == dtls1_use_previous_epoch) { - assert(ssl->d1->w_epoch >= 1); + uint16_t epoch) { + if (epoch < ssl->d1->w_epoch) { + assert(epoch + 1 == ssl->d1->w_epoch); return ssl->d1->last_aead_write_ctx.get(); } + assert(epoch == ssl->d1->w_epoch); return ssl->s3->aead_write_ctx.get(); } size_t dtls_max_seal_overhead(const SSL *ssl, - enum dtls1_use_epoch_t use_epoch) { - return DTLS1_RT_HEADER_LENGTH + get_write_aead(ssl, use_epoch)->MaxOverhead(); + uint16_t epoch) { + return DTLS1_RT_HEADER_LENGTH + get_write_aead(ssl, epoch)->MaxOverhead(); } -size_t dtls_seal_prefix_len(const SSL *ssl, enum dtls1_use_epoch_t use_epoch) { +size_t dtls_seal_prefix_len(const SSL *ssl, uint16_t epoch) { return DTLS1_RT_HEADER_LENGTH + - get_write_aead(ssl, use_epoch)->ExplicitNonceLen(); + get_write_aead(ssl, epoch)->ExplicitNonceLen(); } bool dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, uint8_t type, const uint8_t *in, size_t in_len, - enum dtls1_use_epoch_t use_epoch) { - const size_t prefix = dtls_seal_prefix_len(ssl, use_epoch); + uint16_t epoch) { + const size_t prefix = dtls_seal_prefix_len(ssl, epoch); if (buffers_alias(in, in_len, out, max_out) && (max_out < prefix || out + prefix != in)) { OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); @@ -288,14 +289,14 @@ bool dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, } // Determine the parameters for the current epoch. - uint16_t epoch = ssl->d1->w_epoch; SSLAEADContext *aead = ssl->s3->aead_write_ctx.get(); uint64_t *seq = &ssl->s3->write_sequence; - if (use_epoch == dtls1_use_previous_epoch) { - assert(ssl->d1->w_epoch >= 1); - epoch = ssl->d1->w_epoch - 1; + if (epoch < ssl->d1->w_epoch) { + assert(epoch + 1 == ssl->d1->w_epoch); aead = ssl->d1->last_aead_write_ctx.get(); seq = &ssl->d1->last_write_sequence; + } else { + assert(epoch == ssl->d1->w_epoch); } if (max_out < DTLS1_RT_HEADER_LENGTH) { diff --git a/ssl/internal.h b/ssl/internal.h index 2e4464163..4db9f1750 100644 --- a/ssl/internal.h +++ b/ssl/internal.h @@ -1044,26 +1044,21 @@ size_t ssl_seal_align_prefix_len(const SSL *ssl); bool tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, uint8_t type, const uint8_t *in, size_t in_len); -enum dtls1_use_epoch_t { - dtls1_use_previous_epoch, - dtls1_use_current_epoch, -}; - // dtls_max_seal_overhead returns the maximum overhead, in bytes, of sealing a // record. -size_t dtls_max_seal_overhead(const SSL *ssl, enum dtls1_use_epoch_t use_epoch); +size_t dtls_max_seal_overhead(const SSL *ssl, uint16_t epoch); // dtls_seal_prefix_len returns the number of bytes of prefix to reserve in // front of the plaintext when sealing a record in-place. -size_t dtls_seal_prefix_len(const SSL *ssl, enum dtls1_use_epoch_t use_epoch); +size_t dtls_seal_prefix_len(const SSL *ssl, uint16_t epoch); -// dtls_seal_record implements |tls_seal_record| for DTLS. |use_epoch| selects -// which epoch's cipher state to use. Unlike |tls_seal_record|, |in| and |out| -// may alias but, if they do, |in| must be exactly |dtls_seal_prefix_len| bytes +// dtls_seal_record implements |tls_seal_record| for DTLS. |epoch| selects which +// epoch's cipher state to use. Unlike |tls_seal_record|, |in| and |out| may +// alias but, if they do, |in| must be exactly |dtls_seal_prefix_len| bytes // ahead of |out|. bool dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, uint8_t type, const uint8_t *in, size_t in_len, - enum dtls1_use_epoch_t use_epoch); + uint16_t epoch); // ssl_process_alert processes |in| as an alert and updates |ssl|'s shutdown // state. It returns one of |ssl_open_record_discard|, |ssl_open_record_error|, @@ -3379,7 +3374,7 @@ int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, // dtls1_write_record sends a record. It returns one on success and <= 0 on // error. int dtls1_write_record(SSL *ssl, int type, Span in, - enum dtls1_use_epoch_t use_epoch); + uint16_t epoch); int dtls1_retransmit_outgoing_messages(SSL *ssl); bool dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr, diff --git a/ssl/tls_record.cc b/ssl/tls_record.cc index 395b9a483..5a820f6d6 100644 --- a/ssl/tls_record.cc +++ b/ssl/tls_record.cc @@ -606,7 +606,7 @@ using namespace bssl; size_t SSL_max_seal_overhead(const SSL *ssl) { if (SSL_is_dtls(ssl)) { - return dtls_max_seal_overhead(ssl, dtls1_use_current_epoch); + return dtls_max_seal_overhead(ssl, ssl->d1->w_epoch); } size_t ret = SSL3_RT_HEADER_LENGTH;