Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic handshake defragmentation tests in ssl-opt #9989

Conversation

minosgalanakis
Copy link
Contributor

@minosgalanakis minosgalanakis commented Feb 17, 2025

Description

Implements a portion of the testing needed for #9872. This pr extends #9928 and resolves #9887

PR checklist

Please remove the segment/s on either side of the | symbol as appropriate, and add any relevant link/s to the end of the line.
If the provided content is part of the present PR remove the # symbol.

@minosgalanakis minosgalanakis changed the base branch from development to features/tls-defragmentation/development February 17, 2025 14:59
Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

(Posting partial early review.)

@minosgalanakis minosgalanakis force-pushed the issue9887_add_basic_defragmentation_tests branch from 6e261a1 to aeba05a Compare February 18, 2025 20:59
@minosgalanakis minosgalanakis force-pushed the issue9887_add_basic_defragmentation_tests branch 2 times, most recently from 5bf1ff3 to 5c8cbb2 Compare February 20, 2025 09:44
@minosgalanakis minosgalanakis force-pushed the issue9887_add_basic_defragmentation_tests branch 5 times, most recently from aee03e9 to 765755a Compare February 23, 2025 23:43
@minosgalanakis
Copy link
Contributor Author

Quick update:

I have addressed all the comments, cleaned up the commit history to make it easier to review, and increased coverage.

I will be sharing a table with what is covered for design review purposes.

@mpg
Copy link
Contributor

mpg commented Feb 24, 2025

Thanks! Now that #9872 is merged, can you rebase on top of it?

Also, can you add a commit disabling (by prepending skip_next_test) the failings tests (TLS 1.2 with < 16 fragments) temporarily, just to make it easier to check that those are the only failures (ie, the CI should come back green with those disabled).

Once we've agreed on a solution to the underlying problem, we'll re-enable those tests in some form (probably just assert failure when using 1.2 and with fragment length < 16, but we can't do that right now, as the handshake succeeds with ChachaPoly).

waleed-elmelegy-arm and others added 13 commits February 24, 2025 09:16
Tests uses openssl s_server with a mix of max_send_frag
and split_send_frag options.

Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
* Add tests for the server side.
* Remove restriction for TLS 1.2 so that we can test TLS 1.2 & 1.3.
* Use latest version of openSSL to make sure -max_send_frag &
  -split_send_frag flags are supported.

Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
…entation tests

Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com>
…on tests.

Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
@minosgalanakis
Copy link
Contributor Author

To faciliate the reiview and design review purposes I have compiled a table for the coverage.

Client/Server Fragment Length TLS 1.2 TLS 1.3 Negative
Client No Fragmentation
Client 513
Client 513
Client 512
Client 512
Client 256
Client 256
Client 128
Client 128
Client 64
Client 64
Client 36
Client 36
Client 32
Client 32
Client 16
Client 16
Client 13
Client 13
Client 5
Client 5
Client 4
Client 4
Client 3
Client 3
Server No Fragmentation
Server 513
Server 513
Server 512
Server 512
Server 256
Server 256
Server 128
Server 128
Server 64
Server 64
Server 36
Server 36
Server 32
Server 32
Server 16
Server 16
Server 13
Server 13
Server 5
Server 5
Server 4
Server 4
Server 3
Server 3 (TLS 1.3 -> 1.2)
Server 32 (TLS 1.3 -> 1.2)

Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

LGTM. I have some minor feedback that can either be addressed here (while the 3.6 backport is being prepared) or left for a follow-up - no blocker so far IMO.

I'd still like to make another pass tomorrow before I formally approve, as the relatively high volume makes it hard to remain focused and easy to overlook things.


requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
requires_certificate_authentication
run_test "Handshake defragmentation on client: len=512, TLS 1.3" \
Copy link
Contributor

Choose a reason for hiding this comment

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

Thought: we have several very similar test where the only thing that changes in the fragment size, and it have to be changed in multiple places (message, OpenSSL command line, asserts). I wonder if we should use a helper function for those tests.

(We could have a function for server-side taking as argument the TLS version (and adjusting requires_xxx based on it) and the fragment size, and another for client-side.)

Not requesting any change here, if think a function would help we can do it in a follow-up.

Copy link
Contributor

Choose a reason for hiding this comment

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

Generally speaking, I'm in favor of less repetitive code. Having nearly-identical blocks of ~10 lines has a high risk of mistakes and can obscure the forest for the trees.

Regarding the method, I'm not so keen on a shell function, but not fundamentally opposed. They have several pitfalls:

  • The shell is limited as a programming language, and not very well known.
  • It's harder to locate and figure out test cases that are generated on the fly.
  • The function must not depend on the library configuration or the environment — it must always emit the same test cases as ssl-opt.sh --list-test-cases. For example, it must make requires_xxx calls and a final call to run_test, never return early.

There's another possible approach, which is to generate test cases from a Python script, with an intermediate file containing the individual test cases. It's a bit heavier weight to get going, but then has fewer pitfalls.

In terms of existing infrastructure, we currently have a few functions (run_test_psa, run_test_memory_after_handshake and their variants) and one Python script generate_tls13_compat_tests.py.

tests/ssl-opt.sh Outdated
-c "handshake fragment: 0 \\.\\. 512 of [0-9]\\+ msglen 512" \
-c "waiting for more fragments (512 of [0-9]\\+"

# Since the removal of the DHE-RSA key exchange, the default openssl server
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the comment is confusing outside the context where you first wrote it. I'd suggest a simpler and less context-specific explanation: "The server uses an ECDSA cert, so make sure we have a compatible key exchange".

(Can also wait for a follow-up.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Not just confusing, but the comment would be wrong in the 3.6 backport, whereas the ECDSA requirement is needed there as well. So I think we should fix the comment here at the same time we make the 3.6 backport.

tests/ssl-opt.sh Outdated
-s "handshake fragment: 0 \\.\\. 128 of [0-9]\\+ msglen 128" \
-s "waiting for more fragments (128"

# Server-side ClientHello degfragmentation is only supported for MBEDTLS_SSL_PROTO_TLS1_3. For TLS 1.2 testing
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: deGfragmentation

tests/ssl-opt.sh Outdated
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
requires_certificate_authentication
run_test "Handshake defragmentation on server: len=3, TLS 1.3 Client-Hallo -> 1.2 Handhsake" \
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: s/Hallo/Hello/ - also no dash: ClientHello. (Multiple occurrences.)

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've reviewed only for correctness, not for completeness, since we don't have a clear coverage objective here.

I'd like to fix the copypasta and the comment that would be wrong in 3.6. The rest can wait until follow-ups.

@@ -3,3 +3,10 @@ Bugfix
by the spec. Lack of support was causing handshake failures with some
servers, especially with TLS 1.3 in practice (though both protocol
version could be affected in principle, and both are fixed now).
The initial fragment for each handshake message must be at least 4 bytes.

Server-side, defragmentation of the ClientHello message is only
Copy link
Contributor

Choose a reason for hiding this comment

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

For a follow-up: I think we should document the limitations of defragmentation in the versioned, rendered documentation — so presumably in a Doxygen comment in ssl.h. Especially if this evolves over time, users and maintainers shouldn't have to puzzle out the result from a series of changelog entries. And we then don't need to list all the limitations in the changelog entry.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point. Generally speaking, we (and I'm as guilty of it as anyone) tend to put too much information in the ChangeLog that should really be in the documentation.

In this case though, I'm not entirely sure where this would fit in ssl.h. In the documentation of ssl_handshake()?

Ideally, I think in addition to doxygen comments, we should have a (versioned) summary document for what's implemented or not or partially for TLS 1.2, DTLS and for X.509. I think we have something like this for TLS 1.3 (docs/architecture/tls13-support.md). For TLS 1.2 I thought there was something (as list of implemented RFCs, probably outdated) in the old Knowledge Base but I can't find it any more.

tests/ssl-opt.sh Outdated
-c "handshake fragment: 0 \\.\\. 512 of [0-9]\\+ msglen 512" \
-c "waiting for more fragments (512 of [0-9]\\+"

# Since the removal of the DHE-RSA key exchange, the default openssl server
Copy link
Contributor

Choose a reason for hiding this comment

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

Not just confusing, but the comment would be wrong in the 3.6 backport, whereas the ECDSA requirement is needed there as well. So I think we should fix the comment here at the same time we make the 3.6 backport.

-c "waiting for more fragments (512 of [0-9]\\+"

requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
requires_certificate_authentication
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is there no ECDSA requirement in TLS 1.3? I guess because we never run ssl-opt.sh in a configuration with TLS 1.3 and ECDH and RSA but not ECDSA?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because since #9917 the supported openssl ciphers for TLS.1.2 and what our server provides, do not have any cipher in common when ECDSA is removed.

With TLS1.3 there are plenty of alternatives

Copy link
Contributor

Choose a reason for hiding this comment

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

Surely we have RSA-ECDHE cipher suites in common? You can configure the library with ECDH but not ECDSA. Maybe we don't run TLS tests in such a configuration from all.sh, but it is possible.

Copy link
Contributor

Choose a reason for hiding this comment

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

Surely we have RSA-ECDHE cipher suites in common?

Yes but not when the server only has an ECC cert.

I think the reason we don't need to add an ECDSA requirement for 1.3 is that there the autodetection logic works: it sees one party using server5 and requires ECDSA.

I also think the reason the autodetection does not work for 1.2 is that there things are more complex: if both peers are Mbed TLS, then ECC cert doesn't necessarily mean ECDHE-ECDSA key exchange, a static ECDH key exchange could be used as well so we require any key exchange that can use an ECC cert.

Except OpenSSL doesn't allow static ECDH by default (or even doesn't support it at all, didn't check recently). So the autodetection logic should notice that on of the peers doesn't support static ECDH, and require ECDHE-ECDSA, but apparently it doesn't, so we find ourselves adding the requirement manually. (Or perhaps it's the part that detects the version that's broken?)

I've not actually tested whether this reasoning is correct, but that's what I'm thinking so far based on reading the code. Anyway, from CI failures in past version of this PR, it would appear that the autodetection logic is working for the TLS 1.3 test cases but not for the 1.2 test cases in this series, whatever the reason.

tests/ssl-opt.sh Outdated
Comment on lines 14404 to 14408
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
requires_certificate_authentication
run_test "Handshake defragmentation on server: len=32, TLS 1.3 Client-Hallo -> 1.2 Handhsake" \
"$P_SRV debug_level=4 force_version=tls12 auth_mode=required" \
Copy link
Contributor

Choose a reason for hiding this comment

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

Copypasta: this is testing a 1.2 ClientHello with the 1.2 parser.

Suggested change
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
requires_certificate_authentication
run_test "Handshake defragmentation on server: len=32, TLS 1.3 Client-Hallo -> 1.2 Handhsake" \
"$P_SRV debug_level=4 force_version=tls12 auth_mode=required" \
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
requires_certificate_authentication
run_test "Handshake defragmentation on server: len=32, TLS 1.2 ClientHello" \
"$P_SRV debug_level=4 force_version=tls12 auth_mode=required" \

1 \
-s "The SSL configuration is tls12 only" \
-s "bad client hello message" \
-s "SSL - A message could not be parsed due to a syntactic error"
Copy link
Contributor

Choose a reason for hiding this comment

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

Can wait for a follow-up: We should check "ClientHello fragmentation not supported" in the log.

@gilles-peskine-arm gilles-peskine-arm added needs-work needs-backports Backports are missing or are pending review and approval. component-tls size-s Estimated task size: small (~2d) priority-high High priority - will be reviewed soon labels Feb 27, 2025
Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
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.

There's still one spurious dependency on requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3: #9989 (comment) . Other than that LGTM

tests/ssl-opt.sh Outdated

requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
requires_certificate_authentication
requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
Copy link
Contributor

Choose a reason for hiding this comment

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

I had missed this spurious dependency, good call for removing it from the backport: the negative test for handshake too small doesn't require ECDSA support. In fact it doesn't need certificate authentication at all. We can fix this later.

Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
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

@gilles-peskine-arm gilles-peskine-arm added needs-review Every commit must be reviewed by at least two team members, and removed needs-work labels Feb 27, 2025
@minosgalanakis
Copy link
Contributor Author

One test failedin all_u16-test_tls13_only_psk, because I removed the certifcate requirement for the negative testing. Re-introduced that and should be green.

Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@@ -14220,12 +14217,12 @@ run_test "Handshake defragmentation on server: len=128, TLS 1.3" \
-s "handshake fragment: 0 \\.\\. 128 of [0-9]\\+ msglen 128" \
-s "waiting for more fragments (128"

# Server-side ClientHello degfragmentation is only supported for MBEDTLS_SSL_PROTO_TLS1_3. For TLS 1.2 testing
# Server-side ClientHello defragmentationis only supported for MBEDTLS_SSL_PROTO_TLS1_3. For TLS 1.2 testing
Copy link
Contributor

@mpg mpg Feb 28, 2025

Choose a reason for hiding this comment

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

Introducing a typo: missing space defragmentationis (no need to fix if there's nothing else).

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.

We'll need to have some tests around fragmentation that run with PSK, but ok for now.

@gilles-peskine-arm gilles-peskine-arm merged commit 6eabe58 into Mbed-TLS:features/tls-defragmentation/development Feb 28, 2025
6 checks passed
@gilles-peskine-arm gilles-peskine-arm mentioned this pull request Mar 5, 2025
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component-tls needs-backports Backports are missing or are pending review and approval. needs-review Every commit must be reviewed by at least two team members, 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.

Basic ssl-opt testing for TLS HS defragmentation
5 participants