Add APIs to access DTLS record layer state

DTLS record layer state is more complex and, with DTLS 1.3, we could not
make the simplifying assumptions that we did in DTLS 1.2. Expose enough
information so that, at idle points, we can extract state. See
go/dtls13-handover (internal) for details.

This requires maintaining some extra state on each epoch. We could
recover most of it if we did a better job not allocating unused fields
in DTLS by reworking the transport-specific portions.

Update-Note: Callers that need DTLS record layer state should migrate to
the new APIs. For now, the old APIs continue to work for DTLS 1.2, but
once caller have migrated, we'll make them TLS-only.

Bug: 42290608
Change-Id: Id3f7185e9715b9ee0e5e68108fd44d9484abd569
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/77967
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 3d1db1f..04996d2 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -4482,20 +4482,118 @@
                                           size_t out_len);
 
 // SSL_get_read_sequence returns, in TLS, the expected sequence number of the
-// next incoming record in the current epoch. In DTLS, it returns the maximum
-// sequence number received in the current epoch and includes the epoch number
-// in the two most significant bytes.
+// next incoming record in the current epoch.
+//
+// TODO(crbug.com/42290608): In DTLS, it returns the maximum sequence number
+// received in the current epoch (for some notion of "current" specific to
+// BoringSSL) and includes the epoch number in the two most significant bytes,
+// but this is deprecated. Use |SSL_get_dtls_read_sequence| instead.
 OPENSSL_EXPORT uint64_t SSL_get_read_sequence(const SSL *ssl);
 
 // SSL_get_write_sequence returns the sequence number of the next outgoing
-// record in the current epoch. In DTLS, it includes the epoch number in the
-// two most significant bytes.
+// record in the current epoch.
+//
+// TODO(crbug.com/42290608): In DTLS, it includes the epoch number in the two
+// most significant bytes, but this is deprecated. Use
+// |SSL_get_dtls_read_sequence| instead.
 OPENSSL_EXPORT uint64_t SSL_get_write_sequence(const SSL *ssl);
 
 // SSL_CTX_set_record_protocol_version returns whether |version| is zero.
 OPENSSL_EXPORT int SSL_CTX_set_record_protocol_version(SSL_CTX *ctx,
                                                        int version);
 
+// SSL_is_dtls_handshake_idle returns one |ssl|'s handshake is idle and zero if
+// it is busy. The handshake is considered idle if all of the following are
+// true:
+//
+// - |ssl| is not mid handshake or post-handshake transaction.
+// - In DTLS 1.3, all sent handshake messages have been acknowledged. That is,
+//   |ssl| does not have data to retransmit.
+// - All received handshake data has been processed. That is, |ssl| has no
+//   buffered partial or out-of-order messages.
+//
+// If any condition is false, the handshake is considered busy. If this function
+// reports the handshake is busy, it is expected that the handshake will become
+// idle after short timers and a few roundtrips of successful communication.
+// However, this is not guaranteed if, e.g., the peer misbehaves or sends many
+// KeyUpdates.
+//
+// WARNING: In DTLS 1.3, this function may return one while multiple active read
+// epochs exist in |ssl|.
+//
+// WARNING: In DTLS 1.2 (or earlier), if |ssl| is the role that speaks last, it
+// retains its final flight for retransmission in case of loss. There is no
+// explicit protocol signal for when this completes, though after receiving
+// application data and/or a timeout it is likely that this is no longer needed.
+// BoringSSL does not currently evaluate either condition and leaves it it to
+// the caller to determine whether this is now unnecessary. This applies when
+// |ssl| is a server for full handshakes and when |ssl| is a client for full
+// handshakes.
+OPENSSL_EXPORT int SSL_is_dtls_handshake_idle(const SSL *ssl);
+
+// SSL_get_dtls_handshake_read_seq returns the 16-bit sequence number of the
+// next DTLS handshake message to be read, or 0x10000 if handshake message
+// 0xffff (the maximum) has already been read.
+OPENSSL_EXPORT uint32_t SSL_get_dtls_handshake_read_seq(const SSL *ssl);
+
+// SSL_get_dtls_handshake_write_seq returns the 16-bit sequence number of the
+// next DTLS handshake message to be written or 0x10000 if handshake message
+// 0xffff (the maximum) has already been written.
+OPENSSL_EXPORT uint32_t SSL_get_dtls_handshake_write_seq(const SSL *ssl);
+
+// SSL_get_dtls_read_epoch returns the highest available DTLS read epoch in
+// |ssl|. In DTLS 1.3, |ssl| may have earlier epochs also active, sometimes to
+// optionally improve handling of reordered packets and sometimes as an
+// important part of the protocol correctness in the face of packet loss.
+//
+// The failure conditions of |SSL_get_dtls_read_traffic_secret| and
+// |SSL_get_dtls_read_sequence| can be used to determine if past epochs are
+// active.
+OPENSSL_EXPORT uint16_t SSL_get_dtls_read_epoch(const SSL *ssl);
+
+// SSL_get_dtls_write_epoch returns the current DTLS write epoch. If the
+// handshake is idle (see |SSL_is_dtls_handshake_idle|), no other write epochs
+// will be active.
+OPENSSL_EXPORT uint16_t SSL_get_dtls_write_epoch(const SSL *ssl);
+
+// SSL_get_dtls_read_sequence returns one more than the sequence number of the
+// highest record received in |epoch|. If no records have been received in
+// |epoch|. If the epoch does not exist, it returns |UINT64_MAX|.
+//
+// It is safe to discard all sequence numbers less than the return value of this
+// function. The sequence numbers returned by this function do not include the
+// epoch number in the upper 16 bits.
+OPENSSL_EXPORT uint64_t SSL_get_dtls_read_sequence(const SSL *ssl,
+                                                   uint16_t epoch);
+
+// SSL_get_dtls_write_sequence returns the sequence number of the next record to
+// be sent in |epoch|. If the epoch does not exist, it returns |UINT64_MAX|.
+//
+// The sequence numbers returned by this function do not include the epoch
+// number in the upper 16 bits.
+OPENSSL_EXPORT uint64_t SSL_get_dtls_write_sequence(const SSL *ssl,
+                                                    uint16_t epoch);
+
+// SSL_get_dtls_read_traffic_secret looks up the traffic secret for read epoch
+// |epoch|. If the epoch exists and is an encrypted (not epoch zero) DTLS 1.3
+// epoch, it sets |*out_data| and |*out_len| to a buffer containing the secrets
+// and returns one. Otherwise, it returns zero. The buffer is valid until the
+// next operation on |ssl|.
+OPENSSL_EXPORT int SSL_get_dtls_read_traffic_secret(const SSL *ssl,
+                                                    const uint8_t **out_data,
+                                                    size_t *out_len,
+                                                    uint16_t epoch);
+
+// SSL_get_dtls_write_traffic_secret looks up the traffic secret for write epoch
+// |epoch|. If the epoch exists and is an encrypted (not epoch zero) DTLS 1.3
+// epoch, it sets |*out_data| and |*out_len| to a buffer containing the secrets
+// and returns one. Otherwise, it returns zero. The buffer is valid until the
+// next operation on |ssl|.
+OPENSSL_EXPORT int SSL_get_dtls_write_traffic_secret(const SSL *ssl,
+                                                     const uint8_t **out_data,
+                                                     size_t *out_len,
+                                                     uint16_t epoch);
+
 
 // Handshake hints.
 //
diff --git a/ssl/dtls_method.cc b/ssl/dtls_method.cc
index 7be3159..3ed8a84 100644
--- a/ssl/dtls_method.cc
+++ b/ssl/dtls_method.cc
@@ -80,6 +80,7 @@
 
   DTLSReadEpoch new_epoch;
   new_epoch.aead = std::move(aead_ctx);
+  new_epoch.traffic_secret.CopyFrom(traffic_secret);
   if (!next_epoch(ssl, &new_epoch.epoch, level, ssl->d1->read_epoch.epoch)) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
     return false;
@@ -118,6 +119,7 @@
   DTLSWriteEpoch new_epoch;
   new_epoch.aead = std::move(aead_ctx);
   new_epoch.next_record = DTLSRecordNumber(epoch, 0);
+  new_epoch.traffic_secret.CopyFrom(traffic_secret);
   if (ssl_protocol_version(ssl) > TLS1_2_VERSION) {
     new_epoch.rn_encrypter =
         RecordNumberEncrypter::Create(new_epoch.aead->cipher(), traffic_secret);
diff --git a/ssl/dtls_record.cc b/ssl/dtls_record.cc
index 0077338..da5c318 100644
--- a/ssl/dtls_record.cc
+++ b/ssl/dtls_record.cc
@@ -119,6 +119,33 @@
   return seqnum;
 }
 
+DTLSReadEpoch *dtls_get_read_epoch(const SSL *ssl, uint16_t epoch) {
+  if (epoch == ssl->d1->read_epoch.epoch) {
+    return &ssl->d1->read_epoch;
+  }
+  if (ssl->d1->next_read_epoch != nullptr &&
+      epoch == ssl->d1->next_read_epoch->epoch) {
+    return ssl->d1->next_read_epoch.get();
+  }
+  if (ssl->d1->prev_read_epoch != nullptr &&
+      epoch == ssl->d1->prev_read_epoch->epoch.epoch) {
+    return &ssl->d1->prev_read_epoch->epoch;
+  }
+  return nullptr;
+}
+
+DTLSWriteEpoch *dtls_get_write_epoch(const SSL *ssl, uint16_t epoch) {
+  if (ssl->d1->write_epoch.epoch() == epoch) {
+    return &ssl->d1->write_epoch;
+  }
+  for (const auto &e : ssl->d1->extra_write_epochs) {
+    if (e->epoch() == epoch) {
+      return e.get();
+    }
+  }
+  return nullptr;
+}
+
 static Span<uint8_t> cbs_to_writable_bytes(CBS cbs) {
   return Span(const_cast<uint8_t *>(CBS_data(&cbs)), CBS_len(&cbs));
 }
@@ -177,16 +204,7 @@
 
   // Look up the corresponding epoch. This header form only matches encrypted
   // DTLS 1.3 epochs.
-  DTLSReadEpoch *read_epoch = nullptr;
-  if (epoch == ssl->d1->read_epoch.epoch) {
-    read_epoch = &ssl->d1->read_epoch;
-  } else if (ssl->d1->next_read_epoch != nullptr &&
-             epoch == ssl->d1->next_read_epoch->epoch) {
-    read_epoch = ssl->d1->next_read_epoch.get();
-  } else if (ssl->d1->prev_read_epoch != nullptr &&
-             epoch == ssl->d1->prev_read_epoch->epoch.epoch) {
-    read_epoch = &ssl->d1->prev_read_epoch->epoch;
-  }
+  DTLSReadEpoch *read_epoch = dtls_get_read_epoch(ssl, epoch);
   if (read_epoch != nullptr && use_dtls13_record_header(ssl, epoch)) {
     out->read_epoch = read_epoch;
 
@@ -406,18 +424,6 @@
   return ssl_open_record_success;
 }
 
-static DTLSWriteEpoch *get_write_epoch(const SSL *ssl, uint16_t epoch) {
-  if (ssl->d1->write_epoch.epoch() == epoch) {
-    return &ssl->d1->write_epoch;
-  }
-  for (const auto &e : ssl->d1->extra_write_epochs) {
-    if (e->epoch() == epoch) {
-      return e.get();
-    }
-  }
-  return nullptr;
-}
-
 size_t dtls_record_header_write_len(const SSL *ssl, uint16_t epoch) {
   if (!use_dtls13_record_header(ssl, epoch)) {
     return DTLS_PLAINTEXT_RECORD_HEADER_LENGTH;
@@ -431,7 +437,7 @@
 }
 
 size_t dtls_max_seal_overhead(const SSL *ssl, uint16_t epoch) {
-  DTLSWriteEpoch *write_epoch = get_write_epoch(ssl, epoch);
+  DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
   if (write_epoch == nullptr) {
     return 0;
   }
@@ -445,7 +451,7 @@
 }
 
 size_t dtls_seal_prefix_len(const SSL *ssl, uint16_t epoch) {
-  DTLSWriteEpoch *write_epoch = get_write_epoch(ssl, epoch);
+  DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
   if (write_epoch == nullptr) {
     return 0;
   }
@@ -454,7 +460,7 @@
 }
 
 size_t dtls_seal_max_input_len(const SSL *ssl, uint16_t epoch, size_t max_out) {
-  DTLSWriteEpoch *write_epoch = get_write_epoch(ssl, epoch);
+  DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
   if (write_epoch == nullptr) {
     return 0;
   }
@@ -482,7 +488,7 @@
   }
 
   // Determine the parameters for the current epoch.
-  DTLSWriteEpoch *write_epoch = get_write_epoch(ssl, epoch);
+  DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
   if (write_epoch == nullptr) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return false;
diff --git a/ssl/internal.h b/ssl/internal.h
index 5ec2c95..ba6b444 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1093,7 +1093,7 @@
   // to |max_seq_num_ - i|.
   std::bitset<256> map_;
   // max_seq_num_ is the largest sequence number seen so far as a 64-bit
-  // integer.
+  // integer, or zero if none have been seen.
   uint64_t max_seq_num_ = 0;
 };
 
@@ -1177,6 +1177,7 @@
   UniquePtr<SSLAEADContext> aead;
   UniquePtr<RecordNumberEncrypter> rn_encrypter;
   DTLSReplayBitmap bitmap;
+  InplaceVector<uint8_t, SSL_MAX_MD_SIZE> traffic_secret;
 };
 
 struct DTLSWriteEpoch {
@@ -1187,6 +1188,7 @@
   DTLSRecordNumber next_record;
   UniquePtr<SSLAEADContext> aead;
   UniquePtr<RecordNumberEncrypter> rn_encrypter;
+  InplaceVector<uint8_t, SSL_MAX_MD_SIZE> traffic_secret;
 };
 
 // ssl_record_prefix_len returns the length of the prefix before the ciphertext
@@ -1275,6 +1277,11 @@
 // fit in a record of up to |max_out| bytes, or zero if none may fit.
 size_t dtls_seal_max_input_len(const SSL *ssl, uint16_t epoch, size_t max_out);
 
+// dtls_get_read_epoch and dtls_get_write_epoch return the epoch corresponding
+// to |epoch| or nullptr if there is none.
+DTLSReadEpoch *dtls_get_read_epoch(const SSL *ssl, uint16_t epoch);
+DTLSWriteEpoch *dtls_get_write_epoch(const SSL *ssl, uint16_t epoch);
+
 // 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
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 3ef8e03..d228b1c 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -332,8 +332,9 @@
 bool SSL_get_traffic_secrets(const SSL *ssl,
                              Span<const uint8_t> *out_read_traffic_secret,
                              Span<const uint8_t> *out_write_traffic_secret) {
-  // This API is not well-defined for DTLS 1.3 (see https://crbug.com/42290608)
-  // or QUIC, where multiple epochs may be alive at once.
+  // This API is not well-defined for DTLS, where multiple epochs may be alive
+  // at once. Callers should use |SSL_get_dtls_*_traffic_secret| instead. In
+  // QUIC, the application is already handed the traffic secret.
   if (SSL_is_dtls(ssl) || SSL_is_quic(ssl)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
     return false;
@@ -2813,17 +2814,8 @@
 
 uint64_t SSL_get_read_sequence(const SSL *ssl) {
   if (SSL_is_dtls(ssl)) {
-    // TODO(crbug.com/42290608): This API needs to reworked.
-    //
-    // In DTLS 1.2, right at an epoch transition, |read_epoch| may not have
-    // received any records. We will then return that sequence 0 is the highest
-    // received, but it's really -1, which is not representable. This is mostly
-    // moot because, after the handshake, we will never be in the state.
-    //
-    // In DTLS 1.3, epochs do not transition until the first record comes in.
-    // This avoids the DTLS 1.2 problem but introduces a different problem:
-    // during a KeyUpdate (which may occur in the steady state), both epochs are
-    // live. We'll likely need a new API for DTLS offload.
+    // TODO(crbug.com/42290608): This API should not be implemented for DTLS or
+    // QUIC. In QUIC we do not maintain a sequence number.
     const DTLSReadEpoch *read_epoch = &ssl->d1->read_epoch;
     return DTLSRecordNumber(read_epoch->epoch, read_epoch->bitmap.max_seq_num())
         .combined();
@@ -2832,6 +2824,10 @@
 }
 
 uint64_t SSL_get_write_sequence(const SSL *ssl) {
+  // TODO(crbug.com/42290608): This API should not be implemented for DTLS or
+  // QUIC. In QUIC we do not maintain a sequence number. In DTLS, this API isn't
+  // harmful per se, but the caller already needs to use a DTLS-specific API on
+  // the read side.
   if (SSL_is_dtls(ssl)) {
     return ssl->d1->write_epoch.next_record.combined();
   }
@@ -2839,6 +2835,109 @@
   return ssl->s3->write_sequence;
 }
 
+int SSL_is_dtls_handshake_idle(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+
+  return !SSL_in_init(ssl) &&
+         // No unacknowledged messages in DTLS 1.3. In DTLS 1.2, there no ACKs
+         // and we currently never clear |outgoing_messages| on the side that
+         // speaks last.
+         (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
+          ssl->d1->outgoing_messages.empty()) &&
+         // No partial or out-of-order messages.
+         std::all_of(std::begin(ssl->d1->incoming_messages),
+                     std::end(ssl->d1->incoming_messages),
+                     [](const auto &msg) { return msg == nullptr; }) &&
+         // Not trying to send a KeyUpdate.
+         !ssl->s3->key_update_pending &&
+         ssl->d1->queued_key_update == bssl::QueuedKeyUpdate::kNone;
+}
+
+uint32_t SSL_get_dtls_handshake_read_seq(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  return ssl->d1->handshake_read_overflow
+             ? uint32_t{0x10000}
+             : uint32_t{ssl->d1->handshake_read_seq};
+}
+
+uint32_t SSL_get_dtls_handshake_write_seq(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  return ssl->d1->handshake_write_overflow
+             ? uint32_t{0x10000}
+             : uint32_t{ssl->d1->handshake_write_seq};
+}
+
+uint16_t SSL_get_dtls_read_epoch(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  // Return the highest available epoch.
+  return ssl->d1->next_read_epoch ? ssl->d1->next_read_epoch->epoch
+                                  : ssl->d1->read_epoch.epoch;
+}
+
+uint16_t SSL_get_dtls_write_epoch(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  return ssl->d1->write_epoch.epoch();
+}
+
+uint64_t SSL_get_dtls_read_sequence(const SSL *ssl, uint16_t epoch) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  const DTLSReadEpoch *read_epoch = dtls_get_read_epoch(ssl, epoch);
+  if (read_epoch == nullptr) {
+    return UINT64_MAX;
+  }
+  uint64_t max_seq_num = read_epoch->bitmap.max_seq_num();
+  assert(max_seq_num <= DTLSRecordNumber::kMaxSequence);
+  if (read_epoch->bitmap.ShouldDiscard(max_seq_num)) {
+    // Increment to get to an available sequence number.
+    max_seq_num++;
+  } else {
+    // If |max_seq_num| was available, the bitmap must have been empty.
+    assert(max_seq_num == 0);
+  }
+  return max_seq_num;
+}
+
+uint64_t SSL_get_dtls_write_sequence(const SSL *ssl, uint16_t epoch) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  const DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
+  if (write_epoch == nullptr) {
+    return UINT64_MAX;
+  }
+  return write_epoch->next_record.sequence();
+}
+
+template <typename EpochState>
+static int get_dtls_traffic_secret(
+    const SSL *ssl, EpochState *(*get_epoch)(const SSL *, uint16_t),
+    const uint8_t **out_data, size_t *out_len, uint16_t epoch) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  // This function only applies to encrypted DTLS 1.3 epochs.
+  if (epoch == 0 || ssl->s3->version == 0 ||
+      ssl_protocol_version(ssl) < TLS1_3_VERSION) {
+    return 0;
+  }
+  const EpochState *epoch_state = get_epoch(ssl, epoch);
+  if (epoch_state == nullptr) {
+    return 0;
+  }
+  assert(!epoch_state->traffic_secret.empty());
+  *out_data = epoch_state->traffic_secret.data();
+  *out_len = epoch_state->traffic_secret.size();
+  return 1;
+}
+
+int SSL_get_dtls_read_traffic_secret(const SSL *ssl, const uint8_t **out_data,
+                                     size_t *out_len, uint16_t epoch) {
+  return get_dtls_traffic_secret(ssl, dtls_get_read_epoch, out_data, out_len,
+                                 epoch);
+}
+
+int SSL_get_dtls_write_traffic_secret(const SSL *ssl, const uint8_t **out_data,
+                                      size_t *out_len, uint16_t epoch) {
+  return get_dtls_traffic_secret(ssl, dtls_get_write_epoch, out_data, out_len,
+                                 epoch);
+}
+
 uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl) {
   SSL_SESSION *session = SSL_get_session(ssl);
   if (session == NULL) {
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index cdc2a6e..e08fd64 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -134,6 +134,17 @@
   int index_;
 };
 
+static timeval g_current_time;
+
+static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
+  *out_clock = g_current_time;
+}
+
+static void FrozenTimeCallback(const SSL *ssl, timeval *out_clock) {
+  out_clock->tv_sec = 1000;
+  out_clock->tv_usec = 0;
+}
+
 static const CipherTest kCipherTests[] = {
     // Selecting individual ciphers should work.
     {
@@ -2778,6 +2789,14 @@
                          });
 
 TEST_P(SSLVersionTest, SequenceNumber) {
+  // TODO(crbug.com/42290608): Once |SSL_get_read_sequence| and
+  // |SSL_get_write_sequence| are no longer implemented in DTLS 1.3, make this
+  // test TLS-only and remove the DTLS cases. For now, since we still care about
+  // their behavior in DTLS 1.2, continue testing this behavior.
+  if (is_dtls() && is_tls13()) {
+    return;
+  }
+
   ASSERT_TRUE(Connect());
 
   // Drain any post-handshake messages to ensure there are no unread records
@@ -2790,26 +2809,15 @@
   uint64_t server_write_seq = SSL_get_write_sequence(server_.get());
 
   if (is_dtls()) {
-    if (version() == DTLS1_3_VERSION) {
-      // Both client and server must be at epoch 3 (application data).
-      EXPECT_EQ(EpochFromSequence(client_write_seq), 3);
-      EXPECT_EQ(EpochFromSequence(server_write_seq), 3);
+    // Both client and server must be at epoch 1.
+    EXPECT_EQ(EpochFromSequence(client_read_seq), 1);
+    EXPECT_EQ(EpochFromSequence(client_write_seq), 1);
+    EXPECT_EQ(EpochFromSequence(server_read_seq), 1);
+    EXPECT_EQ(EpochFromSequence(server_write_seq), 1);
 
-      // TODO(crbug.com/42290608): Ideally we would check the read sequence
-      // numbers and compare them against each other, but
-      // |SSL_get_read_sequence| is ill-defined right after DTLS 1.3's key
-      // change. See that function for details.
-    } else {
-      // Both client and server must be at epoch 1.
-      EXPECT_EQ(EpochFromSequence(client_read_seq), 1);
-      EXPECT_EQ(EpochFromSequence(client_write_seq), 1);
-      EXPECT_EQ(EpochFromSequence(server_read_seq), 1);
-      EXPECT_EQ(EpochFromSequence(server_write_seq), 1);
-
-      // The next record to be written should exceed the largest received.
-      EXPECT_GT(client_write_seq, server_read_seq);
-      EXPECT_GT(server_write_seq, client_read_seq);
-    }
+    // The next record to be written should exceed the largest received.
+    EXPECT_GT(client_write_seq, server_read_seq);
+    EXPECT_GT(server_write_seq, client_read_seq);
   } else {
     // The next record to be written should equal the next to be received.
     EXPECT_EQ(client_write_seq, server_read_seq);
@@ -2821,20 +2829,266 @@
   EXPECT_EQ(SSL_write(client_.get(), &byte, 1), 1);
   EXPECT_EQ(SSL_read(server_.get(), &byte, 1), 1);
 
-  if (version() == DTLS1_3_VERSION) {
-    // TODO(crbug.com/42290608): Write an appropriate test for incrementing both
-    // sequence number and epoch in the following test. The server read seq was
-    // in epoch 2, but after the write it's in epoch 3, so adding 1 doesn't work
-    // any more.
-    return;
-  }
-
   // The client write and server read sequence numbers should have
   // incremented.
   EXPECT_EQ(client_write_seq + 1, SSL_get_write_sequence(client_.get()));
   EXPECT_EQ(server_read_seq + 1, SSL_get_read_sequence(server_.get()));
 }
 
+TEST_P(SSLVersionTest, RecordStateDTLS) {
+  if (!is_dtls()) {
+    return;
+  }
+
+  SSL_CTX_set_current_time_cb(client_ctx_.get(), CurrentTimeCallback);
+  SSL_CTX_set_current_time_cb(server_ctx_.get(), CurrentTimeCallback);
+
+  ASSERT_TRUE(CreateClientAndServer(&client_, &server_, client_ctx_.get(),
+                                    server_ctx_.get()));
+
+  // The handshake is incomplete.
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(client_.get()));
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(server_.get()));
+
+  // The initial epoch is zero.
+  EXPECT_EQ(SSL_get_dtls_read_epoch(client_.get()), 0);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 0);
+  EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 0);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 0);
+
+  // We have not sent or received any records.
+  EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 0), 0u);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 0), 0u);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 0), 0u);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 0), 0u);
+
+  // We have not sent or received any handshake messages.
+  EXPECT_EQ(SSL_get_dtls_handshake_read_seq(client_.get()), 0u);
+  EXPECT_EQ(SSL_get_dtls_handshake_write_seq(server_.get()), 0u);
+  EXPECT_EQ(SSL_get_dtls_handshake_read_seq(server_.get()), 0u);
+  EXPECT_EQ(SSL_get_dtls_handshake_write_seq(client_.get()), 0u);
+
+  // Though it exists, epoch zero is unencrypted and does not have traffic
+  // secrets.
+  const uint8_t *data;
+  size_t len;
+  EXPECT_FALSE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 0));
+  EXPECT_FALSE(
+      SSL_get_dtls_write_traffic_secret(client_.get(), &data, &len, 0));
+  EXPECT_FALSE(SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 0));
+  EXPECT_FALSE(
+      SSL_get_dtls_write_traffic_secret(server_.get(), &data, &len, 0));
+
+  // Other epochs do not exist yet.
+  EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 1), UINT64_MAX);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 1), UINT64_MAX);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 1), UINT64_MAX);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 1), UINT64_MAX);
+  EXPECT_FALSE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 1));
+  EXPECT_FALSE(
+      SSL_get_dtls_write_traffic_secret(server_.get(), &data, &len, 1));
+  EXPECT_FALSE(SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 1));
+  EXPECT_FALSE(
+      SSL_get_dtls_write_traffic_secret(client_.get(), &data, &len, 1));
+
+  ASSERT_TRUE(CompleteHandshakes(client_.get(), server_.get()));
+
+  // DTLS 1.0 and 1.2 are relative simple.
+  if (!is_tls13()) {
+    // This handshake is now idle.
+    EXPECT_TRUE(SSL_is_dtls_handshake_idle(client_.get()));
+    EXPECT_TRUE(SSL_is_dtls_handshake_idle(server_.get()));
+
+    // Both sides of both channels are at epoch 1.
+    EXPECT_EQ(SSL_get_dtls_read_epoch(client_.get()), 1);
+    EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 1);
+    EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 1);
+    EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 1);
+
+    // Both sides have sent one record at epoch 1 each (Finished).
+    EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 1), 1u);
+
+    // DTLS 1.2 does not use traffic secrets.
+    EXPECT_FALSE(
+        SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 1));
+    EXPECT_FALSE(
+        SSL_get_dtls_write_traffic_secret(server_.get(), &data, &len, 1));
+    EXPECT_FALSE(
+        SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 1));
+    EXPECT_FALSE(
+        SSL_get_dtls_write_traffic_secret(client_.get(), &data, &len, 1));
+
+    // Send a record from client to server.
+    uint8_t byte = 0;
+    EXPECT_EQ(SSL_write(client_.get(), &byte, 1), 1);
+    EXPECT_EQ(SSL_read(server_.get(), &byte, 1), 1);
+
+    // Sequence numbers should have updated.
+    EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 1), 2u);
+    EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 1), 2u);
+    return;
+  }
+
+  // The client sent Finished, which the server ACKed, but the client hasn't
+  // consumed the ACK.
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(client_.get()));
+  // The server sent NewSessionTicket, which the client hasn't consumed yet.
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(server_.get()));
+
+  // Both sides of both channels are at epoch 3.
+  EXPECT_EQ(SSL_get_dtls_read_epoch(client_.get()), 3);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 3);
+  EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 3);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 3);
+
+  auto check_matching_secret = [&](SSL *reader, SSL *writer, uint16_t epoch) {
+    ASSERT_TRUE(SSL_get_dtls_read_traffic_secret(reader, &data, &len, epoch));
+    auto read_secret = Span(data, len);
+    ASSERT_TRUE(SSL_get_dtls_write_traffic_secret(writer, &data, &len, epoch));
+    auto write_secret = Span(data, len);
+    EXPECT_EQ(Bytes(read_secret), Bytes(write_secret));
+  };
+
+  // Traffic secrets at epoch 3 should match.
+  check_matching_secret(client_.get(), server_.get(), 3);
+  check_matching_secret(server_.get(), client_.get(), 3);
+
+  // Both sides retain read epoch 2 (but not write epoch 2). The server must
+  // retain epoch 2 because it does not know the client has seen the ACK and
+  // therefore must respond to retransmissions of the client's final flight.
+  // The client could discard epoch 2, but our implementation happens not to.
+  EXPECT_LT(SSL_get_dtls_read_sequence(client_.get(), 2), UINT64_MAX);
+  EXPECT_LT(SSL_get_dtls_read_sequence(server_.get(), 2), UINT64_MAX);
+  EXPECT_TRUE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 2));
+  EXPECT_TRUE(SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 2));
+
+  // The client has not sent anything over epoch 3.
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 3), 0u);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 3), 0u);
+
+  // The server has (ACK and NewSessionTicket), but the client has not seen it.
+  EXPECT_GT(SSL_get_dtls_write_sequence(server_.get(), 3), 0u);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 3), 0u);
+
+  // Read from the client. No application data, but this will consume the
+  // records. We send ACKs on a timer, so advance the clock to flush it.
+  uint8_t byte;
+  EXPECT_EQ(SSL_read(client_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(client_.get(), -1), SSL_ERROR_WANT_READ);
+  g_current_time.tv_sec++;
+  EXPECT_EQ(DTLSv1_handle_timeout(client_.get()), 1);
+
+  // The client has now picked up the ACK and is idle.
+  EXPECT_TRUE(SSL_is_dtls_handshake_idle(client_.get()));
+
+  // The client has caught up to what the server wrote.
+  EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 3),
+            SSL_get_dtls_read_sequence(client_.get(), 3));
+
+  // The client saw NewSessionTicket and sent an ACK.
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 3), 1u);
+
+  // Pick up the ACK from the server.
+  EXPECT_EQ(SSL_read(server_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(server_.get(), -1), SSL_ERROR_WANT_READ);
+
+  // Now the server is also idle.
+  EXPECT_TRUE(SSL_is_dtls_handshake_idle(server_.get()));
+
+  // The server has seen the ACK and has caught up to the client.
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 3),
+            SSL_get_dtls_read_sequence(server_.get(), 3));
+
+  // Exchange some data. Sequence numbers should increment.
+  uint64_t old_seq = SSL_get_dtls_write_sequence(server_.get(), 3);
+  byte = 42;
+  ASSERT_EQ(SSL_write(server_.get(), &byte, 1), 1);
+  ASSERT_EQ(SSL_read(client_.get(), &byte, 1), 1);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 3), old_seq + 1);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 3), old_seq + 1);
+
+  // Now that everyone's caught up, handshake sequence numbers should be
+  // non-zero and match.
+  uint32_t client_hs_seq = SSL_get_dtls_handshake_write_seq(client_.get());
+  EXPECT_NE(client_hs_seq, 0u);
+  EXPECT_EQ(client_hs_seq, SSL_get_dtls_handshake_read_seq(server_.get()));
+  uint32_t server_hs_seq = SSL_get_dtls_handshake_write_seq(server_.get());
+  EXPECT_NE(server_hs_seq, 0u);
+  EXPECT_EQ(server_hs_seq, SSL_get_dtls_handshake_read_seq(client_.get()));
+
+  // Enqueue a KeyUpdate that requests the peer do the same. The client is now
+  // busy.
+  ASSERT_TRUE(SSL_key_update(client_.get(), SSL_KEY_UPDATE_REQUESTED));
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(client_.get()));
+  // Flush the KeyUpdate to the transport. (We currently flush incidental
+  // traffic on read because callers are expected to be constantly reading.)
+  // The client has an unacked message, so it is still busy.
+  EXPECT_EQ(SSL_read(client_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(client_.get(), -1), SSL_ERROR_WANT_READ);
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(client_.get()));
+
+  // KeyUpdates are driven by ACKs, so the client is still at epoch 3.
+  EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 3);
+
+  // Consume the KeyUpdate on the server and wait for the ACK timer. The server
+  // has now ACKed the KeyUpdate, advanced to read epoch 4, and sent a KeyUpdate
+  // of its own.
+  EXPECT_EQ(SSL_read(server_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(server_.get(), -1), SSL_ERROR_WANT_READ);
+  g_current_time.tv_sec++;
+  EXPECT_EQ(DTLSv1_handle_timeout(server_.get()), 1);
+  EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 4);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 4), 0u);
+
+  // The server has an outstanding unacked KeyUpdate, so it is busy.
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(server_.get()));
+  EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 3);
+
+  // Consume the ACK and new KeyUpdate on the client. Wait the ACK timer for the
+  // client to flush its ACK.
+  EXPECT_EQ(SSL_read(client_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(client_.get(), -1), SSL_ERROR_WANT_READ);
+  g_current_time.tv_sec++;
+  EXPECT_EQ(DTLSv1_handle_timeout(client_.get()), 1);
+
+  // The client has now seen the ACK to its KeyUpdate, advancing its write
+  // state, and seen the server's KeyUpdate, advancing its read state. It is
+  // now idle.
+  EXPECT_TRUE(SSL_is_dtls_handshake_idle(client_.get()));
+  EXPECT_EQ(SSL_get_dtls_read_epoch(client_.get()), 4);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 4);
+
+  // Both sides now have epoch 4 of the client write channel.
+  check_matching_secret(/*reader=*/server_.get(), /*writer=*/client_.get(), 4);
+
+  // Finally, consume the ACK on the server. The server applies the KeyUpdate
+  // and is also idle.
+  EXPECT_EQ(SSL_read(server_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(server_.get(), -1), SSL_ERROR_WANT_READ);
+  EXPECT_TRUE(SSL_is_dtls_handshake_idle(server_.get()));
+  EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 4);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 4);
+
+  // Both sides now have epoch 4 of the server write channel.
+  check_matching_secret(/*reader=*/client_.get(), /*writer=*/server_.get(), 4);
+
+  // Both sides still retain read epoch 3 because neither side has received data
+  // at epoch 4 and cannot be sure the ACK has gotten through.
+  EXPECT_TRUE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 3));
+  EXPECT_TRUE(SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 3));
+
+  // Handshake sequence numbers should have incremented.
+  EXPECT_EQ(SSL_get_dtls_handshake_write_seq(client_.get()), client_hs_seq + 1);
+  EXPECT_EQ(SSL_get_dtls_handshake_read_seq(server_.get()), client_hs_seq + 1);
+  EXPECT_EQ(SSL_get_dtls_handshake_write_seq(server_.get()), server_hs_seq + 1);
+  EXPECT_EQ(SSL_get_dtls_handshake_read_seq(client_.get()), server_hs_seq + 1);
+}
+
 TEST_P(SSLVersionTest, OneSidedShutdown) {
   // SSL_shutdown is a no-op in DTLS.
   if (is_dtls()) {
@@ -3539,17 +3793,6 @@
                                   false /* expect session not reused */));
 }
 
-static timeval g_current_time;
-
-static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
-  *out_clock = g_current_time;
-}
-
-static void FrozenTimeCallback(const SSL *ssl, timeval *out_clock) {
-  out_clock->tv_sec = 1000;
-  out_clock->tv_usec = 0;
-}
-
 static int RenewTicketCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv,
                                EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
                                int encrypt) {
@@ -9669,20 +9912,26 @@
                                         Key("SERVER_HANDSHAKE_TRAFFIC_SECRET"),
                                         Key("SERVER_TRAFFIC_SECRET_0")));
 
-    if (!is_dtls()) {
-      // Ideally we'd check the other values, but those are harder to check
-      // without actually decrypting the records.
-      //
-      // TODO(crbug.com/42290608): Check the secrets in DTLS, once we have an
-      // API for them.
-      Span<const uint8_t> read_secret, write_secret;
+    Span<const uint8_t> read_secret, write_secret;
+    if (is_dtls()) {
+      // The first application data epoch is 3.
+      const uint8_t *data;
+      size_t len;
+      ASSERT_TRUE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len,
+                                                   /*epoch=*/3));
+      read_secret = Span(data, len);
+      ASSERT_TRUE(SSL_get_dtls_write_traffic_secret(client_.get(), &data, &len,
+                                                   /*epoch=*/3));
+      write_secret = Span(data, len);
+    } else {
       ASSERT_TRUE(
           SSL_get_traffic_secrets(client_.get(), &read_secret, &write_secret));
-      EXPECT_EQ(Bytes(read_secret),
-                Bytes(client_log["SERVER_TRAFFIC_SECRET_0"]));
-      EXPECT_EQ(Bytes(write_secret),
-                Bytes(client_log["CLIENT_TRAFFIC_SECRET_0"]));
     }
+    // Ideally we'd check the other values, but those are harder to check
+    // without actually decrypting the records.
+    EXPECT_EQ(Bytes(read_secret), Bytes(client_log["SERVER_TRAFFIC_SECRET_0"]));
+    EXPECT_EQ(Bytes(write_secret),
+              Bytes(client_log["CLIENT_TRAFFIC_SECRET_0"]));
   } else {
     EXPECT_THAT(client_log, ElementsAre(Key("CLIENT_RANDOM")));