Correctly re-ACK client Finished in DTLS 1.3

If client Finished gets through, but the server's responding ACK is
lost, the client will retransmit Finished (epoch 2). The server must
then process that retransmission and send another ACK.

However, the client may have since sent application data (epoch 3),
which the server may have since processed. Despite receiving data at
epoch 3, the server must keep epoch 2 open for some period of time to
accomodate this.

Unfortunately, there is no explicit signal in the protocol to do this.
The best we have is some guidance to be willing to do this for at least
2x MSL. See this discussion in the TLS mailing list:
https://mailarchive.ietf.org/arch/msg/tls/rof4SqkDrwU8o7WqSa9AO3YEUJI/

Implement this by keeping old epochs around for 2x MSL. This has the
side effect of also keeping old epochs around for a spell on KeyUpdate,
making us more resilient to packet reordering around KeyUpdate. For
simplicity, I've just get the same timeout for both, 2x MSL, or 4
minutes.

This opens a few cans of worms, because now record processing logic must
accomodate old epochs:

- The check against fragments from old epochs gets more complex.

- The check for maximum message size must move later; after the
  handshake, the server has a tight maximum message size, but it must be
  willing to receive (and skip over) retransmits from before the
  handshake when the limit was higher.

- Application data is fine. We already, at a lower layer, forbid any
  application data from coming in epochs 0 and 2.

- The ACK logic already did not make any particular assumptions here.
  Now we'll process ACKs from older epochs for slightly longer, but we
  already check that old epochs cannot ACK new epochs' messsages.

- ChangeCipherSpec is silly and would probably become moot once we start
  rejecting CCS in DTLS 1.3, but I just made it drop old epochs CCS on
  the floor to match the old behavior for now. (May as well avoid
  relying too much on DTLS 1.2 keeping one epoch around at once.)

This also requires tweaking the test slightly. flushHandshake needs to
run after the application data keys are installed, or the callback
cannot send data. That, in turn, means OutEpoch() is no longer the right
epoch for sending an ACK so some of the tests need to be updated to
still pick up epoch 2. (What's going on is that sending ACKs happens
before you construct the flight, but we want to test reordering, so we
simulate it afterwards.)

Bug: 42290594
Change-Id: I199b304fa9c3d8d252d258ab8ff231e3b5688e2e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/74027
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Nick Harper <nharper@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
6 files changed
tree: d02d0f12579ccee837c638786ee49ace27cf548b
  1. .bcr/
  2. .github/
  3. cmake/
  4. crypto/
  5. decrepit/
  6. docs/
  7. fuzz/
  8. gen/
  9. include/
  10. infra/
  11. pki/
  12. rust/
  13. ssl/
  14. third_party/
  15. tool/
  16. util/
  17. .bazelignore
  18. .bazelrc
  19. .bazelversion
  20. .clang-format
  21. .gitignore
  22. API-CONVENTIONS.md
  23. BREAKING-CHANGES.md
  24. BUILD.bazel
  25. build.json
  26. BUILDING.md
  27. CMakeLists.txt
  28. codereview.settings
  29. CONTRIBUTING.md
  30. FUZZING.md
  31. go.mod
  32. go.sum
  33. INCORPORATING.md
  34. LICENSE
  35. MODULE.bazel
  36. MODULE.bazel.lock
  37. PORTING.md
  38. PrivacyInfo.xcprivacy
  39. README.md
  40. SANDBOXING.md
  41. STYLE.md
README.md

BoringSSL

BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.

Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API or ABI stability.

Programs ship their own copies of BoringSSL when they use it and we update everything as needed when deciding to make API changes. This allows us to mostly avoid compromises in the name of compatibility. It works for us, but it may not work for you.

BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved in maintaining all these patches in multiple places was growing steadily.

Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the NDK) and a number of other apps/programs.

Project links:

To file a security issue, use the Chromium process and mention in the report this is for BoringSSL. You can ignore the parts of the process that are specific to Chromium/Chrome.

There are other files in this directory which might be helpful: