mirror of
https://github.com/Mbed-TLS/mbedtls-framework.git
synced 2026-06-06 05:25:18 +00:00
Generate handshake defragmentation test cases
The output is identical to the manually written tests in `tests/opt-testcases/handshake-manual.sh`, except that the script doesn't generate explanatory comments (they're in the generator script instead). Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
@@ -13,6 +13,137 @@ from typing import Optional
|
||||
|
||||
from mbedtls_framework import tls_test_case
|
||||
from mbedtls_framework import typing_util
|
||||
|
||||
from mbedtls_framework.tls_test_case import Side, Version
|
||||
|
||||
|
||||
# Assume that a TLS 1.2 ClientHello used in these tests will be at most
|
||||
# this many bytes long.
|
||||
TLS12_CLIENT_HELLO_ASSUMED_MAX_LENGTH = 255
|
||||
|
||||
# Minimum handshake fragment length that Mbed TLS supports.
|
||||
TLS_HANDSHAKE_FRAGMENT_MIN_LENGTH = 4
|
||||
|
||||
def write_tls_handshake_defragmentation_test(
|
||||
out: typing_util.Writable,
|
||||
side: Side,
|
||||
length: Optional[int],
|
||||
version: Optional[Version] = None
|
||||
) -> None:
|
||||
"""Generate one TLS handshake defragmentation test.
|
||||
|
||||
:param out: file to write to.
|
||||
:param side: which side is Mbed TLS.
|
||||
:param length: fragment length, or None to not fragment.
|
||||
:param version: protocol version, if forced.
|
||||
"""
|
||||
#pylint: disable=chained-comparison,too-many-branches,too-many-statements
|
||||
|
||||
our_args = ''
|
||||
their_args = ''
|
||||
|
||||
if length is None:
|
||||
description = 'no fragmentation, for reference'
|
||||
else:
|
||||
description = 'len=' + str(length)
|
||||
if version is not None:
|
||||
description += ', TLS 1.' + str(version.value)
|
||||
description = f'Handshake defragmentation on {side.name.lower()}: {description}'
|
||||
tc = tls_test_case.TestCase(description)
|
||||
|
||||
if version == Version.TLS12 and \
|
||||
length is not None and \
|
||||
length >= TLS_HANDSHAKE_FRAGMENT_MIN_LENGTH and \
|
||||
length < 16 and \
|
||||
side == side.CLIENT:
|
||||
# Skip test cases where the Finished message is fragmented in TLS 1.2.
|
||||
# This is currently buggy when the symmetric encryption used an
|
||||
# explicit IV (CBC, GCM or CCM; Chachapoly and null work, as does
|
||||
# TLS 1.3, because they use a purely implicit IV).
|
||||
tc.requirements.append('skip_next_test')
|
||||
|
||||
if version is not None:
|
||||
their_args += ' -tls1_' + str(version.value)
|
||||
# Emit a version requirement, because we're forcing the version via
|
||||
# OpenSSL, not via Mbed TLS, and the automatic depdendencies in
|
||||
# ssl-opt.sh only handle forcing the version via Mbed TLS.
|
||||
tc.requirements.append('requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_' +
|
||||
str(version.value))
|
||||
if side == Side.SERVER and version == Version.TLS12 and \
|
||||
length is not None and \
|
||||
length <= TLS12_CLIENT_HELLO_ASSUMED_MAX_LENGTH:
|
||||
# Server-side ClientHello defragmentation is only supported in
|
||||
# the TLS 1.3 message parser. When that parser sees an 1.2-only
|
||||
# ClientHello, it forwards the reassembled record to the
|
||||
# TLS 1.2 ClientHello parser so the ClientHello can be fragmented.
|
||||
# When TLS 1.3 support is disabled in the server (at compile-time
|
||||
# or at runtime), the TLS 1.2 ClientHello parser only sees
|
||||
# the first fragment of the ClientHello.
|
||||
tc.requirements.append('requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3')
|
||||
tc.description += ' TLS 1.3 ClientHello -> 1.2 Handshake'
|
||||
|
||||
# To guarantee that the handhake messages are large enough and need to be
|
||||
# split into fragments, the tests require certificate authentication.
|
||||
# The party in control of the fragmentation operations is OpenSSL and
|
||||
# will always use server5.crt (548 Bytes).
|
||||
if length is not None and \
|
||||
length >= TLS_HANDSHAKE_FRAGMENT_MIN_LENGTH:
|
||||
tc.requirements.append('requires_certificate_authentication')
|
||||
if version == Version.TLS12 and side == Side.CLIENT:
|
||||
#The server uses an ECDSA cert, so make sure we have a compatible key exchange
|
||||
tc.requirements.append(
|
||||
'requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED')
|
||||
|
||||
if length is None:
|
||||
forbidden_patterns = [
|
||||
'reassembled record',
|
||||
'waiting for more fragments',
|
||||
]
|
||||
wanted_patterns = []
|
||||
elif length < TLS_HANDSHAKE_FRAGMENT_MIN_LENGTH:
|
||||
their_args += ' -split_send_frag ' + str(length)
|
||||
tc.exit_code = 1
|
||||
forbidden_patterns = []
|
||||
wanted_patterns = [
|
||||
'handshake message too short: ' + str(length),
|
||||
'SSL - An invalid SSL record was received',
|
||||
]
|
||||
if side == Side.SERVER:
|
||||
wanted_patterns[0:0] = ['<= parse client hello']
|
||||
elif version == Version.TLS13:
|
||||
wanted_patterns[0:0] = ['=> ssl_tls13_process_server_hello']
|
||||
else:
|
||||
their_args += ' -split_send_frag ' + str(length)
|
||||
forbidden_patterns = []
|
||||
wanted_patterns = [
|
||||
'reassembled record',
|
||||
fr'handshake fragment: 0 \.\. {length} of [0-9]\+ msglen {length}',
|
||||
fr'waiting for more fragments ({length} of',
|
||||
]
|
||||
|
||||
if side == Side.CLIENT:
|
||||
tc.client = '$P_CLI debug_level=4' + our_args
|
||||
tc.server = '$O_NEXT_SRV' + their_args
|
||||
tc.wanted_client_patterns = wanted_patterns
|
||||
tc.forbidden_client_patterns = forbidden_patterns
|
||||
else:
|
||||
their_args += ' -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key'
|
||||
our_args += ' auth_mode=required'
|
||||
tc.client = '$O_NEXT_CLI' + their_args
|
||||
tc.server = '$P_SRV debug_level=4' + our_args
|
||||
tc.wanted_server_patterns = wanted_patterns
|
||||
tc.forbidden_server_patterns = forbidden_patterns
|
||||
tc.write(out)
|
||||
|
||||
def write_tls_handshake_defragmentation_tests(out: typing_util.Writable) -> None:
|
||||
"""Generate TLS handshake defragmentation tests."""
|
||||
for side in Side.CLIENT, Side.SERVER:
|
||||
write_tls_handshake_defragmentation_test(out, side, None)
|
||||
for length in [512, 513, 256, 128, 64, 36, 32, 16, 13, 5, 4, 3]:
|
||||
write_tls_handshake_defragmentation_test(out, side, length, Version.TLS13)
|
||||
write_tls_handshake_defragmentation_test(out, side, length, Version.TLS12)
|
||||
|
||||
|
||||
def write_handshake_tests(out: typing_util.Writable) -> None:
|
||||
"""Generate handshake tests."""
|
||||
out.write(f"""\
|
||||
@@ -24,6 +155,7 @@ def write_handshake_tests(out: typing_util.Writable) -> None:
|
||||
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
|
||||
""")
|
||||
write_tls_handshake_defragmentation_tests(out)
|
||||
out.write("""\
|
||||
# End of automatically generated file.
|
||||
""")
|
||||
|
||||
Reference in New Issue
Block a user