Merge pull request #7310 from Mbed-TLS/2.28-sphinx-versioned-documentation
[Backport 2.28] Generate API documentation with Sphinx and Breathe
diff --git a/.travis.yml b/.travis.yml
index eb01a44..ada8fc5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -70,6 +70,7 @@
os: windows
script:
- scripts/windows_msbuild.bat v141 # Visual Studio 2017
+ - visualc/VS2010/x64/Release/selftest.exe --ci
after_failure:
- tests/scripts/travis-log-failure.sh
diff --git a/BRANCHES.md b/BRANCHES.md
index d4fa506..680c0ca 100644
--- a/BRANCHES.md
+++ b/BRANCHES.md
@@ -71,6 +71,6 @@
- [`development`](https://github.com/Mbed-TLS/mbedtls/)
- [`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28)
maintained until at least the end of 2024, see
- <https://github.com/Mbed-TLS/mbedtls/releases/tag/v2.28.2>.
+ <https://github.com/Mbed-TLS/mbedtls/releases/tag/v2.28.3>.
Users are urged to always use the latest version of a maintained branch.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ddeb115..a40f737 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -287,12 +287,23 @@
# to define the test executables.
#
if(ENABLE_TESTING OR ENABLE_PROGRAMS)
- file(GLOB MBEDTLS_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/drivers/*.c)
+ file(GLOB MBEDTLS_TEST_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/drivers/*.c)
add_library(mbedtls_test OBJECT ${MBEDTLS_TEST_FILES})
target_include_directories(mbedtls_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library)
+
+ file(GLOB MBEDTLS_TEST_HELPER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_helpers/*.c)
+ add_library(mbedtls_test_helpers OBJECT ${MBEDTLS_TEST_HELPER_FILES})
+ target_include_directories(mbedtls_test_helpers
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/everest/include)
endif()
if(ENABLE_PROGRAMS)
diff --git a/ChangeLog b/ChangeLog
index 23be7dd..4033839 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,84 @@
Mbed TLS ChangeLog (Sorted per branch, date)
+= Mbed TLS 2.28.3 branch released 2023-03-28
+
+Features
+ * Use HOSTCC (if it is set) when compiling C code during generation of the
+ configuration-independent files. This allows them to be generated when
+ CC is set for cross compilation.
+ * AES-NI is now supported with Visual Studio.
+ * AES-NI is now supported in 32-bit builds, or when MBEDTLS_HAVE_ASM
+ is disabled, when compiling with GCC or Clang or a compatible compiler
+ for a target CPU that supports the requisite instructions (for example
+ gcc -m32 -msse2 -maes -mpclmul). (Generic x86 builds with GCC-like
+ compilers still require MBEDTLS_HAVE_ASM and a 64-bit target.)
+
+Security
+ * MBEDTLS_AESNI_C, which is enabled by default, was silently ignored on
+ builds that couldn't compile the GCC-style assembly implementation
+ (most notably builds with Visual Studio), leaving them vulnerable to
+ timing side-channel attacks. There is now an intrinsics-based AES-NI
+ implementation as a fallback for when the assembly one cannot be used.
+
+Bugfix
+ * Fix a build issue on Windows where the source and build directory could
+ not be on different drives (#5751).
+ * Fix possible integer overflow in mbedtls_timing_hardclock(), which
+ could cause a crash for certain platforms & compiler options.
+ * Fix IAR compiler warnings. Fixes #6924.
+ * Fix a bug in the build where directory names containing spaces were
+ causing generate_errors.pl to error out resulting in a build failure.
+ Fixes issue #6879.
+ * Fix compile error where MBEDTLS_RSA_C and MBEDTLS_X509_CRT_WRITE_C are
+ defined, but MBEDTLS_PK_RSA_ALT_SUPPORT is not defined. Fixes #3174.
+ * Fix a build issue when defining MBEDTLS_TIMING_ALT and MBEDTLS_SELF_TEST.
+ The library would not link if the user didn't provide an external self-test
+ function. The self-test is now provided regardless of the choice of
+ internal/alternative timing implementation. Fixes #6923.
+ * mbedtls_x509write_crt_set_serial() now explicitly rejects serial numbers
+ whose binary representation is longer than 20 bytes. This was already
+ forbidden by the standard (RFC5280 - section 4.1.2.2) and now it's being
+ enforced also at code level.
+ * Fix potential undefined behavior in mbedtls_mpi_sub_abs(). Reported by
+ Pascal Cuoq using TrustInSoft Analyzer in #6701; observed independently by
+ Aaron Ucko under Valgrind.
+ * Fix behavior of certain sample programs which could, when run with no
+ arguments, access uninitialized memory in some cases. Fixes #6700 (which
+ was found by TrustInSoft Analyzer during REDOCS'22) and #1120.
+ * Fix build errors in test programs when MBEDTLS_CERTS_C is disabled.
+ Fixes #6243.
+ * Fix parsing of X.509 SubjectAlternativeName extension. Previously,
+ malformed alternative name components were not caught during initial
+ certificate parsing, but only on subsequent calls to
+ mbedtls_x509_parse_subject_alt_name(). Fixes #2838.
+ * Fix bug in conversion from OID to string in
+ mbedtls_oid_get_numeric_string(). OIDs such as 2.40.0.25 are now printed
+ correctly.
+ * Reject OIDs with overlong-encoded subidentifiers when converting
+ them to a string.
+ * Reject OIDs with subidentifier values exceeding UINT_MAX. Such
+ subidentifiers can be valid, but Mbed TLS cannot currently handle them.
+ * Reject OIDs that have unterminated subidentifiers, or (equivalently)
+ have the most-significant bit set in their last byte.
+ * Silence a warning about an unused local variable in bignum.c on
+ some architectures. Fixes #7166.
+ * Silence warnings from clang -Wdocumentation about empty \retval
+ descriptions, which started appearing with Clang 15. Fixes #6960.
+ * Fix undefined behavior in mbedtls_ssl_read() and mbedtls_ssl_write() if
+ len argument is 0 and buffer is NULL.
+
+Changes
+ * The C code follows a new coding style. This is transparent for users but
+ affects contributors and maintainers of local patches. For more
+ information, see
+ https://mbed-tls.readthedocs.io/en/latest/kb/how-to/rewrite-branch-for-coding-style/
+ * Changed the default MBEDTLS_ECP_WINDOW_SIZE from 6 to 2.
+ As tested in issue 6790, the correlation between this define and
+ RSA decryption performance has changed lately due to security fixes.
+ To fix the performance degradation when using default values the
+ window was reduced from 6 to 2, a value that gives the best or close
+ to best results when tested on Cortex-M4 and Intel i7.
+
= Mbed TLS 2.28.2 branch released 2022-12-14
Security
diff --git a/ChangeLog.d/build-without-certs.txt b/ChangeLog.d/build-without-certs.txt
deleted file mode 100644
index dcb5c77..0000000
--- a/ChangeLog.d/build-without-certs.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix build errors in test programs when MBEDTLS_CERTS_C is disabled.
- Fixes #6243.
diff --git a/ChangeLog.d/c-build-helper-hostcc.txt b/ChangeLog.d/c-build-helper-hostcc.txt
deleted file mode 100644
index 86182c3..0000000
--- a/ChangeLog.d/c-build-helper-hostcc.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
- * Use HOSTCC (if it is set) when compiling C code during generation of the
- configuration-independent files. This allows them to be generated when
- CC is set for cross compilation.
diff --git a/ChangeLog.d/clang-15-bignum-warning.txt b/ChangeLog.d/clang-15-bignum-warning.txt
deleted file mode 100644
index d3308b4..0000000
--- a/ChangeLog.d/clang-15-bignum-warning.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Silence a warning about an unused local variable in bignum.c on
- some architectures. Fixes #7166.
diff --git a/ChangeLog.d/coding-style.txt b/ChangeLog.d/coding-style.txt
deleted file mode 100644
index b2cff5c..0000000
--- a/ChangeLog.d/coding-style.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Changes
- * The C code follows a new coding style. This is transparent for users but
- affects contributors and maintainers of local patches. For more
- information, see
- https://mbed-tls.readthedocs.io/en/latest/kb/how-to/rewrite-branch-for-coding-style/
diff --git a/ChangeLog.d/conditionalize-mbedtls_mpi_sub_abs-memcpy.txt b/ChangeLog.d/conditionalize-mbedtls_mpi_sub_abs-memcpy.txt
deleted file mode 100644
index 0a90721..0000000
--- a/ChangeLog.d/conditionalize-mbedtls_mpi_sub_abs-memcpy.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix potential undefined behavior in mbedtls_mpi_sub_abs(). Reported by
- Pascal Cuoq using TrustInSoft Analyzer in #6701; observed independently by
- Aaron Ucko under Valgrind.
diff --git a/ChangeLog.d/empty-retval-description.txt b/ChangeLog.d/empty-retval-description.txt
deleted file mode 100644
index 491adf5..0000000
--- a/ChangeLog.d/empty-retval-description.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Silence warnings from clang -Wdocumentation about empty \retval
- descriptions, which started appearing with Clang 15. Fixes #6960.
diff --git a/ChangeLog.d/fix-example-programs-no-args.txt b/ChangeLog.d/fix-example-programs-no-args.txt
deleted file mode 100644
index 57fe37a..0000000
--- a/ChangeLog.d/fix-example-programs-no-args.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix behavior of certain sample programs which could, when run with no
- arguments, access uninitialized memory in some cases. Fixes #6700 (which
- was found by TrustInSoft Analyzer during REDOCS'22) and #1120.
diff --git a/ChangeLog.d/fix-gettimeofday-overflow.txt b/ChangeLog.d/fix-gettimeofday-overflow.txt
deleted file mode 100644
index 99a049d..0000000
--- a/ChangeLog.d/fix-gettimeofday-overflow.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix possible integer overflow in mbedtls_timing_hardclock(), which
- could cause a crash for certain platforms & compiler options.
-
diff --git a/ChangeLog.d/fix-iar-warnings.txt b/ChangeLog.d/fix-iar-warnings.txt
deleted file mode 100644
index 8a30132..0000000
--- a/ChangeLog.d/fix-iar-warnings.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Bugfix
- * Fix IAR compiler warnings. Fixes #6924.
diff --git a/ChangeLog.d/fix-oid-to-string-bugs.txt b/ChangeLog.d/fix-oid-to-string-bugs.txt
deleted file mode 100644
index 3cf02c3..0000000
--- a/ChangeLog.d/fix-oid-to-string-bugs.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Bugfix
- * Fix bug in conversion from OID to string in
- mbedtls_oid_get_numeric_string(). OIDs such as 2.40.0.25 are now printed
- correctly.
- * Reject OIDs with overlong-encoded subidentifiers when converting
- them to a string.
- * Reject OIDs with subidentifier values exceeding UINT_MAX. Such
- subidentifiers can be valid, but Mbed TLS cannot currently handle them.
- * Reject OIDs that have unterminated subidentifiers, or (equivalently)
- have the most-significant bit set in their last byte.
diff --git a/ChangeLog.d/fix-rsaalt-test-guards.txt b/ChangeLog.d/fix-rsaalt-test-guards.txt
deleted file mode 100644
index f4f39c9..0000000
--- a/ChangeLog.d/fix-rsaalt-test-guards.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix compile error where MBEDTLS_RSA_C and MBEDTLS_X509_CRT_WRITE_C are
- defined, but MBEDTLS_PK_RSA_ALT_SUPPORT is not defined. Fixes #3174.
diff --git a/ChangeLog.d/fix_build_for_directory_names_containing_spaces.txt b/ChangeLog.d/fix_build_for_directory_names_containing_spaces.txt
deleted file mode 100644
index e7643b7..0000000
--- a/ChangeLog.d/fix_build_for_directory_names_containing_spaces.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix a bug in the build where directory names containing spaces were
- causing generate_errors.pl to error out resulting in a build failure.
- Fixes issue #6879.
diff --git a/ChangeLog.d/fix_hard_link_across_drives b/ChangeLog.d/fix_hard_link_across_drives
deleted file mode 100644
index 0c55c30..0000000
--- a/ChangeLog.d/fix_hard_link_across_drives
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix a build issue on Windows where the source and build directory could not be on
- different drives (#5751).
diff --git a/ChangeLog.d/fix_timing_alt.txt b/ChangeLog.d/fix_timing_alt.txt
deleted file mode 100644
index 86ec16d..0000000
--- a/ChangeLog.d/fix_timing_alt.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
- * Fix a build issue when defining MBEDTLS_TIMING_ALT and MBEDTLS_SELF_TEST.
- The library would not link if the user didn't provide an external self-test
- function. The self-test is now provided regardless of the choice of
- internal/alternative timing implementation. Fixes #6923.
diff --git a/ChangeLog.d/improve_x509_cert_writing_serial_number_management.txt b/ChangeLog.d/improve_x509_cert_writing_serial_number_management.txt
deleted file mode 100644
index a85c79b..0000000
--- a/ChangeLog.d/improve_x509_cert_writing_serial_number_management.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
- * mbedtls_x509write_crt_set_serial() now explicitly rejects serial numbers
- whose binary representation is longer than 20 bytes. This was already
- forbidden by the standard (RFC5280 - section 4.1.2.2) and now it's being
- enforced also at code level.
diff --git a/ChangeLog.d/mbedtls_ssl_read_undefined_behavior.txt b/ChangeLog.d/mbedtls_ssl_read_undefined_behavior.txt
deleted file mode 100644
index 1f2c563..0000000
--- a/ChangeLog.d/mbedtls_ssl_read_undefined_behavior.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix undefined behavior in mbedtls_ssl_read() and mbedtls_ssl_write() if
- len argument is 0 and buffer is NULL.
diff --git a/ChangeLog.d/mpi-window-perf b/ChangeLog.d/mpi-window-perf
deleted file mode 100644
index 0f75d6a..0000000
--- a/ChangeLog.d/mpi-window-perf
+++ /dev/null
@@ -1,7 +0,0 @@
-Changes
- * Changed the default MBEDTLS_ECP_WINDOW_SIZE from 6 to 2.
- As tested in issue 6790, the correlation between this define and
- RSA decryption performance has changed lately due to security fixes.
- To fix the performance degradation when using default values the
- window was reduced from 6 to 2, a value that gives the best or close
- to best results when tested on Cortex-M4 and Intel i7.
diff --git a/ChangeLog.d/x509-subaltname-ext b/ChangeLog.d/x509-subaltname-ext
deleted file mode 100644
index 7845f18..0000000
--- a/ChangeLog.d/x509-subaltname-ext
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
- * Fix parsing of X.509 SubjectAlternativeName extension. Previously,
- malformed alternative name components were not caught during initial
- certificate parsing, but only on subsequent calls to
- mbedtls_x509_parse_subject_alt_name(). Fixes #2838.
diff --git a/SECURITY.md b/SECURITY.md
index 33bbc2f..732335b 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -18,3 +18,120 @@
Only the maintained branches, as listed in [`BRANCHES.md`](BRANCHES.md),
get security fixes.
Users are urged to always use the latest version of a maintained branch.
+
+## Threat model
+
+We classify attacks based on the capabilities of the attacker.
+
+### Remote attacks
+
+In this section, we consider an attacker who can observe and modify data sent
+over the network. This includes observing the content and timing of individual
+packets, as well as suppressing or delaying legitimate messages, and injecting
+messages.
+
+Mbed TLS aims to fully protect against remote attacks and to enable the user
+application in providing full protection against remote attacks. Said
+protection is limited to providing security guarantees offered by the protocol
+being implemented. (For example Mbed TLS alone won't guarantee that the
+messages will arrive without delay, as the TLS protocol doesn't guarantee that
+either.)
+
+**Warning!** Block ciphers do not yet achieve full protection against attackers
+who can measure the timing of packets with sufficient precision. For details
+and workarounds see the [Block Ciphers](#block-ciphers) section.
+
+### Local attacks
+
+In this section, we consider an attacker who can run software on the same
+machine. The attacker has insufficient privileges to directly access Mbed TLS
+assets such as memory and files.
+
+#### Timing attacks
+
+The attacker is able to observe the timing of instructions executed by Mbed TLS
+by leveraging shared hardware that both Mbed TLS and the attacker have access
+to. Typical attack vectors include cache timings, memory bus contention and
+branch prediction.
+
+Mbed TLS provides limited protection against timing attacks. The cost of
+protecting against timing attacks widely varies depending on the granularity of
+the measurements and the noise present. Therefore the protection in Mbed TLS is
+limited. We are only aiming to provide protection against **publicly
+documented attack techniques**.
+
+As attacks keep improving, so does Mbed TLS's protection. Mbed TLS is moving
+towards a model of fully timing-invariant code, but has not reached this point
+yet.
+
+**Remark:** Timing information can be observed over the network or through
+physical side channels as well. Remote and physical timing attacks are covered
+in the [Remote attacks](remote-attacks) and [Physical
+attacks](physical-attacks) sections respectively.
+
+**Warning!** Block ciphers do not yet achieve full protection. For
+details and workarounds see the [Block Ciphers](#block-ciphers) section.
+
+#### Local non-timing side channels
+
+The attacker code running on the platform has access to some sensor capable of
+picking up information on the physical state of the hardware while Mbed TLS is
+running. This could for example be an analogue-to-digital converter on the
+platform that is located unfortunately enough to pick up the CPU noise.
+
+Mbed TLS doesn't make any security guarantees against local non-timing-based
+side channel attacks. If local non-timing attacks are present in a use case or
+a user application's threat model, they need to be mitigated by the platform.
+
+#### Local fault injection attacks
+
+Software running on the same hardware can affect the physical state of the
+device and introduce faults.
+
+Mbed TLS doesn't make any security guarantees against local fault injection
+attacks. If local fault injection attacks are present in a use case or a user
+application's threat model, they need to be mitigated by the platform.
+
+### Physical attacks
+
+In this section, we consider an attacker who has access to physical information
+about the hardware Mbed TLS is running on and/or can alter the physical state
+of the hardware (e.g. power analysis, radio emissions or fault injection).
+
+Mbed TLS doesn't make any security guarantees against physical attacks. If
+physical attacks are present in a use case or a user application's threat
+model, they need to be mitigated by physical countermeasures.
+
+### Caveats
+
+#### Out-of-scope countermeasures
+
+Mbed TLS has evolved organically and a well defined threat model hasn't always
+been present. Therefore, Mbed TLS might have countermeasures against attacks
+outside the above defined threat model.
+
+The presence of such countermeasures don't mean that Mbed TLS provides
+protection against a class of attacks outside of the above described threat
+model. Neither does it mean that the failure of such a countermeasure is
+considered a vulnerability.
+
+#### Block ciphers
+
+Currently there are four block ciphers in Mbed TLS: AES, CAMELLIA, ARIA and
+DES. The pure software implementation in Mbed TLS implementation uses lookup
+tables, which are vulnerable to timing attacks.
+
+These timing attacks can be physical, local or depending on network latency
+even a remote. The attacks can result in key recovery.
+
+**Workarounds:**
+
+- Turn on hardware acceleration for AES. This is supported only on selected
+ architectures and currently only available for AES. See configuration options
+ `MBEDTLS_AESNI_C` and `MBEDTLS_PADLOCK_C` for details.
+- Add a secure alternative implementation (typically hardware acceleration) for
+ the vulnerable cipher. See the [Alternative Implementations
+Guide](docs/architecture/alternative-implementations.md) for more information.
+- Use cryptographic mechanisms that are not based on block ciphers. In
+ particular, for authenticated encryption, use ChaCha20/Poly1305 instead of
+ block cipher modes. For random generation, use HMAC\_DRBG instead of CTR\_DRBG.
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index 54b2f7a..4c76246 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -22,7 +22,7 @@
*/
/**
- * @mainpage mbed TLS v2.28.2 source code documentation
+ * @mainpage mbed TLS v2.28.3 source code documentation
*
* This documentation describes the internal structure of mbed TLS. It was
* automatically generated from specially formatted comment blocks in
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index 38fb8db..78299ed 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -1,4 +1,4 @@
-PROJECT_NAME = "mbed TLS v2.28.2"
+PROJECT_NAME = "mbed TLS v2.28.3"
OUTPUT_DIRECTORY = ../apidoc/
FULL_PATH_NAMES = NO
OPTIMIZE_OUTPUT_FOR_C = YES
diff --git a/include/mbedtls/aesni.h b/include/mbedtls/aesni.h
index 653b146..6741dea 100644
--- a/include/mbedtls/aesni.h
+++ b/include/mbedtls/aesni.h
@@ -36,13 +36,49 @@
#define MBEDTLS_AESNI_AES 0x02000000u
#define MBEDTLS_AESNI_CLMUL 0x00000002u
-#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
+/* Can we do AESNI with inline assembly?
+ * (Only implemented with gas syntax, only for 64-bit.)
+ */
+#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
(defined(__amd64__) || defined(__x86_64__)) && \
!defined(MBEDTLS_HAVE_X86_64)
#define MBEDTLS_HAVE_X86_64
#endif
+#if defined(MBEDTLS_AESNI_C)
+
+/* Can we do AESNI with intrinsics?
+ * (Only implemented with certain compilers, only for certain targets.)
+ *
+ * NOTE: MBEDTLS_AESNI_HAVE_INTRINSICS and MBEDTLS_AESNI_HAVE_CODE are internal
+ * macros that may change in future releases.
+ */
+#undef MBEDTLS_AESNI_HAVE_INTRINSICS
+#if defined(_MSC_VER)
+/* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support
+ * VS 2013 and up for other reasons anyway, so no need to check the version. */
+#define MBEDTLS_AESNI_HAVE_INTRINSICS
+#endif
+/* GCC-like compilers: currently, we only support intrinsics if the requisite
+ * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`
+ * or `clang -maes -mpclmul`). */
+#if defined(__GNUC__) && defined(__AES__) && defined(__PCLMUL__)
+#define MBEDTLS_AESNI_HAVE_INTRINSICS
+#endif
+
+/* Choose the implementation of AESNI, if one is available. */
+#undef MBEDTLS_AESNI_HAVE_CODE
+/* To minimize disruption when releasing the intrinsics-based implementation,
+ * favor the assembly-based implementation if it's available. We intend to
+ * revise this in a later release of Mbed TLS 3.x. In the long run, we will
+ * likely remove the assembly implementation. */
#if defined(MBEDTLS_HAVE_X86_64)
+#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
+#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
+#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics
+#endif
+
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
#ifdef __cplusplus
extern "C" {
@@ -131,6 +167,7 @@
}
#endif
-#endif /* MBEDTLS_HAVE_X86_64 */
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
+#endif /* MBEDTLS_AESNI_C */
#endif /* MBEDTLS_AESNI_H */
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 2ab9982..2cb36e9 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -69,10 +69,6 @@
#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense"
#endif
-#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM)
-#error "MBEDTLS_AESNI_C defined, but not all prerequisites"
-#endif
-
#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C)
#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites"
#endif
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index acdb7ac..1381c1f 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -51,7 +51,7 @@
* include/mbedtls/bn_mul.h
*
* Required by:
- * MBEDTLS_AESNI_C
+ * MBEDTLS_AESNI_C (on some platforms)
* MBEDTLS_PADLOCK_C
*
* Comment to disable the use of assembly code.
@@ -2344,14 +2344,32 @@
/**
* \def MBEDTLS_AESNI_C
*
- * Enable AES-NI support on x86-64.
+ * Enable AES-NI support on x86-64 or x86-32.
+ *
+ * \note AESNI is only supported with certain compilers and target options:
+ * - Visual Studio 2013: supported.
+ * - GCC, x86-64, target not explicitly supporting AESNI:
+ * requires MBEDTLS_HAVE_ASM.
+ * - GCC, x86-32, target not explicitly supporting AESNI:
+ * not supported.
+ * - GCC, x86-64 or x86-32, target supporting AESNI: supported.
+ * For this assembly-less implementation, you must currently compile
+ * `library/aesni.c` and `library/aes.c` with machine options to enable
+ * SSE2 and AESNI instructions: `gcc -msse2 -maes -mpclmul` or
+ * `clang -maes -mpclmul`.
+ * - Non-x86 targets: this option is silently ignored.
+ * - Other compilers: this option is silently ignored.
+ *
+ * \note
+ * Above, "GCC" includes compatible compilers such as Clang.
+ * The limitations on target support are likely to be relaxed in the future.
*
* Module: library/aesni.c
* Caller: library/aes.c
*
- * Requires: MBEDTLS_HAVE_ASM
+ * Requires: MBEDTLS_HAVE_ASM (on some platforms, see note)
*
- * This modules adds support for the AES-NI instructions on x86-64
+ * This modules adds support for the AES-NI instructions on x86.
*/
#define MBEDTLS_AESNI_C
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index 1324eae..0ef5213 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -38,16 +38,16 @@
*/
#define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 28
-#define MBEDTLS_VERSION_PATCH 2
+#define MBEDTLS_VERSION_PATCH 3
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x021C0200
-#define MBEDTLS_VERSION_STRING "2.28.2"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.2"
+#define MBEDTLS_VERSION_NUMBER 0x021C0300
+#define MBEDTLS_VERSION_STRING "2.28.3"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.3"
#if defined(MBEDTLS_VERSION_C)
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index fd3a3e7..553569e 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -204,15 +204,15 @@
if(USE_SHARED_MBEDTLS_LIBRARY)
set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR})
add_library(${mbedcrypto_target} SHARED ${src_crypto})
- set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.2 SOVERSION 7)
+ set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.3 SOVERSION 7)
target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
add_library(${mbedx509_target} SHARED ${src_x509})
- set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.2 SOVERSION 1)
+ set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.3 SOVERSION 1)
target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
add_library(${mbedtls_target} SHARED ${src_tls})
- set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.2 SOVERSION 14)
+ set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.3 SOVERSION 14)
target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
endif(USE_SHARED_MBEDTLS_LIBRARY)
diff --git a/library/aes.c b/library/aes.c
index bcdf3c7..f08a21f 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -50,8 +50,7 @@
#define AES_VALIDATE(cond) \
MBEDTLS_INTERNAL_VALIDATE(cond)
-#if defined(MBEDTLS_PADLOCK_C) && \
- (defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16))
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
static int aes_padlock_ace = -1;
#endif
@@ -512,6 +511,53 @@
}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
+/* Some implementations need the round keys to be aligned.
+ * Return an offset to be added to buf, such that (buf + offset) is
+ * correctly aligned.
+ * Note that the offset is in units of elements of buf, i.e. 32-bit words,
+ * i.e. an offset of 1 means 4 bytes and so on.
+ */
+#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) || \
+ (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)
+#define MAY_NEED_TO_ALIGN
+#endif
+static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
+{
+#if defined(MAY_NEED_TO_ALIGN)
+ int align_16_bytes = 0;
+
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+ if (aes_padlock_ace == -1) {
+ aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
+ }
+ if (aes_padlock_ace) {
+ align_16_bytes = 1;
+ }
+#endif
+
+#if defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2
+ if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+ align_16_bytes = 1;
+ }
+#endif
+
+ if (align_16_bytes) {
+ /* These implementations needs 16-byte alignment
+ * for the round key array. */
+ unsigned delta = ((uintptr_t) buf & 0x0000000fU) / 4;
+ if (delta == 0) {
+ return 0;
+ } else {
+ return 4 - delta; // 16 bytes = 4 uint32_t
+ }
+ }
+#else /* MAY_NEED_TO_ALIGN */
+ (void) buf;
+#endif /* MAY_NEED_TO_ALIGN */
+
+ return 0;
+}
+
/*
* AES key schedule (encryption)
*/
@@ -539,18 +585,9 @@
}
#endif
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
- if (aes_padlock_ace == -1) {
- aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
- }
+ ctx->rk = RK = ctx->buf + mbedtls_aes_rk_offset(ctx->buf);
- if (aes_padlock_ace) {
- ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16(ctx->buf);
- } else
-#endif
- ctx->rk = RK = ctx->buf;
-
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
return mbedtls_aesni_setkey_enc((unsigned char *) ctx->rk, key, keybits);
}
@@ -640,16 +677,7 @@
mbedtls_aes_init(&cty);
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
- if (aes_padlock_ace == -1) {
- aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
- }
-
- if (aes_padlock_ace) {
- ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16(ctx->buf);
- } else
-#endif
- ctx->rk = RK = ctx->buf;
+ ctx->rk = RK = ctx->buf + mbedtls_aes_rk_offset(ctx->buf);
/* Also checks keybits */
if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) {
@@ -658,7 +686,7 @@
ctx->nr = cty.nr;
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
mbedtls_aesni_inverse_key((unsigned char *) ctx->rk,
(const unsigned char *) cty.rk, ctx->nr);
@@ -964,6 +992,30 @@
}
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#if defined(MAY_NEED_TO_ALIGN)
+/* VIA Padlock and our intrinsics-based implementation of AESNI require
+ * the round keys to be aligned on a 16-byte boundary. We take care of this
+ * before creating them, but the AES context may have moved (this can happen
+ * if the library is called from a language with managed memory), and in later
+ * calls it might have a different alignment with respect to 16-byte memory.
+ * So we may need to realign.
+ * NOTE: In the LTS branch, the context contains a pointer to within itself,
+ * so if it has been moved, things will probably go pear-shaped. We keep this
+ * code for compatibility with the development branch, in case of future changes.
+ */
+static void aes_maybe_realign(mbedtls_aes_context *ctx)
+{
+ unsigned current_offset = (unsigned) (ctx->rk - ctx->buf);
+ unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf);
+ if (new_offset != current_offset) {
+ memmove(ctx->buf + new_offset, // new address
+ ctx->buf + current_offset, // current address
+ (ctx->nr + 1) * 16); // number of round keys * bytes per rk
+ ctx->rk = ctx->buf + new_offset;
+ }
+}
+#endif
+
/*
* AES-ECB block encryption/decryption
*/
@@ -978,7 +1030,11 @@
AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT ||
mode == MBEDTLS_AES_DECRYPT);
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MAY_NEED_TO_ALIGN)
+ aes_maybe_realign(ctx);
+#endif
+
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
return mbedtls_aesni_crypt_ecb(ctx, mode, input, output);
}
@@ -986,13 +1042,7 @@
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
if (aes_padlock_ace) {
- if (mbedtls_padlock_xcryptecb(ctx, mode, input, output) == 0) {
- return 0;
- }
-
- // If padlock data misaligned, we just fall back to
- // unaccelerated mode
- //
+ return mbedtls_padlock_xcryptecb(ctx, mode, input, output);
}
#endif
@@ -1785,6 +1835,32 @@
memset(key, 0, 32);
mbedtls_aes_init(&ctx);
+ if (verbose != 0) {
+#if defined(MBEDTLS_AES_ALT)
+ mbedtls_printf(" AES note: alternative implementation.\n");
+#else /* MBEDTLS_AES_ALT */
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+ if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
+ mbedtls_printf(" AES note: using VIA Padlock.\n");
+ } else
+#endif
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+ if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+ mbedtls_printf(" AES note: using AESNI via ");
+#if MBEDTLS_AESNI_HAVE_CODE == 1
+ mbedtls_printf("assembly");
+#elif MBEDTLS_AESNI_HAVE_CODE == 2
+ mbedtls_printf("intrinsics");
+#else
+ mbedtls_printf("(unknown)");
+#endif
+ mbedtls_printf(".\n");
+ } else
+#endif
+ mbedtls_printf(" AES note: built-in implementation.\n");
+#endif /* MBEDTLS_AES_ALT */
+ }
+
/*
* ECB mode
*/
diff --git a/library/aesni.c b/library/aesni.c
index 2a44b0e..c909f65 100644
--- a/library/aesni.c
+++ b/library/aesni.c
@@ -18,21 +18,14 @@
*/
/*
- * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
- * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
+ * [AES-WP] https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html
+ * [CLMUL-WP] https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html
*/
#include "common.h"
#if defined(MBEDTLS_AESNI_C)
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-#warning \
- "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code."
-#endif
-#endif
-
#include "mbedtls/aesni.h"
#include <string.h>
@@ -43,7 +36,14 @@
#endif
/* *INDENT-ON* */
-#if defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+#if !defined(_WIN32)
+#include <cpuid.h>
+#endif
+#include <immintrin.h>
+#endif
/*
* AES-NI support detection routine
@@ -54,17 +54,355 @@
static unsigned int c = 0;
if (!done) {
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+ static unsigned info[4] = { 0, 0, 0, 0 };
+#if defined(_MSC_VER)
+ __cpuid(info, 1);
+#else
+ __cpuid(1, info[0], info[1], info[2], info[3]);
+#endif
+ c = info[2];
+#else /* AESNI using asm */
asm ("movl $1, %%eax \n\t"
"cpuid \n\t"
: "=c" (c)
:
: "eax", "ebx", "edx");
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
done = 1;
}
return (c & what) != 0;
}
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+
+/*
+ * AES-NI AES-ECB block en(de)cryption
+ */
+int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16])
+{
+ const __m128i *rk = (const __m128i *) (ctx->rk);
+ unsigned nr = ctx->nr; // Number of remaining rounds
+
+ // Load round key 0
+ __m128i state;
+ memcpy(&state, input, 16);
+ state = _mm_xor_si128(state, rk[0]); // state ^= *rk;
+ ++rk;
+ --nr;
+
+ if (mode == 0) {
+ while (nr != 0) {
+ state = _mm_aesdec_si128(state, *rk);
+ ++rk;
+ --nr;
+ }
+ state = _mm_aesdeclast_si128(state, *rk);
+ } else {
+ while (nr != 0) {
+ state = _mm_aesenc_si128(state, *rk);
+ ++rk;
+ --nr;
+ }
+ state = _mm_aesenclast_si128(state, *rk);
+ }
+
+ memcpy(output, &state, 16);
+ return 0;
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
+ */
+
+static void gcm_clmul(const __m128i aa, const __m128i bb,
+ __m128i *cc, __m128i *dd)
+{
+ /*
+ * Caryless multiplication dd:cc = aa * bb
+ * using [CLMUL-WP] algorithm 1 (p. 12).
+ */
+ *cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0
+ *dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0
+ __m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0
+ __m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0
+ ff = _mm_xor_si128(ff, ee); // e1+f1:e0+f0
+ ee = ff; // e1+f1:e0+f0
+ ff = _mm_srli_si128(ff, 8); // 0:e1+f1
+ ee = _mm_slli_si128(ee, 8); // e0+f0:0
+ *dd = _mm_xor_si128(*dd, ff); // d1:d0+e1+f1
+ *cc = _mm_xor_si128(*cc, ee); // c1+e0+f0:c0
+}
+
+static void gcm_shift(__m128i *cc, __m128i *dd)
+{
+ /* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left,
+ * taking advantage of [CLMUL-WP] eq 27 (p. 18). */
+ // // *cc = r1:r0
+ // // *dd = r3:r2
+ __m128i cc_lo = _mm_slli_epi64(*cc, 1); // r1<<1:r0<<1
+ __m128i dd_lo = _mm_slli_epi64(*dd, 1); // r3<<1:r2<<1
+ __m128i cc_hi = _mm_srli_epi64(*cc, 63); // r1>>63:r0>>63
+ __m128i dd_hi = _mm_srli_epi64(*dd, 63); // r3>>63:r2>>63
+ __m128i xmm5 = _mm_srli_si128(cc_hi, 8); // 0:r1>>63
+ cc_hi = _mm_slli_si128(cc_hi, 8); // r0>>63:0
+ dd_hi = _mm_slli_si128(dd_hi, 8); // 0:r1>>63
+
+ *cc = _mm_or_si128(cc_lo, cc_hi); // r1<<1|r0>>63:r0<<1
+ *dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // r3<<1|r2>>62:r2<<1|r1>>63
+}
+
+static __m128i gcm_reduce(__m128i xx)
+{
+ // // xx = x1:x0
+ /* [CLMUL-WP] Algorithm 5 Step 2 */
+ __m128i aa = _mm_slli_epi64(xx, 63); // x1<<63:x0<<63 = stuff:a
+ __m128i bb = _mm_slli_epi64(xx, 62); // x1<<62:x0<<62 = stuff:b
+ __m128i cc = _mm_slli_epi64(xx, 57); // x1<<57:x0<<57 = stuff:c
+ __m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); // a+b+c:0
+ return _mm_xor_si128(dd, xx); // x1+a+b+c:x0 = d:x0
+}
+
+static __m128i gcm_mix(__m128i dx)
+{
+ /* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */
+ __m128i ee = _mm_srli_epi64(dx, 1); // e1:x0>>1 = e1:e0'
+ __m128i ff = _mm_srli_epi64(dx, 2); // f1:x0>>2 = f1:f0'
+ __m128i gg = _mm_srli_epi64(dx, 7); // g1:x0>>7 = g1:g0'
+
+ // e0'+f0'+g0' is almost e0+f0+g0, except for some missing
+ // bits carried from d. Now get those bits back in.
+ __m128i eh = _mm_slli_epi64(dx, 63); // d<<63:stuff
+ __m128i fh = _mm_slli_epi64(dx, 62); // d<<62:stuff
+ __m128i gh = _mm_slli_epi64(dx, 57); // d<<57:stuff
+ __m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); // 0:missing bits of d
+
+ return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), gg), hh), dx);
+}
+
+void mbedtls_aesni_gcm_mult(unsigned char c[16],
+ const unsigned char a[16],
+ const unsigned char b[16])
+{
+ __m128i aa, bb, cc, dd;
+
+ /* The inputs are in big-endian order, so byte-reverse them */
+ for (size_t i = 0; i < 16; i++) {
+ ((uint8_t *) &aa)[i] = a[15 - i];
+ ((uint8_t *) &bb)[i] = b[15 - i];
+ }
+
+ gcm_clmul(aa, bb, &cc, &dd);
+ gcm_shift(&cc, &dd);
+ /*
+ * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+ * using [CLMUL-WP] algorithm 5 (p. 18).
+ * Currently dd:cc holds x3:x2:x1:x0 (already shifted).
+ */
+ __m128i dx = gcm_reduce(cc);
+ __m128i xh = gcm_mix(dx);
+ cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0
+
+ /* Now byte-reverse the outputs */
+ for (size_t i = 0; i < 16; i++) {
+ c[i] = ((uint8_t *) &cc)[15 - i];
+ }
+
+ return;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void mbedtls_aesni_inverse_key(unsigned char *invkey,
+ const unsigned char *fwdkey, int nr)
+{
+ __m128i *ik = (__m128i *) invkey;
+ const __m128i *fk = (const __m128i *) fwdkey + nr;
+
+ *ik = *fk;
+ for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) {
+ *ik = _mm_aesimc_si128(*fk);
+ }
+ *ik = *fk;
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static __m128i aesni_set_rk_128(__m128i state, __m128i xword)
+{
+ /*
+ * Finish generating the next round key.
+ *
+ * On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff
+ * with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST).
+ *
+ * On exit, xword is r7:r6:r5:r4
+ * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+ * and this is returned, to be written to the round key buffer.
+ */
+ xword = _mm_shuffle_epi32(xword, 0xff); // X:X:X:X
+ xword = _mm_xor_si128(xword, state); // X+r3:X+r2:X+r1:r4
+ state = _mm_slli_si128(state, 4); // r2:r1:r0:0
+ xword = _mm_xor_si128(xword, state); // X+r3+r2:X+r2+r1:r5:r4
+ state = _mm_slli_si128(state, 4); // r1:r0:0:0
+ xword = _mm_xor_si128(xword, state); // X+r3+r2+r1:r6:r5:r4
+ state = _mm_slli_si128(state, 4); // r0:0:0:0
+ state = _mm_xor_si128(xword, state); // r7:r6:r5:r4
+ return state;
+}
+
+static void aesni_setkey_enc_128(unsigned char *rk_bytes,
+ const unsigned char *key)
+{
+ __m128i *rk = (__m128i *) rk_bytes;
+
+ memcpy(&rk[0], key, 16);
+ rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01));
+ rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02));
+ rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04));
+ rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08));
+ rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10));
+ rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20));
+ rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40));
+ rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80));
+ rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B));
+ rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36));
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword,
+ unsigned char *rk)
+{
+ /*
+ * Finish generating the next 6 quarter-keys.
+ *
+ * On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4
+ * and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON
+ * (obtained with AESKEYGENASSIST).
+ *
+ * On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10
+ * and those are written to the round key buffer.
+ */
+ xword = _mm_shuffle_epi32(xword, 0x55); // X:X:X:X
+ xword = _mm_xor_si128(xword, *state0); // X+r3:X+r2:X+r1:X+r0
+ *state0 = _mm_slli_si128(*state0, 4); // r2:r1:r0:0
+ xword = _mm_xor_si128(xword, *state0); // X+r3+r2:X+r2+r1:X+r1+r0:X+r0
+ *state0 = _mm_slli_si128(*state0, 4); // r1:r0:0:0
+ xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0
+ *state0 = _mm_slli_si128(*state0, 4); // r0:0:0:0
+ xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0
+ *state0 = xword; // = r9:r8:r7:r6
+
+ xword = _mm_shuffle_epi32(xword, 0xff); // r9:r9:r9:r9
+ xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5:r9+r4
+ *state1 = _mm_slli_si128(*state1, 4); // stuff:stuff:r4:0
+ xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5+r4:r9+r4
+ *state1 = xword; // = stuff:stuff:r11:r10
+
+ /* Store state0 and the low half of state1 into rk, which is conceptually
+ * an array of 24-byte elements. Since 24 is not a multiple of 16,
+ * rk is not necessarily aligned so just `*rk = *state0` doesn't work. */
+ memcpy(rk, state0, 16);
+ memcpy(rk + 16, state1, 8);
+}
+
+static void aesni_setkey_enc_192(unsigned char *rk,
+ const unsigned char *key)
+{
+ /* First round: use original key */
+ memcpy(rk, key, 24);
+ /* aes.c guarantees that rk is aligned on a 16-byte boundary. */
+ __m128i state0 = ((__m128i *) rk)[0];
+ __m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1);
+
+ aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x01), rk + 24 * 1);
+ aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x02), rk + 24 * 2);
+ aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x04), rk + 24 * 3);
+ aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x08), rk + 24 * 4);
+ aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x10), rk + 24 * 5);
+ aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x20), rk + 24 * 6);
+ aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7);
+ aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8);
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword,
+ __m128i *rk0, __m128i *rk1)
+{
+ /*
+ * Finish generating the next two round keys.
+ *
+ * On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and
+ * xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+ * (obtained with AESKEYGENASSIST).
+ *
+ * On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12
+ */
+ xword = _mm_shuffle_epi32(xword, 0xff);
+ xword = _mm_xor_si128(xword, state0);
+ state0 = _mm_slli_si128(state0, 4);
+ xword = _mm_xor_si128(xword, state0);
+ state0 = _mm_slli_si128(state0, 4);
+ xword = _mm_xor_si128(xword, state0);
+ state0 = _mm_slli_si128(state0, 4);
+ state0 = _mm_xor_si128(state0, xword);
+ *rk0 = state0;
+
+ /* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 )
+ * and proceed to generate next round key from there */
+ xword = _mm_aeskeygenassist_si128(state0, 0x00);
+ xword = _mm_shuffle_epi32(xword, 0xaa);
+ xword = _mm_xor_si128(xword, state1);
+ state1 = _mm_slli_si128(state1, 4);
+ xword = _mm_xor_si128(xword, state1);
+ state1 = _mm_slli_si128(state1, 4);
+ xword = _mm_xor_si128(xword, state1);
+ state1 = _mm_slli_si128(state1, 4);
+ state1 = _mm_xor_si128(state1, xword);
+ *rk1 = state1;
+}
+
+static void aesni_setkey_enc_256(unsigned char *rk_bytes,
+ const unsigned char *key)
+{
+ __m128i *rk = (__m128i *) rk_bytes;
+
+ memcpy(&rk[0], key, 16);
+ memcpy(&rk[1], key + 16, 16);
+
+ /*
+ * Main "loop" - Generating one more key than necessary,
+ * see definition of mbedtls_aes_context.buf
+ */
+ aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), &rk[2], &rk[3]);
+ aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), &rk[4], &rk[5]);
+ aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), &rk[6], &rk[7]);
+ aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), &rk[8], &rk[9]);
+ aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), &rk[10], &rk[11]);
+ aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]);
+ aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]);
+}
+
+#else /* MBEDTLS_AESNI_HAVE_CODE == 1 */
+
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#warning \
+ "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code."
+#endif
+#endif
+
/*
* Binutils needs to be at least 2.19 to support AES-NI instructions.
* Unfortunately, a lot of users have a lower version now (2014-04).
@@ -75,13 +413,13 @@
* Operand macros are in gas order (src, dst) as opposed to Intel order
* (dst, src) in order to blend better into the surrounding assembly code.
*/
-#define AESDEC ".byte 0x66,0x0F,0x38,0xDE,"
-#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF,"
-#define AESENC ".byte 0x66,0x0F,0x38,0xDC,"
-#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD,"
-#define AESIMC ".byte 0x66,0x0F,0x38,0xDB,"
-#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF,"
-#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44,"
+#define AESDEC(regs) ".byte 0x66,0x0F,0x38,0xDE," regs "\n\t"
+#define AESDECLAST(regs) ".byte 0x66,0x0F,0x38,0xDF," regs "\n\t"
+#define AESENC(regs) ".byte 0x66,0x0F,0x38,0xDC," regs "\n\t"
+#define AESENCLAST(regs) ".byte 0x66,0x0F,0x38,0xDD," regs "\n\t"
+#define AESIMC(regs) ".byte 0x66,0x0F,0x38,0xDB," regs "\n\t"
+#define AESKEYGENA(regs, imm) ".byte 0x66,0x0F,0x3A,0xDF," regs "," imm "\n\t"
+#define PCLMULQDQ(regs, imm) ".byte 0x66,0x0F,0x3A,0x44," regs "," imm "\n\t"
#define xmm0_xmm0 "0xC0"
#define xmm0_xmm1 "0xC8"
@@ -109,25 +447,25 @@
"1: \n\t" // encryption loop
"movdqu (%1), %%xmm1 \n\t" // load round key
- AESENC xmm1_xmm0 "\n\t" // do round
- "add $16, %1 \n\t" // point to next round key
- "subl $1, %0 \n\t" // loop
- "jnz 1b \n\t"
- "movdqu (%1), %%xmm1 \n\t" // load round key
- AESENCLAST xmm1_xmm0 "\n\t" // last round
- "jmp 3f \n\t"
+ AESENC(xmm1_xmm0) // do round
+ "add $16, %1 \n\t" // point to next round key
+ "subl $1, %0 \n\t" // loop
+ "jnz 1b \n\t"
+ "movdqu (%1), %%xmm1 \n\t" // load round key
+ AESENCLAST(xmm1_xmm0) // last round
+ "jmp 3f \n\t"
- "2: \n\t" // decryption loop
- "movdqu (%1), %%xmm1 \n\t"
- AESDEC xmm1_xmm0 "\n\t" // do round
- "add $16, %1 \n\t"
- "subl $1, %0 \n\t"
- "jnz 2b \n\t"
- "movdqu (%1), %%xmm1 \n\t" // load round key
- AESDECLAST xmm1_xmm0 "\n\t" // last round
+ "2: \n\t" // decryption loop
+ "movdqu (%1), %%xmm1 \n\t"
+ AESDEC(xmm1_xmm0) // do round
+ "add $16, %1 \n\t"
+ "subl $1, %0 \n\t"
+ "jnz 2b \n\t"
+ "movdqu (%1), %%xmm1 \n\t" // load round key
+ AESDECLAST(xmm1_xmm0) // last round
- "3: \n\t"
- "movdqu %%xmm0, (%4) \n\t" // export output
+ "3: \n\t"
+ "movdqu %%xmm0, (%4) \n\t" // export output
:
: "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
: "memory", "cc", "xmm0", "xmm1");
@@ -158,84 +496,84 @@
/*
* Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
- * using [CLMUL-WP] algorithm 1 (p. 13).
+ * using [CLMUL-WP] algorithm 1 (p. 12).
*/
"movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0
"movdqa %%xmm1, %%xmm3 \n\t" // same
"movdqa %%xmm1, %%xmm4 \n\t" // same
- PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0
- PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0
- PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0
- PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0
- "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0
- "movdqa %%xmm4, %%xmm3 \n\t" // same
- "psrldq $8, %%xmm4 \n\t" // 0:e1+f1
- "pslldq $8, %%xmm3 \n\t" // e0+f0:0
- "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1
- "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0
+ PCLMULQDQ(xmm0_xmm1, "0x00") // a0*b0 = c1:c0
+ PCLMULQDQ(xmm0_xmm2, "0x11") // a1*b1 = d1:d0
+ PCLMULQDQ(xmm0_xmm3, "0x10") // a0*b1 = e1:e0
+ PCLMULQDQ(xmm0_xmm4, "0x01") // a1*b0 = f1:f0
+ "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0
+ "movdqa %%xmm4, %%xmm3 \n\t" // same
+ "psrldq $8, %%xmm4 \n\t" // 0:e1+f1
+ "pslldq $8, %%xmm3 \n\t" // e0+f0:0
+ "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1
+ "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0
/*
* Now shift the result one bit to the left,
- * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+ * taking advantage of [CLMUL-WP] eq 27 (p. 18)
*/
- "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0
- "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2
- "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1
- "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1
- "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63
- "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63
- "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63
- "pslldq $8, %%xmm3 \n\t" // r0>>63:0
- "pslldq $8, %%xmm4 \n\t" // r2>>63:0
- "psrldq $8, %%xmm5 \n\t" // 0:r1>>63
- "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1
- "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1
- "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
+ "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0
+ "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2
+ "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1
+ "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1
+ "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63
+ "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63
+ "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63
+ "pslldq $8, %%xmm3 \n\t" // r0>>63:0
+ "pslldq $8, %%xmm4 \n\t" // r2>>63:0
+ "psrldq $8, %%xmm5 \n\t" // 0:r1>>63
+ "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1
+ "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1
+ "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
/*
* Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
- * using [CLMUL-WP] algorithm 5 (p. 20).
+ * using [CLMUL-WP] algorithm 5 (p. 18).
* Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
*/
/* Step 2 (1) */
- "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0
- "movdqa %%xmm1, %%xmm4 \n\t" // same
- "movdqa %%xmm1, %%xmm5 \n\t" // same
- "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a
- "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b
- "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c
+ "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0
+ "movdqa %%xmm1, %%xmm4 \n\t" // same
+ "movdqa %%xmm1, %%xmm5 \n\t" // same
+ "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a
+ "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b
+ "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c
/* Step 2 (2) */
- "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b
- "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c
- "pslldq $8, %%xmm3 \n\t" // a+b+c:0
- "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0
+ "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b
+ "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c
+ "pslldq $8, %%xmm3 \n\t" // a+b+c:0
+ "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0
/* Steps 3 and 4 */
- "movdqa %%xmm1,%%xmm0 \n\t" // d:x0
- "movdqa %%xmm1,%%xmm4 \n\t" // same
- "movdqa %%xmm1,%%xmm5 \n\t" // same
- "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0'
- "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0'
- "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0'
- "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0'
- "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0'
+ "movdqa %%xmm1,%%xmm0 \n\t" // d:x0
+ "movdqa %%xmm1,%%xmm4 \n\t" // same
+ "movdqa %%xmm1,%%xmm5 \n\t" // same
+ "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0'
+ "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0'
+ "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0'
+ "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0'
+ "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0'
// e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing
// bits carried from d. Now get those\t bits back in.
- "movdqa %%xmm1,%%xmm3 \n\t" // d:x0
- "movdqa %%xmm1,%%xmm4 \n\t" // same
- "movdqa %%xmm1,%%xmm5 \n\t" // same
- "psllq $63, %%xmm3 \n\t" // d<<63:stuff
- "psllq $62, %%xmm4 \n\t" // d<<62:stuff
- "psllq $57, %%xmm5 \n\t" // d<<57:stuff
- "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff
- "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff
- "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d
- "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0
- "pxor %%xmm1, %%xmm0 \n\t" // h1:h0
- "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0
+ "movdqa %%xmm1,%%xmm3 \n\t" // d:x0
+ "movdqa %%xmm1,%%xmm4 \n\t" // same
+ "movdqa %%xmm1,%%xmm5 \n\t" // same
+ "psllq $63, %%xmm3 \n\t" // d<<63:stuff
+ "psllq $62, %%xmm4 \n\t" // d<<62:stuff
+ "psllq $57, %%xmm5 \n\t" // d<<57:stuff
+ "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff
+ "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff
+ "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d
+ "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0
+ "pxor %%xmm1, %%xmm0 \n\t" // h1:h0
+ "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0
- "movdqu %%xmm0, (%2) \n\t" // done
+ "movdqu %%xmm0, (%2) \n\t" // done
:
: "r" (aa), "r" (bb), "r" (cc)
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
@@ -261,8 +599,8 @@
for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16) {
asm ("movdqu (%0), %%xmm0 \n\t"
- AESIMC xmm0_xmm0 "\n\t"
- "movdqu %%xmm0, (%1) \n\t"
+ AESIMC(xmm0_xmm0)
+ "movdqu %%xmm0, (%1) \n\t"
:
: "r" (fk), "r" (ik)
: "memory", "xmm0");
@@ -306,16 +644,16 @@
/* Main "loop" */
"2: \n\t"
- AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t"
- AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x01") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x02") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x04") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x08") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x10") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x20") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x40") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x80") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x1B") "call 1b \n\t"
+ AESKEYGENA(xmm0_xmm1, "0x36") "call 1b \n\t"
:
: "r" (rk), "r" (key)
: "memory", "cc", "0");
@@ -364,14 +702,14 @@
"ret \n\t"
"2: \n\t"
- AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x80") "call 1b \n\t"
:
: "r" (rk), "r" (key)
@@ -414,36 +752,38 @@
/* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
* and proceed to generate next round key from there */
- AESKEYGENA xmm0_xmm2 ",0x00 \n\t"
- "pshufd $0xaa, %%xmm2, %%xmm2 \n\t"
- "pxor %%xmm1, %%xmm2 \n\t"
- "pslldq $4, %%xmm1 \n\t"
- "pxor %%xmm1, %%xmm2 \n\t"
- "pslldq $4, %%xmm1 \n\t"
- "pxor %%xmm1, %%xmm2 \n\t"
- "pslldq $4, %%xmm1 \n\t"
- "pxor %%xmm2, %%xmm1 \n\t"
- "add $16, %0 \n\t"
- "movdqu %%xmm1, (%0) \n\t"
- "ret \n\t"
+ AESKEYGENA(xmm0_xmm2, "0x00")
+ "pshufd $0xaa, %%xmm2, %%xmm2 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm2, %%xmm1 \n\t"
+ "add $16, %0 \n\t"
+ "movdqu %%xmm1, (%0) \n\t"
+ "ret \n\t"
/*
* Main "loop" - Generating one more key than necessary,
* see definition of mbedtls_aes_context.buf
*/
- "2: \n\t"
- AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
- AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
+ "2: \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t"
+ AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t"
:
: "r" (rk), "r" (key)
: "memory", "cc", "0");
}
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
+
/*
* Key expansion, wrapper
*/
@@ -461,6 +801,6 @@
return 0;
}
-#endif /* MBEDTLS_HAVE_X86_64 */
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
#endif /* MBEDTLS_AESNI_C */
diff --git a/library/common.h b/library/common.h
index 2786c97..e162aa3 100644
--- a/library/common.h
+++ b/library/common.h
@@ -29,6 +29,7 @@
#include "mbedtls/config.h"
#endif
+#include <assert.h>
#include <stddef.h>
#include <stdint.h>
@@ -347,4 +348,18 @@
}
#endif
+/* Always provide a static assert macro, so it can be used unconditionally.
+ * It will expand to nothing on some systems.
+ * Can be used outside functions (but don't add a trailing ';' in that case:
+ * the semicolon is included here to avoid triggering -Wextra-semi when
+ * MBEDTLS_STATIC_ASSERT() expands to nothing).
+ * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
+ * defines static_assert even with -std=c99, but then complains about it.
+ */
+#if defined(static_assert) && !defined(__FreeBSD__)
+#define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg);
+#else
+#define MBEDTLS_STATIC_ASSERT(expr, msg)
+#endif
+
#endif /* MBEDTLS_LIBRARY_COMMON_H */
diff --git a/library/gcm.c b/library/gcm.c
index f7db0d4..0c958c7 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -93,7 +93,7 @@
ctx->HL[8] = vl;
ctx->HH[8] = vh;
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
/* With CLMUL support, we need only h, not the rest of the table */
if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
return 0;
@@ -190,7 +190,7 @@
unsigned char lo, hi, rem;
uint64_t zh, zl;
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
unsigned char h[16];
@@ -202,7 +202,7 @@
mbedtls_aesni_gcm_mult(output, x, h);
return;
}
-#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
lo = x[15] & 0xf;
@@ -754,6 +754,27 @@
int i, j, ret;
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
+ if (verbose != 0) {
+#if defined(MBEDTLS_GCM_ALT)
+ mbedtls_printf(" GCM note: alternative implementation.\n");
+#else /* MBEDTLS_GCM_ALT */
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+ if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
+ mbedtls_printf(" GCM note: using AESNI via ");
+#if MBEDTLS_AESNI_HAVE_CODE == 1
+ mbedtls_printf("assembly");
+#elif MBEDTLS_AESNI_HAVE_CODE == 2
+ mbedtls_printf("intrinsics");
+#else
+ mbedtls_printf("(unknown)");
+#endif
+ mbedtls_printf(".\n");
+ } else
+#endif
+ mbedtls_printf(" GCM note: built-in implementation.\n");
+#endif /* MBEDTLS_GCM_ALT */
+ }
+
for (j = 0; j < 3; j++) {
int key_len = 128 + 64 * j;
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index d8a9940..bad7f46 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -47,7 +47,6 @@
#include "psa_crypto_random_impl.h"
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "mbedtls/platform.h"
@@ -1512,14 +1511,12 @@
return (status == PSA_SUCCESS) ? unlock_status : status;
}
-#if defined(static_assert)
-static_assert((MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
- "One or more key attribute flag is listed as both external-only and dual-use");
-static_assert((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
- "One or more key attribute flag is listed as both internal-only and dual-use");
-static_assert((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY) == 0,
- "One or more key attribute flag is listed as both internal-only and external-only");
-#endif
+MBEDTLS_STATIC_ASSERT((MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
+ "One or more key attribute flag is listed as both external-only and dual-use")
+MBEDTLS_STATIC_ASSERT((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
+ "One or more key attribute flag is listed as both internal-only and dual-use")
+MBEDTLS_STATIC_ASSERT((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY) == 0,
+ "One or more key attribute flag is listed as both internal-only and external-only")
/** Validate that a key policy is internally well-formed.
*
@@ -1782,11 +1779,10 @@
psa_key_slot_number_t slot_number =
psa_key_slot_get_slot_number(slot);
-#if defined(static_assert)
- static_assert(sizeof(slot_number) ==
- sizeof(data.slot_number),
- "Slot number size does not match psa_se_key_data_storage_t");
-#endif
+ MBEDTLS_STATIC_ASSERT(sizeof(slot_number) ==
+ sizeof(data.slot_number),
+ "Slot number size does not match psa_se_key_data_storage_t");
+
memcpy(&data.slot_number, &slot_number, sizeof(slot_number));
status = psa_save_persistent_key(&slot->attr,
(uint8_t *) &data,
diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c
index b660393..7bea10a 100644
--- a/library/psa_crypto_se.c
+++ b/library/psa_crypto_se.c
@@ -22,7 +22,6 @@
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-#include <assert.h>
#include <stdint.h>
#include <string.h>
@@ -315,10 +314,8 @@
}
/* Driver table entries are 0-initialized. 0 is not a valid driver
* location because it means a transparent key. */
-#if defined(static_assert)
- static_assert(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
- "Secure element support requires 0 to mean a local key");
-#endif
+ MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
+ "Secure element support requires 0 to mean a local key");
if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 598c66e..229f0d8 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -353,6 +353,9 @@
unsigned char buf[1000000];
#endif
void *pointer;
+#if defined(_WIN32)
+ int ci = 0; /* ci = 1 => running in CI, so don't wait for a key press */
+#endif
/*
* The C standard doesn't guarantee that all-bits-0 is the representation
@@ -380,6 +383,10 @@
} else if (strcmp(*argp, "--exclude") == 0 ||
strcmp(*argp, "-x") == 0) {
exclude_mode = 1;
+#if defined(_WIN32)
+ } else if (strcmp(*argp, "--ci") == 0) {
+ ci = 1;
+#endif
} else {
break;
}
@@ -450,8 +457,10 @@
mbedtls_printf(" [ All tests PASS ]\n\n");
}
#if defined(_WIN32)
- mbedtls_printf(" Press Enter to exit this program.\n");
- fflush(stdout); getchar();
+ if (!ci) {
+ mbedtls_printf(" Press Enter to exit this program.\n");
+ fflush(stdout); getchar();
+ }
#endif
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index ca477ac..10de8c7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -50,7 +50,9 @@
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py ${mbedtls_target} ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data
)
- add_executable(test_suite_${data_name} test_suite_${data_name}.c $<TARGET_OBJECTS:mbedtls_test>)
+ add_executable(test_suite_${data_name} test_suite_${data_name}.c
+ $<TARGET_OBJECTS:mbedtls_test>
+ $<TARGET_OBJECTS:mbedtls_test_helpers>)
target_link_libraries(test_suite_${data_name} ${libs})
# Include test-specific header files from ./include and private header
# files (used by some invasive tests) from ../library. Public header
diff --git a/tests/Makefile b/tests/Makefile
index 44ff43c..27dcacb 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -86,7 +86,7 @@
$(MBEDLIBS):
$(MAKE) -C ../library
-MBEDTLS_TEST_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c src/drivers/*.c))
+MBEDTLS_TEST_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c src/drivers/*.c src/test_helpers/*.c))
mbedtls_test: $(MBEDTLS_TEST_OBJS)
@@ -107,6 +107,10 @@
echo " CC $<"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
+src/test_helpers/%.o : src/test_helpers/%.c
+ echo " CC $<"
+ $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
+
C_FILES := $(addsuffix .c,$(APPS))
c: $(C_FILES)
@@ -143,7 +147,7 @@
clean:
ifndef WINDOWS
rm -rf $(BINARIES) *.c *.datax
- rm -f src/*.o src/drivers/*.o src/libmbed*
+ rm -f src/*.o src/drivers/*.o src/test_helpers/*.o src/libmbed*
rm -f include/test/instrument_record_status.h
rm -rf libtestdriver1
else
@@ -152,6 +156,7 @@
if exist *.datax del /Q /F *.datax
if exist src/*.o del /Q /F src/*.o
if exist src/drivers/*.o del /Q /F src/drivers/*.o
+ if exist src/test_helpers/*.o del /Q /F src/test_helpers/*.o
if exist src/libmbed* del /Q /F src/libmed*
if exist include/test/instrument_record_status.h del /Q /F include/test/instrument_record_status.h
endif
diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h
index 08179e2..f8b98c0 100644
--- a/tests/include/test/psa_crypto_helpers.h
+++ b/tests/include/test/psa_crypto_helpers.h
@@ -104,11 +104,11 @@
* `TEST_ASSERT( ! mbedtls_test_helper_is_psa_leaking( ) )`
* but with a more informative message.
*/
-#define ASSERT_PSA_PRISTINE() \
+#define ASSERT_PSA_PRISTINE() \
do \
{ \
- if (test_fail_if_psa_leaking(__LINE__, __FILE__)) \
- goto exit; \
+ if (mbedtls_test_fail_if_psa_leaking(__LINE__, __FILE__)) \
+ goto exit; \
} \
while (0)
@@ -122,12 +122,12 @@
* \note Persistent keys must be recorded with #TEST_USES_KEY_ID before
* creating them.
*/
-#define PSA_DONE() \
+#define PSA_DONE() \
do \
{ \
- test_fail_if_psa_leaking(__LINE__, __FILE__); \
- mbedtls_test_psa_purge_key_storage(); \
- mbedtls_psa_crypto_free(); \
+ mbedtls_test_fail_if_psa_leaking(__LINE__, __FILE__); \
+ mbedtls_test_psa_purge_key_storage(); \
+ mbedtls_psa_crypto_free(); \
} \
while (0)
@@ -193,6 +193,14 @@
*/
psa_key_usage_t mbedtls_test_update_key_usage_flags(psa_key_usage_t usage_flags);
+/** Check that no PSA Crypto key slots are in use.
+ *
+ * If any slots are in use, mark the current test as failed.
+ *
+ * \return 0 if the key store is empty, 1 otherwise.
+ */
+int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename);
+
/** Skip a test case if the given key is a 192 bits AES key and the AES
* implementation is at least partially provided by an accelerator or
* alternative implementation.
diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h
new file mode 100644
index 0000000..1957043
--- /dev/null
+++ b/tests/include/test/ssl_helpers.h
@@ -0,0 +1,511 @@
+/** \file ssl_helpers.h
+ *
+ * \brief This file contains helper functions to set up a TLS connection.
+ */
+
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SSL_HELPERS_H
+#define SSL_HELPERS_H
+
+#include <string.h>
+
+#include <test/helpers.h>
+#include <test/macros.h>
+#include <test/random.h>
+#include <test/psa_crypto_helpers.h>
+
+#if defined(MBEDTLS_SSL_TLS_C)
+#include <mbedtls/ssl_internal.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/certs.h>
+#include <mbedtls/timing.h>
+#include <mbedtls/debug.h>
+#include <ssl_tls13_keys.h>
+
+#if defined(MBEDTLS_SSL_CACHE_C)
+#include "mbedtls/ssl_cache.h"
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
+#define MBEDTLS_CAN_HANDLE_RSA_TEST_KEY
+#endif
+
+enum {
+#define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \
+ tls1_3_label_ ## name,
+ MBEDTLS_SSL_TLS1_3_LABEL_LIST
+#undef MBEDTLS_SSL_TLS1_3_LABEL
+};
+
+typedef struct mbedtls_test_ssl_log_pattern {
+ const char *pattern;
+ size_t counter;
+} mbedtls_test_ssl_log_pattern;
+
+/* Invalid minor version used when not specifying a min/max version or expecting a test to fail */
+#define TEST_SSL_MINOR_VERSION_NONE -1
+
+typedef struct mbedtls_test_handshake_test_options {
+ const char *cipher;
+ int client_min_version;
+ int client_max_version;
+ int server_min_version;
+ int server_max_version;
+ int expected_negotiated_version;
+ int pk_alg;
+ data_t *psk_str;
+ int dtls;
+ int srv_auth_mode;
+ int serialize;
+ int mfl;
+ int cli_msg_len;
+ int srv_msg_len;
+ int expected_cli_fragments;
+ int expected_srv_fragments;
+ int renegotiate;
+ int legacy_renegotiation;
+ void *srv_log_obj;
+ void *cli_log_obj;
+ void (*srv_log_fun)(void *, int, const char *, int, const char *);
+ void (*cli_log_fun)(void *, int, const char *, int, const char *);
+ int resize_buffers;
+} mbedtls_test_handshake_test_options;
+
+/*
+ * Buffer structure for custom I/O callbacks.
+ */
+typedef struct mbedtls_test_ssl_buffer {
+ size_t start;
+ size_t content_length;
+ size_t capacity;
+ unsigned char *buffer;
+} mbedtls_test_ssl_buffer;
+
+/*
+ * Context for a message metadata queue (fifo) that is on top of the ring buffer.
+ */
+typedef struct mbedtls_test_ssl_message_queue {
+ size_t *messages;
+ int pos;
+ int num;
+ int capacity;
+} mbedtls_test_ssl_message_queue;
+
+/*
+ * Context for the I/O callbacks simulating network connection.
+ */
+
+#define MBEDTLS_MOCK_SOCKET_CONNECTED 1
+
+typedef struct mbedtls_test_mock_socket {
+ int status;
+ mbedtls_test_ssl_buffer *input;
+ mbedtls_test_ssl_buffer *output;
+ struct mbedtls_test_mock_socket *peer;
+} mbedtls_test_mock_socket;
+
+/* Errors used in the message socket mocks */
+
+#define MBEDTLS_TEST_ERROR_CONTEXT_ERROR -55
+#define MBEDTLS_TEST_ERROR_SEND_FAILED -66
+#define MBEDTLS_TEST_ERROR_RECV_FAILED -77
+
+/*
+ * Structure used as an addon, or a wrapper, around the mocked sockets.
+ * Contains an input queue, to which the other socket pushes metadata,
+ * and an output queue, to which this one pushes metadata. This context is
+ * considered as an owner of the input queue only, which is initialized and
+ * freed in the respective setup and free calls.
+ */
+typedef struct mbedtls_test_message_socket_context {
+ mbedtls_test_ssl_message_queue *queue_input;
+ mbedtls_test_ssl_message_queue *queue_output;
+ mbedtls_test_mock_socket *socket;
+} mbedtls_test_message_socket_context;
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
+ defined(MBEDTLS_CERTS_C) && \
+ defined(MBEDTLS_ENTROPY_C) && \
+ defined(MBEDTLS_CTR_DRBG_C)
+
+/*
+ * Structure with endpoint's certificates for SSL communication tests.
+ */
+typedef struct mbedtls_test_ssl_endpoint_certificate {
+ mbedtls_x509_crt *ca_cert;
+ mbedtls_x509_crt *cert;
+ mbedtls_pk_context *pkey;
+} mbedtls_test_ssl_endpoint_certificate;
+
+/*
+ * Endpoint structure for SSL communication tests.
+ */
+typedef struct mbedtls_test_ssl_endpoint {
+ const char *name;
+ mbedtls_ssl_context ssl;
+ mbedtls_ssl_config conf;
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_entropy_context entropy;
+ mbedtls_test_mock_socket socket;
+ mbedtls_test_ssl_endpoint_certificate cert;
+} mbedtls_test_ssl_endpoint;
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C &&
+ MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
+
+/*
+ * This function can be passed to mbedtls to receive output logs from it. In
+ * this case, it will count the instances of a mbedtls_test_ssl_log_pattern
+ * in the received logged messages.
+ */
+void mbedtls_test_ssl_log_analyzer(void *ctx, int level,
+ const char *file, int line,
+ const char *str);
+
+void mbedtls_test_init_handshake_options(
+ mbedtls_test_handshake_test_options *opts);
+
+/*
+ * Initialises \p buf. After calling this function it is safe to call
+ * `mbedtls_test_ssl_buffer_free()` on \p buf.
+ */
+void mbedtls_test_ssl_buffer_init(mbedtls_test_ssl_buffer *buf);
+
+/*
+ * Sets up \p buf. After calling this function it is safe to call
+ * `mbedtls_test_ssl_buffer_put()` and `mbedtls_test_ssl_buffer_get()`
+ * on \p buf.
+ */
+int mbedtls_test_ssl_buffer_setup(mbedtls_test_ssl_buffer *buf,
+ size_t capacity);
+
+void mbedtls_test_ssl_buffer_free(mbedtls_test_ssl_buffer *buf);
+
+/*
+ * Puts \p input_len bytes from the \p input buffer into the ring buffer \p buf.
+ *
+ * \p buf must have been initialized and set up by calling
+ * `mbedtls_test_ssl_buffer_init()` and `mbedtls_test_ssl_buffer_setup()`.
+ *
+ * \retval \p input_len, if the data fits.
+ * \retval 0 <= value < \p input_len, if the data does not fit.
+ * \retval -1, if \p buf is NULL, it hasn't been set up or \p input_len is not
+ * zero and \p input is NULL.
+ */
+int mbedtls_test_ssl_buffer_put(mbedtls_test_ssl_buffer *buf,
+ const unsigned char *input, size_t input_len);
+
+/*
+ * Gets \p output_len bytes from the ring buffer \p buf into the
+ * \p output buffer. The output buffer can be NULL, in this case a part of the
+ * ring buffer will be dropped, if the requested length is available.
+ *
+ * \p buf must have been initialized and set up by calling
+ * `mbedtls_test_ssl_buffer_init()` and `mbedtls_test_ssl_buffer_setup()`.
+ *
+ * \retval \p output_len, if the data is available.
+ * \retval 0 <= value < \p output_len, if the data is not available.
+ * \retval -1, if \buf is NULL or it hasn't been set up.
+ */
+int mbedtls_test_ssl_buffer_get(mbedtls_test_ssl_buffer *buf,
+ unsigned char *output, size_t output_len);
+
+/*
+ * Errors used in the message transport mock tests
+ */
+ #define MBEDTLS_TEST_ERROR_ARG_NULL -11
+ #define MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED -44
+
+/*
+ * Setup and free functions for the message metadata queue.
+ *
+ * \p capacity describes the number of message metadata chunks that can be held
+ * within the queue.
+ *
+ * \retval 0, if a metadata queue of a given length can be allocated.
+ * \retval MBEDTLS_ERR_SSL_ALLOC_FAILED, if allocation failed.
+ */
+int mbedtls_test_ssl_message_queue_setup(
+ mbedtls_test_ssl_message_queue *queue, size_t capacity);
+
+void mbedtls_test_ssl_message_queue_free(
+ mbedtls_test_ssl_message_queue *queue);
+
+/*
+ * Push message length information onto the message metadata queue.
+ * This will become the last element to leave it (fifo).
+ *
+ * \retval MBEDTLS_TEST_ERROR_ARG_NULL, if the queue is null.
+ * \retval MBEDTLS_ERR_SSL_WANT_WRITE, if the queue is full.
+ * \retval \p len, if the push was successful.
+ */
+int mbedtls_test_ssl_message_queue_push_info(
+ mbedtls_test_ssl_message_queue *queue, size_t len);
+
+/*
+ * Pop information about the next message length from the queue. This will be
+ * the oldest inserted message length(fifo). \p msg_len can be null, in which
+ * case the data will be popped from the queue but not copied anywhere.
+ *
+ * \retval MBEDTLS_TEST_ERROR_ARG_NULL, if the queue is null.
+ * \retval MBEDTLS_ERR_SSL_WANT_READ, if the queue is empty.
+ * \retval message length, if the pop was successful, up to the given
+ \p buf_len.
+ */
+int mbedtls_test_ssl_message_queue_pop_info(
+ mbedtls_test_ssl_message_queue *queue, size_t buf_len);
+
+/*
+ * Setup and teardown functions for mock sockets.
+ */
+void mbedtls_mock_socket_init(mbedtls_test_mock_socket *socket);
+
+/*
+ * Closes the socket \p socket.
+ *
+ * \p socket must have been previously initialized by calling
+ * mbedtls_mock_socket_init().
+ *
+ * This function frees all allocated resources and both sockets are aware of the
+ * new connection state.
+ *
+ * That is, this function does not simulate half-open TCP connections and the
+ * phenomenon that when closing a UDP connection the peer is not aware of the
+ * connection having been closed.
+ */
+void mbedtls_test_mock_socket_close(mbedtls_test_mock_socket *socket);
+
+/*
+ * Establishes a connection between \p peer1 and \p peer2.
+ *
+ * \p peer1 and \p peer2 must have been previously initialized by calling
+ * mbedtls_mock_socket_init().
+ *
+ * The capacities of the internal buffers are set to \p bufsize. Setting this to
+ * the correct value allows for simulation of MTU, sanity testing the mock
+ * implementation and mocking TCP connections with lower memory cost.
+ */
+int mbedtls_test_mock_socket_connect(mbedtls_test_mock_socket *peer1,
+ mbedtls_test_mock_socket *peer2,
+ size_t bufsize);
+
+/*
+ * Callbacks for simulating blocking I/O over connection-oriented transport.
+ */
+int mbedtls_test_mock_tcp_send_b(void *ctx,
+ const unsigned char *buf, size_t len);
+
+int mbedtls_test_mock_tcp_recv_b(void *ctx, unsigned char *buf, size_t len);
+
+/*
+ * Callbacks for simulating non-blocking I/O over connection-oriented transport.
+ */
+int mbedtls_test_mock_tcp_send_nb(void *ctx,
+ const unsigned char *buf, size_t len);
+
+int mbedtls_test_mock_tcp_recv_nb(void *ctx, unsigned char *buf, size_t len);
+
+void mbedtls_test_message_socket_init(
+ mbedtls_test_message_socket_context *ctx);
+
+/*
+ * Setup a given message socket context including initialization of
+ * input/output queues to a chosen capacity of messages. Also set the
+ * corresponding mock socket.
+ *
+ * \retval 0, if everything succeeds.
+ * \retval MBEDTLS_ERR_SSL_ALLOC_FAILED, if allocation of a message
+ * queue failed.
+ */
+int mbedtls_test_message_socket_setup(
+ mbedtls_test_ssl_message_queue *queue_input,
+ mbedtls_test_ssl_message_queue *queue_output,
+ size_t queue_capacity,
+ mbedtls_test_mock_socket *socket,
+ mbedtls_test_message_socket_context *ctx);
+
+/*
+ * Close a given message socket context, along with the socket itself. Free the
+ * memory allocated by the input queue.
+ */
+void mbedtls_test_message_socket_close(
+ mbedtls_test_message_socket_context *ctx);
+
+/*
+ * Send one message through a given message socket context.
+ *
+ * \retval \p len, if everything succeeds.
+ * \retval MBEDTLS_TEST_ERROR_CONTEXT_ERROR, if any of the needed context
+ * elements or the context itself is null.
+ * \retval MBEDTLS_TEST_ERROR_SEND_FAILED if
+ * mbedtls_test_mock_tcp_send_b failed.
+ * \retval MBEDTLS_ERR_SSL_WANT_WRITE, if the output queue is full.
+ *
+ * This function will also return any error from
+ * mbedtls_test_ssl_message_queue_push_info.
+ */
+int mbedtls_test_mock_tcp_send_msg(void *ctx,
+ const unsigned char *buf, size_t len);
+
+/*
+ * Receive one message from a given message socket context and return message
+ * length or an error.
+ *
+ * \retval message length, if everything succeeds.
+ * \retval MBEDTLS_TEST_ERROR_CONTEXT_ERROR, if any of the needed context
+ * elements or the context itself is null.
+ * \retval MBEDTLS_TEST_ERROR_RECV_FAILED if
+ * mbedtls_test_mock_tcp_recv_b failed.
+ *
+ * This function will also return any error other than
+ * MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED from
+ * mbedtls_test_message_queue_peek_info.
+ */
+int mbedtls_test_mock_tcp_recv_msg(void *ctx,
+ unsigned char *buf, size_t buf_len);
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
+ defined(MBEDTLS_CERTS_C) && \
+ defined(MBEDTLS_ENTROPY_C) && \
+ defined(MBEDTLS_CTR_DRBG_C)
+
+/*
+ * Initializes \p ep_cert structure and assigns it to endpoint
+ * represented by \p ep.
+ *
+ * \retval 0 on success, otherwise error code.
+ */
+int mbedtls_test_ssl_endpoint_certificate_init(mbedtls_test_ssl_endpoint *ep,
+ int pk_alg);
+
+/*
+ * Initializes \p ep structure. It is important to call
+ * `mbedtls_test_ssl_endpoint_free()` after calling this function
+ * even if it fails.
+ *
+ * \p endpoint_type must be set as MBEDTLS_SSL_IS_SERVER or
+ * MBEDTLS_SSL_IS_CLIENT.
+ * \p pk_alg the algorithm to use, currently only MBEDTLS_PK_RSA and
+ * MBEDTLS_PK_ECDSA are supported.
+ * \p dtls_context - in case of DTLS - this is the context handling metadata.
+ * \p input_queue - used only in case of DTLS.
+ * \p output_queue - used only in case of DTLS.
+ *
+ * \retval 0 on success, otherwise error code.
+ */
+int mbedtls_test_ssl_endpoint_init(
+ mbedtls_test_ssl_endpoint *ep, int endpoint_type, int pk_alg,
+ mbedtls_test_message_socket_context *dtls_context,
+ mbedtls_test_ssl_message_queue *input_queue,
+ mbedtls_test_ssl_message_queue *output_queue,
+ const mbedtls_ecp_group_id *curves);
+
+/*
+ * Deinitializes endpoint represented by \p ep.
+ */
+void mbedtls_test_ssl_endpoint_free(
+ mbedtls_test_ssl_endpoint *ep,
+ mbedtls_test_message_socket_context *context);
+
+/*
+ * This function moves ssl handshake from \p ssl to prescribed \p state.
+ * /p second_ssl is used as second endpoint and their sockets have to be
+ * connected before calling this function.
+ *
+ * \retval 0 on success, otherwise error code.
+ */
+int mbedtls_test_move_handshake_to_state(mbedtls_ssl_context *ssl,
+ mbedtls_ssl_context *second_ssl,
+ int state);
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C &&
+ MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
+
+/*
+ * Helper function setting up inverse record transformations
+ * using given cipher, hash, EtM mode, authentication tag length,
+ * and version.
+ */
+
+#define CHK(x) \
+ do \
+ { \
+ if (!(x)) \
+ { \
+ ret = -1; \
+ goto cleanup; \
+ } \
+ } while (0)
+
+int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in,
+ mbedtls_ssl_transform *t_out,
+ int cipher_type, int hash_id,
+ int etm, int tag_mode, int ver,
+ size_t cid0_len,
+ size_t cid1_len);
+
+/*
+ * Populate a session structure for serialization tests.
+ * Choose dummy values, mostly non-0 to distinguish from the init default.
+ */
+int mbedtls_test_ssl_populate_session(mbedtls_ssl_session *session,
+ int ticket_len,
+ const char *crt_file);
+
+/*
+ * Perform data exchanging between \p ssl_1 and \p ssl_2 and check if the
+ * message was sent in the correct number of fragments.
+ *
+ * /p ssl_1 and /p ssl_2 Endpoints represented by mbedtls_ssl_context. Both
+ * of them must be initialized and connected
+ * beforehand.
+ * /p msg_len_1 and /p msg_len_2 specify the size of the message to send.
+ * /p expected_fragments_1 and /p expected_fragments_2 determine in how many
+ * fragments the message should be sent.
+ * expected_fragments is 0: can be used for DTLS testing while the message
+ * size is larger than MFL. In that case the message
+ * cannot be fragmented and sent to the second
+ * endpoint.
+ * This value can be used for negative tests.
+ * expected_fragments is 1: can be used for TLS/DTLS testing while the
+ * message size is below MFL
+ * expected_fragments > 1: can be used for TLS testing while the message
+ * size is larger than MFL
+ *
+ * \retval 0 on success, otherwise error code.
+ */
+int mbedtls_exchange_data(mbedtls_ssl_context *ssl_1,
+ int msg_len_1, const int expected_fragments_1,
+ mbedtls_ssl_context *ssl_2,
+ int msg_len_2, const int expected_fragments_2);
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
+ defined(MBEDTLS_CERTS_C) && \
+ defined(MBEDTLS_ENTROPY_C) && \
+ defined(MBEDTLS_CTR_DRBG_C)
+void mbedtls_test_ssl_perform_handshake(
+ mbedtls_test_handshake_test_options *options);
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C &&
+ MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
+#endif /* MBEDTLS_SSL_TLS_C */
+
+#endif /* SSL_HELPERS_H */
diff --git a/tests/src/psa_crypto_helpers.c b/tests/src/psa_crypto_helpers.c
index 06274d3..77c2f89 100644
--- a/tests/src/psa_crypto_helpers.c
+++ b/tests/src/psa_crypto_helpers.c
@@ -138,4 +138,15 @@
return updated_usage;
}
+int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename)
+{
+ const char *msg = mbedtls_test_helper_is_psa_leaking();
+ if (msg == NULL) {
+ return 0;
+ } else {
+ mbedtls_test_fail(msg, line_no, filename);
+ return 1;
+ }
+}
+
#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c
new file mode 100644
index 0000000..b7a7e86
--- /dev/null
+++ b/tests/src/test_helpers/ssl_helpers.c
@@ -0,0 +1,1760 @@
+/** \file ssl_helpers.c
+ *
+ * \brief Helper functions to set up a TLS connection.
+ */
+
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <test/ssl_helpers.h>
+
+#if defined(MBEDTLS_SSL_TLS_C)
+
+void mbedtls_test_ssl_log_analyzer(void *ctx, int level,
+ const char *file, int line,
+ const char *str)
+{
+ mbedtls_test_ssl_log_pattern *p = (mbedtls_test_ssl_log_pattern *) ctx;
+
+ (void) level;
+ (void) line;
+ (void) file;
+
+ if (NULL != p &&
+ NULL != p->pattern &&
+ NULL != strstr(str, p->pattern)) {
+ p->counter++;
+ }
+}
+
+void mbedtls_test_init_handshake_options(
+ mbedtls_test_handshake_test_options *opts)
+{
+ opts->cipher = "";
+ opts->client_min_version = TEST_SSL_MINOR_VERSION_NONE;
+ opts->client_max_version = TEST_SSL_MINOR_VERSION_NONE;
+ opts->server_min_version = TEST_SSL_MINOR_VERSION_NONE;
+ opts->server_max_version = TEST_SSL_MINOR_VERSION_NONE;
+ opts->expected_negotiated_version = MBEDTLS_SSL_MINOR_VERSION_3;
+ opts->pk_alg = MBEDTLS_PK_RSA;
+ opts->psk_str = NULL;
+ opts->dtls = 0;
+ opts->srv_auth_mode = MBEDTLS_SSL_VERIFY_NONE;
+ opts->serialize = 0;
+ opts->mfl = MBEDTLS_SSL_MAX_FRAG_LEN_NONE;
+ opts->cli_msg_len = 100;
+ opts->srv_msg_len = 100;
+ opts->expected_cli_fragments = 1;
+ opts->expected_srv_fragments = 1;
+ opts->renegotiate = 0;
+ opts->legacy_renegotiation = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
+ opts->srv_log_obj = NULL;
+ opts->srv_log_obj = NULL;
+ opts->srv_log_fun = NULL;
+ opts->cli_log_fun = NULL;
+ opts->resize_buffers = 1;
+}
+
+void mbedtls_test_ssl_buffer_init(mbedtls_test_ssl_buffer *buf)
+{
+ memset(buf, 0, sizeof(*buf));
+}
+
+int mbedtls_test_ssl_buffer_setup(mbedtls_test_ssl_buffer *buf,
+ size_t capacity)
+{
+ buf->buffer = (unsigned char *) mbedtls_calloc(capacity,
+ sizeof(unsigned char));
+ if (NULL == buf->buffer) {
+ return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ }
+ buf->capacity = capacity;
+
+ return 0;
+}
+
+void mbedtls_test_ssl_buffer_free(mbedtls_test_ssl_buffer *buf)
+{
+ if (buf->buffer != NULL) {
+ mbedtls_free(buf->buffer);
+ }
+
+ memset(buf, 0, sizeof(*buf));
+}
+
+int mbedtls_test_ssl_buffer_put(mbedtls_test_ssl_buffer *buf,
+ const unsigned char *input, size_t input_len)
+{
+ size_t overflow = 0;
+
+ if ((buf == NULL) || (buf->buffer == NULL)) {
+ return -1;
+ }
+
+ /* Reduce input_len to a number that fits in the buffer. */
+ if ((buf->content_length + input_len) > buf->capacity) {
+ input_len = buf->capacity - buf->content_length;
+ }
+
+ if (input == NULL) {
+ return (input_len == 0) ? 0 : -1;
+ }
+
+ /* Check if the buffer has not come full circle and free space is not in
+ * the middle */
+ if (buf->start + buf->content_length < buf->capacity) {
+
+ /* Calculate the number of bytes that need to be placed at lower memory
+ * address */
+ if (buf->start + buf->content_length + input_len
+ > buf->capacity) {
+ overflow = (buf->start + buf->content_length + input_len)
+ % buf->capacity;
+ }
+
+ memcpy(buf->buffer + buf->start + buf->content_length, input,
+ input_len - overflow);
+ memcpy(buf->buffer, input + input_len - overflow, overflow);
+
+ } else {
+ /* The buffer has come full circle and free space is in the middle */
+ memcpy(buf->buffer + buf->start + buf->content_length - buf->capacity,
+ input, input_len);
+ }
+
+ buf->content_length += input_len;
+ return (input_len > INT_MAX) ? INT_MAX : (int) input_len;
+}
+
+int mbedtls_test_ssl_buffer_get(mbedtls_test_ssl_buffer *buf,
+ unsigned char *output, size_t output_len)
+{
+ size_t overflow = 0;
+
+ if ((buf == NULL) || (buf->buffer == NULL)) {
+ return -1;
+ }
+
+ if (output == NULL && output_len == 0) {
+ return 0;
+ }
+
+ if (buf->content_length < output_len) {
+ output_len = buf->content_length;
+ }
+
+ /* Calculate the number of bytes that need to be drawn from lower memory
+ * address */
+ if (buf->start + output_len > buf->capacity) {
+ overflow = (buf->start + output_len) % buf->capacity;
+ }
+
+ if (output != NULL) {
+ memcpy(output, buf->buffer + buf->start, output_len - overflow);
+ memcpy(output + output_len - overflow, buf->buffer, overflow);
+ }
+
+ buf->content_length -= output_len;
+ buf->start = (buf->start + output_len) % buf->capacity;
+
+ return (output_len > INT_MAX) ? INT_MAX : (int) output_len;
+}
+
+int mbedtls_test_ssl_message_queue_setup(
+ mbedtls_test_ssl_message_queue *queue, size_t capacity)
+{
+ queue->messages = (size_t *) mbedtls_calloc(capacity, sizeof(size_t));
+ if (NULL == queue->messages) {
+ return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ }
+
+ queue->capacity = (capacity > INT_MAX) ? INT_MAX : (int) capacity;
+ queue->pos = 0;
+ queue->num = 0;
+
+ return 0;
+}
+
+void mbedtls_test_ssl_message_queue_free(
+ mbedtls_test_ssl_message_queue *queue)
+{
+ if (queue == NULL) {
+ return;
+ }
+
+ if (queue->messages != NULL) {
+ mbedtls_free(queue->messages);
+ }
+
+ memset(queue, 0, sizeof(*queue));
+}
+
+int mbedtls_test_ssl_message_queue_push_info(
+ mbedtls_test_ssl_message_queue *queue, size_t len)
+{
+ int place;
+ if (queue == NULL) {
+ return MBEDTLS_TEST_ERROR_ARG_NULL;
+ }
+
+ if (queue->num >= queue->capacity) {
+ return MBEDTLS_ERR_SSL_WANT_WRITE;
+ }
+
+ place = (queue->pos + queue->num) % queue->capacity;
+ queue->messages[place] = len;
+ queue->num++;
+ return (len > INT_MAX) ? INT_MAX : (int) len;
+}
+
+int mbedtls_test_ssl_message_queue_pop_info(
+ mbedtls_test_ssl_message_queue *queue, size_t buf_len)
+{
+ size_t message_length;
+ if (queue == NULL) {
+ return MBEDTLS_TEST_ERROR_ARG_NULL;
+ }
+ if (queue->num == 0) {
+ return MBEDTLS_ERR_SSL_WANT_READ;
+ }
+
+ message_length = queue->messages[queue->pos];
+ queue->messages[queue->pos] = 0;
+ queue->num--;
+ queue->pos++;
+ queue->pos %= queue->capacity;
+ if (queue->pos < 0) {
+ queue->pos += queue->capacity;
+ }
+
+ return (message_length > INT_MAX && buf_len > INT_MAX) ? INT_MAX :
+ (message_length > buf_len) ? (int) buf_len : (int) message_length;
+}
+
+/*
+ * Take a peek on the info about the next message length from the queue.
+ * This will be the oldest inserted message length(fifo).
+ *
+ * \retval MBEDTLS_TEST_ERROR_ARG_NULL, if the queue is null.
+ * \retval MBEDTLS_ERR_SSL_WANT_READ, if the queue is empty.
+ * \retval 0, if the peek was successful.
+ * \retval MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED, if the given buffer length is
+ * too small to fit the message. In this case the \p msg_len will be
+ * set to the full message length so that the
+ * caller knows what portion of the message can be dropped.
+ */
+int mbedtls_test_message_queue_peek_info(mbedtls_test_ssl_message_queue *queue,
+ size_t buf_len, size_t *msg_len)
+{
+ if (queue == NULL || msg_len == NULL) {
+ return MBEDTLS_TEST_ERROR_ARG_NULL;
+ }
+ if (queue->num == 0) {
+ return MBEDTLS_ERR_SSL_WANT_READ;
+ }
+
+ *msg_len = queue->messages[queue->pos];
+ return (*msg_len > buf_len) ? MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED : 0;
+}
+
+void mbedtls_mock_socket_init(mbedtls_test_mock_socket *socket)
+{
+ memset(socket, 0, sizeof(*socket));
+}
+
+void mbedtls_test_mock_socket_close(mbedtls_test_mock_socket *socket)
+{
+ if (socket == NULL) {
+ return;
+ }
+
+ if (socket->input != NULL) {
+ mbedtls_test_ssl_buffer_free(socket->input);
+ mbedtls_free(socket->input);
+ }
+
+ if (socket->output != NULL) {
+ mbedtls_test_ssl_buffer_free(socket->output);
+ mbedtls_free(socket->output);
+ }
+
+ if (socket->peer != NULL) {
+ memset(socket->peer, 0, sizeof(*socket->peer));
+ }
+
+ memset(socket, 0, sizeof(*socket));
+}
+
+int mbedtls_test_mock_socket_connect(mbedtls_test_mock_socket *peer1,
+ mbedtls_test_mock_socket *peer2,
+ size_t bufsize)
+{
+ int ret = -1;
+
+ peer1->output =
+ (mbedtls_test_ssl_buffer *) mbedtls_calloc(
+ 1, sizeof(mbedtls_test_ssl_buffer));
+ if (peer1->output == NULL) {
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto exit;
+ }
+ mbedtls_test_ssl_buffer_init(peer1->output);
+ if (0 != (ret = mbedtls_test_ssl_buffer_setup(peer1->output, bufsize))) {
+ goto exit;
+ }
+
+ peer2->output =
+ (mbedtls_test_ssl_buffer *) mbedtls_calloc(
+ 1, sizeof(mbedtls_test_ssl_buffer));
+ if (peer2->output == NULL) {
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto exit;
+ }
+ mbedtls_test_ssl_buffer_init(peer2->output);
+ if (0 != (ret = mbedtls_test_ssl_buffer_setup(peer2->output, bufsize))) {
+ goto exit;
+ }
+
+ peer1->peer = peer2;
+ peer2->peer = peer1;
+ peer1->input = peer2->output;
+ peer2->input = peer1->output;
+
+ peer1->status = peer2->status = MBEDTLS_MOCK_SOCKET_CONNECTED;
+ ret = 0;
+
+exit:
+
+ if (ret != 0) {
+ mbedtls_test_mock_socket_close(peer1);
+ mbedtls_test_mock_socket_close(peer2);
+ }
+
+ return ret;
+}
+
+int mbedtls_test_mock_tcp_send_b(void *ctx,
+ const unsigned char *buf, size_t len)
+{
+ mbedtls_test_mock_socket *socket = (mbedtls_test_mock_socket *) ctx;
+
+ if (socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED) {
+ return -1;
+ }
+
+ return mbedtls_test_ssl_buffer_put(socket->output, buf, len);
+}
+
+int mbedtls_test_mock_tcp_recv_b(void *ctx, unsigned char *buf, size_t len)
+{
+ mbedtls_test_mock_socket *socket = (mbedtls_test_mock_socket *) ctx;
+
+ if (socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED) {
+ return -1;
+ }
+
+ return mbedtls_test_ssl_buffer_get(socket->input, buf, len);
+}
+
+int mbedtls_test_mock_tcp_send_nb(void *ctx,
+ const unsigned char *buf, size_t len)
+{
+ mbedtls_test_mock_socket *socket = (mbedtls_test_mock_socket *) ctx;
+
+ if (socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED) {
+ return -1;
+ }
+
+ if (socket->output->capacity == socket->output->content_length) {
+ return MBEDTLS_ERR_SSL_WANT_WRITE;
+ }
+
+ return mbedtls_test_ssl_buffer_put(socket->output, buf, len);
+}
+
+int mbedtls_test_mock_tcp_recv_nb(void *ctx, unsigned char *buf, size_t len)
+{
+ mbedtls_test_mock_socket *socket = (mbedtls_test_mock_socket *) ctx;
+
+ if (socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED) {
+ return -1;
+ }
+
+ if (socket->input->content_length == 0) {
+ return MBEDTLS_ERR_SSL_WANT_READ;
+ }
+
+ return mbedtls_test_ssl_buffer_get(socket->input, buf, len);
+}
+
+void mbedtls_test_message_socket_init(
+ mbedtls_test_message_socket_context *ctx)
+{
+ ctx->queue_input = NULL;
+ ctx->queue_output = NULL;
+ ctx->socket = NULL;
+}
+
+int mbedtls_test_message_socket_setup(
+ mbedtls_test_ssl_message_queue *queue_input,
+ mbedtls_test_ssl_message_queue *queue_output,
+ size_t queue_capacity,
+ mbedtls_test_mock_socket *socket,
+ mbedtls_test_message_socket_context *ctx)
+{
+ int ret = mbedtls_test_ssl_message_queue_setup(queue_input, queue_capacity);
+ if (ret != 0) {
+ return ret;
+ }
+ ctx->queue_input = queue_input;
+ ctx->queue_output = queue_output;
+ ctx->socket = socket;
+ mbedtls_mock_socket_init(socket);
+
+ return 0;
+}
+
+void mbedtls_test_message_socket_close(
+ mbedtls_test_message_socket_context *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+
+ mbedtls_test_ssl_message_queue_free(ctx->queue_input);
+ mbedtls_test_mock_socket_close(ctx->socket);
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+int mbedtls_test_mock_tcp_send_msg(void *ctx,
+ const unsigned char *buf, size_t len)
+{
+ mbedtls_test_ssl_message_queue *queue;
+ mbedtls_test_mock_socket *socket;
+ mbedtls_test_message_socket_context *context =
+ (mbedtls_test_message_socket_context *) ctx;
+
+ if (context == NULL || context->socket == NULL
+ || context->queue_output == NULL) {
+ return MBEDTLS_TEST_ERROR_CONTEXT_ERROR;
+ }
+
+ queue = context->queue_output;
+ socket = context->socket;
+
+ if (queue->num >= queue->capacity) {
+ return MBEDTLS_ERR_SSL_WANT_WRITE;
+ }
+
+ if (mbedtls_test_mock_tcp_send_b(socket, buf, len) != (int) len) {
+ return MBEDTLS_TEST_ERROR_SEND_FAILED;
+ }
+
+ return mbedtls_test_ssl_message_queue_push_info(queue, len);
+}
+
+int mbedtls_test_mock_tcp_recv_msg(void *ctx,
+ unsigned char *buf, size_t buf_len)
+{
+ mbedtls_test_ssl_message_queue *queue;
+ mbedtls_test_mock_socket *socket;
+ mbedtls_test_message_socket_context *context =
+ (mbedtls_test_message_socket_context *) ctx;
+ size_t drop_len = 0;
+ size_t msg_len;
+ int ret;
+
+ if (context == NULL || context->socket == NULL
+ || context->queue_input == NULL) {
+ return MBEDTLS_TEST_ERROR_CONTEXT_ERROR;
+ }
+
+ queue = context->queue_input;
+ socket = context->socket;
+
+ /* Peek first, so that in case of a socket error the data remains in
+ * the queue. */
+ ret = mbedtls_test_message_queue_peek_info(queue, buf_len, &msg_len);
+ if (ret == MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED) {
+ /* Calculate how much to drop */
+ drop_len = msg_len - buf_len;
+
+ /* Set the requested message len to be buffer length */
+ msg_len = buf_len;
+ } else if (ret != 0) {
+ return ret;
+ }
+
+ if (mbedtls_test_mock_tcp_recv_b(socket, buf, msg_len) != (int) msg_len) {
+ return MBEDTLS_TEST_ERROR_RECV_FAILED;
+ }
+
+ if (ret == MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED) {
+ /* Drop the remaining part of the message */
+ if (mbedtls_test_mock_tcp_recv_b(socket, NULL, drop_len) !=
+ (int) drop_len) {
+ /* Inconsistent state - part of the message was read,
+ * and a part couldn't. Not much we can do here, but it should not
+ * happen in test environment, unless forced manually. */
+ }
+ }
+ mbedtls_test_ssl_message_queue_pop_info(queue, buf_len);
+
+ return (msg_len > INT_MAX) ? INT_MAX : (int) msg_len;
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
+ defined(MBEDTLS_CERTS_C) && \
+ defined(MBEDTLS_ENTROPY_C) && \
+ defined(MBEDTLS_CTR_DRBG_C)
+
+/*
+ * Deinitializes certificates from endpoint represented by \p ep.
+ */
+void mbedtls_endpoint_certificate_free(mbedtls_test_ssl_endpoint *ep)
+{
+ mbedtls_test_ssl_endpoint_certificate *cert = &(ep->cert);
+ if (cert != NULL) {
+ if (cert->ca_cert != NULL) {
+ mbedtls_x509_crt_free(cert->ca_cert);
+ mbedtls_free(cert->ca_cert);
+ cert->ca_cert = NULL;
+ }
+ if (cert->cert != NULL) {
+ mbedtls_x509_crt_free(cert->cert);
+ mbedtls_free(cert->cert);
+ cert->cert = NULL;
+ }
+ if (cert->pkey != NULL) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if (mbedtls_pk_get_type(cert->pkey) == MBEDTLS_PK_OPAQUE) {
+ mbedtls_svc_key_id_t *key_slot = cert->pkey->pk_ctx;
+ psa_destroy_key(*key_slot);
+ }
+#endif
+ mbedtls_pk_free(cert->pkey);
+ mbedtls_free(cert->pkey);
+ cert->pkey = NULL;
+ }
+ }
+}
+
+int mbedtls_test_ssl_endpoint_certificate_init(mbedtls_test_ssl_endpoint *ep,
+ int pk_alg)
+{
+ int i = 0;
+ int ret = -1;
+ mbedtls_test_ssl_endpoint_certificate *cert = NULL;
+
+ if (ep == NULL) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ cert = &(ep->cert);
+ ASSERT_ALLOC(cert->ca_cert, 1);
+ ASSERT_ALLOC(cert->cert, 1);
+ ASSERT_ALLOC(cert->pkey, 1);
+
+ mbedtls_x509_crt_init(cert->ca_cert);
+ mbedtls_x509_crt_init(cert->cert);
+ mbedtls_pk_init(cert->pkey);
+
+ /* Load the trusted CA */
+
+ for (i = 0; mbedtls_test_cas_der[i] != NULL; i++) {
+ ret = mbedtls_x509_crt_parse_der(
+ cert->ca_cert,
+ (const unsigned char *) mbedtls_test_cas_der[i],
+ mbedtls_test_cas_der_len[i]);
+ TEST_ASSERT(ret == 0);
+ }
+
+ /* Load own certificate and private key */
+
+ if (ep->conf.endpoint == MBEDTLS_SSL_IS_SERVER) {
+ if (pk_alg == MBEDTLS_PK_RSA) {
+ ret = mbedtls_x509_crt_parse(
+ cert->cert,
+ (const unsigned char *) mbedtls_test_srv_crt_rsa_sha256_der,
+ mbedtls_test_srv_crt_rsa_sha256_der_len);
+ TEST_ASSERT(ret == 0);
+
+ ret = mbedtls_pk_parse_key(
+ cert->pkey,
+ (const unsigned char *) mbedtls_test_srv_key_rsa_der,
+ mbedtls_test_srv_key_rsa_der_len, NULL, 0);
+ TEST_ASSERT(ret == 0);
+ } else {
+ ret = mbedtls_x509_crt_parse(
+ cert->cert,
+ (const unsigned char *) mbedtls_test_srv_crt_ec_der,
+ mbedtls_test_srv_crt_ec_der_len);
+ TEST_ASSERT(ret == 0);
+
+ ret = mbedtls_pk_parse_key(
+ cert->pkey,
+ (const unsigned char *) mbedtls_test_srv_key_ec_der,
+ mbedtls_test_srv_key_ec_der_len, NULL, 0);
+ TEST_ASSERT(ret == 0);
+ }
+ } else {
+ if (pk_alg == MBEDTLS_PK_RSA) {
+ ret = mbedtls_x509_crt_parse(
+ cert->cert,
+ (const unsigned char *) mbedtls_test_cli_crt_rsa_der,
+ mbedtls_test_cli_crt_rsa_der_len);
+ TEST_ASSERT(ret == 0);
+
+ ret = mbedtls_pk_parse_key(
+ cert->pkey,
+ (const unsigned char *) mbedtls_test_cli_key_rsa_der,
+ mbedtls_test_cli_key_rsa_der_len, NULL, 0);
+ TEST_ASSERT(ret == 0);
+ } else {
+ ret = mbedtls_x509_crt_parse(
+ cert->cert,
+ (const unsigned char *) mbedtls_test_cli_crt_ec_der,
+ mbedtls_test_cli_crt_ec_len);
+ TEST_ASSERT(ret == 0);
+
+ ret = mbedtls_pk_parse_key(
+ cert->pkey,
+ (const unsigned char *) mbedtls_test_cli_key_ec_der,
+ mbedtls_test_cli_key_ec_der_len, NULL, 0);
+ TEST_ASSERT(ret == 0);
+ }
+ }
+
+ mbedtls_ssl_conf_ca_chain(&(ep->conf), cert->ca_cert, NULL);
+
+ ret = mbedtls_ssl_conf_own_cert(&(ep->conf), cert->cert,
+ cert->pkey);
+ TEST_ASSERT(ret == 0);
+
+exit:
+ if (ret != 0) {
+ mbedtls_endpoint_certificate_free(ep);
+ }
+
+ return ret;
+}
+
+int mbedtls_test_ssl_endpoint_init(
+ mbedtls_test_ssl_endpoint *ep, int endpoint_type, int pk_alg,
+ mbedtls_test_message_socket_context *dtls_context,
+ mbedtls_test_ssl_message_queue *input_queue,
+ mbedtls_test_ssl_message_queue *output_queue,
+ const mbedtls_ecp_group_id *curves)
+{
+ int ret = -1;
+
+ if (dtls_context != NULL &&
+ (input_queue == NULL || output_queue == NULL)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ if (ep == NULL) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ memset(ep, 0, sizeof(*ep));
+
+ ep->name = (endpoint_type == MBEDTLS_SSL_IS_SERVER) ? "Server" : "Client";
+
+ mbedtls_ssl_init(&(ep->ssl));
+ mbedtls_ssl_config_init(&(ep->conf));
+ mbedtls_ctr_drbg_init(&(ep->ctr_drbg));
+ mbedtls_ssl_conf_rng(&(ep->conf),
+ mbedtls_ctr_drbg_random,
+ &(ep->ctr_drbg));
+ mbedtls_entropy_init(&(ep->entropy));
+ if (dtls_context != NULL) {
+ TEST_ASSERT(mbedtls_test_message_socket_setup(input_queue, output_queue,
+ 100, &(ep->socket),
+ dtls_context) == 0);
+ } else {
+ mbedtls_mock_socket_init(&(ep->socket));
+ }
+
+ ret = mbedtls_ctr_drbg_seed(&(ep->ctr_drbg), mbedtls_entropy_func,
+ &(ep->entropy),
+ (const unsigned char *) (ep->name),
+ strlen(ep->name));
+ TEST_ASSERT(ret == 0);
+
+ /* Non-blocking callbacks without timeout */
+ if (dtls_context != NULL) {
+ mbedtls_ssl_set_bio(&(ep->ssl), dtls_context,
+ mbedtls_test_mock_tcp_send_msg,
+ mbedtls_test_mock_tcp_recv_msg,
+ NULL);
+ } else {
+ mbedtls_ssl_set_bio(&(ep->ssl), &(ep->socket),
+ mbedtls_test_mock_tcp_send_nb,
+ mbedtls_test_mock_tcp_recv_nb,
+ NULL);
+ }
+
+ ret = mbedtls_ssl_config_defaults(&(ep->conf), endpoint_type,
+ (dtls_context != NULL) ?
+ MBEDTLS_SSL_TRANSPORT_DATAGRAM :
+ MBEDTLS_SSL_TRANSPORT_STREAM,
+ MBEDTLS_SSL_PRESET_DEFAULT);
+ TEST_ASSERT(ret == 0);
+
+#if defined(MBEDTLS_ECP_C)
+ if (curves != NULL) {
+ mbedtls_ssl_conf_curves(&(ep->conf), curves);
+ }
+#else
+ (void) curves;
+#endif
+
+ ret = mbedtls_ssl_setup(&(ep->ssl), &(ep->conf));
+ TEST_ASSERT(ret == 0);
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS) && defined(MBEDTLS_SSL_SRV_C)
+ if (endpoint_type == MBEDTLS_SSL_IS_SERVER && dtls_context != NULL) {
+ mbedtls_ssl_conf_dtls_cookies(&(ep->conf), NULL, NULL, NULL);
+ }
+#endif
+
+ ret = mbedtls_test_ssl_endpoint_certificate_init(ep, pk_alg);
+ TEST_ASSERT(ret == 0);
+
+exit:
+ return ret;
+}
+
+void mbedtls_test_ssl_endpoint_free(
+ mbedtls_test_ssl_endpoint *ep,
+ mbedtls_test_message_socket_context *context)
+{
+ mbedtls_endpoint_certificate_free(ep);
+
+ mbedtls_ssl_free(&(ep->ssl));
+ mbedtls_ssl_config_free(&(ep->conf));
+ mbedtls_ctr_drbg_free(&(ep->ctr_drbg));
+ mbedtls_entropy_free(&(ep->entropy));
+
+ if (context != NULL) {
+ mbedtls_test_message_socket_close(context);
+ } else {
+ mbedtls_test_mock_socket_close(&(ep->socket));
+ }
+}
+
+int mbedtls_test_move_handshake_to_state(mbedtls_ssl_context *ssl,
+ mbedtls_ssl_context *second_ssl,
+ int state)
+{
+ enum { BUFFSIZE = 1024 };
+ int max_steps = 1000;
+ int ret = 0;
+
+ if (ssl == NULL || second_ssl == NULL) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ /* Perform communication via connected sockets */
+ while ((ssl->state != state) && (--max_steps >= 0)) {
+ /* If /p second_ssl ends the handshake procedure before /p ssl then
+ * there is no need to call the next step */
+ if (second_ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
+ ret = mbedtls_ssl_handshake_step(second_ssl);
+ if (ret != 0 && ret != MBEDTLS_ERR_SSL_WANT_READ &&
+ ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+ return ret;
+ }
+ }
+
+ /* We only care about the \p ssl state and returns, so we call it last,
+ * to leave the iteration as soon as the state is as expected. */
+ ret = mbedtls_ssl_handshake_step(ssl);
+ if (ret != 0 && ret != MBEDTLS_ERR_SSL_WANT_READ &&
+ ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+ return ret;
+ }
+ }
+
+ return (max_steps >= 0) ? ret : -1;
+}
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C &&
+ MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
+
+/*
+ * Write application data. Increase write counter if necessary.
+ */
+int mbedtls_ssl_write_fragment(mbedtls_ssl_context *ssl,
+ unsigned char *buf, int buf_len,
+ int *written,
+ const int expected_fragments)
+{
+ /* Verify that calling mbedtls_ssl_write with a NULL buffer and zero length is
+ * a valid no-op for TLS connections. */
+ if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+ TEST_ASSERT(mbedtls_ssl_write(ssl, NULL, 0) == 0);
+ }
+
+ int ret = mbedtls_ssl_write(ssl, buf + *written, buf_len - *written);
+ if (ret > 0) {
+ *written += ret;
+ }
+
+ if (expected_fragments == 0) {
+ /* Used for DTLS and the message size larger than MFL. In that case
+ * the message can not be fragmented and the library should return
+ * MBEDTLS_ERR_SSL_BAD_INPUT_DATA error. This error must be returned
+ * to prevent a dead loop inside mbedtls_exchange_data(). */
+ return ret;
+ } else if (expected_fragments == 1) {
+ /* Used for TLS/DTLS and the message size lower than MFL */
+ TEST_ASSERT(ret == buf_len ||
+ ret == MBEDTLS_ERR_SSL_WANT_READ ||
+ ret == MBEDTLS_ERR_SSL_WANT_WRITE);
+ } else {
+ /* Used for TLS and the message size larger than MFL */
+ TEST_ASSERT(expected_fragments > 1);
+ TEST_ASSERT((ret >= 0 && ret <= buf_len) ||
+ ret == MBEDTLS_ERR_SSL_WANT_READ ||
+ ret == MBEDTLS_ERR_SSL_WANT_WRITE);
+ }
+
+ return 0;
+
+exit:
+ /* Some of the tests failed */
+ return -1;
+}
+
+/*
+ * Read application data and increase read counter and fragments counter
+ * if necessary.
+ */
+int mbedtls_ssl_read_fragment(mbedtls_ssl_context *ssl,
+ unsigned char *buf, int buf_len,
+ int *read, int *fragments,
+ const int expected_fragments)
+{
+ /* Verify that calling mbedtls_ssl_write with a NULL buffer and zero length is
+ * a valid no-op for TLS connections. */
+ if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+ TEST_ASSERT(mbedtls_ssl_read(ssl, NULL, 0) == 0);
+ }
+
+ int ret = mbedtls_ssl_read(ssl, buf + *read, buf_len - *read);
+ if (ret > 0) {
+ (*fragments)++;
+ *read += ret;
+ }
+
+ if (expected_fragments == 0) {
+ TEST_ASSERT(ret == 0);
+ } else if (expected_fragments == 1) {
+ TEST_ASSERT(ret == buf_len ||
+ ret == MBEDTLS_ERR_SSL_WANT_READ ||
+ ret == MBEDTLS_ERR_SSL_WANT_WRITE);
+ } else {
+ TEST_ASSERT(expected_fragments > 1);
+ TEST_ASSERT((ret >= 0 && ret <= buf_len) ||
+ ret == MBEDTLS_ERR_SSL_WANT_READ ||
+ ret == MBEDTLS_ERR_SSL_WANT_WRITE);
+ }
+
+ return 0;
+
+exit:
+ /* Some of the tests failed */
+ return -1;
+}
+
+void set_ciphersuite(mbedtls_ssl_config *conf, const char *cipher,
+ int *forced_ciphersuite)
+{
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+ forced_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id(cipher);
+ forced_ciphersuite[1] = 0;
+
+ ciphersuite_info =
+ mbedtls_ssl_ciphersuite_from_id(forced_ciphersuite[0]);
+
+ TEST_ASSERT(ciphersuite_info != NULL);
+ TEST_ASSERT(ciphersuite_info->min_minor_ver <= conf->max_minor_ver);
+ TEST_ASSERT(ciphersuite_info->max_minor_ver >= conf->min_minor_ver);
+
+ if (conf->max_minor_ver > ciphersuite_info->max_minor_ver) {
+ conf->max_minor_ver = ciphersuite_info->max_minor_ver;
+ }
+ if (conf->min_minor_ver < ciphersuite_info->min_minor_ver) {
+ conf->min_minor_ver = ciphersuite_info->min_minor_ver;
+ }
+
+ mbedtls_ssl_conf_ciphersuites(conf, forced_ciphersuite);
+
+exit:
+ return;
+}
+
+int psk_dummy_callback(void *p_info, mbedtls_ssl_context *ssl,
+ const unsigned char *name, size_t name_len)
+{
+ (void) p_info;
+ (void) ssl;
+ (void) name;
+ (void) name_len;
+
+ return 0;
+}
+
+#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX
+#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_IN_LEN_MAX
+#else
+#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_OUT_LEN_MAX
+#endif
+
+int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in,
+ mbedtls_ssl_transform *t_out,
+ int cipher_type, int hash_id,
+ int etm, int tag_mode, int ver,
+ size_t cid0_len,
+ size_t cid1_len)
+{
+ mbedtls_cipher_info_t const *cipher_info;
+ int ret = 0;
+
+ size_t keylen, maclen, ivlen;
+ unsigned char *key0 = NULL, *key1 = NULL;
+ unsigned char *md0 = NULL, *md1 = NULL;
+ unsigned char iv_enc[16], iv_dec[16];
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ unsigned char cid0[SSL_CID_LEN_MIN];
+ unsigned char cid1[SSL_CID_LEN_MIN];
+
+ mbedtls_test_rnd_std_rand(NULL, cid0, sizeof(cid0));
+ mbedtls_test_rnd_std_rand(NULL, cid1, sizeof(cid1));
+#else
+ ((void) cid0_len);
+ ((void) cid1_len);
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ maclen = 0;
+
+ /* Pick cipher */
+ cipher_info = mbedtls_cipher_info_from_type(cipher_type);
+ CHK(cipher_info != NULL);
+ CHK(cipher_info->iv_size <= 16);
+ CHK(cipher_info->key_bitlen % 8 == 0);
+
+ /* Pick keys */
+ keylen = cipher_info->key_bitlen / 8;
+ /* Allocate `keylen + 1` bytes to ensure that we get
+ * a non-NULL pointers from `mbedtls_calloc` even if
+ * `keylen == 0` in the case of the NULL cipher. */
+ CHK((key0 = mbedtls_calloc(1, keylen + 1)) != NULL);
+ CHK((key1 = mbedtls_calloc(1, keylen + 1)) != NULL);
+ memset(key0, 0x1, keylen);
+ memset(key1, 0x2, keylen);
+
+ /* Setup cipher contexts */
+ CHK(mbedtls_cipher_setup(&t_in->cipher_ctx_enc, cipher_info) == 0);
+ CHK(mbedtls_cipher_setup(&t_in->cipher_ctx_dec, cipher_info) == 0);
+ CHK(mbedtls_cipher_setup(&t_out->cipher_ctx_enc, cipher_info) == 0);
+ CHK(mbedtls_cipher_setup(&t_out->cipher_ctx_dec, cipher_info) == 0);
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ if (cipher_info->mode == MBEDTLS_MODE_CBC) {
+ CHK(mbedtls_cipher_set_padding_mode(&t_in->cipher_ctx_enc,
+ MBEDTLS_PADDING_NONE) == 0);
+ CHK(mbedtls_cipher_set_padding_mode(&t_in->cipher_ctx_dec,
+ MBEDTLS_PADDING_NONE) == 0);
+ CHK(mbedtls_cipher_set_padding_mode(&t_out->cipher_ctx_enc,
+ MBEDTLS_PADDING_NONE) == 0);
+ CHK(mbedtls_cipher_set_padding_mode(&t_out->cipher_ctx_dec,
+ MBEDTLS_PADDING_NONE) == 0);
+ }
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+ CHK(mbedtls_cipher_setkey(&t_in->cipher_ctx_enc, key0,
+ (keylen << 3 > INT_MAX) ? INT_MAX : (int) keylen << 3,
+ MBEDTLS_ENCRYPT)
+ == 0);
+ CHK(mbedtls_cipher_setkey(&t_in->cipher_ctx_dec, key1,
+ (keylen << 3 > INT_MAX) ? INT_MAX : (int) keylen << 3,
+ MBEDTLS_DECRYPT)
+ == 0);
+ CHK(mbedtls_cipher_setkey(&t_out->cipher_ctx_enc, key1,
+ (keylen << 3 > INT_MAX) ? INT_MAX : (int) keylen << 3,
+ MBEDTLS_ENCRYPT)
+ == 0);
+ CHK(mbedtls_cipher_setkey(&t_out->cipher_ctx_dec, key0,
+ (keylen << 3 > INT_MAX) ? INT_MAX : (int) keylen << 3,
+ MBEDTLS_DECRYPT)
+ == 0);
+
+ /* Setup MAC contexts */
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ if (cipher_info->mode == MBEDTLS_MODE_CBC ||
+ cipher_info->mode == MBEDTLS_MODE_STREAM) {
+ mbedtls_md_info_t const *md_info;
+
+ /* Pick hash */
+ md_info = mbedtls_md_info_from_type(hash_id);
+ CHK(md_info != NULL);
+
+ /* Pick hash keys */
+ maclen = mbedtls_md_get_size(md_info);
+ CHK((md0 = mbedtls_calloc(1, maclen)) != NULL);
+ CHK((md1 = mbedtls_calloc(1, maclen)) != NULL);
+ memset(md0, 0x5, maclen);
+ memset(md1, 0x6, maclen);
+
+ CHK(mbedtls_md_setup(&t_out->md_ctx_enc, md_info, 1) == 0);
+ CHK(mbedtls_md_setup(&t_out->md_ctx_dec, md_info, 1) == 0);
+ CHK(mbedtls_md_setup(&t_in->md_ctx_enc, md_info, 1) == 0);
+ CHK(mbedtls_md_setup(&t_in->md_ctx_dec, md_info, 1) == 0);
+
+ if (ver > MBEDTLS_SSL_MINOR_VERSION_0) {
+ CHK(mbedtls_md_hmac_starts(&t_in->md_ctx_enc,
+ md0, maclen) == 0);
+ CHK(mbedtls_md_hmac_starts(&t_in->md_ctx_dec,
+ md1, maclen) == 0);
+ CHK(mbedtls_md_hmac_starts(&t_out->md_ctx_enc,
+ md1, maclen) == 0);
+ CHK(mbedtls_md_hmac_starts(&t_out->md_ctx_dec,
+ md0, maclen) == 0);
+ }
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ else {
+ memcpy(&t_in->mac_enc, md0, maclen);
+ memcpy(&t_in->mac_dec, md1, maclen);
+ memcpy(&t_out->mac_enc, md1, maclen);
+ memcpy(&t_out->mac_dec, md0, maclen);
+ }
+#endif
+ }
+#else
+ ((void) hash_id);
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+
+
+ /* Pick IV's (regardless of whether they
+ * are being used by the transform). */
+ ivlen = cipher_info->iv_size;
+ memset(iv_enc, 0x3, sizeof(iv_enc));
+ memset(iv_dec, 0x4, sizeof(iv_dec));
+
+ /*
+ * Setup transforms
+ */
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \
+ defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ t_out->encrypt_then_mac = etm;
+ t_in->encrypt_then_mac = etm;
+#else
+ ((void) etm);
+#endif
+
+ t_out->minor_ver = ver;
+ t_in->minor_ver = ver;
+ t_out->ivlen = ivlen;
+ t_in->ivlen = ivlen;
+
+ switch (cipher_info->mode) {
+ case MBEDTLS_MODE_GCM:
+ case MBEDTLS_MODE_CCM:
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+ if (ver == MBEDTLS_SSL_MINOR_VERSION_4) {
+ t_out->fixed_ivlen = 12;
+ t_in->fixed_ivlen = 12;
+ } else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+ {
+ t_out->fixed_ivlen = 4;
+ t_in->fixed_ivlen = 4;
+ }
+ t_out->maclen = 0;
+ t_in->maclen = 0;
+ switch (tag_mode) {
+ case 0: /* Full tag */
+ t_out->taglen = 16;
+ t_in->taglen = 16;
+ break;
+ case 1: /* Partial tag */
+ t_out->taglen = 8;
+ t_in->taglen = 8;
+ break;
+ default:
+ ret = 1;
+ goto cleanup;
+ }
+ break;
+
+ case MBEDTLS_MODE_CHACHAPOLY:
+ t_out->fixed_ivlen = 12;
+ t_in->fixed_ivlen = 12;
+ t_out->maclen = 0;
+ t_in->maclen = 0;
+ switch (tag_mode) {
+ case 0: /* Full tag */
+ t_out->taglen = 16;
+ t_in->taglen = 16;
+ break;
+ case 1: /* Partial tag */
+ t_out->taglen = 8;
+ t_in->taglen = 8;
+ break;
+ default:
+ ret = 1;
+ goto cleanup;
+ }
+ break;
+
+ case MBEDTLS_MODE_STREAM:
+ case MBEDTLS_MODE_CBC:
+ t_out->fixed_ivlen = 0; /* redundant, must be 0 */
+ t_in->fixed_ivlen = 0; /* redundant, must be 0 */
+ t_out->taglen = 0;
+ t_in->taglen = 0;
+ switch (tag_mode) {
+ case 0: /* Full tag */
+ t_out->maclen = maclen;
+ t_in->maclen = maclen;
+ break;
+ case 1: /* Partial tag */
+ t_out->maclen = 10;
+ t_in->maclen = 10;
+ break;
+ default:
+ ret = 1;
+ goto cleanup;
+ }
+ break;
+ default:
+ ret = 1;
+ goto cleanup;
+ break;
+ }
+
+ /* Setup IV's */
+
+ memcpy(&t_in->iv_dec, iv_dec, sizeof(iv_dec));
+ memcpy(&t_in->iv_enc, iv_enc, sizeof(iv_enc));
+ memcpy(&t_out->iv_dec, iv_enc, sizeof(iv_enc));
+ memcpy(&t_out->iv_enc, iv_dec, sizeof(iv_dec));
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /* Add CID */
+ memcpy(&t_in->in_cid, cid0, cid0_len);
+ memcpy(&t_in->out_cid, cid1, cid1_len);
+ t_in->in_cid_len = (uint8_t) cid0_len;
+ t_in->out_cid_len = (uint8_t) cid1_len;
+ memcpy(&t_out->in_cid, cid1, cid1_len);
+ memcpy(&t_out->out_cid, cid0, cid0_len);
+ t_out->in_cid_len = (uint8_t) cid1_len;
+ t_out->out_cid_len = (uint8_t) cid0_len;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+cleanup:
+
+ mbedtls_free(key0);
+ mbedtls_free(key1);
+
+ mbedtls_free(md0);
+ mbedtls_free(md1);
+
+ return ret;
+}
+
+int mbedtls_test_ssl_populate_session(mbedtls_ssl_session *session,
+ int ticket_len,
+ const char *crt_file)
+{
+#if defined(MBEDTLS_HAVE_TIME)
+ session->start = mbedtls_time(NULL) - 42;
+#endif
+ session->ciphersuite = 0xabcd;
+ session->compression = 1;
+ session->id_len = sizeof(session->id);
+ memset(session->id, 66, session->id_len);
+ memset(session->master, 17, sizeof(session->master));
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
+ defined(MBEDTLS_CERTS_C) && \
+ defined(MBEDTLS_FS_IO)
+ if (strlen(crt_file) != 0) {
+ mbedtls_x509_crt tmp_crt;
+ int ret;
+
+ mbedtls_x509_crt_init(&tmp_crt);
+ ret = mbedtls_x509_crt_parse_file(&tmp_crt, crt_file);
+ if (ret != 0) {
+ return ret;
+ }
+
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ /* Move temporary CRT. */
+ session->peer_cert = mbedtls_calloc(1, sizeof(*session->peer_cert));
+ if (session->peer_cert == NULL) {
+ return -1;
+ }
+ *session->peer_cert = tmp_crt;
+ memset(&tmp_crt, 0, sizeof(tmp_crt));
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ /* Calculate digest of temporary CRT. */
+ session->peer_cert_digest =
+ mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN);
+ if (session->peer_cert_digest == NULL) {
+ return -1;
+ }
+ ret = mbedtls_md(mbedtls_md_info_from_type(
+ MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE),
+ tmp_crt.raw.p, tmp_crt.raw.len,
+ session->peer_cert_digest);
+ if (ret != 0) {
+ return ret;
+ }
+ session->peer_cert_digest_type =
+ MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
+ session->peer_cert_digest_len =
+ MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+ mbedtls_x509_crt_free(&tmp_crt);
+ }
+#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C && MBEDTLS_FS_IO */
+ (void) crt_file;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C && MBEDTLS_FS_IO */
+ session->verify_result = 0xdeadbeef;
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+ if (ticket_len != 0) {
+ session->ticket = mbedtls_calloc(1, ticket_len);
+ if (session->ticket == NULL) {
+ return -1;
+ }
+ memset(session->ticket, 33, ticket_len);
+ }
+ session->ticket_len = ticket_len;
+ session->ticket_lifetime = 86401;
+#else
+ (void) ticket_len;
+#endif
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ session->mfl_code = 1;
+#endif
+#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+ session->trunc_hmac = 1;
+#endif
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ session->encrypt_then_mac = 1;
+#endif
+
+ return 0;
+}
+
+int mbedtls_exchange_data(mbedtls_ssl_context *ssl_1,
+ int msg_len_1, const int expected_fragments_1,
+ mbedtls_ssl_context *ssl_2,
+ int msg_len_2, const int expected_fragments_2)
+{
+ unsigned char *msg_buf_1 = malloc(msg_len_1);
+ unsigned char *msg_buf_2 = malloc(msg_len_2);
+ unsigned char *in_buf_1 = malloc(msg_len_2);
+ unsigned char *in_buf_2 = malloc(msg_len_1);
+ int msg_type, ret = -1;
+
+ /* Perform this test with two message types. At first use a message
+ * consisting of only 0x00 for the client and only 0xFF for the server.
+ * At the second time use message with generated data */
+ for (msg_type = 0; msg_type < 2; msg_type++) {
+ int written_1 = 0;
+ int written_2 = 0;
+ int read_1 = 0;
+ int read_2 = 0;
+ int fragments_1 = 0;
+ int fragments_2 = 0;
+
+ if (msg_type == 0) {
+ memset(msg_buf_1, 0x00, msg_len_1);
+ memset(msg_buf_2, 0xff, msg_len_2);
+ } else {
+ int i, j = 0;
+ for (i = 0; i < msg_len_1; i++) {
+ msg_buf_1[i] = j++ & 0xFF;
+ }
+ for (i = 0; i < msg_len_2; i++) {
+ msg_buf_2[i] = (j -= 5) & 0xFF;
+ }
+ }
+
+ while (read_1 < msg_len_2 || read_2 < msg_len_1) {
+ /* ssl_1 sending */
+ if (msg_len_1 > written_1) {
+ ret = mbedtls_ssl_write_fragment(ssl_1, msg_buf_1,
+ msg_len_1, &written_1,
+ expected_fragments_1);
+ if (expected_fragments_1 == 0) {
+ /* This error is expected when the message is too large and
+ * cannot be fragmented */
+ TEST_ASSERT(ret == MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
+ msg_len_1 = 0;
+ } else {
+ TEST_ASSERT(ret == 0);
+ }
+ }
+
+ /* ssl_2 sending */
+ if (msg_len_2 > written_2) {
+ ret = mbedtls_ssl_write_fragment(ssl_2, msg_buf_2,
+ msg_len_2, &written_2,
+ expected_fragments_2);
+ if (expected_fragments_2 == 0) {
+ /* This error is expected when the message is too large and
+ * cannot be fragmented */
+ TEST_ASSERT(ret == MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
+ msg_len_2 = 0;
+ } else {
+ TEST_ASSERT(ret == 0);
+ }
+ }
+
+ /* ssl_1 reading */
+ if (read_1 < msg_len_2) {
+ ret = mbedtls_ssl_read_fragment(ssl_1, in_buf_1,
+ msg_len_2, &read_1,
+ &fragments_2,
+ expected_fragments_2);
+ TEST_ASSERT(ret == 0);
+ }
+
+ /* ssl_2 reading */
+ if (read_2 < msg_len_1) {
+ ret = mbedtls_ssl_read_fragment(ssl_2, in_buf_2,
+ msg_len_1, &read_2,
+ &fragments_1,
+ expected_fragments_1);
+ TEST_ASSERT(ret == 0);
+ }
+ }
+
+ ret = -1;
+ TEST_ASSERT(0 == memcmp(msg_buf_1, in_buf_2, msg_len_1));
+ TEST_ASSERT(0 == memcmp(msg_buf_2, in_buf_1, msg_len_2));
+ TEST_ASSERT(fragments_1 == expected_fragments_1);
+ TEST_ASSERT(fragments_2 == expected_fragments_2);
+ }
+
+ ret = 0;
+
+exit:
+ free(msg_buf_1);
+ free(in_buf_1);
+ free(msg_buf_2);
+ free(in_buf_2);
+
+ return ret;
+}
+
+/*
+ * Perform data exchanging between \p ssl_1 and \p ssl_2. Both of endpoints
+ * must be initialized and connected beforehand.
+ *
+ * \retval 0 on success, otherwise error code.
+ */
+int exchange_data(mbedtls_ssl_context *ssl_1,
+ mbedtls_ssl_context *ssl_2)
+{
+ return mbedtls_exchange_data(ssl_1, 256, 1,
+ ssl_2, 256, 1);
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
+ defined(MBEDTLS_CERTS_C) && \
+ defined(MBEDTLS_ENTROPY_C) && \
+ defined(MBEDTLS_CTR_DRBG_C)
+void mbedtls_test_ssl_perform_handshake(
+ mbedtls_test_handshake_test_options *options)
+{
+ /* forced_ciphersuite needs to last until the end of the handshake */
+ int forced_ciphersuite[2];
+ enum { BUFFSIZE = 17000 };
+ mbedtls_test_ssl_endpoint client, server;
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+ const char *psk_identity = "foo";
+#endif
+#if defined(MBEDTLS_TIMING_C)
+ mbedtls_timing_delay_context timer_client, timer_server;
+#endif
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+ unsigned char *context_buf = NULL;
+ size_t context_buf_len;
+#endif
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ int ret = -1;
+#endif
+ int expected_handshake_result = 0;
+
+ USE_PSA_INIT();
+ mbedtls_platform_zeroize(&client, sizeof(client));
+ mbedtls_platform_zeroize(&server, sizeof(server));
+
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
+ mbedtls_test_message_socket_context server_context, client_context;
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
+
+ /* Client side */
+ if (options->dtls != 0) {
+ TEST_ASSERT(mbedtls_test_ssl_endpoint_init(&client,
+ MBEDTLS_SSL_IS_CLIENT,
+ options->pk_alg,
+ &client_context,
+ &client_queue,
+ &server_queue, NULL) == 0);
+#if defined(MBEDTLS_TIMING_C)
+ mbedtls_ssl_set_timer_cb(&client.ssl, &timer_client,
+ mbedtls_timing_set_delay,
+ mbedtls_timing_get_delay);
+#endif
+ } else {
+ TEST_ASSERT(mbedtls_test_ssl_endpoint_init(&client,
+ MBEDTLS_SSL_IS_CLIENT,
+ options->pk_alg, NULL, NULL,
+ NULL, NULL) == 0);
+ }
+
+ if (options->client_min_version != TEST_SSL_MINOR_VERSION_NONE) {
+ mbedtls_ssl_conf_min_version(&client.conf, MBEDTLS_SSL_MAJOR_VERSION_3,
+ options->client_min_version);
+ }
+
+ if (options->client_max_version != TEST_SSL_MINOR_VERSION_NONE) {
+ mbedtls_ssl_conf_max_version(&client.conf, MBEDTLS_SSL_MAJOR_VERSION_3,
+ options->client_max_version);
+ }
+
+ if (strlen(options->cipher) > 0) {
+ set_ciphersuite(&client.conf, options->cipher, forced_ciphersuite);
+ }
+
+#if defined(MBEDTLS_DEBUG_C)
+ if (options->cli_log_fun) {
+ mbedtls_debug_set_threshold(4);
+ mbedtls_ssl_conf_dbg(&client.conf, options->cli_log_fun,
+ options->cli_log_obj);
+ }
+#endif
+
+ /* Server side */
+ if (options->dtls != 0) {
+ TEST_ASSERT(mbedtls_test_ssl_endpoint_init(&server,
+ MBEDTLS_SSL_IS_SERVER,
+ options->pk_alg,
+ &server_context,
+ &server_queue,
+ &client_queue, NULL) == 0);
+#if defined(MBEDTLS_TIMING_C)
+ mbedtls_ssl_set_timer_cb(&server.ssl, &timer_server,
+ mbedtls_timing_set_delay,
+ mbedtls_timing_get_delay);
+#endif
+ } else {
+ TEST_ASSERT(mbedtls_test_ssl_endpoint_init(&server,
+ MBEDTLS_SSL_IS_SERVER,
+ options->pk_alg, NULL, NULL,
+ NULL, NULL) == 0);
+ }
+
+ mbedtls_ssl_conf_authmode(&server.conf, options->srv_auth_mode);
+
+ if (options->server_min_version != TEST_SSL_MINOR_VERSION_NONE) {
+ mbedtls_ssl_conf_min_version(&server.conf, MBEDTLS_SSL_MAJOR_VERSION_3,
+ options->server_min_version);
+ }
+
+ if (options->server_max_version != TEST_SSL_MINOR_VERSION_NONE) {
+ mbedtls_ssl_conf_max_version(&server.conf, MBEDTLS_SSL_MAJOR_VERSION_3,
+ options->server_max_version);
+ }
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ TEST_ASSERT(mbedtls_ssl_conf_max_frag_len(&(server.conf),
+ (unsigned char) options->mfl)
+ == 0);
+ TEST_ASSERT(mbedtls_ssl_conf_max_frag_len(&(client.conf),
+ (unsigned char) options->mfl)
+ == 0);
+#else
+ TEST_ASSERT(MBEDTLS_SSL_MAX_FRAG_LEN_NONE == options->mfl);
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+ if (options->psk_str != NULL && options->psk_str->len > 0) {
+ TEST_ASSERT(mbedtls_ssl_conf_psk(
+ &client.conf, options->psk_str->x,
+ options->psk_str->len,
+ (const unsigned char *) psk_identity,
+ strlen(psk_identity)) == 0);
+
+ TEST_ASSERT(mbedtls_ssl_conf_psk(
+ &server.conf, options->psk_str->x,
+ options->psk_str->len,
+ (const unsigned char *) psk_identity,
+ strlen(psk_identity)) == 0);
+
+ mbedtls_ssl_conf_psk_cb(&server.conf, psk_dummy_callback, NULL);
+ }
+#endif
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ if (options->renegotiate) {
+ mbedtls_ssl_conf_renegotiation(&(server.conf),
+ MBEDTLS_SSL_RENEGOTIATION_ENABLED);
+ mbedtls_ssl_conf_renegotiation(&(client.conf),
+ MBEDTLS_SSL_RENEGOTIATION_ENABLED);
+
+ mbedtls_ssl_conf_legacy_renegotiation(&(server.conf),
+ options->legacy_renegotiation);
+ mbedtls_ssl_conf_legacy_renegotiation(&(client.conf),
+ options->legacy_renegotiation);
+ }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+#if defined(MBEDTLS_DEBUG_C)
+ if (options->srv_log_fun) {
+ mbedtls_debug_set_threshold(4);
+ mbedtls_ssl_conf_dbg(&server.conf, options->srv_log_fun,
+ options->srv_log_obj);
+ }
+#endif
+
+ TEST_ASSERT(mbedtls_test_mock_socket_connect(&(client.socket),
+ &(server.socket),
+ BUFFSIZE) == 0);
+
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+ if (options->resize_buffers != 0) {
+ /* Ensure that the buffer sizes are appropriate before resizes */
+ TEST_ASSERT(client.ssl.out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
+ TEST_ASSERT(client.ssl.in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
+ TEST_ASSERT(server.ssl.out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
+ TEST_ASSERT(server.ssl.in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
+ }
+#endif
+
+ if (options->expected_negotiated_version == TEST_SSL_MINOR_VERSION_NONE) {
+ expected_handshake_result = MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION;
+ }
+
+ TEST_ASSERT(mbedtls_test_move_handshake_to_state(
+ &(client.ssl), &(server.ssl), MBEDTLS_SSL_HANDSHAKE_OVER)
+ == expected_handshake_result);
+
+ if (expected_handshake_result != 0) {
+ /* Connection will have failed by this point, skip to cleanup */
+ goto exit;
+ }
+
+ TEST_ASSERT(client.ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
+ TEST_ASSERT(server.ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
+
+ /* Check that we agree on the version... */
+ TEST_ASSERT(client.ssl.minor_ver == server.ssl.minor_ver);
+
+ /* And check that the version negotiated is the expected one. */
+ TEST_EQUAL(client.ssl.minor_ver, options->expected_negotiated_version);
+
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+ if (options->resize_buffers != 0) {
+ if (options->expected_negotiated_version != MBEDTLS_SSL_MINOR_VERSION_0 &&
+ options->expected_negotiated_version != MBEDTLS_SSL_MINOR_VERSION_1) {
+ /* A server, when using DTLS, might delay a buffer resize to happen
+ * after it receives a message, so we force it. */
+ TEST_ASSERT(exchange_data(&(client.ssl), &(server.ssl)) == 0);
+
+ TEST_ASSERT(client.ssl.out_buf_len ==
+ mbedtls_ssl_get_output_buflen(&client.ssl));
+ TEST_ASSERT(client.ssl.in_buf_len ==
+ mbedtls_ssl_get_input_buflen(&client.ssl));
+ TEST_ASSERT(server.ssl.out_buf_len ==
+ mbedtls_ssl_get_output_buflen(&server.ssl));
+ TEST_ASSERT(server.ssl.in_buf_len ==
+ mbedtls_ssl_get_input_buflen(&server.ssl));
+ }
+ }
+#endif
+
+ if (options->cli_msg_len != 0 || options->srv_msg_len != 0) {
+ /* Start data exchanging test */
+ TEST_ASSERT(mbedtls_exchange_data(&(client.ssl), options->cli_msg_len,
+ options->expected_cli_fragments,
+ &(server.ssl), options->srv_msg_len,
+ options->expected_srv_fragments)
+ == 0);
+ }
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+ if (options->serialize == 1) {
+ TEST_ASSERT(options->dtls == 1);
+
+ TEST_ASSERT(mbedtls_ssl_context_save(&(server.ssl), NULL,
+ 0, &context_buf_len)
+ == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
+
+ context_buf = mbedtls_calloc(1, context_buf_len);
+ TEST_ASSERT(context_buf != NULL);
+
+ TEST_ASSERT(mbedtls_ssl_context_save(&(server.ssl), context_buf,
+ context_buf_len,
+ &context_buf_len)
+ == 0);
+
+ mbedtls_ssl_free(&(server.ssl));
+ mbedtls_ssl_init(&(server.ssl));
+
+ TEST_ASSERT(mbedtls_ssl_setup(&(server.ssl), &(server.conf)) == 0);
+
+ mbedtls_ssl_set_bio(&(server.ssl), &server_context,
+ mbedtls_test_mock_tcp_send_msg,
+ mbedtls_test_mock_tcp_recv_msg,
+ NULL);
+
+#if defined(MBEDTLS_TIMING_C)
+ mbedtls_ssl_set_timer_cb(&server.ssl, &timer_server,
+ mbedtls_timing_set_delay,
+ mbedtls_timing_get_delay);
+#endif
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+ if (options->resize_buffers != 0) {
+ /* Ensure that the buffer sizes are appropriate before resizes */
+ TEST_ASSERT(server.ssl.out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
+ TEST_ASSERT(server.ssl.in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
+ }
+#endif
+ TEST_ASSERT(mbedtls_ssl_context_load(&(server.ssl), context_buf,
+ context_buf_len) == 0);
+
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+ /* Validate buffer sizes after context deserialization */
+ if (options->resize_buffers != 0) {
+ TEST_ASSERT(server.ssl.out_buf_len ==
+ mbedtls_ssl_get_output_buflen(&server.ssl));
+ TEST_ASSERT(server.ssl.in_buf_len ==
+ mbedtls_ssl_get_input_buflen(&server.ssl));
+ }
+#endif
+ /* Retest writing/reading */
+ if (options->cli_msg_len != 0 || options->srv_msg_len != 0) {
+ TEST_ASSERT(mbedtls_exchange_data(
+ &(client.ssl),
+ options->cli_msg_len,
+ options->expected_cli_fragments,
+ &(server.ssl),
+ options->srv_msg_len,
+ options->expected_srv_fragments)
+ == 0);
+ }
+ }
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ if (options->renegotiate) {
+ /* Start test with renegotiation */
+ TEST_ASSERT(server.ssl.renego_status ==
+ MBEDTLS_SSL_INITIAL_HANDSHAKE);
+ TEST_ASSERT(client.ssl.renego_status ==
+ MBEDTLS_SSL_INITIAL_HANDSHAKE);
+
+ /* After calling this function for the server, it only sends a handshake
+ * request. All renegotiation should happen during data exchanging */
+ TEST_ASSERT(mbedtls_ssl_renegotiate(&(server.ssl)) == 0);
+ TEST_ASSERT(server.ssl.renego_status ==
+ MBEDTLS_SSL_RENEGOTIATION_PENDING);
+ TEST_ASSERT(client.ssl.renego_status ==
+ MBEDTLS_SSL_INITIAL_HANDSHAKE);
+
+ TEST_ASSERT(exchange_data(&(client.ssl), &(server.ssl)) == 0);
+ TEST_ASSERT(server.ssl.renego_status ==
+ MBEDTLS_SSL_RENEGOTIATION_DONE);
+ TEST_ASSERT(client.ssl.renego_status ==
+ MBEDTLS_SSL_RENEGOTIATION_DONE);
+
+ /* After calling mbedtls_ssl_renegotiate for the client,
+ * all renegotiation should happen inside this function.
+ * However in this test, we cannot perform simultaneous communication
+ * between client and server so this function will return waiting error
+ * on the socket. All rest of renegotiation should happen
+ * during data exchanging */
+ ret = mbedtls_ssl_renegotiate(&(client.ssl));
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+ if (options->resize_buffers != 0) {
+ /* Ensure that the buffer sizes are appropriate before resizes */
+ TEST_ASSERT(client.ssl.out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
+ TEST_ASSERT(client.ssl.in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
+ }
+#endif
+ TEST_ASSERT(ret == 0 ||
+ ret == MBEDTLS_ERR_SSL_WANT_READ ||
+ ret == MBEDTLS_ERR_SSL_WANT_WRITE);
+ TEST_ASSERT(server.ssl.renego_status ==
+ MBEDTLS_SSL_RENEGOTIATION_DONE);
+ TEST_ASSERT(client.ssl.renego_status ==
+ MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS);
+
+ TEST_ASSERT(exchange_data(&(client.ssl), &(server.ssl)) == 0);
+ TEST_ASSERT(server.ssl.renego_status ==
+ MBEDTLS_SSL_RENEGOTIATION_DONE);
+ TEST_ASSERT(client.ssl.renego_status ==
+ MBEDTLS_SSL_RENEGOTIATION_DONE);
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+ /* Validate buffer sizes after renegotiation */
+ if (options->resize_buffers != 0) {
+ TEST_ASSERT(client.ssl.out_buf_len ==
+ mbedtls_ssl_get_output_buflen(&client.ssl));
+ TEST_ASSERT(client.ssl.in_buf_len ==
+ mbedtls_ssl_get_input_buflen(&client.ssl));
+ TEST_ASSERT(server.ssl.out_buf_len ==
+ mbedtls_ssl_get_output_buflen(&server.ssl));
+ TEST_ASSERT(server.ssl.in_buf_len ==
+ mbedtls_ssl_get_input_buflen(&server.ssl));
+ }
+#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */
+ }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+exit:
+ mbedtls_test_ssl_endpoint_free(&client,
+ options->dtls != 0 ? &client_context : NULL);
+ mbedtls_test_ssl_endpoint_free(&server,
+ options->dtls != 0 ? &server_context : NULL);
+#if defined(MBEDTLS_DEBUG_C)
+ if (options->cli_log_fun || options->srv_log_fun) {
+ mbedtls_debug_set_threshold(0);
+ }
+#endif
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+ if (context_buf != NULL) {
+ mbedtls_free(context_buf);
+ }
+#endif
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C &&
+ MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
+
+#endif /* MBEDTLS_SSL_TLS_C */
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index eb0dc03..efe8408 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -80,25 +80,6 @@
/*----------------------------------------------------------------------------*/
/* Helper Functions */
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-/** Check that no PSA Crypto key slots are in use.
- *
- * If any slots are in use, mark the current test as failed.
- *
- * \return 0 if the key store is empty, 1 otherwise.
- */
-int test_fail_if_psa_leaking(int line_no, const char *filename)
-{
- const char *msg = mbedtls_test_helper_is_psa_leaking();
- if (msg == NULL) {
- return 0;
- } else {
- mbedtls_test_fail(msg, line_no, filename);
- return 1;
- }
-}
-#endif /* defined(MBEDTLS_PSA_CRYPTO_C) */
-
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
static int redirect_output(FILE *out_stream, const char *path)
{
diff --git a/tests/suites/test_suite_aes.ecb.data b/tests/suites/test_suite_aes.ecb.data
index 6349034..faf69c0 100644
--- a/tests/suites/test_suite_aes.ecb.data
+++ b/tests/suites/test_suite_aes.ecb.data
@@ -228,3 +228,12 @@
AES-256-ECB Decrypt NIST KAT #12
aes_decrypt_ecb:"0000000000000000000000000000000000000000000000000000000000000000":"9b80eefb7ebe2d2b16247aa0efc72f5d":"e0000000000000000000000000000000":0
+
+AES-128-ECB context alignment
+aes_ecb_context_alignment:"000102030405060708090a0b0c0d0e0f"
+
+AES-192-ECB context alignment
+aes_ecb_context_alignment:"000102030405060708090a0b0c0d0e0f1011121314151617"
+
+AES-256-ECB context alignment
+aes_ecb_context_alignment:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
diff --git a/tests/suites/test_suite_aes.function b/tests/suites/test_suite_aes.function
index 6b92b87..e96e407 100644
--- a/tests/suites/test_suite_aes.function
+++ b/tests/suites/test_suite_aes.function
@@ -1,5 +1,52 @@
/* BEGIN_HEADER */
#include "mbedtls/aes.h"
+
+/* Test AES with a copied context.
+ *
+ * enc and dec must be AES context objects. They don't need to
+ * be initialized, and are left freed.
+ */
+static int test_ctx_alignment(const data_t *key,
+ mbedtls_aes_context *enc,
+ mbedtls_aes_context *dec)
+{
+ unsigned char plaintext[16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ };
+ unsigned char ciphertext[16];
+ unsigned char output[16];
+
+ // Set key and encrypt with original context
+ mbedtls_aes_init(enc);
+ TEST_ASSERT(mbedtls_aes_setkey_enc(enc, key->x, key->len * 8) == 0);
+ TEST_ASSERT(mbedtls_aes_crypt_ecb(enc, MBEDTLS_AES_ENCRYPT,
+ plaintext, ciphertext) == 0);
+
+ // Set key for decryption with original context
+ mbedtls_aes_init(dec);
+ TEST_ASSERT(mbedtls_aes_setkey_dec(dec, key->x, key->len * 8) == 0);
+
+ // Wipe the original context to make sure nothing from it is used
+ memset(enc, 0, sizeof(*enc));
+ mbedtls_aes_free(enc);
+
+ // Decrypt
+ TEST_ASSERT(mbedtls_aes_crypt_ecb(dec, MBEDTLS_AES_DECRYPT,
+ ciphertext, output) == 0);
+ ASSERT_COMPARE(plaintext, 16, output, 16);
+
+ mbedtls_aes_free(dec);
+
+ return 1;
+
+exit:
+ /* Bug: we may be leaving something unfreed. This is harmless
+ * in our built-in implementations, but might cause a memory leak
+ * with alternative implementations. */
+ return 0;
+}
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -621,6 +668,77 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+void aes_ecb_context_alignment(data_t *key)
+{
+ /* We test alignment multiple times, with different alignments
+ * of the context and of the plaintext/ciphertext. */
+
+ struct align0 {
+ mbedtls_aes_context ctx;
+ };
+ struct align0 *enc0 = NULL;
+ struct align0 *dec0 = NULL;
+
+ struct align1 {
+ char bump;
+ mbedtls_aes_context ctx;
+ };
+ struct align1 *enc1 = NULL;
+ struct align1 *dec1 = NULL;
+
+ /* All peak alignment */
+ ASSERT_ALLOC(enc0, 1);
+ ASSERT_ALLOC(dec0, 1);
+ if (!test_ctx_alignment(key, &enc0->ctx, &dec0->ctx)) {
+ goto exit;
+ }
+ mbedtls_free(enc0);
+ enc0 = NULL;
+ mbedtls_free(dec0);
+ dec0 = NULL;
+
+ /* Enc aligned, dec not */
+ ASSERT_ALLOC(enc0, 1);
+ ASSERT_ALLOC(dec1, 1);
+ if (!test_ctx_alignment(key, &enc0->ctx, &dec1->ctx)) {
+ goto exit;
+ }
+ mbedtls_free(enc0);
+ enc0 = NULL;
+ mbedtls_free(dec1);
+ dec1 = NULL;
+
+ /* Dec aligned, enc not */
+ ASSERT_ALLOC(enc1, 1);
+ ASSERT_ALLOC(dec0, 1);
+ if (!test_ctx_alignment(key, &enc1->ctx, &dec0->ctx)) {
+ goto exit;
+ }
+ mbedtls_free(enc1);
+ enc1 = NULL;
+ mbedtls_free(dec0);
+ dec0 = NULL;
+
+ /* Both shifted */
+ ASSERT_ALLOC(enc1, 1);
+ ASSERT_ALLOC(dec1, 1);
+ if (!test_ctx_alignment(key, &enc1->ctx, &dec1->ctx)) {
+ goto exit;
+ }
+ mbedtls_free(enc1);
+ enc1 = NULL;
+ mbedtls_free(dec1);
+ dec1 = NULL;
+
+exit:
+ mbedtls_free(enc0);
+ mbedtls_free(dec0);
+ mbedtls_free(enc1);
+ mbedtls_free(dec1);
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void aes_selftest()
{
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 39825ed..996ba98 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -1,2024 +1,10 @@
/* BEGIN_HEADER */
-#include <mbedtls/ssl.h>
-#include <mbedtls/ssl_internal.h>
-#include <mbedtls/ctr_drbg.h>
-#include <mbedtls/entropy.h>
-#include <mbedtls/certs.h>
-#include <mbedtls/timing.h>
-#include <mbedtls/debug.h>
-#include <ssl_tls13_keys.h>
+#include <test/ssl_helpers.h>
#include <constant_time_internal.h>
#include <test/constant_flow.h>
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
- defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
- defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-#define MBEDTLS_CAN_HANDLE_RSA_TEST_KEY
-#endif
-
-enum {
-#define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \
- tls1_3_label_ ## name,
- MBEDTLS_SSL_TLS1_3_LABEL_LIST
-#undef MBEDTLS_SSL_TLS1_3_LABEL
-};
-
-typedef struct log_pattern {
- const char *pattern;
- size_t counter;
-} log_pattern;
-
-/*
- * This function can be passed to mbedtls to receive output logs from it. In
- * this case, it will count the instances of a log_pattern in the received
- * logged messages.
- */
-void log_analyzer(void *ctx, int level,
- const char *file, int line,
- const char *str)
-{
- log_pattern *p = (log_pattern *) ctx;
-
- (void) level;
- (void) line;
- (void) file;
-
- if (NULL != p &&
- NULL != p->pattern &&
- NULL != strstr(str, p->pattern)) {
- p->counter++;
- }
-}
-
-/* Invalid minor version used when not specifying a min/max version or expecting a test to fail */
-#define TEST_SSL_MINOR_VERSION_NONE -1
-
-typedef struct handshake_test_options {
- const char *cipher;
- int client_min_version;
- int client_max_version;
- int server_min_version;
- int server_max_version;
- int expected_negotiated_version;
- int pk_alg;
- data_t *psk_str;
- int dtls;
- int srv_auth_mode;
- int serialize;
- int mfl;
- int cli_msg_len;
- int srv_msg_len;
- int expected_cli_fragments;
- int expected_srv_fragments;
- int renegotiate;
- int legacy_renegotiation;
- void *srv_log_obj;
- void *cli_log_obj;
- void (*srv_log_fun)(void *, int, const char *, int, const char *);
- void (*cli_log_fun)(void *, int, const char *, int, const char *);
- int resize_buffers;
-} handshake_test_options;
-
-void init_handshake_options(handshake_test_options *opts)
-{
- opts->cipher = "";
- opts->client_min_version = TEST_SSL_MINOR_VERSION_NONE;
- opts->client_max_version = TEST_SSL_MINOR_VERSION_NONE;
- opts->server_min_version = TEST_SSL_MINOR_VERSION_NONE;
- opts->server_max_version = TEST_SSL_MINOR_VERSION_NONE;
- opts->expected_negotiated_version = MBEDTLS_SSL_MINOR_VERSION_3;
- opts->pk_alg = MBEDTLS_PK_RSA;
- opts->psk_str = NULL;
- opts->dtls = 0;
- opts->srv_auth_mode = MBEDTLS_SSL_VERIFY_NONE;
- opts->serialize = 0;
- opts->mfl = MBEDTLS_SSL_MAX_FRAG_LEN_NONE;
- opts->cli_msg_len = 100;
- opts->srv_msg_len = 100;
- opts->expected_cli_fragments = 1;
- opts->expected_srv_fragments = 1;
- opts->renegotiate = 0;
- opts->legacy_renegotiation = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
- opts->srv_log_obj = NULL;
- opts->srv_log_obj = NULL;
- opts->srv_log_fun = NULL;
- opts->cli_log_fun = NULL;
- opts->resize_buffers = 1;
-}
-/*
- * Buffer structure for custom I/O callbacks.
- */
-
-typedef struct mbedtls_test_buffer {
- size_t start;
- size_t content_length;
- size_t capacity;
- unsigned char *buffer;
-} mbedtls_test_buffer;
-
-/*
- * Initialises \p buf. After calling this function it is safe to call
- * `mbedtls_test_buffer_free()` on \p buf.
- */
-void mbedtls_test_buffer_init(mbedtls_test_buffer *buf)
-{
- memset(buf, 0, sizeof(*buf));
-}
-
-/*
- * Sets up \p buf. After calling this function it is safe to call
- * `mbedtls_test_buffer_put()` and `mbedtls_test_buffer_get()` on \p buf.
- */
-int mbedtls_test_buffer_setup(mbedtls_test_buffer *buf, size_t capacity)
-{
- buf->buffer = (unsigned char *) mbedtls_calloc(capacity,
- sizeof(unsigned char));
- if (NULL == buf->buffer) {
- return MBEDTLS_ERR_SSL_ALLOC_FAILED;
- }
- buf->capacity = capacity;
-
- return 0;
-}
-
-void mbedtls_test_buffer_free(mbedtls_test_buffer *buf)
-{
- if (buf->buffer != NULL) {
- mbedtls_free(buf->buffer);
- }
-
- memset(buf, 0, sizeof(*buf));
-}
-
-/*
- * Puts \p input_len bytes from the \p input buffer into the ring buffer \p buf.
- *
- * \p buf must have been initialized and set up by calling
- * `mbedtls_test_buffer_init()` and `mbedtls_test_buffer_setup()`.
- *
- * \retval \p input_len, if the data fits.
- * \retval 0 <= value < \p input_len, if the data does not fit.
- * \retval -1, if \p buf is NULL, it hasn't been set up or \p input_len is not
- * zero and \p input is NULL.
- */
-int mbedtls_test_buffer_put(mbedtls_test_buffer *buf,
- const unsigned char *input, size_t input_len)
-{
- size_t overflow = 0;
-
- if ((buf == NULL) || (buf->buffer == NULL)) {
- return -1;
- }
-
- /* Reduce input_len to a number that fits in the buffer. */
- if ((buf->content_length + input_len) > buf->capacity) {
- input_len = buf->capacity - buf->content_length;
- }
-
- if (input == NULL) {
- return (input_len == 0) ? 0 : -1;
- }
-
- /* Check if the buffer has not come full circle and free space is not in
- * the middle */
- if (buf->start + buf->content_length < buf->capacity) {
-
- /* Calculate the number of bytes that need to be placed at lower memory
- * address */
- if (buf->start + buf->content_length + input_len
- > buf->capacity) {
- overflow = (buf->start + buf->content_length + input_len)
- % buf->capacity;
- }
-
- memcpy(buf->buffer + buf->start + buf->content_length, input,
- input_len - overflow);
- memcpy(buf->buffer, input + input_len - overflow, overflow);
-
- } else {
- /* The buffer has come full circle and free space is in the middle */
- memcpy(buf->buffer + buf->start + buf->content_length - buf->capacity,
- input, input_len);
- }
-
- buf->content_length += input_len;
- return input_len;
-}
-
-/*
- * Gets \p output_len bytes from the ring buffer \p buf into the
- * \p output buffer. The output buffer can be NULL, in this case a part of the
- * ring buffer will be dropped, if the requested length is available.
- *
- * \p buf must have been initialized and set up by calling
- * `mbedtls_test_buffer_init()` and `mbedtls_test_buffer_setup()`.
- *
- * \retval \p output_len, if the data is available.
- * \retval 0 <= value < \p output_len, if the data is not available.
- * \retval -1, if \buf is NULL or it hasn't been set up.
- */
-int mbedtls_test_buffer_get(mbedtls_test_buffer *buf,
- unsigned char *output, size_t output_len)
-{
- size_t overflow = 0;
-
- if ((buf == NULL) || (buf->buffer == NULL)) {
- return -1;
- }
-
- if (output == NULL && output_len == 0) {
- return 0;
- }
-
- if (buf->content_length < output_len) {
- output_len = buf->content_length;
- }
-
- /* Calculate the number of bytes that need to be drawn from lower memory
- * address */
- if (buf->start + output_len > buf->capacity) {
- overflow = (buf->start + output_len) % buf->capacity;
- }
-
- if (output != NULL) {
- memcpy(output, buf->buffer + buf->start, output_len - overflow);
- memcpy(output + output_len - overflow, buf->buffer, overflow);
- }
-
- buf->content_length -= output_len;
- buf->start = (buf->start + output_len) % buf->capacity;
-
- return output_len;
-}
-
-/*
- * Errors used in the message transport mock tests
- */
- #define MBEDTLS_TEST_ERROR_ARG_NULL -11
- #define MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED -44
-
-/*
- * Context for a message metadata queue (fifo) that is on top of the ring buffer.
- */
-typedef struct mbedtls_test_message_queue {
- size_t *messages;
- int pos;
- int num;
- int capacity;
-} mbedtls_test_message_queue;
-
-/*
- * Setup and free functions for the message metadata queue.
- *
- * \p capacity describes the number of message metadata chunks that can be held
- * within the queue.
- *
- * \retval 0, if a metadata queue of a given length can be allocated.
- * \retval MBEDTLS_ERR_SSL_ALLOC_FAILED, if allocation failed.
- */
-int mbedtls_test_message_queue_setup(mbedtls_test_message_queue *queue,
- size_t capacity)
-{
- queue->messages = (size_t *) mbedtls_calloc(capacity, sizeof(size_t));
- if (NULL == queue->messages) {
- return MBEDTLS_ERR_SSL_ALLOC_FAILED;
- }
-
- queue->capacity = capacity;
- queue->pos = 0;
- queue->num = 0;
-
- return 0;
-}
-
-void mbedtls_test_message_queue_free(mbedtls_test_message_queue *queue)
-{
- if (queue == NULL) {
- return;
- }
-
- if (queue->messages != NULL) {
- mbedtls_free(queue->messages);
- }
-
- memset(queue, 0, sizeof(*queue));
-}
-
-/*
- * Push message length information onto the message metadata queue.
- * This will become the last element to leave it (fifo).
- *
- * \retval MBEDTLS_TEST_ERROR_ARG_NULL, if the queue is null.
- * \retval MBEDTLS_ERR_SSL_WANT_WRITE, if the queue is full.
- * \retval \p len, if the push was successful.
- */
-int mbedtls_test_message_queue_push_info(mbedtls_test_message_queue *queue,
- size_t len)
-{
- int place;
- if (queue == NULL) {
- return MBEDTLS_TEST_ERROR_ARG_NULL;
- }
-
- if (queue->num >= queue->capacity) {
- return MBEDTLS_ERR_SSL_WANT_WRITE;
- }
-
- place = (queue->pos + queue->num) % queue->capacity;
- queue->messages[place] = len;
- queue->num++;
- return len;
-}
-
-/*
- * Pop information about the next message length from the queue. This will be
- * the oldest inserted message length(fifo). \p msg_len can be null, in which
- * case the data will be popped from the queue but not copied anywhere.
- *
- * \retval MBEDTLS_TEST_ERROR_ARG_NULL, if the queue is null.
- * \retval MBEDTLS_ERR_SSL_WANT_READ, if the queue is empty.
- * \retval message length, if the pop was successful, up to the given
- \p buf_len.
- */
-int mbedtls_test_message_queue_pop_info(mbedtls_test_message_queue *queue,
- size_t buf_len)
-{
- size_t message_length;
- if (queue == NULL) {
- return MBEDTLS_TEST_ERROR_ARG_NULL;
- }
- if (queue->num == 0) {
- return MBEDTLS_ERR_SSL_WANT_READ;
- }
-
- message_length = queue->messages[queue->pos];
- queue->messages[queue->pos] = 0;
- queue->num--;
- queue->pos++;
- queue->pos %= queue->capacity;
- if (queue->pos < 0) {
- queue->pos += queue->capacity;
- }
-
- return (message_length > buf_len) ? buf_len : message_length;
-}
-
-/*
- * Take a peek on the info about the next message length from the queue.
- * This will be the oldest inserted message length(fifo).
- *
- * \retval MBEDTLS_TEST_ERROR_ARG_NULL, if the queue is null.
- * \retval MBEDTLS_ERR_SSL_WANT_READ, if the queue is empty.
- * \retval 0, if the peek was successful.
- * \retval MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED, if the given buffer length is
- * too small to fit the message. In this case the \p msg_len will be
- * set to the full message length so that the
- * caller knows what portion of the message can be dropped.
- */
-int mbedtls_test_message_queue_peek_info(mbedtls_test_message_queue *queue,
- size_t buf_len, size_t *msg_len)
-{
- if (queue == NULL || msg_len == NULL) {
- return MBEDTLS_TEST_ERROR_ARG_NULL;
- }
- if (queue->num == 0) {
- return MBEDTLS_ERR_SSL_WANT_READ;
- }
-
- *msg_len = queue->messages[queue->pos];
- return (*msg_len > buf_len) ? MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED : 0;
-}
-/*
- * Context for the I/O callbacks simulating network connection.
- */
-
-#define MBEDTLS_MOCK_SOCKET_CONNECTED 1
-
-typedef struct mbedtls_mock_socket {
- int status;
- mbedtls_test_buffer *input;
- mbedtls_test_buffer *output;
- struct mbedtls_mock_socket *peer;
-} mbedtls_mock_socket;
-
-/*
- * Setup and teardown functions for mock sockets.
- */
-void mbedtls_mock_socket_init(mbedtls_mock_socket *socket)
-{
- memset(socket, 0, sizeof(*socket));
-}
-
-/*
- * Closes the socket \p socket.
- *
- * \p socket must have been previously initialized by calling
- * mbedtls_mock_socket_init().
- *
- * This function frees all allocated resources and both sockets are aware of the
- * new connection state.
- *
- * That is, this function does not simulate half-open TCP connections and the
- * phenomenon that when closing a UDP connection the peer is not aware of the
- * connection having been closed.
- */
-void mbedtls_mock_socket_close(mbedtls_mock_socket *socket)
-{
- if (socket == NULL) {
- return;
- }
-
- if (socket->input != NULL) {
- mbedtls_test_buffer_free(socket->input);
- mbedtls_free(socket->input);
- }
-
- if (socket->output != NULL) {
- mbedtls_test_buffer_free(socket->output);
- mbedtls_free(socket->output);
- }
-
- if (socket->peer != NULL) {
- memset(socket->peer, 0, sizeof(*socket->peer));
- }
-
- memset(socket, 0, sizeof(*socket));
-}
-
-/*
- * Establishes a connection between \p peer1 and \p peer2.
- *
- * \p peer1 and \p peer2 must have been previously initialized by calling
- * mbedtls_mock_socket_init().
- *
- * The capacities of the internal buffers are set to \p bufsize. Setting this to
- * the correct value allows for simulation of MTU, sanity testing the mock
- * implementation and mocking TCP connections with lower memory cost.
- */
-int mbedtls_mock_socket_connect(mbedtls_mock_socket *peer1,
- mbedtls_mock_socket *peer2,
- size_t bufsize)
-{
- int ret = -1;
-
- peer1->output =
- (mbedtls_test_buffer *) mbedtls_calloc(1, sizeof(mbedtls_test_buffer));
- if (peer1->output == NULL) {
- ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
- goto exit;
- }
- mbedtls_test_buffer_init(peer1->output);
- if (0 != (ret = mbedtls_test_buffer_setup(peer1->output, bufsize))) {
- goto exit;
- }
-
- peer2->output =
- (mbedtls_test_buffer *) mbedtls_calloc(1, sizeof(mbedtls_test_buffer));
- if (peer2->output == NULL) {
- ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
- goto exit;
- }
- mbedtls_test_buffer_init(peer2->output);
- if (0 != (ret = mbedtls_test_buffer_setup(peer2->output, bufsize))) {
- goto exit;
- }
-
- peer1->peer = peer2;
- peer2->peer = peer1;
- peer1->input = peer2->output;
- peer2->input = peer1->output;
-
- peer1->status = peer2->status = MBEDTLS_MOCK_SOCKET_CONNECTED;
- ret = 0;
-
-exit:
-
- if (ret != 0) {
- mbedtls_mock_socket_close(peer1);
- mbedtls_mock_socket_close(peer2);
- }
-
- return ret;
-}
-
-/*
- * Callbacks for simulating blocking I/O over connection-oriented transport.
- */
-
-int mbedtls_mock_tcp_send_b(void *ctx, const unsigned char *buf, size_t len)
-{
- mbedtls_mock_socket *socket = (mbedtls_mock_socket *) ctx;
-
- if (socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED) {
- return -1;
- }
-
- return mbedtls_test_buffer_put(socket->output, buf, len);
-}
-
-int mbedtls_mock_tcp_recv_b(void *ctx, unsigned char *buf, size_t len)
-{
- mbedtls_mock_socket *socket = (mbedtls_mock_socket *) ctx;
-
- if (socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED) {
- return -1;
- }
-
- return mbedtls_test_buffer_get(socket->input, buf, len);
-}
-
-/*
- * Callbacks for simulating non-blocking I/O over connection-oriented transport.
- */
-
-int mbedtls_mock_tcp_send_nb(void *ctx, const unsigned char *buf, size_t len)
-{
- mbedtls_mock_socket *socket = (mbedtls_mock_socket *) ctx;
-
- if (socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED) {
- return -1;
- }
-
- if (socket->output->capacity == socket->output->content_length) {
- return MBEDTLS_ERR_SSL_WANT_WRITE;
- }
-
- return mbedtls_test_buffer_put(socket->output, buf, len);
-}
-
-int mbedtls_mock_tcp_recv_nb(void *ctx, unsigned char *buf, size_t len)
-{
- mbedtls_mock_socket *socket = (mbedtls_mock_socket *) ctx;
-
- if (socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED) {
- return -1;
- }
-
- if (socket->input->content_length == 0) {
- return MBEDTLS_ERR_SSL_WANT_READ;
- }
-
- return mbedtls_test_buffer_get(socket->input, buf, len);
-}
-
-/* Errors used in the message socket mocks */
-
-#define MBEDTLS_TEST_ERROR_CONTEXT_ERROR -55
-#define MBEDTLS_TEST_ERROR_SEND_FAILED -66
-#define MBEDTLS_TEST_ERROR_RECV_FAILED -77
-
-/*
- * Structure used as an addon, or a wrapper, around the mocked sockets.
- * Contains an input queue, to which the other socket pushes metadata,
- * and an output queue, to which this one pushes metadata. This context is
- * considered as an owner of the input queue only, which is initialized and
- * freed in the respective setup and free calls.
- */
-typedef struct mbedtls_test_message_socket_context {
- mbedtls_test_message_queue *queue_input;
- mbedtls_test_message_queue *queue_output;
- mbedtls_mock_socket *socket;
-} mbedtls_test_message_socket_context;
-
-void mbedtls_message_socket_init(mbedtls_test_message_socket_context *ctx)
-{
- ctx->queue_input = NULL;
- ctx->queue_output = NULL;
- ctx->socket = NULL;
-}
-
-/*
- * Setup a given message socket context including initialization of
- * input/output queues to a chosen capacity of messages. Also set the
- * corresponding mock socket.
- *
- * \retval 0, if everything succeeds.
- * \retval MBEDTLS_ERR_SSL_ALLOC_FAILED, if allocation of a message
- * queue failed.
- */
-int mbedtls_message_socket_setup(mbedtls_test_message_queue *queue_input,
- mbedtls_test_message_queue *queue_output,
- size_t queue_capacity,
- mbedtls_mock_socket *socket,
- mbedtls_test_message_socket_context *ctx)
-{
- int ret = mbedtls_test_message_queue_setup(queue_input, queue_capacity);
- if (ret != 0) {
- return ret;
- }
- ctx->queue_input = queue_input;
- ctx->queue_output = queue_output;
- ctx->socket = socket;
- mbedtls_mock_socket_init(socket);
-
- return 0;
-}
-
-/*
- * Close a given message socket context, along with the socket itself. Free the
- * memory allocated by the input queue.
- */
-void mbedtls_message_socket_close(mbedtls_test_message_socket_context *ctx)
-{
- if (ctx == NULL) {
- return;
- }
-
- mbedtls_test_message_queue_free(ctx->queue_input);
- mbedtls_mock_socket_close(ctx->socket);
- memset(ctx, 0, sizeof(*ctx));
-}
-
-/*
- * Send one message through a given message socket context.
- *
- * \retval \p len, if everything succeeds.
- * \retval MBEDTLS_TEST_ERROR_CONTEXT_ERROR, if any of the needed context
- * elements or the context itself is null.
- * \retval MBEDTLS_TEST_ERROR_SEND_FAILED if mbedtls_mock_tcp_send_b failed.
- * \retval MBEDTLS_ERR_SSL_WANT_WRITE, if the output queue is full.
- *
- * This function will also return any error from
- * mbedtls_test_message_queue_push_info.
- */
-int mbedtls_mock_tcp_send_msg(void *ctx, const unsigned char *buf, size_t len)
-{
- mbedtls_test_message_queue *queue;
- mbedtls_mock_socket *socket;
- mbedtls_test_message_socket_context *context = (mbedtls_test_message_socket_context *) ctx;
-
- if (context == NULL || context->socket == NULL
- || context->queue_output == NULL) {
- return MBEDTLS_TEST_ERROR_CONTEXT_ERROR;
- }
-
- queue = context->queue_output;
- socket = context->socket;
-
- if (queue->num >= queue->capacity) {
- return MBEDTLS_ERR_SSL_WANT_WRITE;
- }
-
- if (mbedtls_mock_tcp_send_b(socket, buf, len) != (int) len) {
- return MBEDTLS_TEST_ERROR_SEND_FAILED;
- }
-
- return mbedtls_test_message_queue_push_info(queue, len);
-}
-
-/*
- * Receive one message from a given message socket context and return message
- * length or an error.
- *
- * \retval message length, if everything succeeds.
- * \retval MBEDTLS_TEST_ERROR_CONTEXT_ERROR, if any of the needed context
- * elements or the context itself is null.
- * \retval MBEDTLS_TEST_ERROR_RECV_FAILED if mbedtls_mock_tcp_recv_b failed.
- *
- * This function will also return any error other than
- * MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED from mbedtls_test_message_queue_peek_info.
- */
-int mbedtls_mock_tcp_recv_msg(void *ctx, unsigned char *buf, size_t buf_len)
-{
- mbedtls_test_message_queue *queue;
- mbedtls_mock_socket *socket;
- mbedtls_test_message_socket_context *context = (mbedtls_test_message_socket_context *) ctx;
- size_t drop_len = 0;
- size_t msg_len;
- int ret;
-
- if (context == NULL || context->socket == NULL
- || context->queue_input == NULL) {
- return MBEDTLS_TEST_ERROR_CONTEXT_ERROR;
- }
-
- queue = context->queue_input;
- socket = context->socket;
-
- /* Peek first, so that in case of a socket error the data remains in
- * the queue. */
- ret = mbedtls_test_message_queue_peek_info(queue, buf_len, &msg_len);
- if (ret == MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED) {
- /* Calculate how much to drop */
- drop_len = msg_len - buf_len;
-
- /* Set the requested message len to be buffer length */
- msg_len = buf_len;
- } else if (ret != 0) {
- return ret;
- }
-
- if (mbedtls_mock_tcp_recv_b(socket, buf, msg_len) != (int) msg_len) {
- return MBEDTLS_TEST_ERROR_RECV_FAILED;
- }
-
- if (ret == MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED) {
- /* Drop the remaining part of the message */
- if (mbedtls_mock_tcp_recv_b(socket, NULL, drop_len) != (int) drop_len) {
- /* Inconsistent state - part of the message was read,
- * and a part couldn't. Not much we can do here, but it should not
- * happen in test environment, unless forced manually. */
- }
- }
- mbedtls_test_message_queue_pop_info(queue, buf_len);
-
- return msg_len;
-}
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
- defined(MBEDTLS_CERTS_C) && \
- defined(MBEDTLS_ENTROPY_C) && \
- defined(MBEDTLS_CTR_DRBG_C)
-
-/*
- * Structure with endpoint's certificates for SSL communication tests.
- */
-typedef struct mbedtls_endpoint_certificate {
- mbedtls_x509_crt *ca_cert;
- mbedtls_x509_crt *cert;
- mbedtls_pk_context *pkey;
-} mbedtls_endpoint_certificate;
-
-/*
- * Endpoint structure for SSL communication tests.
- */
-typedef struct mbedtls_endpoint {
- const char *name;
- mbedtls_ssl_context ssl;
- mbedtls_ssl_config conf;
- mbedtls_ctr_drbg_context ctr_drbg;
- mbedtls_entropy_context entropy;
- mbedtls_mock_socket socket;
- mbedtls_endpoint_certificate cert;
-} mbedtls_endpoint;
-
-/*
- * Deinitializes certificates from endpoint represented by \p ep.
- */
-void mbedtls_endpoint_certificate_free(mbedtls_endpoint *ep)
-{
- mbedtls_endpoint_certificate *cert = &(ep->cert);
- if (cert != NULL) {
- if (cert->ca_cert != NULL) {
- mbedtls_x509_crt_free(cert->ca_cert);
- mbedtls_free(cert->ca_cert);
- cert->ca_cert = NULL;
- }
- if (cert->cert != NULL) {
- mbedtls_x509_crt_free(cert->cert);
- mbedtls_free(cert->cert);
- cert->cert = NULL;
- }
- if (cert->pkey != NULL) {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
- if (mbedtls_pk_get_type(cert->pkey) == MBEDTLS_PK_OPAQUE) {
- mbedtls_svc_key_id_t *key_slot = cert->pkey->pk_ctx;
- psa_destroy_key(*key_slot);
- }
-#endif
- mbedtls_pk_free(cert->pkey);
- mbedtls_free(cert->pkey);
- cert->pkey = NULL;
- }
- }
-}
-
-/*
- * Initializes \p ep_cert structure and assigns it to endpoint
- * represented by \p ep.
- *
- * \retval 0 on success, otherwise error code.
- */
-int mbedtls_endpoint_certificate_init(mbedtls_endpoint *ep, int pk_alg)
-{
- int i = 0;
- int ret = -1;
- mbedtls_endpoint_certificate *cert = NULL;
-
- if (ep == NULL) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- cert = &(ep->cert);
- ASSERT_ALLOC(cert->ca_cert, 1);
- ASSERT_ALLOC(cert->cert, 1);
- ASSERT_ALLOC(cert->pkey, 1);
-
- mbedtls_x509_crt_init(cert->ca_cert);
- mbedtls_x509_crt_init(cert->cert);
- mbedtls_pk_init(cert->pkey);
-
- /* Load the trusted CA */
-
- for (i = 0; mbedtls_test_cas_der[i] != NULL; i++) {
- ret = mbedtls_x509_crt_parse_der(cert->ca_cert,
- (const unsigned char *) mbedtls_test_cas_der[i],
- mbedtls_test_cas_der_len[i]);
- TEST_ASSERT(ret == 0);
- }
-
- /* Load own certificate and private key */
-
- if (ep->conf.endpoint == MBEDTLS_SSL_IS_SERVER) {
- if (pk_alg == MBEDTLS_PK_RSA) {
- ret = mbedtls_x509_crt_parse(cert->cert,
- (const unsigned char *) mbedtls_test_srv_crt_rsa_sha256_der,
- mbedtls_test_srv_crt_rsa_sha256_der_len);
- TEST_ASSERT(ret == 0);
-
- ret = mbedtls_pk_parse_key(cert->pkey,
- (const unsigned char *) mbedtls_test_srv_key_rsa_der,
- mbedtls_test_srv_key_rsa_der_len, NULL, 0);
- TEST_ASSERT(ret == 0);
- } else {
- ret = mbedtls_x509_crt_parse(cert->cert,
- (const unsigned char *) mbedtls_test_srv_crt_ec_der,
- mbedtls_test_srv_crt_ec_der_len);
- TEST_ASSERT(ret == 0);
-
- ret = mbedtls_pk_parse_key(cert->pkey,
- (const unsigned char *) mbedtls_test_srv_key_ec_der,
- mbedtls_test_srv_key_ec_der_len, NULL, 0);
- TEST_ASSERT(ret == 0);
- }
- } else {
- if (pk_alg == MBEDTLS_PK_RSA) {
- ret = mbedtls_x509_crt_parse(cert->cert,
- (const unsigned char *) mbedtls_test_cli_crt_rsa_der,
- mbedtls_test_cli_crt_rsa_der_len);
- TEST_ASSERT(ret == 0);
-
- ret = mbedtls_pk_parse_key(cert->pkey,
- (const unsigned char *) mbedtls_test_cli_key_rsa_der,
- mbedtls_test_cli_key_rsa_der_len, NULL, 0);
- TEST_ASSERT(ret == 0);
- } else {
- ret = mbedtls_x509_crt_parse(cert->cert,
- (const unsigned char *) mbedtls_test_cli_crt_ec_der,
- mbedtls_test_cli_crt_ec_len);
- TEST_ASSERT(ret == 0);
-
- ret = mbedtls_pk_parse_key(cert->pkey,
- (const unsigned char *) mbedtls_test_cli_key_ec_der,
- mbedtls_test_cli_key_ec_der_len, NULL, 0);
- TEST_ASSERT(ret == 0);
- }
- }
-
- mbedtls_ssl_conf_ca_chain(&(ep->conf), cert->ca_cert, NULL);
-
- ret = mbedtls_ssl_conf_own_cert(&(ep->conf), cert->cert,
- cert->pkey);
- TEST_ASSERT(ret == 0);
-
-exit:
- if (ret != 0) {
- mbedtls_endpoint_certificate_free(ep);
- }
-
- return ret;
-}
-
-/*
- * Initializes \p ep structure. It is important to call `mbedtls_endpoint_free()`
- * after calling this function even if it fails.
- *
- * \p endpoint_type must be set as MBEDTLS_SSL_IS_SERVER or
- * MBEDTLS_SSL_IS_CLIENT.
- * \p pk_alg the algorithm to use, currently only MBEDTLS_PK_RSA and
- * MBEDTLS_PK_ECDSA are supported.
- * \p dtls_context - in case of DTLS - this is the context handling metadata.
- * \p input_queue - used only in case of DTLS.
- * \p output_queue - used only in case of DTLS.
- *
- * \retval 0 on success, otherwise error code.
- */
-int mbedtls_endpoint_init(mbedtls_endpoint *ep, int endpoint_type, int pk_alg,
- mbedtls_test_message_socket_context *dtls_context,
- mbedtls_test_message_queue *input_queue,
- mbedtls_test_message_queue *output_queue,
- const mbedtls_ecp_group_id *curves)
-{
- int ret = -1;
-
- if (dtls_context != NULL && (input_queue == NULL || output_queue == NULL)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- if (ep == NULL) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- memset(ep, 0, sizeof(*ep));
-
- ep->name = (endpoint_type == MBEDTLS_SSL_IS_SERVER) ? "Server" : "Client";
-
- mbedtls_ssl_init(&(ep->ssl));
- mbedtls_ssl_config_init(&(ep->conf));
- mbedtls_ctr_drbg_init(&(ep->ctr_drbg));
- mbedtls_ssl_conf_rng(&(ep->conf),
- mbedtls_ctr_drbg_random,
- &(ep->ctr_drbg));
- mbedtls_entropy_init(&(ep->entropy));
- if (dtls_context != NULL) {
- TEST_ASSERT(mbedtls_message_socket_setup(input_queue, output_queue,
- 100, &(ep->socket),
- dtls_context) == 0);
- } else {
- mbedtls_mock_socket_init(&(ep->socket));
- }
-
- ret = mbedtls_ctr_drbg_seed(&(ep->ctr_drbg), mbedtls_entropy_func,
- &(ep->entropy), (const unsigned char *) (ep->name),
- strlen(ep->name));
- TEST_ASSERT(ret == 0);
-
- /* Non-blocking callbacks without timeout */
- if (dtls_context != NULL) {
- mbedtls_ssl_set_bio(&(ep->ssl), dtls_context,
- mbedtls_mock_tcp_send_msg,
- mbedtls_mock_tcp_recv_msg,
- NULL);
- } else {
- mbedtls_ssl_set_bio(&(ep->ssl), &(ep->socket),
- mbedtls_mock_tcp_send_nb,
- mbedtls_mock_tcp_recv_nb,
- NULL);
- }
-
- ret = mbedtls_ssl_config_defaults(&(ep->conf), endpoint_type,
- (dtls_context != NULL) ?
- MBEDTLS_SSL_TRANSPORT_DATAGRAM :
- MBEDTLS_SSL_TRANSPORT_STREAM,
- MBEDTLS_SSL_PRESET_DEFAULT);
- TEST_ASSERT(ret == 0);
-
-#if defined(MBEDTLS_ECP_C)
- if (curves != NULL) {
- mbedtls_ssl_conf_curves(&(ep->conf), curves);
- }
-#else
- (void) curves;
-#endif
-
- ret = mbedtls_ssl_setup(&(ep->ssl), &(ep->conf));
- TEST_ASSERT(ret == 0);
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS) && defined(MBEDTLS_SSL_SRV_C)
- if (endpoint_type == MBEDTLS_SSL_IS_SERVER && dtls_context != NULL) {
- mbedtls_ssl_conf_dtls_cookies(&(ep->conf), NULL, NULL, NULL);
- }
-#endif
-
- ret = mbedtls_endpoint_certificate_init(ep, pk_alg);
- TEST_ASSERT(ret == 0);
-
-exit:
- return ret;
-}
-
-/*
- * Deinitializes endpoint represented by \p ep.
- */
-void mbedtls_endpoint_free(mbedtls_endpoint *ep,
- mbedtls_test_message_socket_context *context)
-{
- mbedtls_endpoint_certificate_free(ep);
-
- mbedtls_ssl_free(&(ep->ssl));
- mbedtls_ssl_config_free(&(ep->conf));
- mbedtls_ctr_drbg_free(&(ep->ctr_drbg));
- mbedtls_entropy_free(&(ep->entropy));
-
- if (context != NULL) {
- mbedtls_message_socket_close(context);
- } else {
- mbedtls_mock_socket_close(&(ep->socket));
- }
-}
-
-/*
- * This function moves ssl handshake from \p ssl to prescribed \p state.
- * /p second_ssl is used as second endpoint and their sockets have to be
- * connected before calling this function.
- *
- * \retval 0 on success, otherwise error code.
- */
-int mbedtls_move_handshake_to_state(mbedtls_ssl_context *ssl,
- mbedtls_ssl_context *second_ssl,
- int state)
-{
- enum { BUFFSIZE = 1024 };
- int max_steps = 1000;
- int ret = 0;
-
- if (ssl == NULL || second_ssl == NULL) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- /* Perform communication via connected sockets */
- while ((ssl->state != state) && (--max_steps >= 0)) {
- /* If /p second_ssl ends the handshake procedure before /p ssl then
- * there is no need to call the next step */
- if (second_ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
- ret = mbedtls_ssl_handshake_step(second_ssl);
- if (ret != 0 && ret != MBEDTLS_ERR_SSL_WANT_READ &&
- ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
- return ret;
- }
- }
-
- /* We only care about the \p ssl state and returns, so we call it last,
- * to leave the iteration as soon as the state is as expected. */
- ret = mbedtls_ssl_handshake_step(ssl);
- if (ret != 0 && ret != MBEDTLS_ERR_SSL_WANT_READ &&
- ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
- return ret;
- }
- }
-
- return (max_steps >= 0) ? ret : -1;
-}
-
-#endif \
- /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
-
-/*
- * Write application data. Increase write counter if necessary.
- */
-int mbedtls_ssl_write_fragment(mbedtls_ssl_context *ssl, unsigned char *buf,
- int buf_len, int *written,
- const int expected_fragments)
-{
- /* Verify that calling mbedtls_ssl_write with a NULL buffer and zero length is
- * a valid no-op for TLS connections. */
- if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
- TEST_ASSERT(mbedtls_ssl_write(ssl, NULL, 0) == 0);
- }
-
- int ret = mbedtls_ssl_write(ssl, buf + *written, buf_len - *written);
- if (ret > 0) {
- *written += ret;
- }
-
- if (expected_fragments == 0) {
- /* Used for DTLS and the message size larger than MFL. In that case
- * the message can not be fragmented and the library should return
- * MBEDTLS_ERR_SSL_BAD_INPUT_DATA error. This error must be returned
- * to prevent a dead loop inside mbedtls_exchange_data(). */
- return ret;
- } else if (expected_fragments == 1) {
- /* Used for TLS/DTLS and the message size lower than MFL */
- TEST_ASSERT(ret == buf_len ||
- ret == MBEDTLS_ERR_SSL_WANT_READ ||
- ret == MBEDTLS_ERR_SSL_WANT_WRITE);
- } else {
- /* Used for TLS and the message size larger than MFL */
- TEST_ASSERT(expected_fragments > 1);
- TEST_ASSERT((ret >= 0 && ret <= buf_len) ||
- ret == MBEDTLS_ERR_SSL_WANT_READ ||
- ret == MBEDTLS_ERR_SSL_WANT_WRITE);
- }
-
- return 0;
-
-exit:
- /* Some of the tests failed */
- return -1;
-}
-
-/*
- * Read application data and increase read counter and fragments counter if necessary.
- */
-int mbedtls_ssl_read_fragment(mbedtls_ssl_context *ssl, unsigned char *buf,
- int buf_len, int *read,
- int *fragments, const int expected_fragments)
-{
- /* Verify that calling mbedtls_ssl_write with a NULL buffer and zero length is
- * a valid no-op for TLS connections. */
- if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
- TEST_ASSERT(mbedtls_ssl_read(ssl, NULL, 0) == 0);
- }
-
- int ret = mbedtls_ssl_read(ssl, buf + *read, buf_len - *read);
- if (ret > 0) {
- (*fragments)++;
- *read += ret;
- }
-
- if (expected_fragments == 0) {
- TEST_ASSERT(ret == 0);
- } else if (expected_fragments == 1) {
- TEST_ASSERT(ret == buf_len ||
- ret == MBEDTLS_ERR_SSL_WANT_READ ||
- ret == MBEDTLS_ERR_SSL_WANT_WRITE);
- } else {
- TEST_ASSERT(expected_fragments > 1);
- TEST_ASSERT((ret >= 0 && ret <= buf_len) ||
- ret == MBEDTLS_ERR_SSL_WANT_READ ||
- ret == MBEDTLS_ERR_SSL_WANT_WRITE);
- }
-
- return 0;
-
-exit:
- /* Some of the tests failed */
- return -1;
-}
-
-/*
- * Helper function setting up inverse record transformations
- * using given cipher, hash, EtM mode, authentication tag length,
- * and version.
- */
-
-#define CHK(x) \
- do \
- { \
- if (!(x)) \
- { \
- ret = -1; \
- goto cleanup; \
- } \
- } while (0)
-
-void set_ciphersuite(mbedtls_ssl_config *conf, const char *cipher,
- int *forced_ciphersuite)
-{
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
- forced_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id(cipher);
- forced_ciphersuite[1] = 0;
-
- ciphersuite_info =
- mbedtls_ssl_ciphersuite_from_id(forced_ciphersuite[0]);
-
- TEST_ASSERT(ciphersuite_info != NULL);
- TEST_ASSERT(ciphersuite_info->min_minor_ver <= conf->max_minor_ver);
- TEST_ASSERT(ciphersuite_info->max_minor_ver >= conf->min_minor_ver);
-
- if (conf->max_minor_ver > ciphersuite_info->max_minor_ver) {
- conf->max_minor_ver = ciphersuite_info->max_minor_ver;
- }
- if (conf->min_minor_ver < ciphersuite_info->min_minor_ver) {
- conf->min_minor_ver = ciphersuite_info->min_minor_ver;
- }
-
- mbedtls_ssl_conf_ciphersuites(conf, forced_ciphersuite);
-
-exit:
- return;
-}
-
-int psk_dummy_callback(void *p_info, mbedtls_ssl_context *ssl,
- const unsigned char *name, size_t name_len)
-{
- (void) p_info;
- (void) ssl;
- (void) name;
- (void) name_len;
-
- return 0;
-}
-
-#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX
-#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_IN_LEN_MAX
-#else
-#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_OUT_LEN_MAX
-#endif
-
-static int build_transforms(mbedtls_ssl_transform *t_in,
- mbedtls_ssl_transform *t_out,
- int cipher_type, int hash_id,
- int etm, int tag_mode, int ver,
- size_t cid0_len,
- size_t cid1_len)
-{
- mbedtls_cipher_info_t const *cipher_info;
- int ret = 0;
-
- size_t keylen, maclen, ivlen;
- unsigned char *key0 = NULL, *key1 = NULL;
- unsigned char *md0 = NULL, *md1 = NULL;
- unsigned char iv_enc[16], iv_dec[16];
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- unsigned char cid0[SSL_CID_LEN_MIN];
- unsigned char cid1[SSL_CID_LEN_MIN];
-
- mbedtls_test_rnd_std_rand(NULL, cid0, sizeof(cid0));
- mbedtls_test_rnd_std_rand(NULL, cid1, sizeof(cid1));
-#else
- ((void) cid0_len);
- ((void) cid1_len);
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
- maclen = 0;
-
- /* Pick cipher */
- cipher_info = mbedtls_cipher_info_from_type(cipher_type);
- CHK(cipher_info != NULL);
- CHK(cipher_info->iv_size <= 16);
- CHK(cipher_info->key_bitlen % 8 == 0);
-
- /* Pick keys */
- keylen = cipher_info->key_bitlen / 8;
- /* Allocate `keylen + 1` bytes to ensure that we get
- * a non-NULL pointers from `mbedtls_calloc` even if
- * `keylen == 0` in the case of the NULL cipher. */
- CHK((key0 = mbedtls_calloc(1, keylen + 1)) != NULL);
- CHK((key1 = mbedtls_calloc(1, keylen + 1)) != NULL);
- memset(key0, 0x1, keylen);
- memset(key1, 0x2, keylen);
-
- /* Setup cipher contexts */
- CHK(mbedtls_cipher_setup(&t_in->cipher_ctx_enc, cipher_info) == 0);
- CHK(mbedtls_cipher_setup(&t_in->cipher_ctx_dec, cipher_info) == 0);
- CHK(mbedtls_cipher_setup(&t_out->cipher_ctx_enc, cipher_info) == 0);
- CHK(mbedtls_cipher_setup(&t_out->cipher_ctx_dec, cipher_info) == 0);
-
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
- if (cipher_info->mode == MBEDTLS_MODE_CBC) {
- CHK(mbedtls_cipher_set_padding_mode(&t_in->cipher_ctx_enc,
- MBEDTLS_PADDING_NONE) == 0);
- CHK(mbedtls_cipher_set_padding_mode(&t_in->cipher_ctx_dec,
- MBEDTLS_PADDING_NONE) == 0);
- CHK(mbedtls_cipher_set_padding_mode(&t_out->cipher_ctx_enc,
- MBEDTLS_PADDING_NONE) == 0);
- CHK(mbedtls_cipher_set_padding_mode(&t_out->cipher_ctx_dec,
- MBEDTLS_PADDING_NONE) == 0);
- }
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-
- CHK(mbedtls_cipher_setkey(&t_in->cipher_ctx_enc, key0,
- keylen << 3, MBEDTLS_ENCRYPT) == 0);
- CHK(mbedtls_cipher_setkey(&t_in->cipher_ctx_dec, key1,
- keylen << 3, MBEDTLS_DECRYPT) == 0);
- CHK(mbedtls_cipher_setkey(&t_out->cipher_ctx_enc, key1,
- keylen << 3, MBEDTLS_ENCRYPT) == 0);
- CHK(mbedtls_cipher_setkey(&t_out->cipher_ctx_dec, key0,
- keylen << 3, MBEDTLS_DECRYPT) == 0);
-
- /* Setup MAC contexts */
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
- if (cipher_info->mode == MBEDTLS_MODE_CBC ||
- cipher_info->mode == MBEDTLS_MODE_STREAM) {
- mbedtls_md_info_t const *md_info;
-
- /* Pick hash */
- md_info = mbedtls_md_info_from_type(hash_id);
- CHK(md_info != NULL);
-
- /* Pick hash keys */
- maclen = mbedtls_md_get_size(md_info);
- CHK((md0 = mbedtls_calloc(1, maclen)) != NULL);
- CHK((md1 = mbedtls_calloc(1, maclen)) != NULL);
- memset(md0, 0x5, maclen);
- memset(md1, 0x6, maclen);
-
- CHK(mbedtls_md_setup(&t_out->md_ctx_enc, md_info, 1) == 0);
- CHK(mbedtls_md_setup(&t_out->md_ctx_dec, md_info, 1) == 0);
- CHK(mbedtls_md_setup(&t_in->md_ctx_enc, md_info, 1) == 0);
- CHK(mbedtls_md_setup(&t_in->md_ctx_dec, md_info, 1) == 0);
-
- if (ver > MBEDTLS_SSL_MINOR_VERSION_0) {
- CHK(mbedtls_md_hmac_starts(&t_in->md_ctx_enc,
- md0, maclen) == 0);
- CHK(mbedtls_md_hmac_starts(&t_in->md_ctx_dec,
- md1, maclen) == 0);
- CHK(mbedtls_md_hmac_starts(&t_out->md_ctx_enc,
- md1, maclen) == 0);
- CHK(mbedtls_md_hmac_starts(&t_out->md_ctx_dec,
- md0, maclen) == 0);
- }
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- else {
- memcpy(&t_in->mac_enc, md0, maclen);
- memcpy(&t_in->mac_dec, md1, maclen);
- memcpy(&t_out->mac_enc, md1, maclen);
- memcpy(&t_out->mac_dec, md0, maclen);
- }
-#endif
- }
-#else
- ((void) hash_id);
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
-
-
- /* Pick IV's (regardless of whether they
- * are being used by the transform). */
- ivlen = cipher_info->iv_size;
- memset(iv_enc, 0x3, sizeof(iv_enc));
- memset(iv_dec, 0x4, sizeof(iv_dec));
-
- /*
- * Setup transforms
- */
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \
- defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
- t_out->encrypt_then_mac = etm;
- t_in->encrypt_then_mac = etm;
-#else
- ((void) etm);
-#endif
-
- t_out->minor_ver = ver;
- t_in->minor_ver = ver;
- t_out->ivlen = ivlen;
- t_in->ivlen = ivlen;
-
- switch (cipher_info->mode) {
- case MBEDTLS_MODE_GCM:
- case MBEDTLS_MODE_CCM:
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
- if (ver == MBEDTLS_SSL_MINOR_VERSION_4) {
- t_out->fixed_ivlen = 12;
- t_in->fixed_ivlen = 12;
- } else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
- {
- t_out->fixed_ivlen = 4;
- t_in->fixed_ivlen = 4;
- }
- t_out->maclen = 0;
- t_in->maclen = 0;
- switch (tag_mode) {
- case 0: /* Full tag */
- t_out->taglen = 16;
- t_in->taglen = 16;
- break;
- case 1: /* Partial tag */
- t_out->taglen = 8;
- t_in->taglen = 8;
- break;
- default:
- ret = 1;
- goto cleanup;
- }
- break;
-
- case MBEDTLS_MODE_CHACHAPOLY:
- t_out->fixed_ivlen = 12;
- t_in->fixed_ivlen = 12;
- t_out->maclen = 0;
- t_in->maclen = 0;
- switch (tag_mode) {
- case 0: /* Full tag */
- t_out->taglen = 16;
- t_in->taglen = 16;
- break;
- case 1: /* Partial tag */
- t_out->taglen = 8;
- t_in->taglen = 8;
- break;
- default:
- ret = 1;
- goto cleanup;
- }
- break;
-
- case MBEDTLS_MODE_STREAM:
- case MBEDTLS_MODE_CBC:
- t_out->fixed_ivlen = 0; /* redundant, must be 0 */
- t_in->fixed_ivlen = 0; /* redundant, must be 0 */
- t_out->taglen = 0;
- t_in->taglen = 0;
- switch (tag_mode) {
- case 0: /* Full tag */
- t_out->maclen = maclen;
- t_in->maclen = maclen;
- break;
- case 1: /* Partial tag */
- t_out->maclen = 10;
- t_in->maclen = 10;
- break;
- default:
- ret = 1;
- goto cleanup;
- }
- break;
- default:
- ret = 1;
- goto cleanup;
- break;
- }
-
- /* Setup IV's */
-
- memcpy(&t_in->iv_dec, iv_dec, sizeof(iv_dec));
- memcpy(&t_in->iv_enc, iv_enc, sizeof(iv_enc));
- memcpy(&t_out->iv_dec, iv_enc, sizeof(iv_enc));
- memcpy(&t_out->iv_enc, iv_dec, sizeof(iv_dec));
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- /* Add CID */
- memcpy(&t_in->in_cid, cid0, cid0_len);
- memcpy(&t_in->out_cid, cid1, cid1_len);
- t_in->in_cid_len = cid0_len;
- t_in->out_cid_len = cid1_len;
- memcpy(&t_out->in_cid, cid1, cid1_len);
- memcpy(&t_out->out_cid, cid0, cid0_len);
- t_out->in_cid_len = cid1_len;
- t_out->out_cid_len = cid0_len;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-cleanup:
-
- mbedtls_free(key0);
- mbedtls_free(key1);
-
- mbedtls_free(md0);
- mbedtls_free(md1);
-
- return ret;
-}
-
-/*
- * Populate a session structure for serialization tests.
- * Choose dummy values, mostly non-0 to distinguish from the init default.
- */
-static int ssl_populate_session(mbedtls_ssl_session *session,
- int ticket_len,
- const char *crt_file)
-{
-#if defined(MBEDTLS_HAVE_TIME)
- session->start = mbedtls_time(NULL) - 42;
-#endif
- session->ciphersuite = 0xabcd;
- session->compression = 1;
- session->id_len = sizeof(session->id);
- memset(session->id, 66, session->id_len);
- memset(session->master, 17, sizeof(session->master));
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
- defined(MBEDTLS_CERTS_C) && \
- defined(MBEDTLS_FS_IO)
- if (strlen(crt_file) != 0) {
- mbedtls_x509_crt tmp_crt;
- int ret;
-
- mbedtls_x509_crt_init(&tmp_crt);
- ret = mbedtls_x509_crt_parse_file(&tmp_crt, crt_file);
- if (ret != 0) {
- return ret;
- }
-
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- /* Move temporary CRT. */
- session->peer_cert = mbedtls_calloc(1, sizeof(*session->peer_cert));
- if (session->peer_cert == NULL) {
- return -1;
- }
- *session->peer_cert = tmp_crt;
- memset(&tmp_crt, 0, sizeof(tmp_crt));
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
- /* Calculate digest of temporary CRT. */
- session->peer_cert_digest =
- mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN);
- if (session->peer_cert_digest == NULL) {
- return -1;
- }
- ret = mbedtls_md(mbedtls_md_info_from_type(
- MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE),
- tmp_crt.raw.p, tmp_crt.raw.len,
- session->peer_cert_digest);
- if (ret != 0) {
- return ret;
- }
- session->peer_cert_digest_type =
- MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
- session->peer_cert_digest_len =
- MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
- mbedtls_x509_crt_free(&tmp_crt);
- }
-#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C && MBEDTLS_FS_IO */
- (void) crt_file;
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C && MBEDTLS_FS_IO */
- session->verify_result = 0xdeadbeef;
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
- if (ticket_len != 0) {
- session->ticket = mbedtls_calloc(1, ticket_len);
- if (session->ticket == NULL) {
- return -1;
- }
- memset(session->ticket, 33, ticket_len);
- }
- session->ticket_len = ticket_len;
- session->ticket_lifetime = 86401;
-#else
- (void) ticket_len;
-#endif
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
- session->mfl_code = 1;
-#endif
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
- session->trunc_hmac = 1;
-#endif
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- session->encrypt_then_mac = 1;
-#endif
-
- return 0;
-}
-
-/*
- * Perform data exchanging between \p ssl_1 and \p ssl_2 and check if the
- * message was sent in the correct number of fragments.
- *
- * /p ssl_1 and /p ssl_2 Endpoints represented by mbedtls_ssl_context. Both
- * of them must be initialized and connected beforehand.
- * /p msg_len_1 and /p msg_len_2 specify the size of the message to send.
- * /p expected_fragments_1 and /p expected_fragments_2 determine in how many
- * fragments the message should be sent.
- * expected_fragments is 0: can be used for DTLS testing while the message
- * size is larger than MFL. In that case the message
- * cannot be fragmented and sent to the second endpoint.
- * This value can be used for negative tests.
- * expected_fragments is 1: can be used for TLS/DTLS testing while the
- * message size is below MFL
- * expected_fragments > 1: can be used for TLS testing while the message
- * size is larger than MFL
- *
- * \retval 0 on success, otherwise error code.
- */
-int mbedtls_exchange_data(mbedtls_ssl_context *ssl_1,
- int msg_len_1, const int expected_fragments_1,
- mbedtls_ssl_context *ssl_2,
- int msg_len_2, const int expected_fragments_2)
-{
- unsigned char *msg_buf_1 = malloc(msg_len_1);
- unsigned char *msg_buf_2 = malloc(msg_len_2);
- unsigned char *in_buf_1 = malloc(msg_len_2);
- unsigned char *in_buf_2 = malloc(msg_len_1);
- int msg_type, ret = -1;
-
- /* Perform this test with two message types. At first use a message
- * consisting of only 0x00 for the client and only 0xFF for the server.
- * At the second time use message with generated data */
- for (msg_type = 0; msg_type < 2; msg_type++) {
- int written_1 = 0;
- int written_2 = 0;
- int read_1 = 0;
- int read_2 = 0;
- int fragments_1 = 0;
- int fragments_2 = 0;
-
- if (msg_type == 0) {
- memset(msg_buf_1, 0x00, msg_len_1);
- memset(msg_buf_2, 0xff, msg_len_2);
- } else {
- int i, j = 0;
- for (i = 0; i < msg_len_1; i++) {
- msg_buf_1[i] = j++ & 0xFF;
- }
- for (i = 0; i < msg_len_2; i++) {
- msg_buf_2[i] = (j -= 5) & 0xFF;
- }
- }
-
- while (read_1 < msg_len_2 || read_2 < msg_len_1) {
- /* ssl_1 sending */
- if (msg_len_1 > written_1) {
- ret = mbedtls_ssl_write_fragment(ssl_1, msg_buf_1,
- msg_len_1, &written_1,
- expected_fragments_1);
- if (expected_fragments_1 == 0) {
- /* This error is expected when the message is too large and
- * cannot be fragmented */
- TEST_ASSERT(ret == MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
- msg_len_1 = 0;
- } else {
- TEST_ASSERT(ret == 0);
- }
- }
-
- /* ssl_2 sending */
- if (msg_len_2 > written_2) {
- ret = mbedtls_ssl_write_fragment(ssl_2, msg_buf_2,
- msg_len_2, &written_2,
- expected_fragments_2);
- if (expected_fragments_2 == 0) {
- /* This error is expected when the message is too large and
- * cannot be fragmented */
- TEST_ASSERT(ret == MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
- msg_len_2 = 0;
- } else {
- TEST_ASSERT(ret == 0);
- }
- }
-
- /* ssl_1 reading */
- if (read_1 < msg_len_2) {
- ret = mbedtls_ssl_read_fragment(ssl_1, in_buf_1,
- msg_len_2, &read_1,
- &fragments_2,
- expected_fragments_2);
- TEST_ASSERT(ret == 0);
- }
-
- /* ssl_2 reading */
- if (read_2 < msg_len_1) {
- ret = mbedtls_ssl_read_fragment(ssl_2, in_buf_2,
- msg_len_1, &read_2,
- &fragments_1,
- expected_fragments_1);
- TEST_ASSERT(ret == 0);
- }
- }
-
- ret = -1;
- TEST_ASSERT(0 == memcmp(msg_buf_1, in_buf_2, msg_len_1));
- TEST_ASSERT(0 == memcmp(msg_buf_2, in_buf_1, msg_len_2));
- TEST_ASSERT(fragments_1 == expected_fragments_1);
- TEST_ASSERT(fragments_2 == expected_fragments_2);
- }
-
- ret = 0;
-
-exit:
- free(msg_buf_1);
- free(in_buf_1);
- free(msg_buf_2);
- free(in_buf_2);
-
- return ret;
-}
-
-/*
- * Perform data exchanging between \p ssl_1 and \p ssl_2. Both of endpoints
- * must be initialized and connected beforehand.
- *
- * \retval 0 on success, otherwise error code.
- */
-int exchange_data(mbedtls_ssl_context *ssl_1,
- mbedtls_ssl_context *ssl_2)
-{
- return mbedtls_exchange_data(ssl_1, 256, 1,
- ssl_2, 256, 1);
-}
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
- defined(MBEDTLS_CERTS_C) && \
- defined(MBEDTLS_ENTROPY_C) && \
- defined(MBEDTLS_CTR_DRBG_C)
-void perform_handshake(handshake_test_options *options)
-{
- /* forced_ciphersuite needs to last until the end of the handshake */
- int forced_ciphersuite[2];
- enum { BUFFSIZE = 17000 };
- mbedtls_endpoint client, server;
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
- const char *psk_identity = "foo";
-#endif
-#if defined(MBEDTLS_TIMING_C)
- mbedtls_timing_delay_context timer_client, timer_server;
-#endif
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
- unsigned char *context_buf = NULL;
- size_t context_buf_len;
-#endif
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- int ret = -1;
-#endif
- int expected_handshake_result = 0;
-
- USE_PSA_INIT();
- mbedtls_platform_zeroize(&client, sizeof(client));
- mbedtls_platform_zeroize(&server, sizeof(server));
-
- mbedtls_test_message_queue server_queue, client_queue;
- mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
-
- /* Client side */
- if (options->dtls != 0) {
- TEST_ASSERT(mbedtls_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT,
- options->pk_alg, &client_context,
- &client_queue,
- &server_queue, NULL) == 0);
-#if defined(MBEDTLS_TIMING_C)
- mbedtls_ssl_set_timer_cb(&client.ssl, &timer_client,
- mbedtls_timing_set_delay,
- mbedtls_timing_get_delay);
-#endif
- } else {
- TEST_ASSERT(mbedtls_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT,
- options->pk_alg, NULL, NULL,
- NULL, NULL) == 0);
- }
-
- if (options->client_min_version != TEST_SSL_MINOR_VERSION_NONE) {
- mbedtls_ssl_conf_min_version(&client.conf, MBEDTLS_SSL_MAJOR_VERSION_3,
- options->client_min_version);
- }
-
- if (options->client_max_version != TEST_SSL_MINOR_VERSION_NONE) {
- mbedtls_ssl_conf_max_version(&client.conf, MBEDTLS_SSL_MAJOR_VERSION_3,
- options->client_max_version);
- }
-
- if (strlen(options->cipher) > 0) {
- set_ciphersuite(&client.conf, options->cipher, forced_ciphersuite);
- }
-
-#if defined(MBEDTLS_DEBUG_C)
- if (options->cli_log_fun) {
- mbedtls_debug_set_threshold(4);
- mbedtls_ssl_conf_dbg(&client.conf, options->cli_log_fun,
- options->cli_log_obj);
- }
-#endif
-
- /* Server side */
- if (options->dtls != 0) {
- TEST_ASSERT(mbedtls_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER,
- options->pk_alg, &server_context,
- &server_queue,
- &client_queue, NULL) == 0);
-#if defined(MBEDTLS_TIMING_C)
- mbedtls_ssl_set_timer_cb(&server.ssl, &timer_server,
- mbedtls_timing_set_delay,
- mbedtls_timing_get_delay);
-#endif
- } else {
- TEST_ASSERT(mbedtls_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER,
- options->pk_alg, NULL, NULL,
- NULL, NULL) == 0);
- }
-
- mbedtls_ssl_conf_authmode(&server.conf, options->srv_auth_mode);
-
- if (options->server_min_version != TEST_SSL_MINOR_VERSION_NONE) {
- mbedtls_ssl_conf_min_version(&server.conf, MBEDTLS_SSL_MAJOR_VERSION_3,
- options->server_min_version);
- }
-
- if (options->server_max_version != TEST_SSL_MINOR_VERSION_NONE) {
- mbedtls_ssl_conf_max_version(&server.conf, MBEDTLS_SSL_MAJOR_VERSION_3,
- options->server_max_version);
- }
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
- TEST_ASSERT(mbedtls_ssl_conf_max_frag_len(&(server.conf),
- (unsigned char) options->mfl) == 0);
- TEST_ASSERT(mbedtls_ssl_conf_max_frag_len(&(client.conf),
- (unsigned char) options->mfl) == 0);
-#else
- TEST_ASSERT(MBEDTLS_SSL_MAX_FRAG_LEN_NONE == options->mfl);
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
- if (options->psk_str != NULL && options->psk_str->len > 0) {
- TEST_ASSERT(mbedtls_ssl_conf_psk(&client.conf, options->psk_str->x,
- options->psk_str->len,
- (const unsigned char *) psk_identity,
- strlen(psk_identity)) == 0);
-
- TEST_ASSERT(mbedtls_ssl_conf_psk(&server.conf, options->psk_str->x,
- options->psk_str->len,
- (const unsigned char *) psk_identity,
- strlen(psk_identity)) == 0);
-
- mbedtls_ssl_conf_psk_cb(&server.conf, psk_dummy_callback, NULL);
- }
-#endif
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- if (options->renegotiate) {
- mbedtls_ssl_conf_renegotiation(&(server.conf),
- MBEDTLS_SSL_RENEGOTIATION_ENABLED);
- mbedtls_ssl_conf_renegotiation(&(client.conf),
- MBEDTLS_SSL_RENEGOTIATION_ENABLED);
-
- mbedtls_ssl_conf_legacy_renegotiation(&(server.conf),
- options->legacy_renegotiation);
- mbedtls_ssl_conf_legacy_renegotiation(&(client.conf),
- options->legacy_renegotiation);
- }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
-#if defined(MBEDTLS_DEBUG_C)
- if (options->srv_log_fun) {
- mbedtls_debug_set_threshold(4);
- mbedtls_ssl_conf_dbg(&server.conf, options->srv_log_fun,
- options->srv_log_obj);
- }
-#endif
-
- TEST_ASSERT(mbedtls_mock_socket_connect(&(client.socket),
- &(server.socket),
- BUFFSIZE) == 0);
-
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
- if (options->resize_buffers != 0) {
- /* Ensure that the buffer sizes are appropriate before resizes */
- TEST_ASSERT(client.ssl.out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
- TEST_ASSERT(client.ssl.in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
- TEST_ASSERT(server.ssl.out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
- TEST_ASSERT(server.ssl.in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
- }
-#endif
-
- if (options->expected_negotiated_version == TEST_SSL_MINOR_VERSION_NONE) {
- expected_handshake_result = MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION;
- }
-
- TEST_ASSERT(mbedtls_move_handshake_to_state(&(client.ssl),
- &(server.ssl),
- MBEDTLS_SSL_HANDSHAKE_OVER)
- == expected_handshake_result);
-
- if (expected_handshake_result != 0) {
- /* Connection will have failed by this point, skip to cleanup */
- goto exit;
- }
-
- TEST_ASSERT(client.ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
- TEST_ASSERT(server.ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
-
- /* Check that we agree on the version... */
- TEST_ASSERT(client.ssl.minor_ver == server.ssl.minor_ver);
-
- /* And check that the version negotiated is the expected one. */
- TEST_EQUAL(client.ssl.minor_ver, options->expected_negotiated_version);
-
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
- if (options->resize_buffers != 0) {
- if (options->expected_negotiated_version != MBEDTLS_SSL_MINOR_VERSION_0 &&
- options->expected_negotiated_version != MBEDTLS_SSL_MINOR_VERSION_1) {
- /* A server, when using DTLS, might delay a buffer resize to happen
- * after it receives a message, so we force it. */
- TEST_ASSERT(exchange_data(&(client.ssl), &(server.ssl)) == 0);
-
- TEST_ASSERT(client.ssl.out_buf_len ==
- mbedtls_ssl_get_output_buflen(&client.ssl));
- TEST_ASSERT(client.ssl.in_buf_len ==
- mbedtls_ssl_get_input_buflen(&client.ssl));
- TEST_ASSERT(server.ssl.out_buf_len ==
- mbedtls_ssl_get_output_buflen(&server.ssl));
- TEST_ASSERT(server.ssl.in_buf_len ==
- mbedtls_ssl_get_input_buflen(&server.ssl));
- }
- }
-#endif
-
- if (options->cli_msg_len != 0 || options->srv_msg_len != 0) {
- /* Start data exchanging test */
- TEST_ASSERT(mbedtls_exchange_data(&(client.ssl), options->cli_msg_len,
- options->expected_cli_fragments,
- &(server.ssl), options->srv_msg_len,
- options->expected_srv_fragments)
- == 0);
- }
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
- if (options->serialize == 1) {
- TEST_ASSERT(options->dtls == 1);
-
- TEST_ASSERT(mbedtls_ssl_context_save(&(server.ssl), NULL,
- 0, &context_buf_len)
- == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
-
- context_buf = mbedtls_calloc(1, context_buf_len);
- TEST_ASSERT(context_buf != NULL);
-
- TEST_ASSERT(mbedtls_ssl_context_save(&(server.ssl), context_buf,
- context_buf_len,
- &context_buf_len) == 0);
-
- mbedtls_ssl_free(&(server.ssl));
- mbedtls_ssl_init(&(server.ssl));
-
- TEST_ASSERT(mbedtls_ssl_setup(&(server.ssl), &(server.conf)) == 0);
-
- mbedtls_ssl_set_bio(&(server.ssl), &server_context,
- mbedtls_mock_tcp_send_msg,
- mbedtls_mock_tcp_recv_msg,
- NULL);
-
-#if defined(MBEDTLS_TIMING_C)
- mbedtls_ssl_set_timer_cb(&server.ssl, &timer_server,
- mbedtls_timing_set_delay,
- mbedtls_timing_get_delay);
-#endif
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
- if (options->resize_buffers != 0) {
- /* Ensure that the buffer sizes are appropriate before resizes */
- TEST_ASSERT(server.ssl.out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
- TEST_ASSERT(server.ssl.in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
- }
-#endif
- TEST_ASSERT(mbedtls_ssl_context_load(&(server.ssl), context_buf,
- context_buf_len) == 0);
-
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
- /* Validate buffer sizes after context deserialization */
- if (options->resize_buffers != 0) {
- TEST_ASSERT(server.ssl.out_buf_len ==
- mbedtls_ssl_get_output_buflen(&server.ssl));
- TEST_ASSERT(server.ssl.in_buf_len ==
- mbedtls_ssl_get_input_buflen(&server.ssl));
- }
-#endif
- /* Retest writing/reading */
- if (options->cli_msg_len != 0 || options->srv_msg_len != 0) {
- TEST_ASSERT(mbedtls_exchange_data(&(client.ssl),
- options->cli_msg_len,
- options->expected_cli_fragments,
- &(server.ssl),
- options->srv_msg_len,
- options->expected_srv_fragments)
- == 0);
- }
- }
-#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- if (options->renegotiate) {
- /* Start test with renegotiation */
- TEST_ASSERT(server.ssl.renego_status ==
- MBEDTLS_SSL_INITIAL_HANDSHAKE);
- TEST_ASSERT(client.ssl.renego_status ==
- MBEDTLS_SSL_INITIAL_HANDSHAKE);
-
- /* After calling this function for the server, it only sends a handshake
- * request. All renegotiation should happen during data exchanging */
- TEST_ASSERT(mbedtls_ssl_renegotiate(&(server.ssl)) == 0);
- TEST_ASSERT(server.ssl.renego_status ==
- MBEDTLS_SSL_RENEGOTIATION_PENDING);
- TEST_ASSERT(client.ssl.renego_status ==
- MBEDTLS_SSL_INITIAL_HANDSHAKE);
-
- TEST_ASSERT(exchange_data(&(client.ssl), &(server.ssl)) == 0);
- TEST_ASSERT(server.ssl.renego_status ==
- MBEDTLS_SSL_RENEGOTIATION_DONE);
- TEST_ASSERT(client.ssl.renego_status ==
- MBEDTLS_SSL_RENEGOTIATION_DONE);
-
- /* After calling mbedtls_ssl_renegotiate for the client all renegotiation
- * should happen inside this function. However in this test, we cannot
- * perform simultaneous communication between client and server so this
- * function will return waiting error on the socket. All rest of
- * renegotiation should happen during data exchanging */
- ret = mbedtls_ssl_renegotiate(&(client.ssl));
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
- if (options->resize_buffers != 0) {
- /* Ensure that the buffer sizes are appropriate before resizes */
- TEST_ASSERT(client.ssl.out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
- TEST_ASSERT(client.ssl.in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
- }
-#endif
- TEST_ASSERT(ret == 0 ||
- ret == MBEDTLS_ERR_SSL_WANT_READ ||
- ret == MBEDTLS_ERR_SSL_WANT_WRITE);
- TEST_ASSERT(server.ssl.renego_status ==
- MBEDTLS_SSL_RENEGOTIATION_DONE);
- TEST_ASSERT(client.ssl.renego_status ==
- MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS);
-
- TEST_ASSERT(exchange_data(&(client.ssl), &(server.ssl)) == 0);
- TEST_ASSERT(server.ssl.renego_status ==
- MBEDTLS_SSL_RENEGOTIATION_DONE);
- TEST_ASSERT(client.ssl.renego_status ==
- MBEDTLS_SSL_RENEGOTIATION_DONE);
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
- /* Validate buffer sizes after renegotiation */
- if (options->resize_buffers != 0) {
- TEST_ASSERT(client.ssl.out_buf_len ==
- mbedtls_ssl_get_output_buflen(&client.ssl));
- TEST_ASSERT(client.ssl.in_buf_len ==
- mbedtls_ssl_get_input_buflen(&client.ssl));
- TEST_ASSERT(server.ssl.out_buf_len ==
- mbedtls_ssl_get_output_buflen(&server.ssl));
- TEST_ASSERT(server.ssl.in_buf_len ==
- mbedtls_ssl_get_input_buflen(&server.ssl));
- }
-#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */
- }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
-exit:
- mbedtls_endpoint_free(&client, options->dtls != 0 ? &client_context : NULL);
- mbedtls_endpoint_free(&server, options->dtls != 0 ? &server_context : NULL);
-#if defined(MBEDTLS_DEBUG_C)
- if (options->cli_log_fun || options->srv_log_fun) {
- mbedtls_debug_set_threshold(0);
- }
-#endif
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
- if (context_buf != NULL) {
- mbedtls_free(context_buf);
- }
-#endif
-}
-#endif \
- /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
-
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -2030,65 +16,69 @@
void test_callback_buffer_sanity()
{
enum { MSGLEN = 10 };
- mbedtls_test_buffer buf;
+ mbedtls_test_ssl_buffer buf;
unsigned char input[MSGLEN];
unsigned char output[MSGLEN];
memset(input, 0, sizeof(input));
/* Make sure calling put and get on NULL buffer results in error. */
- TEST_ASSERT(mbedtls_test_buffer_put(NULL, input, sizeof(input))
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(NULL, input, sizeof(input))
== -1);
- TEST_ASSERT(mbedtls_test_buffer_get(NULL, output, sizeof(output))
+ TEST_ASSERT(mbedtls_test_ssl_buffer_get(NULL, output, sizeof(output))
== -1);
- TEST_ASSERT(mbedtls_test_buffer_put(NULL, NULL, sizeof(input)) == -1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(NULL, NULL, sizeof(input))
+ == -1);
- TEST_ASSERT(mbedtls_test_buffer_put(NULL, NULL, 0) == -1);
- TEST_ASSERT(mbedtls_test_buffer_get(NULL, NULL, 0) == -1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(NULL, NULL, 0) == -1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_get(NULL, NULL, 0) == -1);
/* Make sure calling put and get on a buffer that hasn't been set up results
* in error. */
- mbedtls_test_buffer_init(&buf);
+ mbedtls_test_ssl_buffer_init(&buf);
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, input, sizeof(input)) == -1);
- TEST_ASSERT(mbedtls_test_buffer_get(&buf, output, sizeof(output))
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, input, sizeof(input))
== -1);
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, NULL, sizeof(input)) == -1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_get(&buf, output, sizeof(output))
+ == -1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, NULL, sizeof(input))
+ == -1);
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, NULL, 0) == -1);
- TEST_ASSERT(mbedtls_test_buffer_get(&buf, NULL, 0) == -1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, NULL, 0) == -1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_get(&buf, NULL, 0) == -1);
/* Make sure calling put and get on NULL input only results in
* error if the length is not zero, and that a NULL output is valid for data
* dropping.
*/
- TEST_ASSERT(mbedtls_test_buffer_setup(&buf, sizeof(input)) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_setup(&buf, sizeof(input)) == 0);
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, NULL, sizeof(input)) == -1);
- TEST_ASSERT(mbedtls_test_buffer_get(&buf, NULL, sizeof(output))
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, NULL, sizeof(input))
+ == -1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_get(&buf, NULL, sizeof(output))
== 0);
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, NULL, 0) == 0);
- TEST_ASSERT(mbedtls_test_buffer_get(&buf, NULL, 0) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, NULL, 0) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_get(&buf, NULL, 0) == 0);
/* Make sure calling put several times in the row is safe */
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, input, sizeof(input))
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, input, sizeof(input))
== sizeof(input));
- TEST_ASSERT(mbedtls_test_buffer_get(&buf, output, 2) == 2);
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, input, 1) == 1);
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, input, 2) == 1);
- TEST_ASSERT(mbedtls_test_buffer_put(&buf, input, 2) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_get(&buf, output, 2) == 2);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, input, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, input, 2) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_put(&buf, input, 2) == 0);
exit:
- mbedtls_test_buffer_free(&buf);
+ mbedtls_test_ssl_buffer_free(&buf);
}
/* END_CASE */
/*
- * Test if the implementation of `mbedtls_test_buffer` related functions is
+ * Test if the implementation of `mbedtls_test_ssl_buffer` related functions is
* correct and works as expected.
*
* That is
@@ -2110,15 +100,15 @@
int put_ret[ROUNDS];
size_t get[ROUNDS];
int get_ret[ROUNDS];
- mbedtls_test_buffer buf;
+ mbedtls_test_ssl_buffer buf;
unsigned char *input = NULL;
size_t input_len;
unsigned char *output = NULL;
size_t output_len;
size_t i, j, written, read;
- mbedtls_test_buffer_init(&buf);
- TEST_ASSERT(mbedtls_test_buffer_setup(&buf, size) == 0);
+ mbedtls_test_ssl_buffer_init(&buf);
+ TEST_ASSERT(mbedtls_test_ssl_buffer_setup(&buf, size) == 0);
/* Check the sanity of input parameters and initialise local variables. That
* is, ensure that the amount of data is not negative and that we are not
@@ -2177,11 +167,11 @@
written = read = 0;
for (j = 0; j < ROUNDS; j++) {
- TEST_ASSERT(put_ret[j] == mbedtls_test_buffer_put(&buf,
- input + written, put[j]));
+ TEST_ASSERT(put_ret[j] == mbedtls_test_ssl_buffer_put(&buf,
+ input + written, put[j]));
written += put_ret[j];
- TEST_ASSERT(get_ret[j] == mbedtls_test_buffer_get(&buf,
- output + read, get[j]));
+ TEST_ASSERT(get_ret[j] == mbedtls_test_ssl_buffer_get(&buf,
+ output + read, get[j]));
read += get_ret[j];
TEST_ASSERT(read <= written);
if (get_ret[j] > 0) {
@@ -2195,13 +185,13 @@
mbedtls_free(input);
mbedtls_free(output);
- mbedtls_test_buffer_free(&buf);
+ mbedtls_test_ssl_buffer_free(&buf);
}
/* END_CASE */
/*
- * Test if the implementation of `mbedtls_mock_socket` related I/O functions is
- * correct and works as expected on unconnected sockets.
+ * Test if the implementation of `mbedtls_test_mock_socket` related
+ * I/O functions is correct and works as expected on unconnected sockets.
*/
/* BEGIN_CASE */
@@ -2210,31 +200,31 @@
enum { MSGLEN = 105 };
unsigned char message[MSGLEN] = { 0 };
unsigned char received[MSGLEN] = { 0 };
- mbedtls_mock_socket socket;
+ mbedtls_test_mock_socket socket;
mbedtls_mock_socket_init(&socket);
- TEST_ASSERT(mbedtls_mock_tcp_send_b(&socket, message, MSGLEN) < 0);
- mbedtls_mock_socket_close(&socket);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_b(&socket, message, MSGLEN) < 0);
+ mbedtls_test_mock_socket_close(&socket);
mbedtls_mock_socket_init(&socket);
- TEST_ASSERT(mbedtls_mock_tcp_recv_b(&socket, received, MSGLEN) < 0);
- mbedtls_mock_socket_close(&socket);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_b(&socket, received, MSGLEN) < 0);
+ mbedtls_test_mock_socket_close(&socket);
mbedtls_mock_socket_init(&socket);
- TEST_ASSERT(mbedtls_mock_tcp_send_nb(&socket, message, MSGLEN) < 0);
- mbedtls_mock_socket_close(&socket);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_nb(&socket, message, MSGLEN) < 0);
+ mbedtls_test_mock_socket_close(&socket);
mbedtls_mock_socket_init(&socket);
- TEST_ASSERT(mbedtls_mock_tcp_recv_nb(&socket, received, MSGLEN) < 0);
- mbedtls_mock_socket_close(&socket);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_nb(&socket, received, MSGLEN) < 0);
+ mbedtls_test_mock_socket_close(&socket);
exit:
- mbedtls_mock_socket_close(&socket);
+ mbedtls_test_mock_socket_close(&socket);
}
/* END_CASE */
/*
- * Test if the implementation of `mbedtls_mock_socket` related functions can
- * send a single message from the client to the server.
+ * Test if the implementation of `mbedtls_test_mock_socket` related functions
+ * can send a single message from the client to the server.
*/
/* BEGIN_CASE */
@@ -2244,8 +234,8 @@
enum { BUFLEN = MSGLEN / 5 };
unsigned char message[MSGLEN];
unsigned char received[MSGLEN];
- mbedtls_mock_socket client;
- mbedtls_mock_socket server;
+ mbedtls_test_mock_socket client;
+ mbedtls_test_mock_socket server;
size_t written, read;
int send_ret, recv_ret;
mbedtls_ssl_send_t *send;
@@ -2253,11 +243,11 @@
unsigned i;
if (blocking == 0) {
- send = mbedtls_mock_tcp_send_nb;
- recv = mbedtls_mock_tcp_recv_nb;
+ send = mbedtls_test_mock_tcp_send_nb;
+ recv = mbedtls_test_mock_tcp_recv_nb;
} else {
- send = mbedtls_mock_tcp_send_b;
- recv = mbedtls_mock_tcp_recv_b;
+ send = mbedtls_test_mock_tcp_send_b;
+ recv = mbedtls_test_mock_tcp_recv_b;
}
mbedtls_mock_socket_init(&client);
@@ -2270,7 +260,7 @@
}
/* Make sure that sending a message takes a few iterations. */
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server, BUFLEN));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server, BUFLEN));
/* Send the message to the server */
send_ret = recv_ret = 1;
@@ -2320,14 +310,14 @@
exit:
- mbedtls_mock_socket_close(&client);
- mbedtls_mock_socket_close(&server);
+ mbedtls_test_mock_socket_close(&client);
+ mbedtls_test_mock_socket_close(&server);
}
/* END_CASE */
/*
- * Test if the implementation of `mbedtls_mock_socket` related functions can
- * send messages in both direction at the same time (with the I/O calls
+ * Test if the implementation of `mbedtls_test_mock_socket` related functions
+ * can send messages in both direction at the same time (with the I/O calls
* interleaving).
*/
@@ -2339,8 +329,8 @@
enum { BUFLEN = MSGLEN / 5 };
unsigned char message[ROUNDS][MSGLEN];
unsigned char received[ROUNDS][MSGLEN];
- mbedtls_mock_socket client;
- mbedtls_mock_socket server;
+ mbedtls_test_mock_socket client;
+ mbedtls_test_mock_socket server;
size_t written[ROUNDS];
size_t read[ROUNDS];
int send_ret[ROUNDS];
@@ -2350,11 +340,11 @@
mbedtls_ssl_recv_t *recv;
if (blocking == 0) {
- send = mbedtls_mock_tcp_send_nb;
- recv = mbedtls_mock_tcp_recv_nb;
+ send = mbedtls_test_mock_tcp_send_nb;
+ recv = mbedtls_test_mock_tcp_recv_nb;
} else {
- send = mbedtls_mock_tcp_send_b;
- recv = mbedtls_mock_tcp_recv_b;
+ send = mbedtls_test_mock_tcp_send_b;
+ recv = mbedtls_test_mock_tcp_recv_b;
}
mbedtls_mock_socket_init(&client);
@@ -2369,7 +359,8 @@
}
/* Make sure that sending a message takes a few iterations. */
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server, BUFLEN));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server,
+ BUFLEN));
/* Send the message from both sides, interleaving. */
progress = 1;
@@ -2380,7 +371,7 @@
/* This loop does not stop as long as there was a successful write or read
* of at least one byte on either side. */
while (progress != 0) {
- mbedtls_mock_socket *socket;
+ mbedtls_test_mock_socket *socket;
for (i = 0; i < ROUNDS; i++) {
/* First sending is from the client */
@@ -2447,134 +438,134 @@
exit:
- mbedtls_mock_socket_close(&client);
- mbedtls_mock_socket_close(&server);
+ mbedtls_test_mock_socket_close(&client);
+ mbedtls_test_mock_socket_close(&server);
}
/* END_CASE */
/* BEGIN_CASE */
void ssl_message_queue_sanity()
{
- mbedtls_test_message_queue queue;
+ mbedtls_test_ssl_message_queue queue;
/* Trying to push/pull to an empty queue */
- TEST_ASSERT(mbedtls_test_message_queue_push_info(NULL, 1)
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(NULL, 1)
== MBEDTLS_TEST_ERROR_ARG_NULL);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(NULL, 1)
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(NULL, 1)
== MBEDTLS_TEST_ERROR_ARG_NULL);
- TEST_ASSERT(mbedtls_test_message_queue_setup(&queue, 3) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_setup(&queue, 3) == 0);
TEST_ASSERT(queue.capacity == 3);
TEST_ASSERT(queue.num == 0);
exit:
- mbedtls_test_message_queue_free(&queue);
+ mbedtls_test_ssl_message_queue_free(&queue);
}
/* END_CASE */
/* BEGIN_CASE */
void ssl_message_queue_basic()
{
- mbedtls_test_message_queue queue;
+ mbedtls_test_ssl_message_queue queue;
- TEST_ASSERT(mbedtls_test_message_queue_setup(&queue, 3) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_setup(&queue, 3) == 0);
/* Sanity test - 3 pushes and 3 pops with sufficient space */
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 1) == 1);
TEST_ASSERT(queue.capacity == 3);
TEST_ASSERT(queue.num == 1);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 1) == 1);
TEST_ASSERT(queue.capacity == 3);
TEST_ASSERT(queue.num == 2);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 2) == 2);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 2) == 2);
TEST_ASSERT(queue.capacity == 3);
TEST_ASSERT(queue.num == 3);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 2) == 2);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 2) == 2);
exit:
- mbedtls_test_message_queue_free(&queue);
+ mbedtls_test_ssl_message_queue_free(&queue);
}
/* END_CASE */
/* BEGIN_CASE */
void ssl_message_queue_overflow_underflow()
{
- mbedtls_test_message_queue queue;
+ mbedtls_test_ssl_message_queue queue;
- TEST_ASSERT(mbedtls_test_message_queue_setup(&queue, 3) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_setup(&queue, 3) == 0);
/* 4 pushes (last one with an error), 4 pops (last one with an error) */
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 2) == 2);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 3)
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 2) == 2);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 3)
== MBEDTLS_ERR_SSL_WANT_WRITE);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 2) == 2);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 2) == 2);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 1)
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 1)
== MBEDTLS_ERR_SSL_WANT_READ);
exit:
- mbedtls_test_message_queue_free(&queue);
+ mbedtls_test_ssl_message_queue_free(&queue);
}
/* END_CASE */
/* BEGIN_CASE */
void ssl_message_queue_interleaved()
{
- mbedtls_test_message_queue queue;
+ mbedtls_test_ssl_message_queue queue;
- TEST_ASSERT(mbedtls_test_message_queue_setup(&queue, 3) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_setup(&queue, 3) == 0);
/* Interleaved test - [2 pushes, 1 pop] twice, and then two pops
* (to wrap around the buffer) */
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 2) == 2);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 3) == 3);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 2) == 2);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 3) == 3);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 1) == 1);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 2) == 2);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 1) == 1);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 2) == 2);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 5) == 5);
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, 8) == 8);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 5) == 5);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, 8) == 8);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 3) == 3);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 3) == 3);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 5) == 5);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 5) == 5);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, 8) == 8);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, 8) == 8);
exit:
- mbedtls_test_message_queue_free(&queue);
+ mbedtls_test_ssl_message_queue_free(&queue);
}
/* END_CASE */
/* BEGIN_CASE */
void ssl_message_queue_insufficient_buffer()
{
- mbedtls_test_message_queue queue;
+ mbedtls_test_ssl_message_queue queue;
size_t message_len = 10;
size_t buffer_len = 5;
- TEST_ASSERT(mbedtls_test_message_queue_setup(&queue, 1) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_setup(&queue, 1) == 0);
/* Popping without a sufficient buffer */
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&queue, message_len)
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&queue, message_len)
== (int) message_len);
- TEST_ASSERT(mbedtls_test_message_queue_pop_info(&queue, buffer_len)
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_pop_info(&queue, buffer_len)
== (int) buffer_len);
exit:
- mbedtls_test_message_queue_free(&queue);
+ mbedtls_test_ssl_message_queue_free(&queue);
}
/* END_CASE */
@@ -2583,44 +574,50 @@
{
enum { MSGLEN = 10 };
unsigned char message[MSGLEN] = { 0 }, received[MSGLEN];
- mbedtls_mock_socket client, server;
- mbedtls_test_message_queue server_queue, client_queue;
+ mbedtls_test_mock_socket client, server;
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
/* Send with a NULL context */
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(NULL, message, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(NULL, message, MSGLEN)
== MBEDTLS_TEST_ERROR_CONTEXT_ERROR);
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(NULL, message, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(NULL, message, MSGLEN)
== MBEDTLS_TEST_ERROR_CONTEXT_ERROR);
- TEST_ASSERT(mbedtls_message_socket_setup(&server_queue, &client_queue, 1,
- &server,
- &server_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&server_queue,
+ &client_queue, 1,
+ &server,
+ &server_context) == 0);
- TEST_ASSERT(mbedtls_message_socket_setup(&client_queue, &server_queue, 1,
- &client,
- &client_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&client_queue,
+ &server_queue, 1,
+ &client,
+ &client_context) == 0);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN)
== MBEDTLS_TEST_ERROR_SEND_FAILED);
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MBEDTLS_ERR_SSL_WANT_READ);
/* Push directly to a queue to later simulate a disconnected behavior */
- TEST_ASSERT(mbedtls_test_message_queue_push_info(&server_queue, MSGLEN)
+ TEST_ASSERT(mbedtls_test_ssl_message_queue_push_info(&server_queue,
+ MSGLEN)
== MSGLEN);
/* Test if there's an error when trying to read from a disconnected
* socket */
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MBEDTLS_TEST_ERROR_RECV_FAILED);
exit:
- mbedtls_message_socket_close(&server_context);
- mbedtls_message_socket_close(&client_context);
+ mbedtls_test_message_socket_close(&server_context);
+ mbedtls_test_message_socket_close(&client_context);
}
/* END_CASE */
@@ -2629,52 +626,57 @@
{
enum { MSGLEN = 10 };
unsigned char message[MSGLEN], received[MSGLEN];
- mbedtls_mock_socket client, server;
+ mbedtls_test_mock_socket client, server;
unsigned i;
- mbedtls_test_message_queue server_queue, client_queue;
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
- TEST_ASSERT(mbedtls_message_socket_setup(&server_queue, &client_queue, 1,
- &server,
- &server_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&server_queue,
+ &client_queue, 1,
+ &server,
+ &server_context) == 0);
- TEST_ASSERT(mbedtls_message_socket_setup(&client_queue, &server_queue, 1,
- &client,
- &client_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&client_queue,
+ &server_queue, 1,
+ &client,
+ &client_context) == 0);
/* Fill up the buffer with structured data so that unwanted changes
* can be detected */
for (i = 0; i < MSGLEN; i++) {
message[i] = i & 0xFF;
}
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server,
- MSGLEN));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server,
+ MSGLEN));
/* Send the message to the server */
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN)
+ == MSGLEN);
/* Read from the server */
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
memset(received, 0, MSGLEN);
/* Send the message to the client */
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&server_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&server_context, message,
+ MSGLEN) == MSGLEN);
/* Read from the client */
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&client_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&client_context, received,
+ MSGLEN)
== MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
exit:
- mbedtls_message_socket_close(&server_context);
- mbedtls_message_socket_close(&client_context);
+ mbedtls_test_message_socket_close(&server_context);
+ mbedtls_test_message_socket_close(&client_context);
}
/* END_CASE */
@@ -2683,55 +685,62 @@
{
enum { MSGLEN = 10 };
unsigned char message[MSGLEN], received[MSGLEN];
- mbedtls_mock_socket client, server;
+ mbedtls_test_mock_socket client, server;
unsigned i;
- mbedtls_test_message_queue server_queue, client_queue;
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
- TEST_ASSERT(mbedtls_message_socket_setup(&server_queue, &client_queue, 2,
- &server,
- &server_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&server_queue,
+ &client_queue, 2,
+ &server,
+ &server_context) == 0);
- TEST_ASSERT(mbedtls_message_socket_setup(&client_queue, &server_queue, 2,
- &client,
- &client_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&client_queue,
+ &server_queue, 2,
+ &client,
+ &client_context) == 0);
/* Fill up the buffer with structured data so that unwanted changes
* can be detected */
for (i = 0; i < MSGLEN; i++) {
message[i] = i & 0xFF;
}
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server,
- MSGLEN*2));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server,
+ MSGLEN*2));
/* Send three message to the server, last one with an error */
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN - 1) == MSGLEN - 1);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN - 1)
+ == MSGLEN - 1);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN)
+ == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN)
== MBEDTLS_ERR_SSL_WANT_WRITE);
/* Read three messages from the server, last one with an error */
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received,
- MSGLEN - 1) == MSGLEN - 1);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN - 1)
+ == MSGLEN - 1);
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MBEDTLS_ERR_SSL_WANT_READ);
exit:
- mbedtls_message_socket_close(&server_context);
- mbedtls_message_socket_close(&client_context);
+ mbedtls_test_message_socket_close(&server_context);
+ mbedtls_test_message_socket_close(&client_context);
}
/* END_CASE */
@@ -2740,46 +749,50 @@
{
enum { MSGLEN = 10 };
unsigned char message[MSGLEN], received[MSGLEN];
- mbedtls_mock_socket client, server;
+ mbedtls_test_mock_socket client, server;
unsigned i;
- mbedtls_test_message_queue server_queue, client_queue;
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
- TEST_ASSERT(mbedtls_message_socket_setup(&server_queue, &client_queue, 2,
- &server,
- &server_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&server_queue,
+ &client_queue, 2,
+ &server,
+ &server_context) == 0);
- TEST_ASSERT(mbedtls_message_socket_setup(&client_queue, &server_queue, 2,
- &client,
- &client_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&client_queue,
+ &server_queue, 2,
+ &client,
+ &client_context) == 0);
/* Fill up the buffer with structured data so that unwanted changes
* can be detected */
for (i = 0; i < MSGLEN; i++) {
message[i] = i & 0xFF;
}
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server,
- MSGLEN));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server,
+ MSGLEN));
/* Send two message to the server, second one with an error */
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN)
+ == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN)
== MBEDTLS_TEST_ERROR_SEND_FAILED);
/* Read the only message from the server */
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
exit:
- mbedtls_message_socket_close(&server_context);
- mbedtls_message_socket_close(&client_context);
+ mbedtls_test_message_socket_close(&server_context);
+ mbedtls_test_message_socket_close(&client_context);
}
/* END_CASE */
@@ -2788,20 +801,22 @@
{
enum { MSGLEN = 10 };
unsigned char message[MSGLEN], received[MSGLEN];
- mbedtls_mock_socket client, server;
+ mbedtls_test_mock_socket client, server;
unsigned i;
- mbedtls_test_message_queue server_queue, client_queue;
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
- TEST_ASSERT(mbedtls_message_socket_setup(&server_queue, &client_queue, 2,
- &server,
- &server_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&server_queue,
+ &client_queue, 2,
+ &server,
+ &server_context) == 0);
- TEST_ASSERT(mbedtls_message_socket_setup(&client_queue, &server_queue, 2,
- &client,
- &client_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&client_queue,
+ &server_queue, 2,
+ &client,
+ &client_context) == 0);
memset(received, 0, MSGLEN);
/* Fill up the buffer with structured data so that unwanted changes
@@ -2809,17 +824,20 @@
for (i = 0; i < MSGLEN; i++) {
message[i] = i & 0xFF;
}
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server,
- 2 * MSGLEN));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server,
+ 2 * MSGLEN));
/* Send two messages to the server, the second one small enough to fit in the
* receiver's buffer. */
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN / 2) == MSGLEN / 2);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN)
+ == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN / 2)
+ == MSGLEN / 2);
/* Read a truncated message from the server */
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN/2)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN/2)
== MSGLEN/2);
/* Test that the first half of the message is valid, and second one isn't */
@@ -2829,15 +847,16 @@
memset(received, 0, MSGLEN);
/* Read a full message from the server */
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN/2)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN/2)
== MSGLEN / 2);
/* Test that the first half of the message is valid */
TEST_ASSERT(memcmp(message, received, MSGLEN/2) == 0);
exit:
- mbedtls_message_socket_close(&server_context);
- mbedtls_message_socket_close(&client_context);
+ mbedtls_test_message_socket_close(&server_context);
+ mbedtls_test_message_socket_close(&client_context);
}
/* END_CASE */
@@ -2846,35 +865,39 @@
{
enum { MSGLEN = 10 };
unsigned char message[MSGLEN], received[MSGLEN];
- mbedtls_mock_socket client, server;
+ mbedtls_test_mock_socket client, server;
unsigned i;
- mbedtls_test_message_queue server_queue, client_queue;
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
- TEST_ASSERT(mbedtls_message_socket_setup(&server_queue, &client_queue, 1,
- &server,
- &server_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&server_queue,
+ &client_queue, 1,
+ &server,
+ &server_context) == 0);
- TEST_ASSERT(mbedtls_message_socket_setup(&client_queue, &server_queue, 1,
- &client,
- &client_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&client_queue,
+ &server_queue, 1,
+ &client,
+ &client_context) == 0);
/* Fill up the buffer with structured data so that unwanted changes
* can be detected */
for (i = 0; i < MSGLEN; i++) {
message[i] = i & 0xFF;
}
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server,
- MSGLEN));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server,
+ MSGLEN));
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN)
+ == MSGLEN);
/* Force a read error by disconnecting the socket by hand */
server.status = 0;
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MBEDTLS_TEST_ERROR_RECV_FAILED);
/* Return to a valid state */
server.status = MBEDTLS_MOCK_SOCKET_CONNECTED;
@@ -2883,14 +906,15 @@
/* Test that even though the server tried to read once disconnected, the
* continuity is preserved */
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
exit:
- mbedtls_message_socket_close(&server_context);
- mbedtls_message_socket_close(&client_context);
+ mbedtls_test_message_socket_close(&server_context);
+ mbedtls_test_message_socket_close(&client_context);
}
/* END_CASE */
@@ -2899,55 +923,58 @@
{
enum { MSGLEN = 10 };
unsigned char message[MSGLEN], received[MSGLEN];
- mbedtls_mock_socket client, server;
+ mbedtls_test_mock_socket client, server;
unsigned i;
- mbedtls_test_message_queue server_queue, client_queue;
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
- TEST_ASSERT(mbedtls_message_socket_setup(&server_queue, &client_queue, 3,
- &server,
- &server_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&server_queue,
+ &client_queue, 3,
+ &server,
+ &server_context) == 0);
- TEST_ASSERT(mbedtls_message_socket_setup(&client_queue, &server_queue, 3,
- &client,
- &client_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&client_queue,
+ &server_queue, 3,
+ &client,
+ &client_context) == 0);
/* Fill up the buffer with structured data so that unwanted changes
* can be detected */
for (i = 0; i < MSGLEN; i++) {
message[i] = i & 0xFF;
}
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server,
- MSGLEN*3));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server,
+ MSGLEN*3));
/* Interleaved test - [2 sends, 1 read] twice, and then two reads
* (to wrap around the buffer) */
for (i = 0; i < 2; i++) {
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN) == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN) == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN) == MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
memset(received, 0, sizeof(received));
}
for (i = 0; i < 2; i++) {
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN) == MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
}
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MBEDTLS_ERR_SSL_WANT_READ);
exit:
- mbedtls_message_socket_close(&server_context);
- mbedtls_message_socket_close(&client_context);
+ mbedtls_test_message_socket_close(&server_context);
+ mbedtls_test_message_socket_close(&client_context);
}
/* END_CASE */
@@ -2956,53 +983,55 @@
{
enum { MSGLEN = 10 };
unsigned char message[MSGLEN], received[MSGLEN];
- mbedtls_mock_socket client, server;
+ mbedtls_test_mock_socket client, server;
unsigned i;
- mbedtls_test_message_queue server_queue, client_queue;
+ mbedtls_test_ssl_message_queue server_queue, client_queue;
mbedtls_test_message_socket_context server_context, client_context;
- mbedtls_message_socket_init(&server_context);
- mbedtls_message_socket_init(&client_context);
+ mbedtls_test_message_socket_init(&server_context);
+ mbedtls_test_message_socket_init(&client_context);
- TEST_ASSERT(mbedtls_message_socket_setup(&server_queue, &client_queue, 3,
- &server,
- &server_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&server_queue,
+ &client_queue, 3,
+ &server,
+ &server_context) == 0);
- TEST_ASSERT(mbedtls_message_socket_setup(&client_queue, &server_queue, 3,
- &client,
- &client_context) == 0);
+ TEST_ASSERT(mbedtls_test_message_socket_setup(&client_queue,
+ &server_queue, 3,
+ &client,
+ &client_context) == 0);
/* Fill up the buffer with structured data so that unwanted changes
* can be detected */
for (i = 0; i < MSGLEN; i++) {
message[i] = i & 0xFF;
}
- TEST_ASSERT(0 == mbedtls_mock_socket_connect(&client, &server,
- MSGLEN*3));
+ TEST_ASSERT(0 == mbedtls_test_mock_socket_connect(&client, &server,
+ MSGLEN*3));
/* Interleaved test - [2 sends, 1 read] twice, both ways, and then two reads
* (to wrap around the buffer) both ways. */
for (i = 0; i < 2; i++) {
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN) == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&client_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&client_context, message,
+ MSGLEN) == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&server_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&server_context, message,
+ MSGLEN) == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_send_msg(&server_context, message,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_send_msg(&server_context, message,
+ MSGLEN) == MSGLEN);
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN) == MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
memset(received, 0, sizeof(received));
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&client_context, received,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&client_context, received,
+ MSGLEN) == MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
@@ -3010,27 +1039,29 @@
}
for (i = 0; i < 2; i++) {
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN) == MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
memset(received, 0, sizeof(received));
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&client_context, received,
- MSGLEN) == MSGLEN);
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&client_context, received,
+ MSGLEN) == MSGLEN);
TEST_ASSERT(memcmp(message, received, MSGLEN) == 0);
memset(received, 0, sizeof(received));
}
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&server_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&server_context, received,
+ MSGLEN)
== MBEDTLS_ERR_SSL_WANT_READ);
- TEST_ASSERT(mbedtls_mock_tcp_recv_msg(&client_context, received, MSGLEN)
+ TEST_ASSERT(mbedtls_test_mock_tcp_recv_msg(&client_context, received,
+ MSGLEN)
== MBEDTLS_ERR_SSL_WANT_READ);
exit:
- mbedtls_message_socket_close(&server_context);
- mbedtls_message_socket_close(&client_context);
+ mbedtls_test_message_socket_close(&server_context);
+ mbedtls_test_message_socket_close(&client_context);
}
/* END_CASE */
@@ -3101,10 +1132,10 @@
mbedtls_ssl_init(&ssl);
mbedtls_ssl_transform_init(&t0);
mbedtls_ssl_transform_init(&t1);
- TEST_ASSERT(build_transforms(&t0, &t1, cipher_type, hash_id,
- etm, tag_mode, ver,
- (size_t) cid0_len,
- (size_t) cid1_len) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_build_transforms(&t0, &t1, cipher_type, hash_id,
+ etm, tag_mode, ver,
+ (size_t) cid0_len,
+ (size_t) cid1_len) == 0);
TEST_ASSERT((buf = mbedtls_calloc(1, buflen)) != NULL);
@@ -3250,10 +1281,10 @@
mbedtls_ssl_init(&ssl);
mbedtls_ssl_transform_init(&t0);
mbedtls_ssl_transform_init(&t1);
- TEST_ASSERT(build_transforms(&t0, &t1, cipher_type, hash_id,
- etm, tag_mode, ver,
- (size_t) cid0_len,
- (size_t) cid1_len) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_build_transforms(&t0, &t1, cipher_type, hash_id,
+ etm, tag_mode, ver,
+ (size_t) cid0_len,
+ (size_t) cid1_len) == 0);
TEST_ASSERT((buf = mbedtls_calloc(1, buflen)) != NULL);
@@ -3402,10 +1433,10 @@
mbedtls_ssl_transform_init(&t1);
/* Set up transforms with dummy keys */
- TEST_ASSERT(build_transforms(&t0, &t1, cipher_type, hash_id,
- 0, trunc_hmac,
- MBEDTLS_SSL_MINOR_VERSION_3,
- 0, 0) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_build_transforms(&t0, &t1, cipher_type, hash_id,
+ 0, trunc_hmac,
+ MBEDTLS_SSL_MINOR_VERSION_3,
+ 0, 0) == 0);
/* Determine padding/plaintext length */
TEST_ASSERT(length_selector >= -2 && length_selector <= 255);
@@ -3626,10 +1657,12 @@
/* Check sanity of test parameters. */
TEST_ASSERT(client_secret->len == server_secret->len);
- TEST_ASSERT(expected_client_write_iv->len == expected_server_write_iv->len &&
- expected_client_write_iv->len == (size_t) desired_iv_len);
- TEST_ASSERT(expected_client_write_key->len == expected_server_write_key->len &&
- expected_client_write_key->len == (size_t) desired_key_len);
+ TEST_ASSERT(
+ expected_client_write_iv->len == expected_server_write_iv->len &&
+ expected_client_write_iv->len == (size_t) desired_iv_len);
+ TEST_ASSERT(
+ expected_client_write_key->len == expected_server_write_key->len &&
+ expected_client_write_key->len == (size_t) desired_key_len);
TEST_ASSERT(mbedtls_ssl_tls1_3_make_traffic_keys(
(mbedtls_md_type_t) hash_alg,
@@ -3760,7 +1793,8 @@
mbedtls_ssl_session_init(&restored);
/* Prepare a dummy session to work on */
- TEST_ASSERT(ssl_populate_session(&original, ticket_len, crt_file) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_populate_session(
+ &original, ticket_len, crt_file) == 0);
/* Serialize it */
TEST_ASSERT(mbedtls_ssl_session_save(&original, NULL, 0, &len)
@@ -3858,7 +1892,8 @@
mbedtls_ssl_session_init(&session);
/* Prepare a dummy session to work on */
- TEST_ASSERT(ssl_populate_session(&session, ticket_len, crt_file) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_populate_session(
+ &session, ticket_len, crt_file) == 0);
/* Get desired buffer size for serializing */
TEST_ASSERT(mbedtls_ssl_session_save(&session, NULL, 0, &len0)
@@ -3908,7 +1943,8 @@
mbedtls_ssl_session_init(&session);
/* Prepare dummy session and get serialized size */
- TEST_ASSERT(ssl_populate_session(&session, ticket_len, crt_file) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_populate_session(
+ &session, ticket_len, crt_file) == 0);
TEST_ASSERT(mbedtls_ssl_session_save(&session, NULL, 0, &good_len)
== MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
@@ -3943,7 +1979,8 @@
mbedtls_ssl_session_init(&session);
/* Prepare serialized session data */
- TEST_ASSERT(ssl_populate_session(&session, ticket_len, crt_file) == 0);
+ TEST_ASSERT(mbedtls_test_ssl_populate_session(
+ &session, ticket_len, crt_file) == 0);
TEST_ASSERT(mbedtls_ssl_session_save(&session, NULL, 0, &good_len)
== MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
TEST_ASSERT((good_buf = mbedtls_calloc(1, good_len)) != NULL);
@@ -4036,22 +2073,22 @@
void mbedtls_endpoint_sanity(int endpoint_type)
{
enum { BUFFSIZE = 1024 };
- mbedtls_endpoint ep;
+ mbedtls_test_ssl_endpoint ep;
int ret = -1;
- ret = mbedtls_endpoint_init(NULL, endpoint_type, MBEDTLS_PK_RSA,
- NULL, NULL, NULL, NULL);
+ ret = mbedtls_test_ssl_endpoint_init(NULL, endpoint_type, MBEDTLS_PK_RSA,
+ NULL, NULL, NULL, NULL);
TEST_ASSERT(MBEDTLS_ERR_SSL_BAD_INPUT_DATA == ret);
- ret = mbedtls_endpoint_certificate_init(NULL, MBEDTLS_PK_RSA);
+ ret = mbedtls_test_ssl_endpoint_certificate_init(NULL, MBEDTLS_PK_RSA);
TEST_ASSERT(MBEDTLS_ERR_SSL_BAD_INPUT_DATA == ret);
- ret = mbedtls_endpoint_init(&ep, endpoint_type, MBEDTLS_PK_RSA,
- NULL, NULL, NULL, NULL);
+ ret = mbedtls_test_ssl_endpoint_init(&ep, endpoint_type, MBEDTLS_PK_RSA,
+ NULL, NULL, NULL, NULL);
TEST_ASSERT(ret == 0);
exit:
- mbedtls_endpoint_free(&ep, NULL);
+ mbedtls_test_ssl_endpoint_free(&ep, NULL);
}
/* END_CASE */
@@ -4059,30 +2096,32 @@
void move_handshake_to_state(int endpoint_type, int state, int need_pass)
{
enum { BUFFSIZE = 1024 };
- mbedtls_endpoint base_ep, second_ep;
+ mbedtls_test_ssl_endpoint base_ep, second_ep;
int ret = -1;
mbedtls_platform_zeroize(&base_ep, sizeof(base_ep));
mbedtls_platform_zeroize(&second_ep, sizeof(second_ep));
- ret = mbedtls_endpoint_init(&base_ep, endpoint_type, MBEDTLS_PK_RSA,
- NULL, NULL, NULL, NULL);
+ ret = mbedtls_test_ssl_endpoint_init(&base_ep, endpoint_type,
+ MBEDTLS_PK_RSA,
+ NULL, NULL, NULL, NULL);
TEST_ASSERT(ret == 0);
- ret = mbedtls_endpoint_init(&second_ep,
- (endpoint_type == MBEDTLS_SSL_IS_SERVER) ?
- MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
- MBEDTLS_PK_RSA, NULL, NULL, NULL, NULL);
+ ret = mbedtls_test_ssl_endpoint_init(
+ &second_ep,
+ (endpoint_type == MBEDTLS_SSL_IS_SERVER) ?
+ MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
+ MBEDTLS_PK_RSA, NULL, NULL, NULL, NULL);
TEST_ASSERT(ret == 0);
- ret = mbedtls_mock_socket_connect(&(base_ep.socket),
- &(second_ep.socket),
- BUFFSIZE);
+ ret = mbedtls_test_mock_socket_connect(&(base_ep.socket),
+ &(second_ep.socket),
+ BUFFSIZE);
TEST_ASSERT(ret == 0);
- ret = mbedtls_move_handshake_to_state(&(base_ep.ssl),
- &(second_ep.ssl),
- state);
+ ret = mbedtls_test_move_handshake_to_state(&(base_ep.ssl),
+ &(second_ep.ssl),
+ state);
if (need_pass) {
TEST_ASSERT(ret == 0);
TEST_ASSERT(base_ep.ssl.state == state);
@@ -4092,8 +2131,8 @@
}
exit:
- mbedtls_endpoint_free(&base_ep, NULL);
- mbedtls_endpoint_free(&second_ep, NULL);
+ mbedtls_test_ssl_endpoint_free(&base_ep, NULL);
+ mbedtls_test_ssl_endpoint_free(&second_ep, NULL);
}
/* END_CASE */
@@ -4102,8 +2141,8 @@
int server_min_version, int server_max_version,
int expected_negotiated_version)
{
- handshake_test_options options;
- init_handshake_options(&options);
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_init_handshake_options(&options);
options.client_min_version = client_min_version;
options.client_max_version = client_max_version;
@@ -4120,7 +2159,7 @@
options.expected_cli_fragments = 2;
options.expected_srv_fragments = 2;
}
- perform_handshake(&options);
+ mbedtls_test_ssl_perform_handshake(&options);
/* The goto below is used to avoid an "unused label" warning.*/
goto exit;
@@ -4130,15 +2169,15 @@
/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:!MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C:MBEDTLS_SHA256_C */
void handshake_psk_cipher(char *cipher, int pk_alg, data_t *psk_str, int dtls)
{
- handshake_test_options options;
- init_handshake_options(&options);
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_init_handshake_options(&options);
options.cipher = cipher;
options.dtls = dtls;
options.psk_str = psk_str;
options.pk_alg = pk_alg;
- perform_handshake(&options);
+ mbedtls_test_ssl_perform_handshake(&options);
/* The goto below is used to avoid an "unused label" warning.*/
goto exit;
@@ -4160,8 +2199,8 @@
int expected_cli_fragments,
int expected_srv_fragments, int dtls)
{
- handshake_test_options options;
- init_handshake_options(&options);
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_init_handshake_options(&options);
options.mfl = mfl;
options.cli_msg_len = cli_msg_len;
@@ -4170,7 +2209,7 @@
options.expected_srv_fragments = expected_srv_fragments;
options.dtls = dtls;
- perform_handshake(&options);
+ mbedtls_test_ssl_perform_handshake(&options);
/* The goto below is used to avoid an "unused label" warning.*/
goto exit;
}
@@ -4203,12 +2242,12 @@
/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:!MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_SSL_CONTEXT_SERIALIZATION:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C:MBEDTLS_SHA256_C:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
void handshake_serialization()
{
- handshake_test_options options;
- init_handshake_options(&options);
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_init_handshake_options(&options);
options.serialize = 1;
options.dtls = 1;
- perform_handshake(&options);
+ mbedtls_test_ssl_perform_handshake(&options);
/* The goto below is used to avoid an "unused label" warning.*/
goto exit;
}
@@ -4219,14 +2258,14 @@
int expected_srv_hs_fragmentation,
int expected_cli_hs_fragmentation)
{
- handshake_test_options options;
- log_pattern srv_pattern, cli_pattern;
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_ssl_log_pattern srv_pattern, cli_pattern;
srv_pattern.pattern = cli_pattern.pattern = "found fragmented DTLS handshake";
srv_pattern.counter = 0;
cli_pattern.counter = 0;
- init_handshake_options(&options);
+ mbedtls_test_init_handshake_options(&options);
options.dtls = 1;
options.mfl = mfl;
/* Set cipher to one using CBC so that record splitting can be tested */
@@ -4234,10 +2273,10 @@
options.srv_auth_mode = MBEDTLS_SSL_VERIFY_REQUIRED;
options.srv_log_obj = &srv_pattern;
options.cli_log_obj = &cli_pattern;
- options.srv_log_fun = log_analyzer;
- options.cli_log_fun = log_analyzer;
+ options.srv_log_fun = mbedtls_test_ssl_log_analyzer;
+ options.cli_log_fun = mbedtls_test_ssl_log_analyzer;
- perform_handshake(&options);
+ mbedtls_test_ssl_perform_handshake(&options);
/* Test if the server received a fragmented handshake */
if (expected_srv_hs_fragmentation) {
@@ -4253,14 +2292,14 @@
/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:!MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C:MBEDTLS_SHA256_C:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
void renegotiation(int legacy_renegotiation)
{
- handshake_test_options options;
- init_handshake_options(&options);
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_init_handshake_options(&options);
options.renegotiate = 1;
options.legacy_renegotiation = legacy_renegotiation;
options.dtls = 1;
- perform_handshake(&options);
+ mbedtls_test_ssl_perform_handshake(&options);
/* The goto below is used to avoid an "unused label" warning.*/
goto exit;
}
@@ -4270,8 +2309,8 @@
void resize_buffers(int mfl, int renegotiation, int legacy_renegotiation,
int serialize, int dtls, char *cipher)
{
- handshake_test_options options;
- init_handshake_options(&options);
+ mbedtls_test_handshake_test_options options;
+ mbedtls_test_init_handshake_options(&options);
options.mfl = mfl;
options.cipher = cipher;
@@ -4281,7 +2320,7 @@
options.dtls = dtls;
options.resize_buffers = 1;
- perform_handshake(&options);
+ mbedtls_test_ssl_perform_handshake(&options);
/* The goto below is used to avoid an "unused label" warning.*/
goto exit;
}
@@ -4313,7 +2352,7 @@
void raw_key_agreement_fail(int bad_server_ecdhe_key)
{
enum { BUFFSIZE = 17000 };
- mbedtls_endpoint client, server;
+ mbedtls_test_ssl_endpoint client, server;
mbedtls_psa_stats_t stats;
size_t free_slots_before = -1;
@@ -4326,22 +2365,22 @@
/* Client side, force SECP256R1 to make one key bitflip fail
* the raw key agreement. Flipping the first byte makes the
* required 0x04 identifier invalid. */
- TEST_EQUAL(mbedtls_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT,
- MBEDTLS_PK_ECDSA, NULL, NULL,
- NULL, curve_list), 0);
+ TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT,
+ MBEDTLS_PK_ECDSA, NULL, NULL,
+ NULL, curve_list), 0);
/* Server side */
- TEST_EQUAL(mbedtls_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER,
- MBEDTLS_PK_ECDSA, NULL, NULL,
- NULL, NULL), 0);
+ TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER,
+ MBEDTLS_PK_ECDSA, NULL, NULL,
+ NULL, NULL), 0);
- TEST_EQUAL(mbedtls_mock_socket_connect(&(client.socket),
- &(server.socket),
- BUFFSIZE), 0);
+ TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client.socket),
+ &(server.socket),
+ BUFFSIZE), 0);
- TEST_EQUAL(mbedtls_move_handshake_to_state(&(client.ssl),
- &(server.ssl),
- MBEDTLS_SSL_CLIENT_KEY_EXCHANGE)
+ TEST_EQUAL(mbedtls_test_move_handshake_to_state(
+ &(client.ssl), &(server.ssl),
+ MBEDTLS_SSL_CLIENT_KEY_EXCHANGE)
, 0);
mbedtls_psa_get_stats(&stats);
@@ -4355,9 +2394,8 @@
(client.ssl).handshake->ecdh_psa_peerkey[0] ^= 0x02;
}
- TEST_EQUAL(mbedtls_move_handshake_to_state(&(client.ssl),
- &(server.ssl),
- MBEDTLS_SSL_HANDSHAKE_OVER),
+ TEST_EQUAL(mbedtls_test_move_handshake_to_state(
+ &(client.ssl), &(server.ssl), MBEDTLS_SSL_HANDSHAKE_OVER),
bad_server_ecdhe_key ? MBEDTLS_ERR_SSL_HW_ACCEL_FAILED : 0);
mbedtls_psa_get_stats(&stats);
@@ -4369,8 +2407,8 @@
}
exit:
- mbedtls_endpoint_free(&client, NULL);
- mbedtls_endpoint_free(&server, NULL);
+ mbedtls_test_ssl_endpoint_free(&client, NULL);
+ mbedtls_test_ssl_endpoint_free(&server, NULL);
USE_PSA_DONE();
}
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index 69f8a84..4b57192 100644
--- a/tests/suites/test_suite_version.data
+++ b/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
Check compile time library version
-check_compiletime_version:"2.28.2"
+check_compiletime_version:"2.28.3"
Check runtime library version
-check_runtime_version:"2.28.2"
+check_runtime_version:"2.28.3"
Check for MBEDTLS_VERSION_C
check_feature:"MBEDTLS_VERSION_C":0
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 88ffe1b..b6df742 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -246,6 +246,7 @@
<ClInclude Include="..\..\tests\include\test\psa_exercise_key.h" />
<ClInclude Include="..\..\tests\include\test\psa_helpers.h" />
<ClInclude Include="..\..\tests\include\test\random.h" />
+ <ClInclude Include="..\..\tests\include\test\ssl_helpers.h" />
<ClInclude Include="..\..\tests\include\test\drivers\aead.h" />
<ClInclude Include="..\..\tests\include\test\drivers\cipher.h" />
<ClInclude Include="..\..\tests\include\test\drivers\config_test_driver.h" />