diff --git a/CMakeLists.txt b/CMakeLists.txt index bc122f5167..42e4ccb34d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -373,6 +373,20 @@ foreach(target IN LISTS tf_psa_crypto_library_targets) endif() endforeach(target) +# +# TF-PSA-Crypto directories with internal headers that are currently still +# consumed by Mbed TLS. When we have finished cleaning up this list should be +# empty. +# +set(TF_PSA_CRYPTO_PRIVATE_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/core + ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/dispatch + ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/drivers/builtin/src + ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/extras + ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/platform + ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/utilities +) + add_subdirectory(library) add_subdirectory(pkgconfig) @@ -416,16 +430,16 @@ if(ENABLE_TESTING OR ENABLE_PROGRAMS) endif() target_include_directories(mbedtls_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/tests/include - PRIVATE ${MBEDTLS_FRAMEWORK_DIR}/tests/include - PRIVATE tests/include - PRIVATE include - PRIVATE tf-psa-crypto/include - PRIVATE tf-psa-crypto/drivers/builtin/include - PRIVATE tf-psa-crypto/drivers/everest/include - PRIVATE tf-psa-crypto/drivers/pqcp/include - PRIVATE library - PRIVATE tf-psa-crypto/core - PRIVATE tf-psa-crypto/drivers/builtin/src) + ${MBEDTLS_FRAMEWORK_DIR}/tests/include + tests/include + include + tf-psa-crypto/include + tf-psa-crypto/drivers/builtin/include + tf-psa-crypto/drivers/everest/include + tf-psa-crypto/drivers/pqcp/include + library + ${TF_PSA_CRYPTO_PRIVATE_INCLUDE_DIRS} + ) # Request C11, needed for memory poisoning tests set_target_properties(mbedtls_test PROPERTIES C_STANDARD 11) set_config_files_compile_definitions(mbedtls_test) @@ -453,16 +467,15 @@ if(ENABLE_TESTING OR ENABLE_PROGRAMS) endif() target_include_directories(mbedtls_test_helpers PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/tests/include - PRIVATE ${MBEDTLS_FRAMEWORK_DIR}/tests/include - PRIVATE tests/include - PRIVATE include - PRIVATE tf-psa-crypto/include - PRIVATE tf-psa-crypto/drivers/builtin/include - PRIVATE library - PRIVATE tf-psa-crypto/core - PRIVATE tf-psa-crypto/drivers/builtin/src - PRIVATE tf-psa-crypto/drivers/everest/include - PRIVATE tf-psa-crypto/drivers/pqcp/include + ${MBEDTLS_FRAMEWORK_DIR}/tests/include + tests/include + include + tf-psa-crypto/include + tf-psa-crypto/drivers/builtin/include + library + tf-psa-crypto/drivers/everest/include + tf-psa-crypto/drivers/pqcp/include + ${TF_PSA_CRYPTO_PRIVATE_INCLUDE_DIRS} ) set_config_files_compile_definitions(mbedtls_test_helpers) diff --git a/ChangeLog.d/dtls-client-hello-defragmentation.txt b/ChangeLog.d/dtls-client-hello-defragmentation.txt new file mode 100644 index 0000000000..f5ff0b754c --- /dev/null +++ b/ChangeLog.d/dtls-client-hello-defragmentation.txt @@ -0,0 +1,5 @@ +Bugfix + * Support re-assembly of fragmented DTLS 1.2 ClientHello in Mbed TLS server. + * Support re-assembly of fragmented TLS 1.2 ClientHello in Mbed TLS server + even if TLS 1.3 support is disabled. This removes the main limitation on + support for re-assembly of fragmented handshake messages in TLS 1.2. diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 1425896976..8f58b3e9c0 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -4788,13 +4788,6 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, * 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 diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 5474e2cacf..f1b7c74aba 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -236,15 +236,14 @@ foreach(target IN LISTS target_libraries) add_library(MbedTLS::${target} ALIAS ${target}) # add_subdirectory support # Include public header files from /include, /tf-psa-crypto/include/ and # tf-psa-crypto/drivers/builtin/include/. Include private header files - # from /library, tf-psa-crypto/core/ and tf-psa-crypto/drivers/builtin/src/. + # from /library and ${TF_PSA_CRYPTO_PRIVATE_INCLUDE_DIRS}. target_include_directories(${target} PUBLIC $ $ $ $ PRIVATE ${MBEDTLS_DIR}/library/ - ${MBEDTLS_DIR}/tf-psa-crypto/core - ${MBEDTLS_DIR}/tf-psa-crypto/drivers/builtin/src + ${TF_PSA_CRYPTO_PRIVATE_INCLUDE_DIRS} # needed for generated headers ${CMAKE_CURRENT_BINARY_DIR}) set_config_files_compile_definitions(${target}) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index d159f8fd33..abb5a5696f 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -2967,6 +2967,49 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) return MBEDTLS_ERR_SSL_INVALID_RECORD; } + if (ssl->in_msg[0] == MBEDTLS_SSL_HS_CLIENT_HELLO && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + if (ssl->state == MBEDTLS_SSL_CLIENT_HELLO +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) { + /* + * When establishing the connection, the client may go through + * a series of ClientHello and HelloVerifyRequest requests and + * responses. The server intentionally does not keep trace of + * these initial round trips: minimum allocated ressources as + * long as the reachability of the client has not been + * confirmed. When receiving the "first ClientHello" from + * server perspective, we may thus need to adapt the next + * expected `message_seq` for the incoming and outgoing + * handshake messages. + */ + ssl->handshake->in_msg_seq = recv_msg_seq; + ssl->handshake->out_msg_seq = recv_msg_seq; + + /* Epoch should be 0 for initial handshakes */ + if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, + sizeof(ssl->cur_out_ctr) - 2); + } else if (mbedtls_ssl_is_handshake_over(ssl) == 1) { + /* In case of a post-handshake ClientHello that initiates a + * renegotiation check that the handshake message sequence + * number is zero. + */ + if (recv_msg_seq != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message_seq: " + "%u (expected 0)", + recv_msg_seq)); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + } + } + if (ssl->handshake != NULL && ((mbedtls_ssl_is_handshake_over(ssl) == 0 && recv_msg_seq != ssl->handshake->in_msg_seq) || @@ -4843,14 +4886,9 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl) /* The record content type may change during decryption, * so re-read it. */ ssl->in_msgtype = rec.type; - /* Also update the input buffer, because unfortunately - * the server-side ssl_parse_client_hello() reparses the - * record header when receiving a ClientHello initiating - * a renegotiation. */ - ssl->in_hdr[0] = rec.type; + ssl->in_msg = rec.buf + rec.data_offset; ssl->in_msglen = rec.data_len; - MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->in_len, 0); return 0; } @@ -5504,6 +5542,11 @@ static int ssl_tls12_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; } #endif + + /* Keep the ClientHello message for ssl_parse_client_hello() */ + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + ssl->keep_current_message = 1; + } ret = mbedtls_ssl_start_renegotiation(ssl); if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && ret != 0) { diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 24ac3cec4d..6df6c4bd88 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2892,13 +2892,6 @@ size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_PROTO_DTLS) size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl) { - /* Return unlimited mtu for client hello messages to avoid fragmentation. */ - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - (ssl->state == MBEDTLS_SSL_CLIENT_HELLO || - ssl->state == MBEDTLS_SSL_SERVER_HELLO)) { - return 0; - } - if (ssl->handshake == NULL || ssl->handshake->mtu == 0) { return ssl->mtu; } diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index ec4446c1b4..94e61a8aca 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -869,131 +869,35 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); - int renegotiating; - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -read_record_header: -#endif /* - * If renegotiating, then the input was read with mbedtls_ssl_read_record(), - * otherwise read it ourselves manually in order to support SSLv2 - * ClientHello, which doesn't use the same record layer format. - * Otherwise in a scenario of TLS 1.3/TLS 1.2 version negotiation, the - * ClientHello has been already fully fetched by the TLS 1.3 code and the - * flag ssl->keep_current_message is raised. + * Fetch the expected ClientHello handshake message. Do not ask + * mbedtls_ssl_read_record() to update the handshake digest, because the + * ClientHello may already have been read in ssl_tls13_process_client_hello() + * or as a post-handshake message (renegotiation). In those cases we need + * to update the digest ourselves, and it is simpler to do so + * unconditionally than to track whether it is needed. */ - renegotiating = 0; -#if defined(MBEDTLS_SSL_RENEGOTIATION) - renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); -#endif - if (!renegotiating && !ssl->keep_current_message) { - if ((ret = mbedtls_ssl_fetch_input(ssl, 5)) != 0) { - /* No alert on a read error. */ - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); - return ret; - } + if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record ", ret); + return ret; } - buf = ssl->in_hdr; - - MBEDTLS_SSL_DEBUG_BUF(4, "record header", buf, mbedtls_ssl_in_hdr_len(ssl)); - /* - * TLS Client Hello + * Update the handshake checksum. * - * Record layer: - * 0 . 0 message type - * 1 . 2 protocol version - * 3 . 11 DTLS: epoch + record sequence number - * 3 . 4 message length + * Note that the checksum must be updated before parsing the extensions + * because ssl_parse_session_ticket_ext() may decrypt the ticket in place + * and therefore modify the ClientHello message. This occurs when using + * the Mbed TLS ssl_ticket.c implementation. */ - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message type: %d", - buf[0])); - - if (buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; - } - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message len.: %d", - MBEDTLS_GET_UINT16_BE(ssl->in_len, 0))); - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, protocol version: [%d:%d]", - buf[1], buf[2])); - - /* For DTLS if this is the initial handshake, remember the client sequence - * number to use it in our next message (RFC 6347 4.2.1) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE -#endif - ) { - /* Epoch should be 0 for initial handshakes */ - if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; - } - - memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, - sizeof(ssl->cur_out_ctr) - 2); - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - if (mbedtls_ssl_dtls_replay_check(ssl) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("replayed record, discarding")); - ssl->next_record_offset = 0; - ssl->in_left = 0; - goto read_record_header; - } - - /* No MAC to check yet, so we can update right now */ - mbedtls_ssl_dtls_replay_update(ssl); -#endif - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - msg_len = MBEDTLS_GET_UINT16_BE(ssl->in_len, 0); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { - /* Set by mbedtls_ssl_read_record() */ - msg_len = ssl->in_hslen; - } else -#endif - { - if (ssl->keep_current_message) { - ssl->keep_current_message = 0; - } else { - if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; - } - - if ((ret = mbedtls_ssl_fetch_input(ssl, - mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); - return ret; - } - - /* Done reading this record, get ready for the next one */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl); - } else -#endif - ssl->in_left = 0; - } + ret = mbedtls_ssl_update_handshake_status(ssl); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); + return ret; } buf = ssl->in_msg; - - MBEDTLS_SSL_DEBUG_BUF(4, "record contents", buf, msg_len); - - ret = ssl->handshake->update_checksum(ssl, buf, msg_len); - if (0 != ret) { - MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); - return ret; - } + msg_len = ssl->in_hslen; /* * Handshake layer: @@ -1003,64 +907,12 @@ read_record_header: * 6 . 8 DTLS only: fragment offset * 9 . 11 DTLS only: fragment length */ - if (msg_len < mbedtls_ssl_hs_hdr_len(ssl)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_DECODE_ERROR; - } - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake type: %d", buf[0])); - - if (buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) { + if ((ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) || + (buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - /* - * Copy the client's handshake message_seq on initial handshakes, - * check sequence number on renego. - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { - /* This couldn't be done in ssl_prepare_handshake_record() */ - unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); - if (cli_msg_seq != ssl->handshake->in_msg_seq) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message_seq: " - "%u (expected %u)", cli_msg_seq, - ssl->handshake->in_msg_seq)); - return MBEDTLS_ERR_SSL_DECODE_ERROR; - } - - ssl->handshake->in_msg_seq++; - } else -#endif - { - unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); - ssl->handshake->out_msg_seq = cli_msg_seq; - ssl->handshake->in_msg_seq = cli_msg_seq + 1; - } - { - /* - * For now we don't support fragmentation, so make sure - * fragment_offset == 0 and fragment_length == length - */ - size_t fragment_offset, fragment_length, length; - fragment_offset = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6); - fragment_length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9); - length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1); - MBEDTLS_SSL_DEBUG_MSG( - 4, ("fragment_offset=%u fragment_length=%u length=%u", - (unsigned) fragment_offset, (unsigned) fragment_length, - (unsigned) length)); - if (fragment_offset != 0 || length != fragment_length) { - MBEDTLS_SSL_DEBUG_MSG(1, ("ClientHello fragmentation not supported")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - } - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - buf += mbedtls_ssl_hs_hdr_len(ssl); msg_len -= mbedtls_ssl_hs_hdr_len(ssl); @@ -1390,7 +1242,11 @@ read_record_header: #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_TLS_EXT_SESSION_TICKET: MBEDTLS_SSL_DEBUG_MSG(3, ("found session ticket extension")); - + /* + * If the Mbed TLS ssl_ticket.c implementation is used, the + * ticket is decrypted in place. This modifies the ClientHello + * message in the input buffer. + */ ret = ssl_parse_session_ticket_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; diff --git a/programs/Makefile b/programs/Makefile index 36679dcb0f..846361d788 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -199,7 +199,7 @@ endif test/metatest$(EXEXT): $(FRAMEWORK)/tests/programs/metatest.c $(DEP) echo " CC $(FRAMEWORK)/tests/programs/metatest.c" - $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -I../library -I../tf-psa-crypto/core -I../tf-psa-crypto/drivers/builtin/include -I../tf-psa-crypto/drivers/builtin/src $(FRAMEWORK)/tests/programs/metatest.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -I../library -I../tf-psa-crypto/core -I../tf-psa-crypto/drivers/builtin/src -I../tf-psa-crypto/platform $(FRAMEWORK)/tests/programs/metatest.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ test/query_config.o: test/query_config.c $(FRAMEWORK)/tests/programs/query_config.h $(DEP) echo " CC test/query_config.c" diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 79cbad877d..f2e8eff47a 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -4131,7 +4131,55 @@ close_notify: } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); ret = 0; - mbedtls_printf(" done\n"); + /* + * In the DTLS case, attempt to read a possible response to the close + * notification. This avoids reconnecting to the same client when we + * reset and later receive its close-notification response during + * step 3 (waiting for a client to connect). + * + * Stop waiting for the response if the connection has already ended. + * + * The waiting loop below relies on mbedtls_ssl_read() returning regularly + * in order to keep the total waiting time approximately bounded to 1s. If + * no read timeout is configured (see the read_timeout option), or if the + * configured timeout is close to or larger than 1s, the total waiting time + * may exceed 1s by a significant margin. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) && defined(MBEDTLS_HAVE_TIME) + if (opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + mbedtls_ms_time_t start = mbedtls_ms_time(); + for (;;) { + ret = mbedtls_ssl_read(&ssl, buf, opt.buffer_size); + /* + * mbedtls_ssl_read() returned some data or timed out, loop if we + * have not spent already too much time, quite arbitrarily 1s. + */ + if ((ret > 0) || (ret == MBEDTLS_ERR_SSL_TIMEOUT)) { + if ((mbedtls_ms_time() - start) < 1000) { + continue; + } + } + + if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + mbedtls_printf(" done, received client close notification.\n"); + } else { + /* ret = 0, silent transport EOF or ret < 0 except + * MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY. Note that we do not + * handle specifically the non-fatal error codes like + * MBEDTLS_ERR_SSL_WANT_READ as we do not really expect them + * here. + */ + mbedtls_printf(" done\n"); + } + break; + } + ret = 0; + } else +#endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_HAVE_TIME */ + { + mbedtls_printf(" done\n"); + } + fflush(stdout); #if defined(MBEDTLS_SSL_CACHE_C) if (opt.cache_remove > 0) { diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt index 8a5d6ba822..0de71a9b03 100644 --- a/programs/test/CMakeLists.txt +++ b/programs/test/CMakeLists.txt @@ -103,9 +103,9 @@ foreach(exe IN LISTS executables) endforeach() target_include_directories(metatest - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tf-psa-crypto/drivers/builtin/include - ${CMAKE_CURRENT_SOURCE_DIR}/../../tf-psa-crypto/drivers/builtin/src) - + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tf-psa-crypto/drivers/builtin/src + ${CMAKE_CURRENT_SOURCE_DIR}/../../tf-psa-crypto/platform +) install(TARGETS ${executables} DESTINATION "bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/scripts/abi_check.py b/scripts/abi_check.py index 4fe7f54fc0..517d40e355 100755 --- a/scripts/abi_check.py +++ b/scripts/abi_check.py @@ -1,711 +1,16 @@ #!/usr/bin/env python3 -"""This script compares the interfaces of two versions of Mbed TLS, looking -for backward incompatibilities between two different Git revisions within -an Mbed TLS repository. It must be run from the root of a Git working tree. - -### How the script works ### - -For the source (API) and runtime (ABI) interface compatibility, this script -is a small wrapper around the abi-compliance-checker and abi-dumper tools, -applying them to compare the header and library files. - -For the storage format, this script compares the automatically generated -storage tests and the manual read tests, and complains if there is a -reduction in coverage. A change in test data will be signaled as a -coverage reduction since the old test data is no longer present. A change in -how test data is presented will be signaled as well; this would be a false -positive. - -The results of the API/ABI comparison are either formatted as HTML and stored -at a configurable location, or are given as a brief list of problems. -Returns 0 on success, 1 on non-compliance, and 2 if there is an error -while running the script. - -### How to interpret non-compliance ### - -This script has relatively common false positives. In many scenarios, it only -reports a pass if there is a strict textual match between the old version and -the new version, and it reports problems where there is a sufficient semantic -match but not a textual match. This section lists some common false positives. -This is not an exhaustive list: in the end what matters is whether we are -breaking a backward compatibility goal. - -**API**: the goal is that if an application works with the old version of the -library, it can be recompiled against the new version and will still work. -This is normally validated by comparing the declarations in `include/*/*.h`. -A failure is a declaration that has disappeared or that now has a different -type. - - * It's ok to change or remove macros and functions that are documented as - for internal use only or as experimental. - * It's ok to rename function or macro parameters as long as the semantics - has not changed. - * It's ok to change or remove structure fields that are documented as - private. - * It's ok to add fields to a structure that already had private fields - or was documented as extensible. - -**ABI**: the goal is that if an application was built against the old version -of the library, the same binary will work when linked against the new version. -This is normally validated by comparing the symbols exported by `libmbed*.so`. -A failure is a symbol that is no longer exported by the same library or that -now has a different type. - - * All ABI changes are acceptable if the library version is bumped - (see `scripts/bump_version.sh`). - * ABI changes that concern functions which are declared only inside the - library directory, and not in `include/*/*.h`, are acceptable only if - the function was only ever used inside the same library (libmbedcrypto, - libmbedx509, libmbedtls). As a counter example, if the old version - of libmbedtls calls mbedtls_foo() from libmbedcrypto, and the new version - of libmbedcrypto no longer has a compatible mbedtls_foo(), this does - require a version bump for libmbedcrypto. - -**Storage format**: the goal is to check that persistent keys stored by the -old version can be read by the new version. This is normally validated by -comparing the `*read*` test cases in `test_suite*storage_format*.data`. -A failure is a storage read test case that is no longer present with the same -function name and parameter list. - - * It's ok if the same test data is present, but its presentation has changed, - for example if a test function is renamed or has different parameters. - * It's ok if redundant tests are removed. - -**Generated test coverage**: the goal is to check that automatically -generated tests have as much coverage as before. This is normally validated -by comparing the test cases that are automatically generated by a script. -A failure is a generated test case that is no longer present with the same -function name and parameter list. - - * It's ok if the same test data is present, but its presentation has changed, - for example if a test function is renamed or has different parameters. - * It's ok if redundant tests are removed. +"""Bridge script +See framework/scripts/mbedtls_framework/interface_checks.py for detailed documentation. +This is a convenient place to encode any branch-specific information we might want to add +in the future. """ # Copyright The Mbed TLS Contributors # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later -import glob -import os -import re -import sys -import traceback -import shutil -import subprocess -import argparse -import logging -import tempfile -import fnmatch -from types import SimpleNamespace - -import xml.etree.ElementTree as ET - import framework_scripts_path # pylint: disable=unused-import -from mbedtls_framework import build_tree - - -class AbiChecker: - """API and ABI checker.""" - - def __init__(self, old_version, new_version, configuration): - """Instantiate the API/ABI checker. - - old_version: RepoVersion containing details to compare against - new_version: RepoVersion containing details to check - configuration.report_dir: directory for output files - configuration.keep_all_reports: if false, delete old reports - configuration.brief: if true, output shorter report to stdout - configuration.check_abi: if true, compare ABIs - configuration.check_api: if true, compare APIs - configuration.check_storage: if true, compare storage format tests - configuration.skip_file: path to file containing symbols and types to skip - """ - self.repo_path = "." - self.log = None - self.verbose = configuration.verbose - self._setup_logger() - self.report_dir = os.path.abspath(configuration.report_dir) - self.keep_all_reports = configuration.keep_all_reports - self.can_remove_report_dir = not (os.path.exists(self.report_dir) or - self.keep_all_reports) - self.old_version = old_version - self.new_version = new_version - self.skip_file = configuration.skip_file - self.check_abi = configuration.check_abi - self.check_api = configuration.check_api - if self.check_abi != self.check_api: - raise Exception('Checking API without ABI or vice versa is not supported') - self.check_storage_tests = configuration.check_storage - self.brief = configuration.brief - self.git_command = "git" - self.make_command = "make" - - def _setup_logger(self): - self.log = logging.getLogger() - if self.verbose: - self.log.setLevel(logging.DEBUG) - else: - self.log.setLevel(logging.INFO) - self.log.addHandler(logging.StreamHandler()) - - @staticmethod - def check_abi_tools_are_installed(): - for command in ["abi-dumper", "abi-compliance-checker"]: - if not shutil.which(command): - raise Exception("{} not installed, aborting".format(command)) - - def _get_clean_worktree_for_git_revision(self, version): - """Make a separate worktree with version.revision checked out. - Do not modify the current worktree.""" - git_worktree_path = tempfile.mkdtemp() - if version.repository: - self.log.debug( - "Checking out git worktree for revision {} from {}".format( - version.revision, version.repository - ) - ) - fetch_output = subprocess.check_output( - [self.git_command, "fetch", - version.repository, version.revision], - cwd=self.repo_path, - stderr=subprocess.STDOUT - ) - self.log.debug(fetch_output.decode("utf-8")) - worktree_rev = "FETCH_HEAD" - else: - self.log.debug("Checking out git worktree for revision {}".format( - version.revision - )) - worktree_rev = version.revision - worktree_output = subprocess.check_output( - [self.git_command, "worktree", "add", "--detach", - git_worktree_path, worktree_rev], - cwd=self.repo_path, - stderr=subprocess.STDOUT - ) - self.log.debug(worktree_output.decode("utf-8")) - version.commit = subprocess.check_output( - [self.git_command, "rev-parse", "HEAD"], - cwd=git_worktree_path, - stderr=subprocess.STDOUT - ).decode("ascii").rstrip() - self.log.debug("Commit is {}".format(version.commit)) - return git_worktree_path - - def _update_git_submodules(self, git_worktree_path, version): - """If the crypto submodule is present, initialize it. - if version.crypto_revision exists, update it to that revision, - otherwise update it to the default revision""" - submodule_output = subprocess.check_output( - [self.git_command, "submodule", "foreach", "--recursive", - f'git worktree add --detach "{git_worktree_path}/$displaypath" HEAD'], - cwd=self.repo_path, - stderr=subprocess.STDOUT - ) - self.log.debug(submodule_output.decode("utf-8")) - - try: - # Try to update the submodules using local commits - # (Git will sometimes insist on fetching the remote without --no-fetch - # if the submodules are shallow clones) - update_output = subprocess.check_output( - [self.git_command, "submodule", "update", "--init", '--recursive', '--no-fetch'], - cwd=git_worktree_path, - stderr=subprocess.STDOUT - ) - except subprocess.CalledProcessError as err: - self.log.debug(err.stdout.decode("utf-8")) - - # Checkout with --no-fetch failed, falling back to fetching from origin - update_output = subprocess.check_output( - [self.git_command, "submodule", "update", "--init", '--recursive'], - cwd=git_worktree_path, - stderr=subprocess.STDOUT - ) - self.log.debug(update_output.decode("utf-8")) - if not (os.path.exists(os.path.join(git_worktree_path, "crypto")) - and version.crypto_revision): - return - - if version.crypto_repository: - fetch_output = subprocess.check_output( - [self.git_command, "fetch", version.crypto_repository, - version.crypto_revision], - cwd=os.path.join(git_worktree_path, "crypto"), - stderr=subprocess.STDOUT - ) - self.log.debug(fetch_output.decode("utf-8")) - crypto_rev = "FETCH_HEAD" - else: - crypto_rev = version.crypto_revision - - checkout_output = subprocess.check_output( - [self.git_command, "checkout", crypto_rev], - cwd=os.path.join(git_worktree_path, "crypto"), - stderr=subprocess.STDOUT - ) - self.log.debug(checkout_output.decode("utf-8")) - - def _build_shared_libraries(self, git_worktree_path, version): - """Build the shared libraries in the specified worktree.""" - my_environment = os.environ.copy() - my_environment["CFLAGS"] = "-g -Og" - my_environment["SHARED"] = "1" - if os.path.exists(os.path.join(git_worktree_path, "crypto")): - my_environment["USE_CRYPTO_SUBMODULE"] = "1" - - if os.path.exists(os.path.join(git_worktree_path, "scripts", "legacy.make")): - command = [self.make_command, "-f", "scripts/legacy.make", "lib"] - else: - command = [self.make_command, "lib"] - - make_output = subprocess.check_output( - command, - env=my_environment, - cwd=git_worktree_path, - stderr=subprocess.STDOUT - ) - self.log.debug(make_output.decode("utf-8")) - for root, _dirs, files in os.walk(git_worktree_path): - for file in fnmatch.filter(files, "*.so"): - version.modules[os.path.splitext(file)[0]] = ( - os.path.join(root, file) - ) - - @staticmethod - def _pretty_revision(version): - if version.revision == version.commit: - return version.revision - else: - return "{} ({})".format(version.revision, version.commit) - - def _get_abi_dumps_from_shared_libraries(self, version): - """Generate the ABI dumps for the specified git revision. - The shared libraries must have been built and the module paths - present in version.modules.""" - for mbed_module, module_path in version.modules.items(): - output_path = os.path.join( - self.report_dir, "{}-{}-{}.dump".format( - mbed_module, version.revision, version.version - ) - ) - abi_dump_command = [ - "abi-dumper", - module_path, - "-o", output_path, - "-lver", self._pretty_revision(version), - ] - abi_dump_output = subprocess.check_output( - abi_dump_command, - stderr=subprocess.STDOUT - ) - self.log.debug(abi_dump_output.decode("utf-8")) - version.abi_dumps[mbed_module] = output_path - - @staticmethod - def _normalize_storage_test_case_data(line): - """Eliminate cosmetic or irrelevant details in storage format test cases.""" - line = re.sub(r'\s+', r'', line) - return line - - def _read_storage_tests(self, - directory, - filename, - is_generated, - storage_tests): - """Record storage tests from the given file. - - Populate the storage_tests dictionary with test cases read from - filename under directory. - """ - at_paragraph_start = True - description = None - full_path = os.path.join(directory, filename) - with open(full_path) as fd: - for line_number, line in enumerate(fd, 1): - line = line.strip() - if not line: - at_paragraph_start = True - continue - if line.startswith('#'): - continue - if at_paragraph_start: - description = line.strip() - at_paragraph_start = False - continue - if line.startswith('depends_on:'): - continue - # We've reached a test case data line - test_case_data = self._normalize_storage_test_case_data(line) - if not is_generated: - # In manual test data, only look at read tests. - function_name = test_case_data.split(':', 1)[0] - if 'read' not in function_name.split('_'): - continue - metadata = SimpleNamespace( - filename=filename, - line_number=line_number, - description=description - ) - storage_tests[test_case_data] = metadata - - @staticmethod - def _list_generated_test_data_files(git_worktree_path): - """List the generated test data files.""" - generate_psa_tests = 'framework/scripts/generate_psa_tests.py' - if not os.path.isfile(git_worktree_path + '/' + generate_psa_tests): - # The checked-out revision is from before generate_psa_tests.py - # was moved to the framework submodule. Use the old location. - generate_psa_tests = 'tests/scripts/generate_psa_tests.py' - - output = subprocess.check_output( - [generate_psa_tests, '--list'], - cwd=git_worktree_path, - ).decode('ascii') - return [line for line in output.split('\n') if line] - - def _get_storage_format_tests(self, version, git_worktree_path): - """Record the storage format tests for the specified git version. - - The storage format tests are the test suite data files whose name - contains "storage_format". - - The version must be checked out at git_worktree_path. - - This function creates or updates the generated data files. - """ - # Existing test data files. This may be missing some automatically - # generated files if they haven't been generated yet. - if os.path.isdir(os.path.join(git_worktree_path, 'tf-psa-crypto', - 'tests', 'suites')): - storage_data_files = set(glob.glob( - 'tf-psa-crypto/tests/suites/test_suite_*storage_format*.data' - )) - else: - storage_data_files = set(glob.glob( - 'tests/suites/test_suite_*storage_format*.data' - )) - # Discover and (re)generate automatically generated data files. - to_be_generated = set() - for filename in self._list_generated_test_data_files(git_worktree_path): - if 'storage_format' in filename: - storage_data_files.add(filename) - to_be_generated.add(filename) - - generate_psa_tests = 'framework/scripts/generate_psa_tests.py' - if not os.path.isfile(git_worktree_path + '/' + generate_psa_tests): - # The checked-out revision is from before generate_psa_tests.py - # was moved to the framework submodule. Use the old location. - generate_psa_tests = 'tests/scripts/generate_psa_tests.py' - subprocess.check_call( - [generate_psa_tests] + sorted(to_be_generated), - cwd=git_worktree_path, - ) - for test_file in sorted(storage_data_files): - self._read_storage_tests(git_worktree_path, - test_file, - test_file in to_be_generated, - version.storage_tests) - - def _cleanup_worktree(self, git_worktree_path): - """Remove the specified git worktree.""" - shutil.rmtree(git_worktree_path) - submodule_output = subprocess.check_output( - [self.git_command, "submodule", "foreach", "--recursive", - f'git worktree remove "{git_worktree_path}/$displaypath"'], - cwd=self.repo_path, - stderr=subprocess.STDOUT - ) - self.log.debug(submodule_output.decode("utf-8")) - worktree_output = subprocess.check_output( - [self.git_command, "worktree", "remove", git_worktree_path], - cwd=self.repo_path, - stderr=subprocess.STDOUT - ) - self.log.debug(worktree_output.decode("utf-8")) - - def _get_abi_dump_for_ref(self, version): - """Generate the interface information for the specified git revision.""" - git_worktree_path = self._get_clean_worktree_for_git_revision(version) - self._update_git_submodules(git_worktree_path, version) - if self.check_abi: - self._build_shared_libraries(git_worktree_path, version) - self._get_abi_dumps_from_shared_libraries(version) - if self.check_storage_tests: - self._get_storage_format_tests(version, git_worktree_path) - self._cleanup_worktree(git_worktree_path) - - def _remove_children_with_tag(self, parent, tag): - children = parent.getchildren() - for child in children: - if child.tag == tag: - parent.remove(child) - else: - self._remove_children_with_tag(child, tag) - - def _remove_extra_detail_from_report(self, report_root): - for tag in ['test_info', 'test_results', 'problem_summary', - 'added_symbols', 'affected']: - self._remove_children_with_tag(report_root, tag) - - for report in report_root: - for problems in report.getchildren()[:]: - if not problems.getchildren(): - report.remove(problems) - - def _abi_compliance_command(self, mbed_module, output_path): - """Build the command to run to analyze the library mbed_module. - The report will be placed in output_path.""" - abi_compliance_command = [ - "abi-compliance-checker", - "-l", mbed_module, - "-old", self.old_version.abi_dumps[mbed_module], - "-new", self.new_version.abi_dumps[mbed_module], - "-strict", - "-report-path", output_path, - ] - if self.skip_file: - abi_compliance_command += ["-skip-symbols", self.skip_file, - "-skip-types", self.skip_file] - if self.brief: - abi_compliance_command += ["-report-format", "xml", - "-stdout"] - return abi_compliance_command - - def _is_library_compatible(self, mbed_module, compatibility_report): - """Test if the library mbed_module has remained compatible. - Append a message regarding compatibility to compatibility_report.""" - output_path = os.path.join( - self.report_dir, "{}-{}-{}.html".format( - mbed_module, self.old_version.revision, - self.new_version.revision - ) - ) - try: - subprocess.check_output( - self._abi_compliance_command(mbed_module, output_path), - stderr=subprocess.STDOUT - ) - except subprocess.CalledProcessError as err: - if err.returncode != 1: - raise err - if self.brief: - self.log.info( - "Compatibility issues found for {}".format(mbed_module) - ) - report_root = ET.fromstring(err.output.decode("utf-8")) - self._remove_extra_detail_from_report(report_root) - self.log.info(ET.tostring(report_root).decode("utf-8")) - else: - self.can_remove_report_dir = False - compatibility_report.append( - "Compatibility issues found for {}, " - "for details see {}".format(mbed_module, output_path) - ) - return False - compatibility_report.append( - "No compatibility issues for {}".format(mbed_module) - ) - if not (self.keep_all_reports or self.brief): - os.remove(output_path) - return True - - @staticmethod - def _is_storage_format_compatible(old_tests, new_tests, - compatibility_report): - """Check whether all tests present in old_tests are also in new_tests. - - Append a message regarding compatibility to compatibility_report. - """ - missing = frozenset(old_tests.keys()).difference(new_tests.keys()) - for test_data in sorted(missing): - metadata = old_tests[test_data] - compatibility_report.append( - 'Test case from {} line {} "{}" has disappeared: {}'.format( - metadata.filename, metadata.line_number, - metadata.description, test_data - ) - ) - compatibility_report.append( - 'FAIL: {}/{} storage format test cases have changed or disappeared.'.format( - len(missing), len(old_tests) - ) if missing else - 'PASS: All {} storage format test cases are preserved.'.format( - len(old_tests) - ) - ) - compatibility_report.append( - 'Info: number of storage format tests cases: {} -> {}.'.format( - len(old_tests), len(new_tests) - ) - ) - return not missing - - def get_abi_compatibility_report(self): - """Generate a report of the differences between the reference ABI - and the new ABI. ABI dumps from self.old_version and self.new_version - must be available.""" - compatibility_report = ["Checking evolution from {} to {}".format( - self._pretty_revision(self.old_version), - self._pretty_revision(self.new_version) - )] - compliance_return_code = 0 - - if self.check_abi: - shared_modules = list(set(self.old_version.modules.keys()) & - set(self.new_version.modules.keys())) - for mbed_module in shared_modules: - if not self._is_library_compatible(mbed_module, - compatibility_report): - compliance_return_code = 1 - - if self.check_storage_tests: - if not self._is_storage_format_compatible( - self.old_version.storage_tests, - self.new_version.storage_tests, - compatibility_report): - compliance_return_code = 1 - - for version in [self.old_version, self.new_version]: - for mbed_module, mbed_module_dump in version.abi_dumps.items(): - os.remove(mbed_module_dump) - if self.can_remove_report_dir: - os.rmdir(self.report_dir) - self.log.info("\n".join(compatibility_report)) - return compliance_return_code - - def check_for_abi_changes(self): - """Generate a report of ABI differences - between self.old_rev and self.new_rev.""" - build_tree.check_repo_path() - if self.check_api or self.check_abi: - self.check_abi_tools_are_installed() - self._get_abi_dump_for_ref(self.old_version) - self._get_abi_dump_for_ref(self.new_version) - return self.get_abi_compatibility_report() - - -def run_main(): - try: - parser = argparse.ArgumentParser( - description=__doc__ - ) - parser.add_argument( - "-v", "--verbose", action="store_true", - help="set verbosity level", - ) - parser.add_argument( - "-r", "--report-dir", type=str, default="reports", - help="directory where reports are stored, default is reports", - ) - parser.add_argument( - "-k", "--keep-all-reports", action="store_true", - help="keep all reports, even if there are no compatibility issues", - ) - parser.add_argument( - "-o", "--old-rev", type=str, help="revision for old version.", - required=True, - ) - parser.add_argument( - "-or", "--old-repo", type=str, help="repository for old version." - ) - parser.add_argument( - "-oc", "--old-crypto-rev", type=str, - help="revision for old crypto submodule." - ) - parser.add_argument( - "-ocr", "--old-crypto-repo", type=str, - help="repository for old crypto submodule." - ) - parser.add_argument( - "-n", "--new-rev", type=str, help="revision for new version", - required=True, - ) - parser.add_argument( - "-nr", "--new-repo", type=str, help="repository for new version." - ) - parser.add_argument( - "-nc", "--new-crypto-rev", type=str, - help="revision for new crypto version" - ) - parser.add_argument( - "-ncr", "--new-crypto-repo", type=str, - help="repository for new crypto submodule." - ) - parser.add_argument( - "-s", "--skip-file", type=str, - help=("path to file containing symbols and types to skip " - "(typically \"-s identifiers\" after running " - "\"tests/scripts/list-identifiers.sh --internal\")") - ) - parser.add_argument( - "--check-abi", - action='store_true', default=True, - help="Perform ABI comparison (default: yes)" - ) - parser.add_argument("--no-check-abi", action='store_false', dest='check_abi') - parser.add_argument( - "--check-api", - action='store_true', default=True, - help="Perform API comparison (default: yes)" - ) - parser.add_argument("--no-check-api", action='store_false', dest='check_api') - parser.add_argument( - "--check-storage", - action='store_true', default=True, - help="Perform storage tests comparison (default: yes)" - ) - parser.add_argument("--no-check-storage", action='store_false', dest='check_storage') - parser.add_argument( - "-b", "--brief", action="store_true", - help="output only the list of issues to stdout, instead of a full report", - ) - abi_args = parser.parse_args() - if os.path.isfile(abi_args.report_dir): - print("Error: {} is not a directory".format(abi_args.report_dir)) - parser.exit() - old_version = SimpleNamespace( - version="old", - repository=abi_args.old_repo, - revision=abi_args.old_rev, - commit=None, - crypto_repository=abi_args.old_crypto_repo, - crypto_revision=abi_args.old_crypto_rev, - abi_dumps={}, - storage_tests={}, - modules={} - ) - new_version = SimpleNamespace( - version="new", - repository=abi_args.new_repo, - revision=abi_args.new_rev, - commit=None, - crypto_repository=abi_args.new_crypto_repo, - crypto_revision=abi_args.new_crypto_rev, - abi_dumps={}, - storage_tests={}, - modules={} - ) - configuration = SimpleNamespace( - verbose=abi_args.verbose, - report_dir=abi_args.report_dir, - keep_all_reports=abi_args.keep_all_reports, - brief=abi_args.brief, - check_abi=abi_args.check_abi, - check_api=abi_args.check_api, - check_storage=abi_args.check_storage, - skip_file=abi_args.skip_file - ) - abi_check = AbiChecker(old_version, new_version, configuration) - return_code = abi_check.check_for_abi_changes() - sys.exit(return_code) - except Exception: # pylint: disable=broad-except - # Print the backtrace and exit explicitly so as to exit with - # status 2, not 1. - traceback.print_exc() - sys.exit(2) - +from mbedtls_framework import interface_checks if __name__ == "__main__": - run_main() + interface_checks.run_main() diff --git a/scripts/generate_tls_handshake_tests.py b/scripts/generate_tls_handshake_tests.py index 30f27b1b37..76c8e45d57 100755 --- a/scripts/generate_tls_handshake_tests.py +++ b/scripts/generate_tls_handshake_tests.py @@ -6,12 +6,9 @@ Generate miscellaneous TLS test cases relating to the handshake. # Copyright The Mbed TLS Contributors # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later -import sys - import framework_scripts_path # pylint: disable=unused-import from mbedtls_framework import tls_handshake_tests if __name__ == '__main__': - sys.argv[1:1] = ["--no-tls12-client-hello-defragmentation-support"] tls_handshake_tests.main() diff --git a/scripts/legacy.make b/scripts/legacy.make index b22b8ef8bf..5726f9e82a 100644 --- a/scripts/legacy.make +++ b/scripts/legacy.make @@ -180,6 +180,10 @@ C_SOURCE_FILES = $(wildcard \ tf-psa-crypto/drivers/*/*/*.c \ tf-psa-crypto/drivers/*/*/*/*.c \ tf-psa-crypto/drivers/*/*/*/*/*.c \ + tf-psa-crypto/dispatch/*.[hc] \ + tf-psa-crypto/extras/*.[hc] \ + tf-psa-crypto/platform/*.[hc] \ + tf-psa-crypto/utilities/*.[hc] \ programs/*/*.[hc] \ framework/tests/include/*/*.h framework/tests/include/*/*/*.h \ framework/tests/src/*.c framework/tests/src/*/*.c \ @@ -200,5 +204,9 @@ cscope.in.out cscope.po.out cscope.out: $(C_SOURCE_FILES) cscope -bq -u -Iinclude -Ilibrary -Itf-psa-crypto/core \ -Itf-psa-crypto/include \ -Itf-psa-crypto/drivers/builtin/src \ + -Itf-psa-crypto/dispatch \ + -Itf-psa-crypto/extras \ + -Itf-psa-crypto/platform \ + -Itf-psa-crypto/utilities \ $(patsubst %,-I%,$(wildcard tf-psa-crypto/drivers/*/include)) -Iframework/tests/include $(C_SOURCE_FILES) .PHONY: cscope global diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ec625234dc..09913b56e7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -177,11 +177,11 @@ function(add_test_suite suite_name) # them as PUBLIC. target_include_directories(test_suite_${data_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../framework/tests/include - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../library - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/core - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/drivers/builtin/src) + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/framework/tests/include + ${PROJECT_SOURCE_DIR}/library + ${TF_PSA_CRYPTO_PRIVATE_INCLUDE_DIRS} + ) # Request C11, which is needed for memory poisoning tests set_target_properties(test_suite_${data_name} PROPERTIES C_STANDARD 11) diff --git a/tests/Makefile b/tests/Makefile index 745a09d240..62a7b82e61 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -252,7 +252,19 @@ libtestdriver1.a: cp -Rf ../scripts ./libtestdriver1 cp -Rf ../tf-psa-crypto/core ./libtestdriver1/tf-psa-crypto cp -Rf ../tf-psa-crypto/include ./libtestdriver1/tf-psa-crypto - cp -Rf ../tf-psa-crypto/drivers/builtin ./libtestdriver1/tf-psa-crypto/drivers + cp -Rf ../tf-psa-crypto/drivers/builtin ./libtestdriver1/tf-psa-crypto/drivers/builtin + if [ -d ../tf-psa-crypto/dispatch ]; then \ + cp -Rf ../tf-psa-crypto/dispatch ./libtestdriver1/tf-psa-crypto/dispatch; \ + fi + if [ -d ../tf-psa-crypto/extras ]; then \ + cp -Rf ../tf-psa-crypto/extras ./libtestdriver1/tf-psa-crypto/extras; \ + fi + if [ -d ../tf-psa-crypto/platform ]; then \ + cp -Rf ../tf-psa-crypto/platform ./libtestdriver1/tf-psa-crypto/platform; \ + fi + if [ -d ../tf-psa-crypto/utilities ]; then \ + cp -Rf ../tf-psa-crypto/utilities ./libtestdriver1/tf-psa-crypto/utilities; \ + fi cp -Rf ../tf-psa-crypto/scripts ./libtestdriver1/tf-psa-crypto # Set the test driver base (minimal) configuration. @@ -285,7 +297,18 @@ libtestdriver1.a: perl -i ./scripts/libtestdriver1_rewrite.pl ./libtestdriver1/tf-psa-crypto/drivers/builtin/include/*/*.h perl -i ./scripts/libtestdriver1_rewrite.pl ./libtestdriver1/tf-psa-crypto/drivers/builtin/include/*/*/*.h perl -i ./scripts/libtestdriver1_rewrite.pl ./libtestdriver1/tf-psa-crypto/drivers/builtin/src/*.[ch] - + if [ -d ../tf-psa-crypto/dispatch ]; then \ + perl -i ./scripts/libtestdriver1_rewrite.pl ./libtestdriver1/tf-psa-crypto/dispatch/*.[ch]; \ + fi + if [ -d ../tf-psa-crypto/extras ]; then \ + perl -i ./scripts/libtestdriver1_rewrite.pl ./libtestdriver1/tf-psa-crypto/extras/*.[ch]; \ + fi + if [ -d ../tf-psa-crypto/platform ]; then \ + perl -i ./scripts/libtestdriver1_rewrite.pl ./libtestdriver1/tf-psa-crypto/platform/*.[ch]; \ + fi + if [ -d ../tf-psa-crypto/utilities ]; then \ + perl -i ./scripts/libtestdriver1_rewrite.pl ./libtestdriver1/tf-psa-crypto/utilities/*.[ch]; \ + fi $(MAKE) -C ./libtestdriver1/library CFLAGS="-I../../ $(CFLAGS)" LDFLAGS="$(LDFLAGS)" libmbedcrypto.a cp ./libtestdriver1/library/libmbedcrypto.a ../library/libtestdriver1.a diff --git a/tests/compat.sh b/tests/compat.sh index 2b6f454127..3f44c984fb 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -557,6 +557,7 @@ setup_arguments() # with OpenSSL 1.0.1h, -www, -WWW and -HTTP break DTLS handshakes if is_dtls "$MODE"; then O_SERVER_ARGS="$O_SERVER_ARGS" + M_SERVER_ARGS="$M_SERVER_ARGS read_timeout=1000" else O_SERVER_ARGS="$O_SERVER_ARGS -www" fi diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py index 29c41beba2..2bd4bd8162 100755 --- a/tests/scripts/analyze_outcomes.py +++ b/tests/scripts/analyze_outcomes.py @@ -43,7 +43,7 @@ class CoverageTask(outcome_analysis.CoverageTask): 'DTLS cookie: enabled, IPv6', # Disabled due to OpenSSL bug. # https://github.com/openssl/openssl/issues/18887 - 'DTLS fragmenting: 3d, openssl client, DTLS 1.2', + 'DTLS fragmenting: 3d, MTU=512, openssl client, DTLS 1.2', # We don't run ssl-opt.sh with Valgrind on the CI because # it's extremely slow. We don't intend to change this. 'DTLS fragmenting: proxy MTU: auto-reduction (with valgrind)', diff --git a/tests/scripts/components-basic-checks.sh b/tests/scripts/components-basic-checks.sh index 6a5bc3a1d7..1e480dd12b 100644 --- a/tests/scripts/components-basic-checks.sh +++ b/tests/scripts/components-basic-checks.sh @@ -12,8 +12,6 @@ component_check_recursion () { msg "Check: recursion.pl" # < 1s ./framework/scripts/recursion.pl library/*.c - ./framework/scripts/recursion.pl ${PSA_CORE_PATH}/*.c - ./framework/scripts/recursion.pl ${BUILTIN_SRC_PATH}/*.c } component_check_generated_files () { diff --git a/tests/scripts/components-configuration-crypto.sh b/tests/scripts/components-configuration-crypto.sh index baa59fb5f5..6a6b0a70de 100644 --- a/tests/scripts/components-configuration-crypto.sh +++ b/tests/scripts/components-configuration-crypto.sh @@ -10,6 +10,7 @@ ################################################################ CMAKE_BUILTIN_BUILD_DIR="tf-psa-crypto/drivers/builtin/CMakeFiles/builtin.dir/src" +CMAKE_EXTRAS_BUILD_DIR="tf-psa-crypto/extras/CMakeFiles/extras.dir" component_test_psa_crypto_key_id_encodes_owner () { msg "build: full config + PSA_CRYPTO_KEY_ID_ENCODES_OWNER, cmake, gcc, ASan" @@ -280,8 +281,13 @@ component_full_no_pkparse_pkwrite () { cmake --build . # Ensure that PK_[PARSE|WRITE]_C were not re-enabled accidentally (additive config). - not grep mbedtls_pk_parse_key ${CMAKE_BUILTIN_BUILD_DIR}/pkparse.c.o - not grep mbedtls_pk_write_key_der ${CMAKE_BUILTIN_BUILD_DIR}/pkwrite.c.o + if [ -f ${TF_PSA_CRYPTO_ROOT_DIR}/extras/pkparse.c ]; then + not grep mbedtls_pk_parse_key ${CMAKE_EXTRAS_BUILD_DIR}/pkparse.c.o + not grep mbedtls_pk_write_key_der ${CMAKE_EXTRAS_BUILD_DIR}/pkwrite.c.o + else + not grep mbedtls_pk_parse_key ${CMAKE_BUILTIN_BUILD_DIR}/pkparse.c.o + not grep mbedtls_pk_write_key_der ${CMAKE_BUILTIN_BUILD_DIR}/pkwrite.c.o + fi msg "test: full without pkparse and pkwrite" ctest @@ -302,7 +308,11 @@ component_full_no_pkwrite () { make # Ensure that PK_WRITE_C was not re-enabled accidentally (additive config). - not grep mbedtls_pk_write_key_der ${CMAKE_BUILTIN_BUILD_DIR}/pkwrite.c.o + if [ -f ${TF_PSA_CRYPTO_ROOT_DIR}/extras/pkwrite.c ]; then + not grep mbedtls_pk_write_key_der ${CMAKE_EXTRAS_BUILD_DIR}/pkwrite.c.o + else + not grep mbedtls_pk_write_key_der ${CMAKE_BUILTIN_BUILD_DIR}/pkwrite.c.o + fi msg "test: full without pkwrite" make test @@ -329,8 +339,13 @@ component_test_crypto_full_md_light_only () { cmake --build . # Make sure we don't have the HMAC functions, but the hashing functions - not grep mbedtls_md_hmac ${CMAKE_BUILTIN_BUILD_DIR}/md.c.o - grep mbedtls_md ${CMAKE_BUILTIN_BUILD_DIR}/md.c.o + if [ -f ${TF_PSA_CRYPTO_ROOT_DIR}/extras/md.c ]; then + not grep mbedtls_md_hmac ${CMAKE_EXTRAS_BUILD_DIR}/md.c.o + grep mbedtls_md ${CMAKE_EXTRAS_BUILD_DIR}/md.c.o + else + not grep mbedtls_md_hmac ${CMAKE_BUILTIN_BUILD_DIR}/md.c.o + grep mbedtls_md ${CMAKE_BUILTIN_BUILD_DIR}/md.c.o + fi msg "test: crypto_full with only the light subset of MD" ctest @@ -1668,7 +1683,11 @@ component_test_psa_crypto_config_accel_hmac () { helper_libtestdriver1_make_main "$loc_accel_list" # Ensure that built-in support for HMAC is disabled. - not grep mbedtls_md_hmac ${BUILTIN_SRC_PATH}/md.o + if [ -f ${TF_PSA_CRYPTO_ROOT_DIR}/extras/md.c ]; then + not grep mbedtls_md_hmac ${TF_PSA_CRYPTO_ROOT_DIR}/extras/md.o + else + not grep mbedtls_md_hmac ${BUILTIN_SRC_PATH}/md.o + fi # Run the tests # ------------- diff --git a/tests/scripts/components-configuration-tls.sh b/tests/scripts/components-configuration-tls.sh index 5a77c4defc..d017eef182 100644 --- a/tests/scripts/components-configuration-tls.sh +++ b/tests/scripts/components-configuration-tls.sh @@ -165,6 +165,7 @@ component_test_tls1_2_ccm_psk_dtls () { msg "build: configs/config-ccm-psk-dtls1_2.h" MBEDTLS_CONFIG="configs/config-ccm-psk-dtls1_2.h" CRYPTO_CONFIG="configs/crypto-config-ccm-psk-tls1_2.h" + tf-psa-crypto/scripts/config.py -f "$CRYPTO_CONFIG" set MBEDTLS_HAVE_TIME CC=$ASAN_CC cmake -DMBEDTLS_CONFIG_FILE="$MBEDTLS_CONFIG" -DTF_PSA_CRYPTO_CONFIG_FILE="$CRYPTO_CONFIG" -D CMAKE_BUILD_TYPE:String=Asan . make diff --git a/tests/scripts/components-platform.sh b/tests/scripts/components-platform.sh index d6eef6f781..b68a4aeafc 100644 --- a/tests/scripts/components-platform.sh +++ b/tests/scripts/components-platform.sh @@ -439,6 +439,18 @@ component_build_arm_none_eabi_gcc () { ${ARM_NONE_EABI_GCC_PREFIX}size -t library/*.o ${ARM_NONE_EABI_GCC_PREFIX}size -t ${PSA_CORE_PATH}/*.o ${ARM_NONE_EABI_GCC_PREFIX}size -t ${BUILTIN_SRC_PATH}/*.o + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o + fi } component_build_arm_linux_gnueabi_gcc_arm5vte () { @@ -455,6 +467,18 @@ component_build_arm_linux_gnueabi_gcc_arm5vte () { ${ARM_LINUX_GNUEABI_GCC_PREFIX}size -t library/*.o ${ARM_LINUX_GNUEABI_GCC_PREFIX}size -t ${PSA_CORE_PATH}/*.o ${ARM_LINUX_GNUEABI_GCC_PREFIX}size -t ${BUILTIN_SRC_PATH}/*.o + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o" > /dev/null; then + ${ARM_LINUX_GNUEABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o" > /dev/null; then + ${ARM_LINUX_GNUEABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o" > /dev/null; then + ${ARM_LINUX_GNUEABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o" > /dev/null; then + ${ARM_LINUX_GNUEABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o + fi } support_build_arm_linux_gnueabi_gcc_arm5vte () { @@ -473,6 +497,18 @@ component_build_arm_none_eabi_gcc_arm5vte () { ${ARM_NONE_EABI_GCC_PREFIX}size -t library/*.o ${ARM_NONE_EABI_GCC_PREFIX}size -t ${PSA_CORE_PATH}/*.o ${ARM_NONE_EABI_GCC_PREFIX}size -t ${BUILTIN_SRC_PATH}/*.o + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o + fi } component_build_arm_none_eabi_gcc_m0plus () { @@ -484,6 +520,18 @@ component_build_arm_none_eabi_gcc_m0plus () { ${ARM_NONE_EABI_GCC_PREFIX}size -t library/*.o ${ARM_NONE_EABI_GCC_PREFIX}size -t ${PSA_CORE_PATH}/*.o ${ARM_NONE_EABI_GCC_PREFIX}size -t ${BUILTIN_SRC_PATH}/*.o + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o" > /dev/null; then + ${ARM_NONE_EABI_GCC_PREFIX}size -t ${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o + fi for lib in library/*.a; do echo "$lib:" ${ARM_NONE_EABI_GCC_PREFIX}size -t $lib | grep TOTALS @@ -499,6 +547,18 @@ component_build_arm_none_eabi_gcc_no_udbl_division () { not grep __aeabi_uldiv library/*.o not grep __aeabi_uldiv ${PSA_CORE_PATH}/*.o not grep __aeabi_uldiv ${BUILTIN_SRC_PATH}/*.o + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o" > /dev/null; then + not grep __aeabi_uldiv ${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o" > /dev/null; then + not grep __aeabi_uldiv ${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o" > /dev/null; then + not grep __aeabi_uldiv ${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o" > /dev/null; then + not grep __aeabi_uldiv ${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o + fi } component_build_arm_none_eabi_gcc_no_64bit_multiplication () { @@ -510,6 +570,18 @@ component_build_arm_none_eabi_gcc_no_64bit_multiplication () { not grep __aeabi_lmul library/*.o not grep __aeabi_lmul ${PSA_CORE_PATH}/*.o not grep __aeabi_lmul ${BUILTIN_SRC_PATH}/*.o + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o" > /dev/null; then + not grep __aeabi_lmul ${TF_PSA_CRYPTO_ROOT_DIR}/dispatch/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o" > /dev/null; then + not grep __aeabi_lmul ${TF_PSA_CRYPTO_ROOT_DIR}/extras/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o" > /dev/null; then + not grep __aeabi_lmul ${TF_PSA_CRYPTO_ROOT_DIR}/platform/*.o + fi + if compgen -G "${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o" > /dev/null; then + not grep __aeabi_lmul ${TF_PSA_CRYPTO_ROOT_DIR}/utilities/*.o + fi } component_build_arm_clang_thumb () { diff --git a/tests/scripts/list_internal_identifiers.py b/tests/scripts/list_internal_identifiers.py index 2cbfdce8d5..445aeda352 100755 --- a/tests/scripts/list_internal_identifiers.py +++ b/tests/scripts/list_internal_identifiers.py @@ -37,7 +37,9 @@ def main(): "include/mbedtls/*_internal.h", "library/*.h", "tf-psa-crypto/core/*.h", - "tf-psa-crypto/drivers/builtin/src/*.h" + "tf-psa-crypto/drivers/builtin/src/*.h", + "tf-psa-crypto/platform/*.h", + "tf-psa-crypto/utilities/*.h", ])[0] result.sort(key=lambda x: x.name) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 9b5987188f..a999c94f5b 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -9931,7 +9931,7 @@ run_test "DTLS reassembly: more fragmentation (gnutls server)" \ requires_gnutls requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS reassembly: more fragmentation, nbio (gnutls server)" \ - "$G_SRV -u --mtu 128" \ + "$G_SRV -u --mtu 109" \ "$P_CLI dtls=1 nbio=2 debug_level=2" \ 0 \ -c "found fragmented DTLS handshake message" \ @@ -9943,7 +9943,7 @@ requires_gnutls requires_config_enabled MBEDTLS_SSL_RENEGOTIATION requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS reassembly: fragmentation, renego (gnutls server)" \ - "$G_SRV -u --mtu 256" \ + "$G_SRV -u --mtu 241" \ "$P_CLI debug_level=3 dtls=1 renegotiation=1 renegotiate=1" \ 0 \ -c "found fragmented DTLS handshake message" \ @@ -9971,6 +9971,52 @@ run_test "DTLS reassembly: fragmentation, nbio, renego (gnutls server)" \ -C "error" \ -s "Extra-header:" +requires_gnutls +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS reassembly: no fragmentation (gnutls client)" \ + "$P_SRV debug_level=2 dtls=1" \ + "$G_NEXT_CLI -u --mtu 2048 --insecure 127.0.0.1" \ + 0 \ + -S "found fragmented DTLS handshake message" \ + -S "error" + +requires_gnutls +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS reassembly: some fragmentation (gnutls client)" \ + "$P_SRV debug_level=2 dtls=1 auth_mode=required" \ + "$G_NEXT_CLI -u --mtu 211 --insecure 127.0.0.1 --x509certfile $DATA_FILES_PATH/server5.crt --x509keyfile $DATA_FILES_PATH/server5.key" \ + 0 \ + -s "found fragmented DTLS handshake message" \ + -s "Certificate handshake message has been buffered and reassembled" \ + -S "error" + +# Set the MTU to 128 bytes. The minimum size of a DTLS 1.2 record +# containing a ClientHello handshake message is 69 bytes, without any cookie, +# ciphersuite, or extension. With an MTU of 128 bytes, the ClientHello handshake +# message is therefore very likely to be fragmented, regardless of the +# GnuTLS client version. For example, the ClientHello sent by the GnuTLS 3.7.2 +# client is 206 bytes in this test. +requires_gnutls +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS reassembly: more fragmentation (gnutls client)" \ + "$P_SRV debug_level=2 dtls=1" \ + "$G_NEXT_CLI -u --mtu 103 --insecure 127.0.0.1" \ + 0 \ + -s "ClientHello handshake message has been buffered and reassembled" \ + -S "error" + +requires_gnutls +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS reassembly: more fragmentation, nbio (gnutls client)" \ + "$P_SRV debug_level=2 dtls=1 nbio=2" \ + "$G_NEXT_CLI -u --mtu 103 --insecure 127.0.0.1" \ + 0 \ + -s "ClientHello handshake message has been buffered and reassembled" \ + -S "error" + +# No fragmentation and renegotiation tests with GnuTLS client as the feature +# does not work properly. + requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS reassembly: no fragmentation (openssl server)" \ "$O_SRV -dtls -mtu 2048" \ @@ -9994,13 +10040,45 @@ run_test "DTLS reassembly: fragmentation (openssl server)" \ requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS reassembly: fragmentation, nbio (openssl server)" \ - "$O_SRV -dtls -mtu 256" \ + "$O_SRV -dtls -mtu 273" \ "$P_CLI dtls=1 nbio=2 debug_level=2" \ 0 \ -c "found fragmented DTLS handshake message" \ -c "Certificate handshake message has been buffered and reassembled" \ -C "error" +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS reassembly: no fragmentation (openssl client)" \ + "$P_SRV debug_level=2 dtls=1 auth_mode=required" \ + "$O_NEXT_CLI -dtls -mtu 2048 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \ + 0 \ + -S "found fragmented DTLS handshake message" \ + -S "error" + +# Minimum possible MTU for OpenSSL server: 256 bytes. +# We expect the client Certificate handshake message to be fragmented and +# verify that this is the case. With OpenSSL 3.0.13, the ClientHello handshake +# message is 224 bytes and also fragmented. However, it may not hold across +# OpenSSL version updates. Therefore, we do not verify that the ClientHello is +# reassembled by the server. +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS reassembly: some fragmentation (openssl client)" \ + "$P_SRV debug_level=2 dtls=1 auth_mode=required" \ + "$O_NEXT_CLI -dtls -mtu 256 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \ + 0 \ + -s "found fragmented DTLS handshake message" \ + -s "Certificate handshake message has been buffered and reassembled" \ + -S "error" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS reassembly: fragmentation, nbio (openssl client)" \ + "$P_SRV debug_level=2 dtls=1 auth_mode=required nbio=2" \ + "$O_NEXT_CLI -dtls -mtu 269 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \ + 0 \ + -s "found fragmented DTLS handshake message" \ + -s "Certificate handshake message has been buffered and reassembled" \ + -S "error" + # Tests for sending fragmented handshake messages with DTLS # # Use client auth when we need the client to send large messages, @@ -10242,20 +10320,20 @@ run_test "DTLS fragmenting: server (MTU)" \ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC -requires_max_content_len 2048 +requires_max_content_len 1038 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 -run_test "DTLS fragmenting: both (MTU=1024)" \ - -p "$P_PXY mtu=1024" \ +run_test "DTLS fragmenting: both (MTU=1038)" \ + -p "$P_PXY mtu=1038" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ key_file=$DATA_FILES_PATH/server7.key \ hs_timeout=2500-60000 \ - mtu=1024" \ + mtu=1038" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ key_file=$DATA_FILES_PATH/server8.key \ hs_timeout=2500-60000 \ - mtu=1024" \ + mtu=1038" \ 0 \ -s "found fragmented DTLS handshake message" \ -c "found fragmented DTLS handshake message" \ @@ -10265,25 +10343,108 @@ run_test "DTLS fragmenting: both (MTU=1024)" \ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_hash_alg SHA_256 -requires_max_content_len 2048 -run_test "DTLS fragmenting: both (MTU=512)" \ - -p "$P_PXY mtu=512" \ +requires_max_content_len 509 +run_test "DTLS fragmenting: both (MTU=509)" \ + -p "$P_PXY mtu=509" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ key_file=$DATA_FILES_PATH/server7.key \ hs_timeout=2500-60000 \ - mtu=512" \ + mtu=509" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ key_file=$DATA_FILES_PATH/server8.key \ force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ hs_timeout=2500-60000 \ - mtu=512" \ + mtu=509" \ 0 \ -s "found fragmented DTLS handshake message" \ -c "found fragmented DTLS handshake message" \ -C "error" +# Depending on the ciphersuite selected to encrypt the application data, the +# maximum application data payload per record may be small with an MTU of 128. +# For example, with TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384, this maximum is +# 35 bytes. We therefore reduce the size of the client request and the server +# response in this test and the two following tests. +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_max_content_len 128 +run_test "DTLS fragmenting: both (MTU=128)" \ + -p "$P_PXY mtu=128" \ + "$P_SRV dtls=1 debug_level=5 auth_mode=required \ + crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ + key_file=$DATA_FILES_PATH/server7.key \ + response_size=8 \ + hs_timeout=2500-60000 \ + mtu=128" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ + key_file=$DATA_FILES_PATH/server8.key \ + request_size=8 \ + hs_timeout=2500-60000 \ + mtu=128" \ + 0 \ + -s "found fragmented DTLS handshake message" \ + -s "fragmenting Certificate handshake message" \ + -s "fragmenting ServerKeyExchange handshake message" \ + -c "found fragmented DTLS handshake message" \ + -c "fragmenting ClientHello handshake message" \ + -c "fragmenting Certificate handshake message" \ + -c "fragmenting CertificateVerify handshake message" \ + -C "error" + +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_max_content_len 2048 +run_test "DTLS fragmenting: both (MTU=107)" \ + -p "$P_PXY mtu=107" \ + "$P_SRV dtls=1 debug_level=5 auth_mode=required \ + crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ + key_file=$DATA_FILES_PATH/server7.key \ + response_size=8 \ + hs_timeout=2500-60000 \ + mtu=107" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ + key_file=$DATA_FILES_PATH/server8.key \ + request_size=8 \ + hs_timeout=2500-60000 \ + mtu=107" \ + 0 \ + -s "found fragmented DTLS handshake message" \ + -s "fragmenting Certificate handshake message" \ + -s "fragmenting ServerKeyExchange handshake message" \ + -c "found fragmented DTLS handshake message" \ + -c "fragmenting ClientHello handshake message" \ + -c "fragmenting Certificate handshake message" \ + -c "fragmenting CertificateVerify handshake message" \ + -C "error" + +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_max_content_len 2048 +run_test "DTLS fragmenting: both (MTU=133)" \ + -p "$P_PXY mtu=133" \ + "$P_SRV dtls=1 debug_level=5 auth_mode=required \ + crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ + key_file=$DATA_FILES_PATH/server7.key \ + response_size=8 \ + hs_timeout=2500-60000 \ + mtu=133" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ + key_file=$DATA_FILES_PATH/server8.key \ + request_size=8 \ + hs_timeout=2500-60000 \ + mtu=133" \ + 0 \ + -s "found fragmented DTLS handshake message" \ + -s "fragmenting Certificate handshake message" \ + -s "fragmenting ServerKeyExchange handshake message" \ + -c "found fragmented DTLS handshake message" \ + -c "fragmenting ClientHello handshake message" \ + -c "fragmenting Certificate handshake message" \ + -c "fragmenting CertificateVerify handshake message" \ + -C "error" + # Test for automatic MTU reduction on repeated resend. # Forcing ciphersuite for this test to fit the MTU of 508 with full config. # The ratio of max/min timeout should ideally equal 4 to accept two @@ -10337,7 +10498,7 @@ run_test "DTLS fragmenting: proxy MTU: auto-reduction (with valgrind)" \ not_with_valgrind # spurious autoreduction due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC -requires_max_content_len 2048 +requires_max_content_len 1024 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS fragmenting: proxy MTU, simple handshake (MTU=1024)" \ -p "$P_PXY mtu=1024" \ @@ -10364,7 +10525,7 @@ run_test "DTLS fragmenting: proxy MTU, simple handshake (MTU=1024)" \ not_with_valgrind # spurious autoreduction due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC -requires_max_content_len 2048 +requires_max_content_len 512 run_test "DTLS fragmenting: proxy MTU, simple handshake (MTU=512)" \ -p "$P_PXY mtu=512" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10387,7 +10548,7 @@ run_test "DTLS fragmenting: proxy MTU, simple handshake (MTU=512)" \ not_with_valgrind # spurious autoreduction due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC -requires_max_content_len 2048 +requires_max_content_len 1024 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS fragmenting: proxy MTU, simple handshake, nbio (MTU=1024)" \ -p "$P_PXY mtu=1024" \ @@ -10411,7 +10572,7 @@ run_test "DTLS fragmenting: proxy MTU, simple handshake, nbio (MTU=1024)" \ not_with_valgrind # spurious autoreduction due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC -requires_max_content_len 2048 +requires_max_content_len 512 run_test "DTLS fragmenting: proxy MTU, simple handshake, nbio (MTU=512)" \ -p "$P_PXY mtu=512" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10444,7 +10605,7 @@ run_test "DTLS fragmenting: proxy MTU, simple handshake, nbio (MTU=512)" \ not_with_valgrind # spurious autoreduction due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC -requires_max_content_len 2048 +requires_max_content_len 1450 run_test "DTLS fragmenting: proxy MTU, resumed handshake" \ -p "$P_PXY mtu=1450" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10471,7 +10632,7 @@ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_hash_alg SHA_256 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -requires_max_content_len 2048 +requires_max_content_len 512 run_test "DTLS fragmenting: proxy MTU, ChachaPoly renego" \ -p "$P_PXY mtu=512" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10500,7 +10661,7 @@ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_hash_alg SHA_256 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -requires_max_content_len 2048 +requires_max_content_len 512 run_test "DTLS fragmenting: proxy MTU, AES-GCM renego" \ -p "$P_PXY mtu=512" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10529,7 +10690,7 @@ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_hash_alg SHA_256 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -requires_max_content_len 2048 +requires_max_content_len 1024 run_test "DTLS fragmenting: proxy MTU, AES-CCM renego" \ -p "$P_PXY mtu=1024" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10559,7 +10720,7 @@ requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_hash_alg SHA_256 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION requires_config_enabled MBEDTLS_SSL_ENCRYPT_THEN_MAC -requires_max_content_len 2048 +requires_max_content_len 1024 run_test "DTLS fragmenting: proxy MTU, AES-CBC EtM renego" \ -p "$P_PXY mtu=1024" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10588,7 +10749,7 @@ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_hash_alg SHA_256 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -requires_max_content_len 2048 +requires_max_content_len 1024 run_test "DTLS fragmenting: proxy MTU, AES-CBC non-EtM renego" \ -p "$P_PXY mtu=1024" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10614,7 +10775,7 @@ run_test "DTLS fragmenting: proxy MTU, AES-CBC non-EtM renego" \ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC client_needs_more_time 2 -requires_max_content_len 2048 +requires_max_content_len 512 run_test "DTLS fragmenting: proxy MTU + 3d" \ -p "$P_PXY mtu=512 drop=8 delay=8 duplicate=8" \ "$P_SRV dgram_packing=0 dtls=1 debug_level=2 auth_mode=required \ @@ -10635,7 +10796,7 @@ run_test "DTLS fragmenting: proxy MTU + 3d" \ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC client_needs_more_time 2 -requires_max_content_len 2048 +requires_max_content_len 512 run_test "DTLS fragmenting: proxy MTU + 3d, nbio" \ -p "$P_PXY mtu=512 drop=8 delay=8 duplicate=8" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ @@ -10660,16 +10821,32 @@ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_gnutls requires_max_content_len 2048 -run_test "DTLS fragmenting: gnutls server, DTLS 1.2" \ +run_test "DTLS fragmenting: MTU=501, gnutls server, DTLS 1.2" \ "$G_SRV -u" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ key_file=$DATA_FILES_PATH/server8.key \ - mtu=512 force_version=dtls12" \ + mtu=501 force_version=dtls12" \ 0 \ -c "fragmenting Certificate handshake message" \ -C "error" +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC +requires_gnutls +requires_max_content_len 2048 +run_test "DTLS fragmenting: MTU=110, gnutls server, DTLS 1.2" \ + "$G_NEXT_SRV -u" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ + key_file=$DATA_FILES_PATH/server8.key \ + request_size=35 \ + mtu=110 force_version=dtls12" \ + 0 \ + -c "fragmenting ClientHello handshake message" \ + -c "fragmenting Certificate handshake message" \ + -C "error" + # We use --insecure for the GnuTLS client because it expects # the hostname / IP it connects to to be the name used in the # certificate obtained from the server. Here, however, it @@ -10682,11 +10859,25 @@ requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_gnutls requires_not_i686 requires_max_content_len 2048 -run_test "DTLS fragmenting: gnutls client, DTLS 1.2" \ +run_test "DTLS fragmenting: MTU=536, gnutls client, DTLS 1.2" \ "$P_SRV dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ key_file=$DATA_FILES_PATH/server7.key \ - mtu=512 force_version=dtls12" \ + mtu=536 force_version=dtls12" \ + "$G_CLI -u --insecure 127.0.0.1" \ + 0 \ + -s "fragmenting Certificate handshake message" + +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC +requires_gnutls +requires_not_i686 +requires_max_content_len 2048 +run_test "DTLS fragmenting: MTU=149, gnutls client, DTLS 1.2" \ + "$P_SRV dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ + key_file=$DATA_FILES_PATH/server7.key \ + mtu=149 force_version=dtls12" \ "$G_CLI -u --insecure 127.0.0.1" \ 0 \ -s "fragmenting Certificate handshake message" @@ -10694,20 +10885,39 @@ run_test "DTLS fragmenting: gnutls client, DTLS 1.2" \ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_max_content_len 2048 -run_test "DTLS fragmenting: openssl server, DTLS 1.2" \ +run_test "DTLS fragmenting: MTU=525, openssl server, DTLS 1.2" \ "$O_SRV -dtls1_2 -verify 10" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ key_file=$DATA_FILES_PATH/server8.key \ - mtu=512 force_version=dtls12" \ + mtu=525 force_version=dtls12" \ 0 \ -c "fragmenting Certificate handshake message" \ -C "error" +# Depending on the ciphersuite selected to encrypt the application data, the +# maximum application data payload per record may be small with an MTU of 128. +# For example, with TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384, this maximum is +# 35 bytes. We therefore reduce the size of the client request in this test. +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC +requires_max_content_len 2048 +run_test "DTLS fragmenting: MTU=130, openssl server, DTLS 1.2" \ + "$O_NEXT_SRV -dtls1_2 -verify 10" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ + key_file=$DATA_FILES_PATH/server8.key \ + request_size=8 \ + mtu=130 force_version=dtls12" \ + 0 \ + -c "fragmenting ClientHello handshake message" \ + -c "fragmenting Certificate handshake message" \ + -C "error" + requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC requires_max_content_len 2048 -run_test "DTLS fragmenting: openssl client, DTLS 1.2" \ +run_test "DTLS fragmenting: MTU=512, openssl client, DTLS 1.2" \ "$P_SRV dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ key_file=$DATA_FILES_PATH/server7.key \ @@ -10716,6 +10926,18 @@ run_test "DTLS fragmenting: openssl client, DTLS 1.2" \ 0 \ -s "fragmenting Certificate handshake message" +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC +requires_max_content_len 2048 +run_test "DTLS fragmenting: MTU=131, openssl client, DTLS 1.2" \ + "$P_SRV dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ + key_file=$DATA_FILES_PATH/server7.key \ + mtu=131 force_version=dtls12" \ + "$O_CLI -dtls1_2" \ + 0 \ + -s "fragmenting Certificate handshake message" + # interop tests for DTLS fragmentating with unreliable connection # # again we just want to test that the we fragment in a way that @@ -10725,28 +10947,61 @@ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC client_needs_more_time 4 requires_max_content_len 2048 -run_test "DTLS fragmenting: 3d, gnutls server, DTLS 1.2" \ +run_test "DTLS fragmenting: 3d, MTU=434, gnutls server, DTLS 1.2" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \ "$G_NEXT_SRV -u" \ "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ key_file=$DATA_FILES_PATH/server8.key \ - hs_timeout=250-60000 mtu=512 force_version=dtls12" \ + hs_timeout=250-60000 mtu=434 force_version=dtls12" \ 0 \ -c "fragmenting Certificate handshake message" \ -C "error" +requires_gnutls_next +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC +client_needs_more_time 6 +requires_max_content_len 2048 +run_test "DTLS fragmenting: 3d, MTU=103, gnutls server, DTLS 1.2" \ + -p "$P_PXY drop=8 delay=8 duplicate=8" \ + "$G_NEXT_SRV -u" \ + "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ + key_file=$DATA_FILES_PATH/server8.key \ + request_size=35 \ + hs_timeout=250-60000 mtu=103 force_version=dtls12" \ + 0 \ + -c "fragmenting ClientHello handshake message" \ + -c "fragmenting Certificate handshake message" \ + -C "error" + requires_gnutls_next requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC client_needs_more_time 4 requires_max_content_len 2048 -run_test "DTLS fragmenting: 3d, gnutls client, DTLS 1.2" \ +run_test "DTLS fragmenting: 3d, MTU=614, gnutls client, DTLS 1.2" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \ "$P_SRV dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ key_file=$DATA_FILES_PATH/server7.key \ - hs_timeout=250-60000 mtu=512 force_version=dtls12" \ + hs_timeout=250-60000 mtu=614 force_version=dtls12" \ + "$G_NEXT_CLI -u --insecure 127.0.0.1" \ + 0 \ + -s "fragmenting Certificate handshake message" + +requires_gnutls_next +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC +client_needs_more_time 4 +requires_max_content_len 2048 +run_test "DTLS fragmenting: 3d, MTU=116, gnutls client, DTLS 1.2" \ + -p "$P_PXY drop=8 delay=8 duplicate=8" \ + "$P_SRV dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ + key_file=$DATA_FILES_PATH/server7.key \ + hs_timeout=250-60000 mtu=116 force_version=dtls12" \ "$G_NEXT_CLI -u --insecure 127.0.0.1" \ 0 \ -s "fragmenting Certificate handshake message" @@ -10758,17 +11013,39 @@ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC client_needs_more_time 4 requires_max_content_len 2048 -run_test "DTLS fragmenting: 3d, openssl server, DTLS 1.2" \ +run_test "DTLS fragmenting: 3d, MTU=541, openssl server, DTLS 1.2" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \ "$O_NEXT_SRV -dtls1_2 -verify 10" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ key_file=$DATA_FILES_PATH/server8.key \ - hs_timeout=250-60000 mtu=512 force_version=dtls12" \ + hs_timeout=250-60000 mtu=541 force_version=dtls12" \ 0 \ -c "fragmenting Certificate handshake message" \ -C "error" +# Depending on the ciphersuite selected to encrypt the application data, the +# maximum application data payload per record may be small with an MTU of 128. +# For example, with TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384, this maximum is +# 35 bytes. We therefore reduce the size of the client request in this test. +requires_openssl_next +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC +client_needs_more_time 4 +requires_max_content_len 2048 +run_test "DTLS fragmenting: 3d, MTU=108, openssl server, DTLS 1.2" \ + -p "$P_PXY drop=8 delay=8 duplicate=8" \ + "$O_NEXT_SRV -dtls1_2 -verify 10" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=$DATA_FILES_PATH/server8_int-ca2.crt \ + key_file=$DATA_FILES_PATH/server8.key \ + request_size=8 \ + hs_timeout=250-60000 mtu=108 force_version=dtls12" \ + 0 \ + -c "fragmenting ClientHello handshake message" \ + -c "fragmenting Certificate handshake message" \ + -C "error" + ## the test below will time out with certain seed. ## The cause is an openssl bug (https://github.com/openssl/openssl/issues/18887) skip_next_test @@ -10776,7 +11053,7 @@ requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC client_needs_more_time 4 requires_max_content_len 2048 -run_test "DTLS fragmenting: 3d, openssl client, DTLS 1.2" \ +run_test "DTLS fragmenting: 3d, MTU=512, openssl client, DTLS 1.2" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \ "$P_SRV dtls=1 debug_level=2 \ crt_file=$DATA_FILES_PATH/server7_int-ca.crt \ @@ -11863,7 +12140,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS proxy: 3d, openssl server, fragmentation" \ -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \ - "$O_NEXT_SRV -dtls1_2 -mtu 256" \ + "$O_NEXT_SRV -dtls1_2 -mtu 277" \ "$P_CLI dgram_packing=0 dtls=1 debug_level=2 hs_timeout=500-60000 tickets=0" \ 0 \ -c "HTTP/1.0 200 OK" \ @@ -11875,12 +12152,49 @@ not_with_valgrind # risk of non-mbedtls peer timing out requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS proxy: 3d, openssl server, fragmentation, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \ - "$O_NEXT_SRV -dtls1_2 -mtu 256" \ + "$O_NEXT_SRV -dtls1_2 -mtu 268" \ "$P_CLI dgram_packing=0 dtls=1 debug_level=2 hs_timeout=500-60000 nbio=2 tickets=0" \ 0 \ -c "HTTP/1.0 200 OK" \ -c "Certificate handshake message has been buffered and reassembled" +requires_openssl_next +client_needs_more_time 6 +not_with_valgrind # risk of non-mbedtls peer timing out +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS proxy: 3d, openssl client" \ + -p "$P_PXY drop=5 delay=5 duplicate=5" \ + "$P_SRV dgram_packing=0 dtls=1 hs_timeout=500-60000 tickets=0" \ + "$O_NEXT_CLI -dtls1_2 -mtu 2048" \ + 0 \ + -s "HTTP/1.0 200 OK" + +requires_openssl_next +client_needs_more_time 8 +not_with_valgrind # risk of non-mbedtls peer timing out +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS proxy: 3d, openssl client, fragmentation" \ + -p "$P_PXY drop=5 delay=5 duplicate=5" \ + "$P_SRV debug_level=2 dgram_packing=0 auth_mode=required dtls=1 hs_timeout=500-60000 tickets=0" \ + "$O_NEXT_CLI -dtls1_2 -mtu 260 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \ + 0 \ + -s "HTTP/1.0 200 OK" \ + -s "found fragmented DTLS handshake message" \ + -s "Certificate handshake message has been buffered and reassembled" + +requires_openssl_next +client_needs_more_time 8 +not_with_valgrind # risk of non-mbedtls peer timing out +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS proxy: 3d, openssl client, fragmentation, nbio" \ + -p "$P_PXY drop=5 delay=5 duplicate=5" \ + "$P_SRV debug_level=2 dgram_packing=0 auth_mode=required dtls=1 hs_timeout=500-60000 nbio=2 tickets=0" \ + "$O_NEXT_CLI -dtls1_2 -mtu 259 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \ + 0 \ + -s "HTTP/1.0 200 OK" \ + -s "found fragmented DTLS handshake message" \ + -s "Certificate handshake message has been buffered and reassembled" + requires_gnutls client_needs_more_time 6 not_with_valgrind # risk of non-mbedtls peer timing out @@ -11899,7 +12213,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS proxy: 3d, gnutls server, fragmentation" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$G_NEXT_SRV -u --mtu 512" \ + "$G_NEXT_SRV -u --mtu 499" \ "$P_CLI dgram_packing=0 dtls=1 debug_level=2 hs_timeout=500-60000" \ 0 \ -s "Extra-header:" \ @@ -11912,13 +12226,54 @@ not_with_valgrind # risk of non-mbedtls peer timing out requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS proxy: 3d, gnutls server, fragmentation, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$G_NEXT_SRV -u --mtu 512" \ + "$G_NEXT_SRV -u --mtu 528" \ "$P_CLI dgram_packing=0 dtls=1 debug_level=2 hs_timeout=500-60000 nbio=2" \ 0 \ -s "Extra-header:" \ -c "Extra-header:" \ -c "Certificate handshake message has been buffered and reassembled" +requires_gnutls +client_needs_more_time 6 +not_with_valgrind # risk of non-mbedtls peer timing out +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS proxy: 3d, gnutls client" \ + -p "$P_PXY drop=5 delay=5 duplicate=5" \ + "$P_SRV dgram_packing=0 dtls=1" \ + "$G_NEXT_CLI -u --mtu 2048 --insecure 127.0.0.1" \ + 0 \ + -s "HTTP/1.0 200 OK" + +# Set the MTU to 131 bytes. The ClientHello is not guaranteed to be surely +# fragmented but it is very likely. For example, the ClientHello sent by the +# GnuTLS 3.7.2 client is 206 bytes in this test. We expect ClientHello +# fragmentation to remain the case across GnuTLS version updates. Avoid using a +# smaller MTU, as the smaller the MTU, the more likely the handshake is to fail +# in this very unreliable connection emulation. +requires_gnutls +client_needs_more_time 8 +not_with_valgrind # risk of non-mbedtls peer timing out +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS proxy: 3d, gnutls client, fragmentation" \ + -p "$P_PXY drop=5 delay=5 duplicate=5" \ + "$P_SRV dgram_packing=0 dtls=1 debug_level=2" \ + "$G_NEXT_CLI -u --mtu 131 --insecure 127.0.0.1" \ + 0 \ + -s "HTTP/1.0 200 OK" \ + -s "ClientHello handshake message has been buffered and reassembled" + +requires_gnutls +client_needs_more_time 8 +not_with_valgrind # risk of non-mbedtls peer timing out +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "DTLS proxy: 3d, gnutls client, fragmentation, nbio=2" \ + -p "$P_PXY drop=5 delay=5 duplicate=5" \ + "$P_SRV dgram_packing=0 dtls=1 debug_level=2 nbio=2" \ + "$G_NEXT_CLI -u --mtu 135 --insecure 127.0.0.1" \ + 0 \ + -s "HTTP/1.0 200 OK" \ + -s "ClientHello handshake message has been buffered and reassembled" + requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "export keys functionality" \ "$P_SRV eap_tls=1 debug_level=3" \ @@ -13826,7 +14181,6 @@ run_test "Handshake defragmentation on server: len=256, client-initiated rene -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" \ @@ -13843,7 +14197,6 @@ run_test "Handshake defragmentation on server: len=128, client-initiated rene -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" \ @@ -13860,7 +14213,6 @@ run_test "Handshake defragmentation on server: len=4, client-initiated renego -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" \ diff --git a/tf-psa-crypto b/tf-psa-crypto index 293cfe5ece..125474d4e0 160000 --- a/tf-psa-crypto +++ b/tf-psa-crypto @@ -1 +1 @@ -Subproject commit 293cfe5eceed98a2ee75d5241a78657b466750c7 +Subproject commit 125474d4e05965a6dfe2af350b5462ce62bed4cd