Skip to content

Conversation

@mpg
Copy link
Contributor

@mpg mpg commented Feb 13, 2025

Description

This adds three families of tests for TLS handshake defragmentation:

  1. More precise positive testing where we control the size of the fragments exactly, answering questions like "what if the last fragment is exactly 1 byte"?
  2. Negative testing of what happens when the peer sends a non-handshake message between two fragments.
  3. Negative testing of what happens when the peer sends a super long message, either:
    a. whose announced size is larger than our input buffer, or
    b. whose size would fit except it doesn't due to fragmentation overhead.

In addition, there are a few test cases, with "for reference" in the name, that are really about validating the new test function rather than testing the library.

Regarding the kind of things being tested:

  1. Found no issue, we seem to be good here.
  2. Found an issue (infinite loop for some kind of messages), fixed by commit "Cleanly reject non-HS in-between HS fragments".
  3. Found no issue (fetch_input() acts as a reliable defence against overflowing the input buffer).
    a. The case where the announced size if too large could perhaps be rejected earlier?
    b. The case where the message would fit except for fragmentation overhead has been adapted to incremental defragmentation.

Depends on: #10043 merged

PR checklist

  • changelog not required because: test only
  • development PR provided Defragment ext test dev #10052
  • TF-PSA-Crypto PR not required because: TLS only
  • framework PR not required
  • 3.6 PR here
  • 2.28 PR not required because: feature not in 2.28
  • tests provided | not required because:

@mpg mpg added the needs-ci Needs to pass CI tests label Feb 13, 2025
@mpg mpg changed the base branch from development to mbedtls-3.6 February 13, 2025 12:02
@mpg mpg force-pushed the defragment-ext-test-3.6 branch 2 times, most recently from 03ef604 to 5d5d64a Compare February 24, 2025 09:05
@mpg mpg changed the base branch from mbedtls-3.6 to features/tls-defragmentation/3.6 February 24, 2025 09:06
@mpg mpg force-pushed the defragment-ext-test-3.6 branch from 39c85c4 to 6f55ec6 Compare February 27, 2025 11:10
@gilles-peskine-arm gilles-peskine-arm added needs-work component-tls size-s Estimated task size: small (~2d) priority-high High priority - will be reviewed soon labels Feb 27, 2025

TLS 1.3 srv, max early data size, HRR, 98, wsz=49
tls13_srv_max_early_data_size:TEST_EARLY_DATA_HRR:97:0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest placing the new tests in a separate .data file. test_suite_ssl.data is already huge. Creating a new .data file for an existing .function file is trivial, it doesn't need to be recorded in any build script.

@mpg mpg force-pushed the defragment-ext-test-3.6 branch 2 times, most recently from d301ac7 to aa6d3d4 Compare March 4, 2025 12:02
@mpg mpg marked this pull request as ready for review March 5, 2025 09:08
@mpg mpg added needs-review Every commit must be reviewed by at least two team members, and removed needs-ci Needs to pass CI tests labels Mar 5, 2025
@mpg mpg force-pushed the defragment-ext-test-3.6 branch from aa6d3d4 to d1587e2 Compare March 5, 2025 10:55
@@ -0,0 +1,181 @@
# (Minimal) ClientHello breakdown:
Copy link
Contributor

@gilles-peskine-arm gilles-peskine-arm Mar 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before I review the test coverage, here's a list of things I would like to test. They don't have to all be done in this pull request, it's perfectly fine if anything missing is done in a follow-up.

These test cases should run both in TLS 1.2 and TLS 1.3 where applicable, and both with and without MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Receiving a message whose length is ≥65536, meaning that it cannot be correctly formatted as a single reassembled record.

Or buffer is 2^14 or smaller, so we'll end up rejecting fragments because they'd overflow our buffer before we get to this issue.

Receiving a 0-byte subsequent handshake fragment.

Note that 0-length handshake fragments are forbidden by the standard (both 1.2 and 1.3). (Only 0-length ApplicationData records are allowed.) Not saying we shouldn't test it, just saying I think the desired behaviour is for our code to reject it.

Copy link
Contributor

@gilles-peskine-arm gilles-peskine-arm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am satisfied that in 1f216de, the tests do what they say on the tin, and they are explained as well as they can be given the time constraints. (Ideally I'd prefer not to rely on a bunch of hex strings, but moving away from that would take far more time than we have now.)

I want more test coverage before we release, but I'm in favor of merging this PR ASAP and improving coverage in a follow-up.

ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
MBEDTLS_SSL_DEBUG_MSG(1, ("non-handshake message in the middle"
" of a fragmented handshake message"));
return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocker: should we send an alert?


/* Send initial fragment and have the server process it. */
ret = mbedtls_test_mock_tcp_send_b(&client.socket, first_frag, first_len);
TEST_ASSERT(ret >= 0 && (size_t) ret == first_len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: why not

Suggested change
TEST_ASSERT(ret >= 0 && (size_t) ret == first_len);
TEST_EQUAL(ret, (int) first_len);

which prints out the values of ret and first_len if it fails?

send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 4:3:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA

Send large fragmented ClientHello: would fit without overhead #5
send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 4:4:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess after incremental defragmentation, we expect to add this?

Send large fragmented ClientHello: just fits
send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 5:0:"":0
``

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well if we want it to return 0, we'll need to pass a valid supersize ClientHello. I think that can be achieved by putting junk into an unknown extension, but that would require changes to the test function.

Also, I'm not sure the previous negative tests will still be valid after incremental defrag: we have some extra room in the buffer for encryption overhead, that's unused for the unencrypted ClientHello, so I'm actually expecting we don't be getting the same error from fetch_input for messages just over the limit. We'll see when I rebase.

TBH I'm not sure what we should do here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'm going with the same invalid ClientHello as for the other tests. We'll know that defragmentation succeeded when we get a return value of MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION with Unsupported version of TLS in the logs as opposed MBEDTLS_ERR_SSL_BAD_INPUT_DATA + requesting more data than fits when it was too large for reassembly.

@mpg mpg force-pushed the defragment-ext-test-3.6 branch from 1f216de to 035a249 Compare March 7, 2025 12:00
@mpg mpg removed the needs-work label Mar 7, 2025
@mpg mpg requested a review from minosgalanakis March 7, 2025 14:17
@mpg mpg added the needs-preceding-pr Requires another PR to be merged first label Mar 7, 2025
mpg added 14 commits March 14, 2025 09:21
In addition to secp256r1 for the handshake, we need secp384r1 as it's
used by the CA certificate.

Caught by depends.py curves

Also, for the "unknown ciphersuite" 1.2 test, use the same key type and
all the same dependencies as of the "good" test above, to avoid having
to determine a second set of correct dependencies just for this one.

Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
We're not sending a signature_algorithm extension, which means SHA-1.

Caught by depends.py hashes

Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Declare the same dependencies as for the previous TLS 1.3 tests, except
for part that varies with the cipher suite (ie AES-GCM).

Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
This should avoid running into a bug with printf format specifiers one
windows.

It's also a logical move for actual tests: I used the highest debug
level for discovery, but we don't need that all the time.

Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
This is more flexible: the test data gets to decide whether we want to
assert the presence of a pattern or not.

Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
That way if it ever fails it will print the values.

Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
Signed-off-by: Manuel Pégourié-Gonnard <[email protected]>
@mpg mpg force-pushed the defragment-ext-test-3.6 branch from 7932fbe to 43a04e7 Compare March 14, 2025 08:24
@mpg mpg removed the needs-preceding-pr Requires another PR to be merged first label Mar 14, 2025
@mpg
Copy link
Contributor Author

mpg commented Mar 14, 2025

Rebased on 3.6 now that #10043 is merged and Open CI came back fully green as expected. Ready for review, I will no longer be rebasing, nor pushing changes (except to address review feedback).

Copy link
Contributor

@gilles-peskine-arm gilles-peskine-arm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM at 43a04e7

As suggested by Minos, I'd like to add a test of a 1.2 ClientHello that's embedded in a larger record, followed in the same record by a ClientKeyExchange that would be valid for some server response. But that's technically out of scope here.

Copy link
Contributor

@minosgalanakis minosgalanakis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@github-project-automation github-project-automation bot moved this from In Review to Has Approval in Roadmap pull requests (new board) Mar 17, 2025
@mpg mpg added approved Design and code approved - may be waiting for CI or backports and removed needs-backports Backports are missing or are pending review and approval. needs-review Every commit must be reviewed by at least two team members, labels Mar 17, 2025
@mpg mpg added this pull request to the merge queue Mar 17, 2025
Merged via the queue into Mbed-TLS:mbedtls-3.6 with commit b6ad19b Mar 17, 2025
6 checks passed
@github-project-automation github-project-automation bot moved this from Has Approval to Done in Roadmap pull requests (new board) Mar 17, 2025
Comment on lines +31 to +42
/* Change 0 to 1 for debugging of test cases that use this function. */
#if 0
const char *q, *basename;
/* Extract basename from file */
for (q = basename = file; *q != '\0'; q++) {
if (*q == '/' || *q == '\\') {
basename = q + 1;
}
}
printf("%s:%04d: |%d| %s",
basename, line, level, str);
#else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, that's very helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Design and code approved - may be waiting for CI or backports component-tls priority-high High priority - will be reviewed soon size-s Estimated task size: small (~2d)

Development

Successfully merging this pull request may close these issues.

3 participants