Merge pull request #8096 from davidhorstmann-arm/2.28-initialize-struct-get-other-name
[Backport 2.28] Coverity fix: Set `type_id` in `x509_get_other_name()`
diff --git a/.travis.yml b/.travis.yml
index ada8fc5..0ffe249 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,6 +34,10 @@
packages:
- clang-10
- gnutls-bin
+ env:
+ # Platform tests have an allocation that returns null
+ - ASAN_OPTIONS="allocator_may_return_null=1"
+ - MSAN_OPTIONS="allocator_may_return_null=1"
script:
# Do a manual build+test sequence rather than using all.sh,
# because there's no all.sh component that does what we want,
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a7bf198..8bbcdcb 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -84,8 +84,14 @@
License and Copyright
---------------------
-All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible. For licensing details, please see the [License section of the README](README.md#License).
+Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license.
+
+Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. This enables LTS (Long Term Support) branches of the software to be provided under either the Apache-2.0 or GPL-2.0-or-later licenses.
+
+All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible.
The copyright on contributions is retained by the original authors of the code. Where possible for new files, this should be noted in a comment at the top of the file in the form: "Copyright The Mbed TLS Contributors".
-When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and be subject to the same Apache 2.0 license. This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line.
+When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and is submitted under both the Apache-2.0 AND GPL-2.0-or-later licenses.
+
+This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line.
diff --git a/ChangeLog.d/fix-a-few-unchecked-return.txt b/ChangeLog.d/fix-a-few-unchecked-return.txt
new file mode 100644
index 0000000..aadde36
--- /dev/null
+++ b/ChangeLog.d/fix-a-few-unchecked-return.txt
@@ -0,0 +1,3 @@
+Bugfix
+ * Fix some cases where mbedtls_mpi_mod_exp, RSA key construction or ECDSA
+ signature can silently return an incorrect result in low memory conditions.
diff --git a/ChangeLog.d/fix-iar-compiler-warnings.txt b/ChangeLog.d/fix-iar-compiler-warnings.txt
new file mode 100644
index 0000000..50f1dca
--- /dev/null
+++ b/ChangeLog.d/fix-iar-compiler-warnings.txt
@@ -0,0 +1,2 @@
+Bugfix
+ * Fix IAR compiler warnings. Fixes #7873, #4300.
diff --git a/README.md b/README.md
index d5b6c12..875e6bf 100644
--- a/README.md
+++ b/README.md
@@ -249,7 +249,7 @@
License
-------
-Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license. Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. This enables LTS (Long Term Support) branches of the software to be provided under either the Apache-2.0 OR GPL-2.0-or-later licenses.
+Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license, and [the 'License and Copyright' section in the contributing guidelines](CONTRIBUTING.md#License-and-Copyright) for more information.
Contributing
------------
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index 2f22e3f..0fc2da0 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -51,4 +51,5 @@
"MBEDTLS_CHECK_RETURN_TYPICAL=" \
"MBEDTLS_CHECK_RETURN_OPTIONAL=" \
"MBEDTLS_PRINTF_ATTRIBUTE(a,b)=" \
+ "__DOXYGEN__" \
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 04acc1c..fa5ebd7 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -167,15 +167,47 @@
* This allows different allocators (self-implemented or provided) to be
* provided to the platform abstraction layer.
*
- * Enabling MBEDTLS_PLATFORM_MEMORY without the
+ * Enabling #MBEDTLS_PLATFORM_MEMORY without the
* MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
* "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
* free() function pointer at runtime.
*
- * Enabling MBEDTLS_PLATFORM_MEMORY and specifying
+ * Enabling #MBEDTLS_PLATFORM_MEMORY and specifying
* MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
* alternate function at compile time.
*
+ * An overview of how the value of mbedtls_calloc is determined:
+ *
+ * - if !MBEDTLS_PLATFORM_MEMORY
+ * - mbedtls_calloc = calloc
+ * - if MBEDTLS_PLATFORM_MEMORY
+ * - if (MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO):
+ * - mbedtls_calloc = MBEDTLS_PLATFORM_CALLOC_MACRO
+ * - if !(MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO):
+ * - Dynamic setup via mbedtls_platform_set_calloc_free is now possible with a default value MBEDTLS_PLATFORM_STD_CALLOC.
+ * - How is MBEDTLS_PLATFORM_STD_CALLOC handled?
+ * - if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS:
+ * - MBEDTLS_PLATFORM_STD_CALLOC is not set to anything;
+ * - MBEDTLS_PLATFORM_STD_MEM_HDR can be included if present;
+ * - if !MBEDTLS_PLATFORM_NO_STD_FUNCTIONS:
+ * - if MBEDTLS_PLATFORM_STD_CALLOC is present:
+ * - User-defined MBEDTLS_PLATFORM_STD_CALLOC is respected;
+ * - if !MBEDTLS_PLATFORM_STD_CALLOC:
+ * - MBEDTLS_PLATFORM_STD_CALLOC = calloc
+ *
+ * - At this point the presence of MBEDTLS_PLATFORM_STD_CALLOC is checked.
+ * - if !MBEDTLS_PLATFORM_STD_CALLOC
+ * - MBEDTLS_PLATFORM_STD_CALLOC = uninitialized_calloc
+ *
+ * - mbedtls_calloc = MBEDTLS_PLATFORM_STD_CALLOC.
+ *
+ * Defining MBEDTLS_PLATFORM_CALLOC_MACRO and #MBEDTLS_PLATFORM_STD_CALLOC at the same time is not possible.
+ * MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO must both be defined or undefined at the same time.
+ * #MBEDTLS_PLATFORM_STD_CALLOC and #MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used,
+ * dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases.
+ * An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer.
+ * An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything.
+ *
* Requires: MBEDTLS_PLATFORM_C
*
* Enable this layer to allow use of alternative memory allocators.
@@ -3798,8 +3830,29 @@
/* Platform options */
//#define MBEDTLS_PLATFORM_STD_MEM_HDR <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
-//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */
+
+/** \def MBEDTLS_PLATFORM_STD_CALLOC
+ *
+ * Default allocator to use, can be undefined.
+ * It must initialize the allocated buffer memory to zeroes.
+ * The size of the buffer is the product of the two parameters.
+ * The calloc function returns either a null pointer or a pointer to the allocated space.
+ * If the product is 0, the function may either return NULL or a valid pointer to an array of size 0 which is a valid input to the deallocation function.
+ * An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer.
+ * See the description of #MBEDTLS_PLATFORM_MEMORY for more details.
+ * The corresponding deallocation function is #MBEDTLS_PLATFORM_STD_FREE.
+ */
+//#define MBEDTLS_PLATFORM_STD_CALLOC calloc
+
+/** \def MBEDTLS_PLATFORM_STD_FREE
+ *
+ * Default free to use, can be undefined.
+ * NULL is a valid parameter, and the function must do nothing.
+ * A non-null parameter will always be a pointer previously returned by #MBEDTLS_PLATFORM_STD_CALLOC and not yet freed.
+ * An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything.
+ * See the description of #MBEDTLS_PLATFORM_MEMORY for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply).
+ */
+//#define MBEDTLS_PLATFORM_STD_FREE free
//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */
//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */
@@ -3812,10 +3865,10 @@
//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */
-/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
+/* To use the following function macros, MBEDTLS_PLATFORM_C must be enabled. */
/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
-//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */
-//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_CALLOC for requirements. */
+//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_FREE for requirements. */
//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */
//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
diff --git a/include/mbedtls/net_sockets.h b/include/mbedtls/net_sockets.h
index c8bcde0..6bcd920 100644
--- a/include/mbedtls/net_sockets.h
+++ b/include/mbedtls/net_sockets.h
@@ -283,6 +283,10 @@
* \brief Closes down the connection and free associated data
*
* \param ctx The context to close
+ *
+ * \note This function frees and clears data associated with the
+ * context but does not free the memory pointed to by \p ctx.
+ * This memory is the responsibility of the caller.
*/
void mbedtls_net_close(mbedtls_net_context *ctx);
@@ -290,6 +294,10 @@
* \brief Gracefully shutdown the connection and free associated data
*
* \param ctx The context to free
+ *
+ * \note This function frees and clears data associated with the
+ * context but does not free the memory pointed to by \p ctx.
+ * This memory is the responsibility of the caller.
*/
void mbedtls_net_free(mbedtls_net_context *ctx);
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index d6faa7e..c8c6e63 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -135,11 +135,22 @@
#endif
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
+/* Enable certain documented defines only when generating doxygen to avoid
+ * an "unrecognized define" error. */
+#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_CALLOC)
+#define MBEDTLS_PLATFORM_STD_CALLOC
+#endif
+
+#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_FREE)
+#define MBEDTLS_PLATFORM_STD_FREE
+#endif
/** \} name SECTION: Module settings */
/*
* The function pointers for calloc and free.
+ * Please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE
+ * in mbedtls_config.h for more information about behaviour and requirements.
*/
#if defined(MBEDTLS_PLATFORM_MEMORY)
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \
diff --git a/library/bignum.c b/library/bignum.c
index 5dca3a9..384b924 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -2121,8 +2121,9 @@
* and squarings. Firstly, when multiplying by an element of the window
* W[i], we do a constant-trace table lookup to obfuscate i. This leaves
* squarings as having a different memory access patterns from other
- * multiplications. So secondly, we put the accumulator X in the table as
- * well, and also do a constant-trace table lookup to multiply by X.
+ * multiplications. So secondly, we put the accumulator in the table as
+ * well, and also do a constant-trace table lookup to multiply by the
+ * accumulator which is W[x_index].
*
* This way, all multiplications take the form of a lookup-and-multiply.
* The number of lookup-and-multiply operations inside each iteration of
@@ -2135,19 +2136,16 @@
* observe both memory accesses and branches. However, branch prediction
* exploitation typically requires many traces of execution over the same
* data, which is defeated by randomized blinding.
- *
- * To achieve this, we make a copy of X and we use the table entry in each
- * calculation from this point on.
*/
const size_t x_index = 0;
mbedtls_mpi_init(&W[x_index]);
- mbedtls_mpi_copy(&W[x_index], X);
j = N->n + 1;
- /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
- * and mpi_montred() calls later. Here we ensure that W[1] and X are
- * large enough, and later we'll grow other W[i] to the same length.
- * They must not be shrunk midway through this function!
+ /* All W[i] including the accumulator must have at least N->n limbs for
+ * the mpi_montmul() and mpi_montred() calls later. Here we ensure that
+ * W[1] and the accumulator W[x_index] are large enough. later we'll grow
+ * other W[i] to the same length. They must not be shrunk midway through
+ * this function!
*/
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
@@ -2328,7 +2326,7 @@
/*
* Load the result in the output variable.
*/
- mbedtls_mpi_copy(X, &W[x_index]);
+ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
cleanup:
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 1f0b37d..3ede933 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -366,7 +366,7 @@
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->sig != NULL) {
- mbedtls_mpi_copy(r, pr);
+ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr));
}
#endif
@@ -457,7 +457,7 @@
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len));
MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len));
- mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len);
+ MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len));
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->det != NULL) {
diff --git a/library/rsa_internal.c b/library/rsa_internal.c
index 2ff51c3..41ceff0 100644
--- a/library/rsa_internal.c
+++ b/library/rsa_internal.c
@@ -126,7 +126,7 @@
}
for (; attempt < num_primes; ++attempt) {
- mbedtls_mpi_lset(&K, primes[attempt]);
+ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt]));
/* Check if gcd(K,N) = 1 */
MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 229f0d8..f45eb85 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -77,23 +77,51 @@
void *empty2 = mbedtls_calloc(0, 1);
void *buffer1 = mbedtls_calloc(1, 1);
void *buffer2 = mbedtls_calloc(1, 1);
+ unsigned int buffer_3_size = 256;
+ unsigned int buffer_4_size = 4097; /* Allocate more than the usual page size */
+ unsigned char *buffer3 = mbedtls_calloc(buffer_3_size, 1);
+ unsigned char *buffer4 = mbedtls_calloc(buffer_4_size, 1);
if (empty1 == NULL && empty2 == NULL) {
if (verbose) {
- mbedtls_printf(" CALLOC(0): passed (NULL)\n");
+ mbedtls_printf(" CALLOC(0,1): passed (NULL)\n");
}
} else if (empty1 == NULL || empty2 == NULL) {
if (verbose) {
- mbedtls_printf(" CALLOC(0): failed (mix of NULL and non-NULL)\n");
+ mbedtls_printf(" CALLOC(0,1): failed (mix of NULL and non-NULL)\n");
}
++failures;
} else if (empty1 == empty2) {
if (verbose) {
- mbedtls_printf(" CALLOC(0): passed (same non-null)\n");
+ mbedtls_printf(" CALLOC(0,1): passed (same non-null)\n");
}
} else {
if (verbose) {
- mbedtls_printf(" CALLOC(0): passed (distinct non-null)\n");
+ mbedtls_printf(" CALLOC(0,1): passed (distinct non-null)\n");
+ }
+ }
+
+ mbedtls_free(empty1);
+ mbedtls_free(empty2);
+
+ empty1 = mbedtls_calloc(1, 0);
+ empty2 = mbedtls_calloc(1, 0);
+ if (empty1 == NULL && empty2 == NULL) {
+ if (verbose) {
+ mbedtls_printf(" CALLOC(1,0): passed (NULL)\n");
+ }
+ } else if (empty1 == NULL || empty2 == NULL) {
+ if (verbose) {
+ mbedtls_printf(" CALLOC(1,0): failed (mix of NULL and non-NULL)\n");
+ }
+ ++failures;
+ } else if (empty1 == empty2) {
+ if (verbose) {
+ mbedtls_printf(" CALLOC(1,0): passed (same non-null)\n");
+ }
+ } else {
+ if (verbose) {
+ mbedtls_printf(" CALLOC(1,0): passed (distinct non-null)\n");
}
}
@@ -126,6 +154,28 @@
}
}
+ for (unsigned int i = 0; i < buffer_3_size; i++) {
+ if (buffer3[i] != 0) {
+ ++failures;
+ if (verbose) {
+ mbedtls_printf(" CALLOC(%u): failed (memory not initialized to 0)\n",
+ buffer_3_size);
+ }
+ break;
+ }
+ }
+
+ for (unsigned int i = 0; i < buffer_4_size; i++) {
+ if (buffer4[i] != 0) {
+ ++failures;
+ if (verbose) {
+ mbedtls_printf(" CALLOC(%u): failed (memory not initialized to 0)\n",
+ buffer_4_size);
+ }
+ break;
+ }
+ }
+
if (verbose) {
mbedtls_printf("\n");
}
@@ -133,6 +183,8 @@
mbedtls_free(empty2);
mbedtls_free(buffer1);
mbedtls_free(buffer2);
+ mbedtls_free(buffer3);
+ mbedtls_free(buffer4);
return failures;
}
#endif /* MBEDTLS_SELF_TEST */
diff --git a/tests/compat.sh b/tests/compat.sh
index 75d5461..9529975 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -128,10 +128,40 @@
printf " \tAlso available: GnuTLS (needs v3.2.15 or higher)\n"
printf " -M|--memcheck\tCheck memory leaks and errors.\n"
printf " -v|--verbose\tSet verbose output.\n"
+ printf " --list-test-case\tList all potential test cases (No Execution)\n"
printf " --outcome-file\tFile where test outcomes are written\n"
printf " \t(default: \$MBEDTLS_TEST_OUTCOME_FILE, none if empty)\n"
}
+# print_test_case <CLIENT> <SERVER> <STANDARD_CIPHER_SUITE>
+print_test_case() {
+ for i in $3; do
+ uniform_title $1 $2 $i
+ echo $TITLE
+ done
+}
+
+# list_test_case lists all potential test cases in compat.sh without execution
+list_test_case() {
+ for MODE in $MODES; do
+ for TYPE in $TYPES; do
+ for VERIFY in $VERIFIES; do
+ VERIF=$(echo $VERIFY | tr '[:upper:]' '[:lower:]')
+ reset_ciphersuites
+ add_common_ciphersuites
+ add_openssl_ciphersuites
+ add_gnutls_ciphersuites
+ add_mbedtls_ciphersuites
+ print_test_case m O "$O_CIPHERS"
+ print_test_case O m "$O_CIPHERS"
+ print_test_case m G "$G_CIPHERS"
+ print_test_case G m "$G_CIPHERS"
+ print_test_case m m "$M_CIPHERS"
+ done
+ done
+ done
+}
+
get_options() {
while [ $# -gt 0 ]; do
case "$1" in
@@ -159,6 +189,12 @@
-M|--memcheck)
MEMCHECK=1
;;
+ # Please check scripts/check_test_cases.py correspondingly
+ # if you have to modify option, --list-test-case
+ --list-test-case)
+ list_test_case
+ exit $?
+ ;;
--outcome-file)
shift; MBEDTLS_TEST_OUTCOME_FILE=$1
;;
@@ -1199,15 +1235,21 @@
fi
}
+# uniform_title <CLIENT> <SERVER> <STANDARD_CIPHER_SUITE>
+# $TITLE is considered as test case description for both --list-test-case and
+# MBEDTLS_TEST_OUTCOME_FILE. This function aims to control the format of
+# each test case description.
+uniform_title() {
+ TITLE="$1->$2 $MODE,$VERIF $3"
+}
+
# run_client <name> <cipher>
run_client() {
# announce what we're going to do
TESTS=$(( $TESTS + 1 ))
- TITLE="`echo $1 | head -c1`->`echo $SERVER_NAME | head -c1`"
- TITLE="$TITLE $MODE,$VERIF $2"
- printf "%s " "$TITLE"
- LEN=$(( 72 - `echo "$TITLE" | wc -c` ))
- for i in `seq 1 $LEN`; do printf '.'; done; printf ' '
+ uniform_title "${1%"${1#?}"}" "${SERVER_NAME%"${SERVER_NAME#?}"}" $2
+ DOTS72="........................................................................"
+ printf "%s %.*s " "$TITLE" "$((71 - ${#TITLE}))" "$DOTS72"
# should we skip?
if [ "X$SKIP_NEXT" = "XYES" ]; then
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index c357f43..5cbf19e 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -192,6 +192,10 @@
# default to -O2, use -Ox _after_ this if you want another level
ASAN_CFLAGS='-O2 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all'
+ # Platform tests have an allocation that returns null
+ export ASAN_OPTIONS="allocator_may_return_null=1"
+ export MSAN_OPTIONS="allocator_may_return_null=1"
+
# Gather the list of available components. These are the functions
# defined in this script whose name starts with "component_".
ALL_COMPONENTS=$(compgen -A function component_ | sed 's/component_//')
diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py
index d06a059..d50a04e 100755
--- a/tests/scripts/analyze_outcomes.py
+++ b/tests/scripts/analyze_outcomes.py
@@ -9,6 +9,7 @@
import argparse
import sys
import traceback
+import re
import check_test_cases
@@ -50,20 +51,28 @@
"""
return len(self.successes) + len(self.failures)
-def analyze_coverage(results, outcomes):
+def analyze_coverage(results, outcomes, allow_list, full_coverage):
"""Check that all available test cases are executed at least once."""
available = check_test_cases.collect_available_test_cases()
for key in available:
hits = outcomes[key].hits() if key in outcomes else 0
- if hits == 0:
- # Make this a warning, not an error, as long as we haven't
- # fixed this branch to have full coverage of test cases.
- results.warning('Test case not executed: {}', key)
+ if hits == 0 and key not in allow_list:
+ if full_coverage:
+ results.error('Test case not executed: {}', key)
+ else:
+ results.warning('Test case not executed: {}', key)
+ elif hits != 0 and key in allow_list:
+ # Test Case should be removed from the allow list.
+ if full_coverage:
+ results.error('Allow listed test case was executed: {}', key)
+ else:
+ results.warning('Allow listed test case was executed: {}', key)
-def analyze_outcomes(outcomes):
+def analyze_outcomes(outcomes, args):
"""Run all analyses on the given outcome collection."""
results = Results()
- analyze_coverage(results, outcomes)
+ analyze_coverage(results, outcomes, args['allow_list'],
+ args['full_coverage'])
return results
def read_outcome_file(outcome_file):
@@ -87,20 +96,76 @@
outcomes[key].failures.append(setup)
return outcomes
-def analyze_outcome_file(outcome_file):
- """Analyze the given outcome file."""
+def do_analyze_coverage(outcome_file, args):
+ """Perform coverage analysis."""
outcomes = read_outcome_file(outcome_file)
- return analyze_outcomes(outcomes)
+ Results.log("\n*** Analyze coverage ***\n")
+ results = analyze_outcomes(outcomes, args)
+ return results.error_count == 0
+
+# List of tasks with a function that can handle this task and additional arguments if required
+TASKS = {
+ 'analyze_coverage': {
+ 'test_function': do_analyze_coverage,
+ 'args': {
+ 'allow_list': [
+ # Algorithm not supported yet
+ 'test_suite_psa_crypto_metadata;Asymmetric signature: pure EdDSA',
+ # Algorithm not supported yet
+ 'test_suite_psa_crypto_metadata;Cipher: XTS',
+ ],
+ 'full_coverage': False,
+ }
+ },
+}
def main():
try:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('outcomes', metavar='OUTCOMES.CSV',
help='Outcome file to analyze')
+ parser.add_argument('task', default='all', nargs='?',
+ help='Analysis to be done. By default, run all tasks. '
+ 'With one or more TASK, run only those. '
+ 'TASK can be the name of a single task or '
+ 'comma/space-separated list of tasks. ')
+ parser.add_argument('--list', action='store_true',
+ help='List all available tasks and exit.')
+ parser.add_argument('--require-full-coverage', action='store_true',
+ dest='full_coverage', help="Require all available "
+ "test cases to be executed and issue an error "
+ "otherwise. This flag is ignored if 'task' is "
+ "neither 'all' nor 'analyze_coverage'")
options = parser.parse_args()
- results = analyze_outcome_file(options.outcomes)
- if results.error_count > 0:
+
+ if options.list:
+ for task in TASKS:
+ Results.log(task)
+ sys.exit(0)
+
+ result = True
+
+ if options.task == 'all':
+ tasks = TASKS.keys()
+ else:
+ tasks = re.split(r'[, ]+', options.task)
+
+ for task in tasks:
+ if task not in TASKS:
+ Results.log('Error: invalid task: {}'.format(task))
+ sys.exit(1)
+
+ TASKS['analyze_coverage']['args']['full_coverage'] = \
+ options.full_coverage
+
+ for task in TASKS:
+ if task in tasks:
+ if not TASKS[task]['test_function'](options.outcomes, TASKS[task]['args']):
+ result = False
+
+ if result is False:
sys.exit(1)
+ Results.log("SUCCESS :-)")
except Exception: # pylint: disable=broad-except
# Print the backtrace and exit explicitly with our chosen status.
traceback.print_exc()
diff --git a/tests/scripts/check_test_cases.py b/tests/scripts/check_test_cases.py
index c9f5e11..213708b 100755
--- a/tests/scripts/check_test_cases.py
+++ b/tests/scripts/check_test_cases.py
@@ -25,6 +25,7 @@
import glob
import os
import re
+import subprocess
import sys
class Results:
@@ -111,6 +112,19 @@
self.process_test_case(descriptions,
file_name, line_number, description)
+ def walk_compat_sh(self, file_name):
+ """Iterate over the test cases compat.sh with a similar format."""
+ descriptions = self.new_per_file_state() # pylint: disable=assignment-from-none
+ compat_cmd = ['sh', file_name, '--list-test-case']
+ compat_output = subprocess.check_output(compat_cmd)
+ # Assume compat.sh is responsible for printing identical format of
+ # test case description between --list-test-case and its OUTCOME.CSV
+ description = compat_output.strip().split(b'\n')
+ # idx indicates the number of test case since there is no line number
+ # in `compat.sh` for each test case.
+ for idx, descrip in enumerate(description):
+ self.process_test_case(descriptions, file_name, idx, descrip)
+
@staticmethod
def collect_test_directories():
"""Get the relative path for the TLS and Crypto test directories."""
@@ -133,6 +147,9 @@
ssl_opt_sh = os.path.join(directory, 'ssl-opt.sh')
if os.path.exists(ssl_opt_sh):
self.walk_ssl_opt_sh(ssl_opt_sh)
+ compat_sh = os.path.join(directory, 'compat.sh')
+ if os.path.exists(compat_sh):
+ self.walk_compat_sh(compat_sh)
class TestDescriptions(TestDescriptionExplorer):
"""Collect the available test cases."""
diff --git a/tests/suites/test_suite_debug.data b/tests/suites/test_suite_debug.data
index 0092774..87ec67c 100644
--- a/tests/suites/test_suite_debug.data
+++ b/tests/suites/test_suite_debug.data
@@ -65,3 +65,6 @@
Debug print certificate #2 (EC)
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_BASE64_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
mbedtls_debug_print_crt:"data_files/test-ca2.crt":"MyFile":999:"PREFIX_":"MyFile(0999)\: PREFIX_ #1\:\nMyFile(0999)\: cert. version \: 3\nMyFile(0999)\: serial number \: C1\:43\:E2\:7E\:62\:43\:CC\:E8\nMyFile(0999)\: issuer name \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nMyFile(0999)\: subject name \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nMyFile(0999)\: issued on \: 2019-02-10 14\:44\:00\nMyFile(0999)\: expires on \: 2029-02-10 14\:44\:00\nMyFile(0999)\: signed using \: ECDSA with SHA256\nMyFile(0999)\: EC key size \: 384 bits\nMyFile(0999)\: basic constraints \: CA=true\nMyFile(0999)\: value of 'crt->eckey.Q(X)' (384 bits) is\:\nMyFile(0999)\: c3 da 2b 34 41 37 58 2f 87 56 fe fc 89 ba 29 43\nMyFile(0999)\: 4b 4e e0 6e c3 0e 57 53 33 39 58 d4 52 b4 91 95\nMyFile(0999)\: 39 0b 23 df 5f 17 24 62 48 fc 1a 95 29 ce 2c 2d\nMyFile(0999)\: value of 'crt->eckey.Q(Y)' (384 bits) is\:\nMyFile(0999)\: 87 c2 88 52 80 af d6 6a ab 21 dd b8 d3 1c 6e 58\nMyFile(0999)\: b8 ca e8 b2 69 8e f3 41 ad 29 c3 b4 5f 75 a7 47\nMyFile(0999)\: 6f d5 19 29 55 69 9a 53 3b 20 b4 66 16 60 33 1e\n"
+
+Check mbedtls_calloc overallocation
+check_mbedtls_calloc_overallocation:1:1
diff --git a/tests/suites/test_suite_debug.function b/tests/suites/test_suite_debug.function
index 4e85d62..9ece280 100644
--- a/tests/suites/test_suite_debug.function
+++ b/tests/suites/test_suite_debug.function
@@ -205,3 +205,17 @@
USE_PSA_DONE();
}
/* END_CASE */
+
+/* BEGIN_CASE */
+void check_mbedtls_calloc_overallocation(int num, int size)
+{
+ unsigned char *buf;
+ buf = mbedtls_calloc((size_t) num * SIZE_MAX/2, (size_t) size * SIZE_MAX/2);
+ /* Dummy usage of the pointer to prevent optimizing it */
+ mbedtls_printf("calloc pointer : %p\n", buf);
+ TEST_ASSERT(buf == NULL);
+
+exit:
+ mbedtls_free(buf);
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_its.function b/tests/suites/test_suite_psa_its.function
index 7864b9c..2f8b8f9 100644
--- a/tests/suites/test_suite_psa_its.function
+++ b/tests/suites/test_suite_psa_its.function
@@ -10,7 +10,7 @@
* before changing how test data is constructed or validated.
*/
-#include "../library/psa_crypto_its.h"
+#include "psa_crypto_its.h"
#include "test/psa_helpers.h"