Merge pull request #10039 from bjwtaylor/remove-rng-from-ssl
Remove RNG parameters from public SSL APIs
diff --git a/ChangeLog.d/fix-msvc-version-guard-format-zu.txt b/ChangeLog.d/fix-msvc-version-guard-format-zu.txt
new file mode 100644
index 0000000..eefda61
--- /dev/null
+++ b/ChangeLog.d/fix-msvc-version-guard-format-zu.txt
@@ -0,0 +1,5 @@
+Bugfix
+ * Fix definition of MBEDTLS_PRINTF_SIZET to prevent runtime crashes that
+ occurred whenever SSL debugging was enabled on a copy of Mbed TLS built
+ with Visual Studio 2013 or MinGW.
+ Fixes #10017.
diff --git a/ChangeLog.d/tls-hs-defrag-in.txt b/ChangeLog.d/tls-hs-defrag-in.txt
new file mode 100644
index 0000000..6bab02a
--- /dev/null
+++ b/ChangeLog.d/tls-hs-defrag-in.txt
@@ -0,0 +1,7 @@
+Bugfix
+ * Support re-assembly of fragmented handshake messages in TLS (both
+ 1.2 and 1.3). The lack of support was causing handshake failures with
+ some servers, especially with TLS 1.3 in practice. There are a few
+ limitations, notably a fragmented ClientHello is only supported when
+ TLS 1.3 support is enabled. See the documentation of
+ mbedtls_ssl_handshake() for details.
diff --git a/README.md b/README.md
index b00d21a..448f372 100644
--- a/README.md
+++ b/README.md
@@ -299,7 +299,7 @@
Mbed TLS supports drivers for cryptographic accelerators, secure elements and random generators. This is work in progress. Please note that the driver interfaces are not fully stable yet and may change without notice. We intend to preserve backward compatibility for application code (using the PSA Crypto API), but the code of the drivers may have to change in future minor releases of Mbed TLS.
-Please see the [PSA driver example and guide](docs/psa-driver-example-and-guide.md) for information on writing a driver.
+Please see the [PSA driver example and guide](https://github.com/Mbed-TLS/TF-PSA-Crypto/blob/development/docs/psa-driver-example-and-guide.md) for information on writing a driver.
License
-------
diff --git a/docs/3.0-migration-guide.md b/docs/3.0-migration-guide.md
index 42af9db..e927667 100644
--- a/docs/3.0-migration-guide.md
+++ b/docs/3.0-migration-guide.md
@@ -71,7 +71,7 @@
If no accessor function exists, please open an [enhancement request against Mbed TLS](https://github.com/Mbed-TLS/mbedtls/issues/new?template=feature_request.md) and describe your use case. The Mbed TLS development team is aware that some useful accessor functions are missing in the 3.0 release, and we expect to add them to the first minor release(s) (3.1, etc.).
-As a last resort, you can access the field `foo` of a structure `bar` by writing `bar.MBEDTLS_PRIVATE(foo)`. Note that you do so at your own risk, since such code is likely to break in a future minor version of Mbed TLS.
+As a last resort, you can access the field `foo` of a structure `bar` by writing `bar.MBEDTLS_PRIVATE(foo)`. Note that you do so at your own risk, since such code is likely to break in a future minor version of Mbed TLS. In the Mbed TLS 3.6 LTS this will tend to be safer than in a normal minor release because LTS versions try to maintain ABI stability.
### Move part of timing module out of the library
@@ -349,7 +349,7 @@
| `mbedtls_sha512_finish_ret` | `mbedtls_sha512_finish` |
| `mbedtls_sha512_ret` | `mbedtls_sha512` |
-To migrate to the this change the user can keep the `*_ret` names in their code
+To migrate to this change the user can keep the `*_ret` names in their code
and include the `compat_2.x.h` header file which holds macros with proper
renaming or to rename those functions in their code according to the list from
mentioned header file.
@@ -409,7 +409,7 @@
Previously, the documentation didn't state explicitly if it was OK to call
`mbedtls_cipher_check_tag()` or `mbedtls_cipher_write_tag()` directly after
the last call to `mbedtls_cipher_update()` — that is, without calling
-`mbedtls_cipher_finish()` in-between. If you code was missing that call,
+`mbedtls_cipher_finish()` in-between. If your code was missing that call,
please add it and be prepared to get as much as 15 bytes of output.
Currently the output is always 0 bytes, but it may be more when alternative
@@ -422,7 +422,7 @@
They are already niche or obsolete and most of them are weak or broken. For
those reasons possible users should consider switching to modern and safe
-alternatives to be found in literature.
+alternatives to be found in the literature.
### Deprecated functions were removed from cipher
@@ -806,11 +806,11 @@
In Mbed TLS 2.x, users would observe later calls overwriting
the effect of earlier calls, with the prevailing PSK being
the one that has been configured last. In Mbed TLS 3.0,
-calling `mbedtls_ssl_conf_[opaque_]psk()` multiple times
+calling `mbedtls_ssl_conf_psk[_opaque]()` multiple times
will return an error, leaving the first PSK intact.
To achieve equivalent functionality when migrating to Mbed TLS 3.0,
-users calling `mbedtls_ssl_conf_[opaque_]psk()` multiple times should
+users calling `mbedtls_ssl_conf_psk[_opaque]()` multiple times should
remove all but the last call, so that only one call to _either_
`mbedtls_ssl_conf_psk()` _or_ `mbedtls_ssl_conf_psk_opaque()`
remains.
diff --git a/framework b/framework
index 523a12d..cab0c5f 160000
--- a/framework
+++ b/framework
@@ -1 +1 @@
-Subproject commit 523a12d05b91301b020e2aa560d9774135e3a801
+Subproject commit cab0c5fe19d5747cb9603552b80ebe64b9c67fdd
diff --git a/include/mbedtls/debug.h b/include/mbedtls/debug.h
index 424ed4b..e6f5dad 100644
--- a/include/mbedtls/debug.h
+++ b/include/mbedtls/debug.h
@@ -108,16 +108,16 @@
*
* This module provides debugging functions.
*/
-#if (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800)
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900)
#include <inttypes.h>
#define MBEDTLS_PRINTF_SIZET PRIuPTR
#define MBEDTLS_PRINTF_LONGLONG "I64d"
#else \
- /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */
+ /* defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900) */
#define MBEDTLS_PRINTF_SIZET "zu"
#define MBEDTLS_PRINTF_LONGLONG "lld"
#endif \
- /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */
+ /* defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900) */
#if !defined(MBEDTLS_PRINTF_MS_TIME)
#include <inttypes.h>
diff --git a/include/mbedtls/net_sockets.h b/include/mbedtls/net_sockets.h
index 85c1197..8e69bc0 100644
--- a/include/mbedtls/net_sockets.h
+++ b/include/mbedtls/net_sockets.h
@@ -229,7 +229,7 @@
/**
* \brief Write at most 'len' characters. If no error occurs,
- * the actual amount read is returned.
+ * the actual amount written is returned.
*
* \param ctx Socket
* \param buf The buffer to read from
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 958ee9b..681584b 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1782,6 +1782,8 @@
size_t MBEDTLS_PRIVATE(in_hslen); /*!< current handshake message length,
including the handshake header */
+ size_t MBEDTLS_PRIVATE(in_hsfraglen); /*!< accumulated length of hs fragments
+ (up to in_hslen) */
int MBEDTLS_PRIVATE(nb_zero); /*!< # of 0-length encrypted messages */
int MBEDTLS_PRIVATE(keep_current_message); /*!< drop or reuse current message
@@ -4302,6 +4304,10 @@
* with \c mbedtls_ssl_read()), not handshake messages.
* With DTLS, this affects both ApplicationData and handshake.
*
+ * \note Defragmentation of TLS handshake messages is supported
+ * with some limitations. See the documentation of
+ * mbedtls_ssl_handshake() for details.
+ *
* \note This sets the maximum length for a record's payload,
* excluding record overhead that will be added to it, see
* \c mbedtls_ssl_get_record_expansion().
@@ -4791,6 +4797,24 @@
* currently being processed might or might not contain further
* DTLS records.
*
+ * \note In TLS, reception of fragmented handshake messages is
+ * supported with some limitations (those limitations do
+ * not apply to DTLS, where defragmentation is fully
+ * supported):
+ * - On an Mbed TLS server that only accepts TLS 1.2,
+ * the initial ClientHello message must not be fragmented.
+ * A TLS 1.2 ClientHello may be fragmented if the server
+ * also accepts TLS 1.3 connections (meaning
+ * that #MBEDTLS_SSL_PROTO_TLS1_3 enabled, and the
+ * accepted versions have not been restricted with
+ * mbedtls_ssl_conf_max_tls_version() or the like).
+ * - The first fragment of a handshake message must be
+ * at least 4 bytes long.
+ * - Non-handshake records must not be interleaved between
+ * the fragments of a handshake message. (This is permitted
+ * in TLS 1.2 but not in TLS 1.3, but Mbed TLS rejects it
+ * even in TLS 1.2.)
+ *
* \note The PSA crypto subsystem must have been initialized by
* calling psa_crypto_init() before calling this function.
*/
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 9ff0fca..164a230 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -1752,10 +1752,11 @@
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl);
-void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl);
+void mbedtls_ssl_reset_in_pointers(mbedtls_ssl_context *ssl);
+void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl);
+void mbedtls_ssl_reset_out_pointers(mbedtls_ssl_context *ssl);
void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl,
mbedtls_ssl_transform *transform);
-void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial);
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 97c4866..f5ea8dd 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -2962,19 +2962,34 @@
int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
{
- if (ssl->in_msglen < mbedtls_ssl_hs_hdr_len(ssl)) {
- MBEDTLS_SSL_DEBUG_MSG(1, ("handshake message too short: %" MBEDTLS_PRINTF_SIZET,
- ssl->in_msglen));
- return MBEDTLS_ERR_SSL_INVALID_RECORD;
- }
+ if (ssl->in_hsfraglen == 0) {
+ /* The handshake message must at least include the header.
+ * We may not have the full message yet in case of fragmentation.
+ * To simplify the code, we insist on having the header (and in
+ * particular the handshake message length) in the first
+ * fragment. */
+ if (ssl->in_msglen < mbedtls_ssl_hs_hdr_len(ssl)) {
+ MBEDTLS_SSL_DEBUG_MSG(1, ("handshake message too short: %" MBEDTLS_PRINTF_SIZET,
+ ssl->in_msglen));
+ return MBEDTLS_ERR_SSL_INVALID_RECORD;
+ }
- ssl->in_hslen = mbedtls_ssl_hs_hdr_len(ssl) + ssl_get_hs_total_len(ssl);
+ ssl->in_hslen = mbedtls_ssl_hs_hdr_len(ssl) + ssl_get_hs_total_len(ssl);
+ }
MBEDTLS_SSL_DEBUG_MSG(3, ("handshake message: msglen ="
" %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %"
MBEDTLS_PRINTF_SIZET,
ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen));
+ if (ssl->transform_in != NULL) {
+ MBEDTLS_SSL_DEBUG_MSG(4, ("decrypted handshake message:"
+ " iv-buf=%d hdr-buf=%d hdr-buf=%d",
+ (int) (ssl->in_iv - ssl->in_buf),
+ (int) (ssl->in_hdr - ssl->in_buf),
+ (int) (ssl->in_msg - ssl->in_buf)));
+ }
+
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3034,10 +3049,105 @@
}
} else
#endif /* MBEDTLS_SSL_PROTO_DTLS */
- /* With TLS we don't handle fragmentation (for now) */
- if (ssl->in_msglen < ssl->in_hslen) {
- MBEDTLS_SSL_DEBUG_MSG(1, ("TLS handshake fragmentation not supported"));
- return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ {
+ unsigned char *const reassembled_record_start =
+ ssl->in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+ unsigned char *const payload_start =
+ reassembled_record_start + mbedtls_ssl_in_hdr_len(ssl);
+ unsigned char *payload_end = payload_start + ssl->in_hsfraglen;
+ /* How many more bytes we want to have a complete handshake message. */
+ const size_t hs_remain = ssl->in_hslen - ssl->in_hsfraglen;
+ /* How many bytes of the current record are part of the first
+ * handshake message. There may be more handshake messages (possibly
+ * incomplete) in the same record; if so, we leave them after the
+ * current record, and ssl_consume_current_message() will take
+ * care of consuming the next handshake message. */
+ const size_t hs_this_fragment_len =
+ ssl->in_msglen > hs_remain ? hs_remain : ssl->in_msglen;
+ (void) hs_this_fragment_len;
+
+ MBEDTLS_SSL_DEBUG_MSG(3,
+ ("%s handshake fragment: %" MBEDTLS_PRINTF_SIZET
+ ", %" MBEDTLS_PRINTF_SIZET
+ "..%" MBEDTLS_PRINTF_SIZET
+ " of %" MBEDTLS_PRINTF_SIZET,
+ (ssl->in_hsfraglen != 0 ?
+ "subsequent" :
+ hs_this_fragment_len == ssl->in_hslen ?
+ "sole" :
+ "initial"),
+ ssl->in_msglen,
+ ssl->in_hsfraglen,
+ ssl->in_hsfraglen + hs_this_fragment_len,
+ ssl->in_hslen));
+
+ /* Move the received handshake fragment to have the whole message
+ * (at least the part received so far) in a single segment at a
+ * known offset in the input buffer.
+ * - When receiving a non-initial handshake fragment, append it to
+ * the initial segment.
+ * - Even the initial handshake fragment is moved, if it was
+ * encrypted with an explicit IV: decryption leaves the payload
+ * after the explicit IV, but here we move it to start where the
+ * IV was.
+ */
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+ size_t const in_buf_len = ssl->in_buf_len;
+#else
+ size_t const in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
+#endif
+ if (payload_end + ssl->in_msglen > ssl->in_buf + in_buf_len) {
+ MBEDTLS_SSL_DEBUG_MSG(1,
+ ("Shouldn't happen: no room to move handshake fragment %"
+ MBEDTLS_PRINTF_SIZET " from %p to %p (buf=%p len=%"
+ MBEDTLS_PRINTF_SIZET ")",
+ ssl->in_msglen,
+ (void *) ssl->in_msg, (void *) payload_end,
+ (void *) ssl->in_buf, in_buf_len));
+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ }
+ memmove(payload_end, ssl->in_msg, ssl->in_msglen);
+
+ ssl->in_hsfraglen += ssl->in_msglen;
+ payload_end += ssl->in_msglen;
+
+ if (ssl->in_hsfraglen < ssl->in_hslen) {
+ MBEDTLS_SSL_DEBUG_MSG(3, ("Prepare: waiting for more handshake fragments %"
+ MBEDTLS_PRINTF_SIZET "/%"
+ MBEDTLS_PRINTF_SIZET,
+ ssl->in_hsfraglen, ssl->in_hslen));
+ ssl->in_hdr = payload_end;
+ ssl->in_msglen = 0;
+ mbedtls_ssl_update_in_pointers(ssl);
+ return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+ } else {
+ ssl->in_msglen = ssl->in_hsfraglen;
+ ssl->in_hsfraglen = 0;
+ ssl->in_hdr = reassembled_record_start;
+ mbedtls_ssl_update_in_pointers(ssl);
+
+ /* Update the record length in the fully reassembled record */
+ if (ssl->in_msglen > 0xffff) {
+ MBEDTLS_SSL_DEBUG_MSG(1,
+ ("Shouldn't happen: in_msglen=%"
+ MBEDTLS_PRINTF_SIZET " > 0xffff",
+ ssl->in_msglen));
+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ }
+ MBEDTLS_PUT_UINT16_BE(ssl->in_msglen, ssl->in_len, 0);
+
+ size_t record_len = mbedtls_ssl_in_hdr_len(ssl) + ssl->in_msglen;
+ (void) record_len;
+ MBEDTLS_SSL_DEBUG_BUF(4, "reassembled record",
+ ssl->in_hdr, record_len);
+ if (ssl->in_hslen < ssl->in_msglen) {
+ MBEDTLS_SSL_DEBUG_MSG(3,
+ ("More handshake messages in the record: "
+ "%" MBEDTLS_PRINTF_SIZET " + %" MBEDTLS_PRINTF_SIZET,
+ ssl->in_hslen,
+ ssl->in_msglen - ssl->in_hslen));
+ }
+ }
}
return 0;
@@ -4382,6 +4492,14 @@
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
+ if (ssl->in_hsfraglen != 0) {
+ /* Not all handshake fragments have arrived, do not consume. */
+ MBEDTLS_SSL_DEBUG_MSG(3, ("Consume: waiting for more handshake fragments %"
+ MBEDTLS_PRINTF_SIZET "/%" MBEDTLS_PRINTF_SIZET,
+ ssl->in_hsfraglen, ssl->in_hslen));
+ return 0;
+ }
+
/*
* Get next Handshake message in the current record
*/
@@ -4407,6 +4525,7 @@
ssl->in_msglen -= ssl->in_hslen;
memmove(ssl->in_msg, ssl->in_msg + ssl->in_hslen,
ssl->in_msglen);
+ MBEDTLS_PUT_UINT16_BE(ssl->in_msglen, ssl->in_len, 0);
MBEDTLS_SSL_DEBUG_BUF(4, "remaining content in record",
ssl->in_msg, ssl->in_msglen);
@@ -4770,6 +4889,18 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ /* If we're in the middle of a fragmented TLS handshake message,
+ * we don't accept any other message type. For TLS 1.3, the spec forbids
+ * interleaving other message types between handshake fragments. For TLS
+ * 1.2, the spec does not forbid it but we do. */
+ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM &&
+ ssl->in_hsfraglen != 0 &&
+ 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;
+ }
+
/*
* Handle particular types of records
*/
@@ -5081,7 +5212,7 @@
} else
#endif
{
- ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+ ssl->in_ctr = ssl->in_buf;
ssl->in_len = ssl->in_hdr + 3;
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
ssl->in_cid = ssl->in_len;
@@ -5097,24 +5228,35 @@
* Setup an SSL context
*/
-void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl)
+void mbedtls_ssl_reset_in_pointers(mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+ ssl->in_hdr = ssl->in_buf;
+ } else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ ssl->in_hdr = ssl->in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+ }
+
+ /* Derive other internal pointers. */
+ mbedtls_ssl_update_in_pointers(ssl);
+}
+
+void mbedtls_ssl_reset_out_pointers(mbedtls_ssl_context *ssl)
{
/* Set the incoming and outgoing record pointers. */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
ssl->out_hdr = ssl->out_buf;
- ssl->in_hdr = ssl->in_buf;
} else
#endif /* MBEDTLS_SSL_PROTO_DTLS */
{
ssl->out_ctr = ssl->out_buf;
- ssl->out_hdr = ssl->out_buf + 8;
- ssl->in_hdr = ssl->in_buf + 8;
+ ssl->out_hdr = ssl->out_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
}
-
/* Derive other internal pointers. */
mbedtls_ssl_update_out_pointers(ssl, NULL /* no transform enabled */);
- mbedtls_ssl_update_in_pointers(ssl);
}
/*
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index ec4272a..3572f3f 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -339,12 +339,13 @@
size_t out_buf_new_len)
{
int modified = 0;
- size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0;
+ size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0, hdr_in = 0;
size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0;
if (ssl->in_buf != NULL) {
written_in = ssl->in_msg - ssl->in_buf;
iv_offset_in = ssl->in_iv - ssl->in_buf;
len_offset_in = ssl->in_len - ssl->in_buf;
+ hdr_in = ssl->in_hdr - ssl->in_buf;
if (downsizing ?
ssl->in_buf_len > in_buf_new_len && ssl->in_left < in_buf_new_len :
ssl->in_buf_len < in_buf_new_len) {
@@ -376,7 +377,10 @@
}
if (modified) {
/* Update pointers here to avoid doing it twice. */
- mbedtls_ssl_reset_in_out_pointers(ssl);
+ ssl->in_hdr = ssl->in_buf + hdr_in;
+ mbedtls_ssl_update_in_pointers(ssl);
+ mbedtls_ssl_reset_out_pointers(ssl);
+
/* Fields below might not be properly updated with record
* splitting or with CID, so they are manually updated here. */
ssl->out_msg = ssl->out_buf + written_out;
@@ -1274,7 +1278,8 @@
goto error;
}
- mbedtls_ssl_reset_in_out_pointers(ssl);
+ mbedtls_ssl_reset_in_pointers(ssl);
+ mbedtls_ssl_reset_out_pointers(ssl);
#if defined(MBEDTLS_SSL_DTLS_SRTP)
memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info));
@@ -1339,7 +1344,8 @@
/* Cancel any possibly running timer */
mbedtls_ssl_set_timer(ssl, 0);
- mbedtls_ssl_reset_in_out_pointers(ssl);
+ mbedtls_ssl_reset_in_pointers(ssl);
+ mbedtls_ssl_reset_out_pointers(ssl);
/* Reset incoming message parsing */
ssl->in_offt = NULL;
@@ -1347,6 +1353,7 @@
ssl->in_msgtype = 0;
ssl->in_msglen = 0;
ssl->in_hslen = 0;
+ ssl->in_hsfraglen = 0;
ssl->keep_current_message = 0;
ssl->transform_in = NULL;
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index fc9b860..a302af4 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -1015,28 +1015,6 @@
MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
}
- {
- size_t handshake_len = MBEDTLS_GET_UINT24_BE(buf, 1);
- MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake len.: %u",
- (unsigned) handshake_len));
-
- /* The record layer has a record size limit of 2^14 - 1 and
- * fragmentation is not supported, so buf[1] should be zero. */
- if (buf[1] != 0) {
- MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != 0",
- (unsigned) buf[1]));
- return MBEDTLS_ERR_SSL_DECODE_ERROR;
- }
-
- /* We don't support fragmentation of ClientHello (yet?) */
- if (msg_len != mbedtls_ssl_hs_hdr_len(ssl) + handshake_len) {
- MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != %u + %u",
- (unsigned) msg_len,
- (unsigned) mbedtls_ssl_hs_hdr_len(ssl),
- (unsigned) handshake_len));
- return MBEDTLS_ERR_SSL_DECODE_ERROR;
- }
- }
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 7273eb9..1dde4ab 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -91,7 +91,7 @@
return;
}
- MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%lx",
+ MBEDTLS_SSL_DEBUG_MSG(1, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%lx",
(unsigned) psk_ciphersuite_id,
(unsigned long) psk_hash_alg));
}
@@ -1365,6 +1365,7 @@
}
if (ret == 0) {
+ MBEDTLS_SSL_DEBUG_MSG(2, ("no supported_versions extension"));
return SSL_CLIENT_HELLO_TLS1_2;
}
@@ -1386,6 +1387,7 @@
* the TLS version to negotiate.
*/
if (MBEDTLS_SSL_VERSION_TLS1_2 == ret) {
+ MBEDTLS_SSL_DEBUG_MSG(2, ("supported_versions without 1.3"));
return SSL_CLIENT_HELLO_TLS1_2;
}
}
@@ -1964,6 +1966,7 @@
}
ssl->keep_current_message = 1;
ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+ MBEDTLS_SSL_DEBUG_MSG(1, ("non-1.3 ClientHello left for later processing"));
return 0;
}
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 6742925..d5c2a63 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -75,6 +75,7 @@
#define DFL_RECO_SERVER_NAME NULL
#define DFL_RECO_DELAY 0
#define DFL_RECO_MODE 1
+#define DFL_RENEGO_DELAY -2
#define DFL_CID_ENABLED 0
#define DFL_CID_VALUE ""
#define DFL_CID_ENABLED_RENEGO -1
@@ -298,7 +299,8 @@
#if defined(MBEDTLS_SSL_RENEGOTIATION)
#define USAGE_RENEGO \
" renegotiation=%%d default: 0 (disabled)\n" \
- " renegotiate=%%d default: 0 (disabled)\n"
+ " renegotiate=%%d default: 0 (disabled)\n" \
+ " renego_delay=%%d default: -2 (library default)\n"
#else
#define USAGE_RENEGO ""
#endif
@@ -938,6 +940,7 @@
opt.renegotiation = DFL_RENEGOTIATION;
opt.allow_legacy = DFL_ALLOW_LEGACY;
opt.renegotiate = DFL_RENEGOTIATE;
+ opt.renego_delay = DFL_RENEGO_DELAY;
opt.exchanges = DFL_EXCHANGES;
opt.min_version = DFL_MIN_VERSION;
opt.max_version = DFL_MAX_VERSION;
@@ -1172,6 +1175,8 @@
break;
default: goto usage;
}
+ } else if (strcmp(p, "renego_delay") == 0) {
+ opt.renego_delay = (atoi(q));
} else if (strcmp(p, "renegotiate") == 0) {
opt.renegotiate = atoi(q);
if (opt.renegotiate < 0 || opt.renegotiate > 1) {
@@ -1923,6 +1928,9 @@
}
#if defined(MBEDTLS_SSL_RENEGOTIATION)
mbedtls_ssl_conf_renegotiation(&conf, opt.renegotiation);
+ if (opt.renego_delay != DFL_RENEGO_DELAY) {
+ mbedtls_ssl_conf_renegotiation_enforced(&conf, opt.renego_delay);
+ }
#endif
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
@@ -2467,6 +2475,8 @@
}
mbedtls_printf(" ok\n");
}
+
+
#endif /* MBEDTLS_SSL_RENEGOTIATION */
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h
index 6fc3d73..bc5cce5 100644
--- a/programs/ssl/ssl_test_lib.h
+++ b/programs/ssl/ssl_test_lib.h
@@ -243,8 +243,8 @@
* - free the provided PK context and re-initilize it as an opaque PK context
* wrapping the PSA key imported in the above step.
*
- * \param[in/out] pk On input the non-opaque PK context which contains the
- * key to be wrapped. On output the re-initialized PK
+ * \param[in,out] pk On input, the non-opaque PK context which contains the
+ * key to be wrapped. On output, the re-initialized PK
* context which represents the opaque version of the one
* provided as input.
* \param[in] psa_alg The primary algorithm that will be associated to the
diff --git a/scripts/make_generated_files.bat b/scripts/make_generated_files.bat
index 4982f77..bef198f 100644
--- a/scripts/make_generated_files.bat
+++ b/scripts/make_generated_files.bat
@@ -32,4 +32,5 @@
python framework\scripts\generate_test_keys.py --output framework\tests\include\test\test_keys.h || exit /b 1
python tf-psa-crypto\framework\scripts\generate_test_keys.py --output tf-psa-crypto\framework\tests\include\test\test_keys.h || exit /b 1
python framework\scripts\generate_test_cert_macros.py --output tests\src\test_certs.h || exit /b 1
+python framework\scripts\generate_tls_handshake_tests.py || exit /b 1
python framework\scripts\generate_tls13_compat_tests.py || exit /b 1
diff --git a/tests/.gitignore b/tests/.gitignore
index 997101c..a4a0309 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -18,6 +18,7 @@
###START_GENERATED_FILES###
# Generated source files
+/opt-testcases/handshake-generated.sh
/opt-testcases/tls13-compat.sh
/suites/*.generated.data
/suites/test_suite_config.mbedtls_boolean.data
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 950c365..a56a707 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -57,6 +57,24 @@
# change too often in ways that don't affect the result
# ((un)commenting some options).
)
+
+ add_custom_command(
+ OUTPUT
+ ${CMAKE_CURRENT_SOURCE_DIR}/opt-testcases/handshake-generated.sh
+ WORKING_DIRECTORY
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+ COMMAND
+ "${MBEDTLS_PYTHON_EXECUTABLE}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_tls_handshake_tests.py"
+ DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/tls_test_case.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_tls_handshake_tests.py
+ )
+ add_custom_target(handshake-generated.sh
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/opt-testcases/handshake-generated.sh)
+ set_target_properties(handshake-generated.sh PROPERTIES EXCLUDE_FROM_ALL NO)
+ add_dependencies(${ssl_opt_target} handshake-generated.sh)
+
add_custom_command(
OUTPUT
${CMAKE_CURRENT_SOURCE_DIR}/opt-testcases/tls13-compat.sh
diff --git a/tests/Makefile b/tests/Makefile
index 7bd9953..b6f2f8c 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -64,6 +64,13 @@
# Generated files needed to (fully) run ssl-opt.sh
.PHONY: ssl-opt
+opt-testcases/handshake-generated.sh: ../framework/scripts/mbedtls_framework/tls_test_case.py
+opt-testcases/handshake-generated.sh: ../framework/scripts/generate_tls_handshake_tests.py
+ echo " Gen $@"
+ $(PYTHON) ../framework/scripts/generate_tls_handshake_tests.py -o $@
+GENERATED_FILES += opt-testcases/handshake-generated.sh
+ssl-opt: opt-testcases/handshake-generated.sh
+
opt-testcases/tls13-compat.sh: ../framework/scripts/generate_tls13_compat_tests.py
echo " Gen $@"
$(PYTHON) ../framework/scripts/generate_tls13_compat_tests.py -o $@
diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh
index 8cc341d..ba10024 100755
--- a/tests/scripts/check-generated-files.sh
+++ b/tests/scripts/check-generated-files.sh
@@ -179,6 +179,7 @@
check scripts/generate_query_config.pl programs/test/query_config.c
check scripts/generate_features.pl library/version_features.c
check framework/scripts/generate_ssl_debug_helpers.py library/ssl_debug_helpers_generated.c
+ check framework/scripts/generate_tls_handshake_tests.py tests/opt-testcases/handshake-generated.sh
check framework/scripts/generate_tls13_compat_tests.py tests/opt-testcases/tls13-compat.sh
check framework/scripts/generate_test_cert_macros.py tests/src/test_certs.h
# generate_visualc_files enumerates source files (library/*.c). It doesn't
diff --git a/tests/scripts/components-build-system.sh b/tests/scripts/components-build-system.sh
index 91a999e..3108aa7 100644
--- a/tests/scripts/components-build-system.sh
+++ b/tests/scripts/components-build-system.sh
@@ -123,27 +123,6 @@
fi
}
-component_test_tf_psa_crypto_cmake_as_package () {
- # Remove existing generated files so that we use the ones CMake
- # generates
- make neat
-
- msg "build: cmake 'as-package' build"
- root_dir="$(pwd)"
- cd tf-psa-crypto/programs/test/cmake_package
- build_variant_dir="$(pwd)"
- cmake .
- make
- ./cmake_package
- if [[ "$OSTYPE" == linux* ]]; then
- PKG_CONFIG_PATH="${build_variant_dir}/tf-psa-crypto/pkgconfig" \
- ${root_dir}/framework/scripts/pkgconfig.sh \
- tfpsacrypto
- # This is the EXPECTED package name. Renaming it could break consumers
- # of pkg-config, consider carefully.
- fi
-}
-
support_test_cmake_as_package () {
support_test_cmake_out_of_source
}
diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c
index 44e07ef..3c3bb6a 100644
--- a/tests/src/test_helpers/ssl_helpers.c
+++ b/tests/src/test_helpers/ssl_helpers.c
@@ -28,9 +28,22 @@
{
mbedtls_test_ssl_log_pattern *p = (mbedtls_test_ssl_log_pattern *) ctx;
+/* 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
(void) level;
(void) line;
(void) file;
+#endif
if (NULL != p &&
NULL != p->pattern &&
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 75ab938..6a5e760 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -103,12 +103,14 @@
O_NEXT_SRV_NO_CERT="$OPENSSL_NEXT s_server -www "
O_NEXT_CLI="echo 'GET / HTTP/1.0' | $OPENSSL_NEXT s_client -CAfile $DATA_FILES_PATH/test-ca_cat12.crt"
O_NEXT_CLI_NO_CERT="echo 'GET / HTTP/1.0' | $OPENSSL_NEXT s_client"
+ O_NEXT_CLI_RENEGOTIATE="echo 'R' | $OPENSSL_NEXT s_client -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key"
else
O_NEXT_SRV=false
O_NEXT_SRV_NO_CERT=false
O_NEXT_SRV_EARLY_DATA=false
O_NEXT_CLI_NO_CERT=false
O_NEXT_CLI=false
+ O_NEXT_CLI_RENEGOTIATE=false
fi
if [ -n "${GNUTLS_NEXT_SERV:-}" ]; then
@@ -13705,6 +13707,179 @@
-c "Handshake was completed" \
-s "dumping .client hello, compression. (2 bytes)"
+# Handshake defragmentation testing
+
+# Most test cases are in opt-testcases/handshake-generated.sh
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_certificate_authentication
+run_test "Handshake defragmentation on server: len=32, TLS 1.2 ClientHello (unsupported)" \
+ "$P_SRV debug_level=4 force_version=tls12 auth_mode=required" \
+ "$O_NEXT_CLI -tls1_2 -split_send_frag 32 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \
+ 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"
+
+# Test server-side buffer resizing with fragmented handshake on TLS1.2
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_config_enabled MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
+requires_max_content_len 1025
+run_test "Handshake defragmentation on server: len=256, buffer resizing with MFL=1024" \
+ "$P_SRV debug_level=4 auth_mode=required" \
+ "$O_NEXT_CLI -tls1_2 -split_send_frag 256 -maxfraglen 1024 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \
+ 0 \
+ -s "Reallocating in_buf" \
+ -s "Reallocating out_buf" \
+ -s "reassembled record" \
+ -s "initial handshake fragment: 256, 0\\.\\.256 of [0-9]\\+" \
+ -s "Prepare: waiting for more handshake fragments 256/" \
+ -s "Consume: waiting for more handshake fragments 256/"
+
+# Test client-initiated renegotiation with fragmented handshake on TLS1.2
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on server: len=512, client-initiated renegotiation" \
+ "$P_SRV debug_level=4 exchanges=2 renegotiation=1 auth_mode=required" \
+ "$O_NEXT_CLI_RENEGOTIATE -tls1_2 -split_send_frag 512 -connect 127.0.0.1:+$SRV_PORT" \
+ 0 \
+ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+ -s "found renegotiation extension" \
+ -s "server hello, secure renegotiation extension" \
+ -s "=> renegotiate" \
+ -S "write hello request" \
+ -s "reassembled record" \
+ -s "initial handshake fragment: 512, 0\\.\\.512 of [0-9]\\+" \
+ -s "Prepare: waiting for more handshake fragments 512/" \
+ -s "Consume: waiting for more handshake fragments 512/" \
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on server: len=256, client-initiated renegotiation" \
+ "$P_SRV debug_level=4 exchanges=2 renegotiation=1 auth_mode=required" \
+ "$O_NEXT_CLI_RENEGOTIATE -tls1_2 -split_send_frag 256 -connect 127.0.0.1:+$SRV_PORT" \
+ 0 \
+ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+ -s "found renegotiation extension" \
+ -s "server hello, secure renegotiation extension" \
+ -s "=> renegotiate" \
+ -S "write hello request" \
+ -s "reassembled record" \
+ -s "initial handshake fragment: 256, 0\\.\\.256 of [0-9]\\+" \
+ -s "Prepare: waiting for more handshake fragments 256/" \
+ -s "Consume: waiting for more handshake fragments 256/" \
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on server: len=128, client-initiated renegotiation" \
+ "$P_SRV debug_level=4 exchanges=2 renegotiation=1 auth_mode=required" \
+ "$O_NEXT_CLI_RENEGOTIATE -tls1_2 -split_send_frag 128 -connect 127.0.0.1:+$SRV_PORT" \
+ 0 \
+ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+ -s "found renegotiation extension" \
+ -s "server hello, secure renegotiation extension" \
+ -s "=> renegotiate" \
+ -S "write hello request" \
+ -s "reassembled record" \
+ -s "initial handshake fragment: 128, 0\\.\\.128 of [0-9]\\+" \
+ -s "Prepare: waiting for more handshake fragments 128/" \
+ -s "Consume: waiting for more handshake fragments 128/" \
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on server: len=4, client-initiated renegotiation" \
+ "$P_SRV debug_level=4 exchanges=2 renegotiation=1 auth_mode=required" \
+ "$O_NEXT_CLI_RENEGOTIATE -tls1_2 -split_send_frag 4 -connect 127.0.0.1:+$SRV_PORT" \
+ 0 \
+ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+ -s "found renegotiation extension" \
+ -s "server hello, secure renegotiation extension" \
+ -s "=> renegotiate" \
+ -S "write hello request" \
+ -s "reassembled record" \
+ -s "initial handshake fragment: 4, 0\\.\\.4 of [0-9]\\+" \
+ -s "Prepare: waiting for more handshake fragments 4/" \
+ -s "Consume: waiting for more handshake fragments 4/" \
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on server: len=4, client-initiated server-rejected renegotiation" \
+ "$P_SRV debug_level=4 exchanges=2 renegotiation=0 auth_mode=required" \
+ "$O_NEXT_CLI_RENEGOTIATE -tls1_2 -split_send_frag 4 -connect 127.0.0.1:+$SRV_PORT" \
+ 1 \
+ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \
+ -s "refusing renegotiation, sending alert" \
+ -s "server hello, secure renegotiation extension" \
+ -s "initial handshake fragment: 4, 0\\.\\.4 of [0-9]\\+" \
+ -s "Prepare: waiting for more handshake fragments 4/" \
+ -s "Consume: waiting for more handshake fragments 4/" \
+
+# Test server-initiated renegotiation with fragmented handshake on TLS1.2
+
+# Note: The /reneg endpoint serves as a directive for OpenSSL's s_server
+# to initiate a handshake renegotiation.
+# Note: Adjusting the renegotiation delay beyond the library's default
+# value of 16 is necessary. This parameter defines the maximum
+# number of records received before renegotiation is completed.
+# By fragmenting records and thereby increasing their quantity,
+# the default threshold can be reached more quickly.
+# Setting it to -1 disables that policy's enforment.
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on client: len=512, server-initiated renegotiation" \
+ "$O_NEXT_SRV -tls1_2 -split_send_frag 512 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \
+ "$P_CLI debug_level=3 renegotiation=1 request_page=/reneg" \
+ 0 \
+ -c "initial handshake fragment: 512, 0\\.\\.512 of [0-9]\\+" \
+ -c "Prepare: waiting for more handshake fragments 512/" \
+ -c "Consume: waiting for more handshake fragments 512/" \
+ -c "client hello, adding renegotiation extension" \
+ -c "found renegotiation extension" \
+ -c "=> renegotiate"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on client: len=256, server-initiated renegotiation" \
+ "$O_NEXT_SRV -tls1_2 -split_send_frag 256 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \
+ "$P_CLI debug_level=3 renegotiation=1 renego_delay=-1 request_page=/reneg" \
+ 0 \
+ -c "initial handshake fragment: 256, 0\\.\\.256 of [0-9]\\+" \
+ -c "Prepare: waiting for more handshake fragments 256/" \
+ -c "Consume: waiting for more handshake fragments 256/" \
+ -c "client hello, adding renegotiation extension" \
+ -c "found renegotiation extension" \
+ -c "=> renegotiate"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on client: len=128, server-initiated renegotiation" \
+ "$O_NEXT_SRV -tls1_2 -split_send_frag 128 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \
+ "$P_CLI debug_level=3 renegotiation=1 renego_delay=-1 request_page=/reneg" \
+ 0 \
+ -c "initial handshake fragment: 128, 0\\.\\.128 of [0-9]\\+" \
+ -c "Prepare: waiting for more handshake fragments 128/" \
+ -c "Consume: waiting for more handshake fragments 128/" \
+ -c "client hello, adding renegotiation extension" \
+ -c "found renegotiation extension" \
+ -c "=> renegotiate"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+run_test "Handshake defragmentation on client: len=4, server-initiated renegotiation" \
+ "$O_NEXT_SRV -tls1_2 -split_send_frag 4 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \
+ "$P_CLI debug_level=3 renegotiation=1 renego_delay=-1 request_page=/reneg" \
+ 0 \
+ -c "initial handshake fragment: 4, 0\\.\\.4 of [0-9]\\+" \
+ -c "Prepare: waiting for more handshake fragments 4/" \
+ -c "Consume: waiting for more handshake fragments 4/" \
+ -c "client hello, adding renegotiation extension" \
+ -c "found renegotiation extension" \
+ -c "=> renegotiate"
+
# Test heap memory usage after handshake
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
requires_config_enabled MBEDTLS_MEMORY_DEBUG
diff --git a/tests/suites/test_suite_debug.data b/tests/suites/test_suite_debug.data
index c8f40a0..0989e61 100644
--- a/tests/suites/test_suite_debug.data
+++ b/tests/suites/test_suite_debug.data
@@ -1,3 +1,12 @@
+printf "%" MBEDTLS_PRINTF_SIZET, 0
+printf_int_expr:PRINTF_SIZET:sizeof(size_t):0:"0"
+
+printf "%" MBEDTLS_PRINTF_LONGLONG, 0
+printf_int_expr:PRINTF_LONGLONG:sizeof(long long):0:"0"
+
+printf "%" MBEDTLS_PRINTF_MS_TIME, 0
+printf_int_expr:PRINTF_MS_TIME:sizeof(mbedtls_ms_time_t):0:"0"
+
Debug print msg (threshold 1, level 0)
debug_print_msg_threshold:1:0:"MyFile":999:"MyFile(0999)\: Text message, 2 == 2\n"
diff --git a/tests/suites/test_suite_debug.function b/tests/suites/test_suite_debug.function
index a71db14..f3c8ff6 100644
--- a/tests/suites/test_suite_debug.function
+++ b/tests/suites/test_suite_debug.function
@@ -4,11 +4,34 @@
#include "mbedtls/pk.h"
#include <test/ssl_helpers.h>
+#if defined(_WIN32)
+# include <stdlib.h>
+# include <crtdbg.h>
+#endif
+
+// Dummy type for builds without MBEDTLS_HAVE_TIME
+#if !defined(MBEDTLS_HAVE_TIME)
+typedef int64_t mbedtls_ms_time_t;
+#endif
+
+typedef enum {
+ PRINTF_SIZET,
+ PRINTF_LONGLONG,
+ PRINTF_MS_TIME,
+} printf_format_indicator_t;
+
+const char *const printf_formats[] = {
+ [PRINTF_SIZET] = "%" MBEDTLS_PRINTF_SIZET,
+ [PRINTF_LONGLONG] = "%" MBEDTLS_PRINTF_LONGLONG,
+ [PRINTF_MS_TIME] = "%" MBEDTLS_PRINTF_MS_TIME,
+};
+
struct buffer_data {
char buf[2000];
char *ptr;
};
+#if defined(MBEDTLS_SSL_TLS_C)
static void string_debug(void *data, int level, const char *file, int line, const char *str)
{
struct buffer_data *buffer = (struct buffer_data *) data;
@@ -44,14 +67,77 @@
buffer->ptr = p;
}
+#endif /* MBEDTLS_SSL_TLS_C */
+
+#if defined(_WIN32)
+static void noop_invalid_parameter_handler(
+ const wchar_t *expression,
+ const wchar_t *function,
+ const wchar_t *file,
+ unsigned int line,
+ uintptr_t pReserved)
+{
+ (void) expression;
+ (void) function;
+ (void) file;
+ (void) line;
+ (void) pReserved;
+}
+#endif /* _WIN32 */
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_DEBUG_C:MBEDTLS_SSL_TLS_C
+ * depends_on:MBEDTLS_DEBUG_C
* END_DEPENDENCIES
*/
/* BEGIN_CASE */
+void printf_int_expr(int format_indicator, intmax_t sizeof_x, intmax_t x, char *result)
+{
+#if defined(_WIN32)
+ /* Windows treats any invalid format specifiers passsed to the CRT as fatal assertion failures.
+ Disable this behaviour temporarily, so the rest of the test cases can complete. */
+ _invalid_parameter_handler saved_handler =
+ _set_invalid_parameter_handler(noop_invalid_parameter_handler);
+
+ // Disable assertion pop-up window in Debug builds
+ int saved_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_REPORT_MODE);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
+#endif
+
+ const char *format = printf_formats[format_indicator];
+ char *output = NULL;
+ const size_t n = strlen(result);
+
+ /* Nominal case: buffer just large enough */
+ TEST_CALLOC(output, n + 1);
+ if ((size_t) sizeof_x <= sizeof(int)) { // Any smaller integers would be promoted to an int due to calling a vararg function
+ TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (int) x));
+ } else if (sizeof_x == sizeof(long)) {
+ TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (long) x));
+ } else if (sizeof_x == sizeof(long long)) {
+ TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (long long) x));
+ } else {
+ TEST_FAIL(
+ "sizeof_x <= sizeof(int) || sizeof_x == sizeof(long) || sizeof_x == sizeof(long long)");
+ }
+ TEST_MEMORY_COMPARE(result, n + 1, output, n + 1);
+
+exit:
+ mbedtls_free(output);
+ output = NULL;
+
+#if defined(_WIN32)
+ // Restore default Windows behaviour
+ _set_invalid_parameter_handler(saved_handler);
+ _CrtSetReportMode(_CRT_ASSERT, saved_report_mode);
+ (void) saved_report_mode;
+#endif
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C */
void debug_print_msg_threshold(int threshold, int level, char *file,
int line, char *result_str)
{
@@ -89,7 +175,7 @@
}
/* END_CASE */
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C */
void mbedtls_debug_print_ret(char *file, int line, char *text, int value,
char *result_str)
{
@@ -124,7 +210,7 @@
}
/* END_CASE */
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C */
void mbedtls_debug_print_buf(char *file, int line, char *text,
data_t *data, char *result_str)
{
@@ -159,7 +245,7 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_X509_REMOVE_INFO */
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_X509_REMOVE_INFO */
void mbedtls_debug_print_crt(char *crt_file, char *file, int line,
char *prefix, char *result_str)
{
@@ -199,7 +285,7 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C:MBEDTLS_BIGNUM_C */
void mbedtls_debug_print_mpi(char *value, char *file, int line,
char *prefix, char *result_str)
{
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index e9584dc..6b491d4 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -5013,3 +5013,193 @@
PSA_DONE();
}
/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_DEBUG_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+void inject_client_content_on_the_wire(int pk_alg,
+ int state, data_t *data,
+ char *log_pattern, int expected_ret)
+{
+ /* This function allows us to inject content at a specific state
+ * in the handshake, or when it's completed. The content is injected
+ * on the mock TCP socket, as if we were an active network attacker.
+ *
+ * This function is suitable to inject:
+ * - crafted records, at any point;
+ * - valid records that contain crafted handshake messages, but only
+ * when the traffic is still unprotected (for TLS 1.2 that's most of the
+ * handshake, for TLS 1.3 that's only the Hello messages);
+ * - handshake messages that are fragmented in a specific way,
+ * under the same conditions as above.
+ */
+ enum { BUFFSIZE = 16384 };
+ mbedtls_test_ssl_endpoint server, client;
+ mbedtls_platform_zeroize(&server, sizeof(server));
+ mbedtls_platform_zeroize(&client, sizeof(client));
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_init_handshake_options(&options);
+ mbedtls_test_ssl_log_pattern srv_pattern;
+ memset(&srv_pattern, 0, sizeof(srv_pattern));
+ int ret = -1;
+
+ PSA_INIT();
+
+ srv_pattern.pattern = log_pattern;
+ options.srv_log_obj = &srv_pattern;
+ options.srv_log_fun = mbedtls_test_ssl_log_analyzer;
+ mbedtls_debug_set_threshold(3);
+
+ options.pk_alg = pk_alg;
+
+ ret = mbedtls_test_ssl_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER,
+ &options, NULL, NULL, NULL);
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_test_ssl_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT,
+ &options, NULL, NULL, NULL);
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_test_mock_socket_connect(&server.socket, &client.socket,
+ BUFFSIZE);
+ TEST_EQUAL(ret, 0);
+
+ /* Make the server move to the required state */
+ ret = mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl, state);
+ TEST_EQUAL(ret, 0);
+
+ /* Send the crafted message */
+ ret = mbedtls_test_mock_tcp_send_b(&client.socket, data->x, data->len);
+ TEST_EQUAL(ret, (int) data->len);
+
+ /* Have the server process it.
+ * Need the loop because a server that support 1.3 and 1.2
+ * will process a 1.2 ClientHello in two steps.
+ */
+ do {
+ ret = mbedtls_ssl_handshake_step(&server.ssl);
+ } while (ret == 0 && server.ssl.state == state);
+ TEST_EQUAL(ret, expected_ret);
+ TEST_ASSERT(srv_pattern.counter >= 1);
+
+exit:
+ mbedtls_test_free_handshake_options(&options);
+ mbedtls_test_ssl_endpoint_free(&server, NULL);
+ mbedtls_test_ssl_endpoint_free(&client, NULL);
+ mbedtls_debug_set_threshold(0);
+ PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_DEBUG_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY */
+void send_large_fragmented_hello(int hs_len_int, int first_frag_content_len_int,
+ char *log_pattern, int expected_ret)
+{
+ /* This function sends a long message (claiming to be a ClientHello)
+ * fragmented in 1-byte fragments (except the initial fragment).
+ * The purpose is to test how the stack reacts when receiving:
+ * - a message larger than our buffer;
+ * - a message smaller than our buffer, but where the intermediate size of
+ * holding all the fragments (including overhead) is larger than our
+ * buffer.
+ */
+ enum { BUFFSIZE = 16384 };
+ mbedtls_test_ssl_endpoint server, client;
+ mbedtls_platform_zeroize(&server, sizeof(server));
+ mbedtls_platform_zeroize(&client, sizeof(client));
+
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_init_handshake_options(&options);
+
+ mbedtls_test_ssl_log_pattern srv_pattern;
+ memset(&srv_pattern, 0, sizeof(srv_pattern));
+
+ unsigned char *first_frag = NULL;
+ int ret = -1;
+
+ size_t hs_len = (size_t) hs_len_int;
+ size_t first_frag_content_len = (size_t) first_frag_content_len_int;
+
+ PSA_INIT();
+
+ srv_pattern.pattern = log_pattern;
+ options.srv_log_obj = &srv_pattern;
+ options.srv_log_fun = mbedtls_test_ssl_log_analyzer;
+ mbedtls_debug_set_threshold(1);
+
+ // Does't really matter but we want to know to declare dependencies.
+ options.pk_alg = MBEDTLS_PK_ECDSA;
+
+ ret = mbedtls_test_ssl_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER,
+ &options, NULL, NULL, NULL);
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_test_ssl_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT,
+ &options, NULL, NULL, NULL);
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_test_mock_socket_connect(&server.socket, &client.socket,
+ BUFFSIZE);
+ TEST_EQUAL(ret, 0);
+
+ /* Make the server move past the initial dummy state */
+ ret = mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl,
+ MBEDTLS_SSL_CLIENT_HELLO);
+ TEST_EQUAL(ret, 0);
+
+ /* Prepare initial fragment */
+ const size_t first_len = 5 // record header, see below
+ + 4 // handshake header, see balow
+ + first_frag_content_len;
+ TEST_CALLOC(first_frag, first_len);
+ unsigned char *p = first_frag;
+ // record header
+ // record type: handshake
+ *p++ = 0x16,
+ // record version (actually common to TLS 1.2 and TLS 1.3)
+ *p++ = 0x03,
+ *p++ = 0x03,
+ // record length: two bytes
+ *p++ = (unsigned char) (((4 + first_frag_content_len) >> 8) & 0xff);
+ *p++ = (unsigned char) (((4 + first_frag_content_len) >> 0) & 0xff);
+ // handshake header
+ // handshake type: ClientHello
+ *p++ = 0x01,
+ // handshake length: three bytes
+ *p++ = (unsigned char) ((hs_len >> 16) & 0xff);
+ *p++ = (unsigned char) ((hs_len >> 8) & 0xff);
+ *p++ = (unsigned char) ((hs_len >> 0) & 0xff);
+ // handshake content: dummy value
+ memset(p, 0x2a, first_frag_content_len);
+
+ /* 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);
+
+ ret = mbedtls_ssl_handshake_step(&server.ssl);
+ TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ);
+
+ /* Dummy 1-byte fragment to repeatedly send next */
+ const unsigned char next[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x01, // record header (see above)
+ 0x2a, // Dummy handshake message content
+ };
+ for (size_t left = hs_len - first_frag_content_len; left != 0; left--) {
+ ret = mbedtls_test_mock_tcp_send_b(&client.socket, next, sizeof(next));
+ TEST_ASSERT(ret >= 0 && (size_t) ret == sizeof(next));
+
+ ret = mbedtls_ssl_handshake_step(&server.ssl);
+ if (ret != MBEDTLS_ERR_SSL_WANT_READ) {
+ break;
+ }
+ }
+ TEST_EQUAL(ret, expected_ret);
+ TEST_EQUAL(srv_pattern.counter, 1);
+
+exit:
+ mbedtls_test_free_handshake_options(&options);
+ mbedtls_test_ssl_endpoint_free(&server, NULL);
+ mbedtls_test_ssl_endpoint_free(&client, NULL);
+ mbedtls_debug_set_threshold(0);
+ mbedtls_free(first_frag);
+ PSA_DONE();
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_ssl.tls-defrag.data b/tests/suites/test_suite_ssl.tls-defrag.data
new file mode 100644
index 0000000..7817c4f
--- /dev/null
+++ b/tests/suites/test_suite_ssl.tls-defrag.data
@@ -0,0 +1,215 @@
+# (Minimal) ClientHello breakdown:
+# 160303rlrl - record header, 2-byte record contents len
+# 01hlhlhl - handshake header, 3-byte handshake message len
+# 0303 - protocol version: 1.2
+# 0123456789abcdef (repeated, 4 times total) - 32-byte "random"
+# 00 - session ID (empty)
+# 0002cvcv - ciphersuite list: 2-byte len + list of 2-byte values (see below)
+# 0100 - compression methods: 1-byte len then "null" (only legal value now)
+# [then end, or extensions, see notes below]
+# elel - 2-byte extensions length
+# ...
+# 000a - elliptic_curves aka supported_groups
+# 0004 - extension length
+# 0002 - length of named_curve_list / named_group_list
+# 0017 - secp256r1 aka NIST P-256
+# ...
+# 002b - supported version (for TLS 1.3)
+# 0003 - extension length
+# 02 - length of versions
+# 0304 - TLS 1.3 ("SSL 3.4")
+# ...
+# 000d - signature algorithms
+# 0004 - extension length
+# 0002 - SignatureSchemeList length
+# 0403 - ecdsa_secp256r1_sha256
+# ...
+# 0033 - key share
+# 0002 - extension length
+# 0000 - length of client_shares (empty is valid)
+#
+# Note: currently our TLS "1.3 or 1.2" code requires extension length to be
+# present even it it's 0. This is not strictly compliant but doesn't matter
+# much in practice as these days everyone wants to use signature_algorithms
+# (for hashes better than SHA-1), secure_renego (even if you have renego
+# disabled), and most people want either ECC or PSK related extensions.
+# See https://github.com/Mbed-TLS/mbedtls/issues/9963
+#
+# Also, currently we won't negotiate ECC ciphersuites unless at least the
+# supported_groups extension is present, see
+# https://github.com/Mbed-TLS/mbedtls/issues/7458
+#
+# For TLS 1.3 with ephemeral key exchange, mandatory extensions are:
+# - supported versions (as for all of TLS 1.3)
+# - supported groups
+# - key share
+# - signature algorithms
+# (see ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange()).
+#
+# Note: cccc is currently not assigned, so can be used get a consistent
+# "no matching ciphersuite" behaviour regardless of the configuration.
+# c02b is MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (1.2)
+# 1301 is MBEDTLS_TLS1_3_AES_128_GCM_SHA256 (1.3)
+
+# See "ClientHello breakdown" above
+# MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 with secp256r1
+Inject ClientHello - TLS 1.2 good (for reference)
+depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_1
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"16030300370100003303030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef000002c02b01000008000a000400020017":"<= parse client hello":0
+
+# See "ClientHello breakdown" above
+# Same as the above test with s/c02b/cccc/ as the ciphersuite
+Inject ClientHello - TLS 1.2 unknown ciphersuite (for reference)
+depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_1
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303002f0100002b03030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef000002cccc01000000":"got no ciphersuites in common":MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 good (for reference)
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303004c0100004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"key exchange mode\: ephemeral":0
+
+# See "ClientHello breakdown" above
+# Same as the above test with s/1301/cccc/ as the ciphersuite
+Inject ClientHello - TLS 1.3 unknown ciphersuite (for reference)
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303004c0100004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef000002cccc0100001d000a000400020017002b0003020304000d000400020403003300020000":"No matched ciphersuite":MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+# The purpose of this test case is to ensure nothing bad happens when the
+# connection is closed while we're waiting for more fragments.
+Inject ClientHello - TLS 1.3 4 + 71 then EOF (missing 1 byte)
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303000401000048160303004703030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d0004000204030033000200":"waiting for more handshake fragments":MBEDTLS_ERR_SSL_WANT_READ
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+# The purpose of this test case is to ensure nothing bad happens when the
+# connection is closed while we're waiting for more fragments.
+Inject ClientHello - TLS 1.3 4 then EOF (missing 72 bytes)
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303000401000048":"waiting for more handshake fragments":MBEDTLS_ERR_SSL_WANT_READ
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 4 + 72 OK
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303000401000048160303004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"key exchange mode\: ephemeral":0
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 3 + 73 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303000301000016030300494803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"handshake message too short":MBEDTLS_ERR_SSL_INVALID_RECORD
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 2 + 74 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"16030300020100160303004a004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"handshake message too short":MBEDTLS_ERR_SSL_INVALID_RECORD
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 1 + 75 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303000101160303004b00004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"handshake message too short":MBEDTLS_ERR_SSL_INVALID_RECORD
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 0 + 76 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"1603030000160303004c0100004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"ssl_get_next_record() returned":MBEDTLS_ERR_SSL_INVALID_RECORD
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 72 + 4 OK
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"16030300480100004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d0004000204030033160303000400020000":"key exchange mode\: ephemeral":0
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 73 + 3 OK
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"16030300490100004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d0004000204030033001603030003020000":"key exchange mode\: ephemeral":0
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 74 + 2 OK
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303004a0100004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d0004000204030033000216030300020000":"key exchange mode\: ephemeral":0
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 73 + 1 OK
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303004b0100004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d0004000204030033000200160303000100":"key exchange mode\: ephemeral":0
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 4 + appdata + 72 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"16030300040100004817030300020102160303004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"non-handshake message in the middle of a fragmented handshake message":MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 4 + alert(warn) + 72 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"1603030004010000481503030002015a160303004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"non-handshake message in the middle of a fragmented handshake message":MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 4 + alert(fatal) + 72 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"1603030004010000481503030002025a160303004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"non-handshake message in the middle of a fragmented handshake message":MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 4 + CCS + 72 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160303000401000048140303000101160303004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"non-handshake message in the middle of a fragmented handshake message":MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE
+
+# See "ClientHello breakdown" above
+# ephemeral with secp256r1 + MBEDTLS_TLS1_3_AES_128_GCM_SHA256
+Inject ClientHello - TLS 1.3 fragmented 4 + invalid type + 72 rejected
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_GCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY
+inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"1603030004010000481003030002015a160303004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"unknown record type":MBEDTLS_ERR_SSL_INVALID_RECORD
+
+# The buffer is actually larger than IN_CONTENT_LEN as we leave room for
+# record protection overhead (IV, MAC/tag, padding (up to 256 bytes)), CID...
+# The maximum size for an unencrypted (and without CID which is DTLS only)
+# handshake message we can hold in the buffer is
+# MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 4
+# (the 4 is for the handshake header).
+# However, due to overhead, fragmented messages need to be 5 bytes shorter in
+# order to actually fit (leave room for an extra record header).
+Send large fragmented ClientHello: reassembled 1 byte larger than the buffer
+send_large_fragmented_hello:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 3:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA
+
+Send large fragmented ClientHello: would just fit except for overhead
+send_large_fragmented_hello:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 4:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA
+
+Send large fragmented ClientHello: would fit except for overhead (1)
+send_large_fragmented_hello:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 5:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA
+
+Send large fragmented ClientHello: would fit except for overhead (2)
+send_large_fragmented_hello:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 6:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA
+
+Send large fragmented ClientHello: would fit except for overhead (3)
+send_large_fragmented_hello:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 7:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA
+
+Send large fragmented ClientHello: would fit except for overhead (4)
+send_large_fragmented_hello:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 8:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA
+
+# Since we're sending dummy contents (all 0x2a) for the ClientHello,
+# the first thing that's going to fail is the version check. The fact that we
+# got around to checking it confirms reassembly completed sucessfully.
+Send large fragmented ClientHello: just fits
+send_large_fragmented_hello:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 9:0:"Unsupported version of TLS":MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION
+
+# We're generating a virtual record header for the reassembled HS message,
+# which requires that the length fits in two bytes. Of course we won't get
+# there because if the length doesn't fit in two bytes then the message won't
+# fit in the buffer, but still add a test just in case.
+Send large fragmented ClientHello: length doesn't fit in two bytes
+send_large_fragmented_hello:0x10000:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA
diff --git a/tf-psa-crypto b/tf-psa-crypto
index 7d60bf1..399c5f9 160000
--- a/tf-psa-crypto
+++ b/tf-psa-crypto
@@ -1 +1 @@
-Subproject commit 7d60bf1078578bfc809f1516c195c54cefdb510d
+Subproject commit 399c5f9e1d71cb177eb0c16cb934755b409abe23