aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.pylintrc1
-rw-r--r--.uncrustify.cfg4
-rw-r--r--BRANCHES.md2
-rw-r--r--CMakeLists.txt29
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--ChangeLog206
-rw-r--r--ChangeLog.d/LMS.txt11
-rw-r--r--ChangeLog.d/add-rsa-pss-rsae-support-for-tls12.txt8
-rw-r--r--ChangeLog.d/bn_mul-fix-x86-pic-compilation-for-gcc-4.txt4
-rw-r--r--ChangeLog.d/cert_write-set-extended-key-usages.txt6
-rw-r--r--ChangeLog.d/cmake-install.txt3
-rw-r--r--ChangeLog.d/driver-only-hashes.txt19
-rw-r--r--ChangeLog.d/dtls-connection-id.txt17
-rw-r--r--ChangeLog.d/ecdsa-verify-fixes.txt5
-rw-r--r--ChangeLog.d/ecjpake-in-tls.txt5
-rw-r--r--ChangeLog.d/ecjpake_to_pms.txt5
-rw-r--r--ChangeLog.d/extend-query_compile_time_config-to-psa_want.txt2
-rw-r--r--ChangeLog.d/fix-aes-shallow-copying.txt2
-rw-r--r--ChangeLog.d/fix-ctr-drbg-may-free-invalid-aes-context.txt4
-rw-r--r--ChangeLog.d/fix-gettimeofday-overflow.txt3
-rw-r--r--ChangeLog.d/fix-possible-false-success-in-mbedtls_cipher_check_tag.txt5
-rw-r--r--ChangeLog.d/fix-tls12server-sent-sigalgs.txt5
-rw-r--r--ChangeLog.d/fix_aead_psa_driver_build.txt3
-rw-r--r--ChangeLog.d/fix_arm_compile_erorr.txt3
-rw-r--r--ChangeLog.d/fix_build_error_for_mbedtls_deprecated_removed.txt3
-rw-r--r--ChangeLog.d/fix_build_tls1_2_with_single_encryption_type.txt3
-rw-r--r--ChangeLog.d/fix_cmake_gen_files.txt4
-rw-r--r--ChangeLog.d/fix_cmake_using_iar_toolchain.txt3
-rw-r--r--ChangeLog.d/fix_dh_genprime_error_reporting.txt4
-rw-r--r--ChangeLog.d/fix_hard_link_across_drives.txt3
-rw-r--r--ChangeLog.d/fix_psa_crypto_cipher_h_include.txt4
-rw-r--r--ChangeLog.d/fix_tls13_session_resumption_fail_when_hostname_is_not_localhost.txt4
-rw-r--r--ChangeLog.d/fix_x509_get_name_mem_leak.txt4
-rw-r--r--ChangeLog.d/fix_x509_info_hwmodulename.txt5
-rw-r--r--ChangeLog.d/fix_zeroization.txt3
-rw-r--r--ChangeLog.d/mbedtls_asn1_type_free.txt8
-rw-r--r--ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt6
-rw-r--r--ChangeLog.d/move-ssl-modules.txt3
-rw-r--r--ChangeLog.d/mpi-add-0-ub.txt4
-rw-r--r--ChangeLog.d/mpi-most-negative-sint.txt4
-rw-r--r--ChangeLog.d/muladdc_microblaze.txt3
-rw-r--r--ChangeLog.d/negative-zero-from-add.txt6
-rw-r--r--ChangeLog.d/nonversioned-library-soname.txt5
-rw-r--r--ChangeLog.d/pk-sign-restartable.txt5
-rw-r--r--ChangeLog.d/platform-setbuf.txt3
-rw-r--r--ChangeLog.d/psa-ecb-ub.txt3
-rw-r--r--ChangeLog.d/psa_crypto_code_gen_1_1.txt13
-rw-r--r--ChangeLog.d/psa_crypto_pake.txt4
-rw-r--r--ChangeLog.d/psa_driver_wrapper_for_raw_key_agreement.txt5
-rw-r--r--ChangeLog.d/psa_rsa_needs_pk.txt5
-rw-r--r--ChangeLog.d/tls13-misc.txt8
-rw-r--r--ChangeLog.d/tls13_sig_alg_selection.txt3
-rw-r--r--ChangeLog.d/x509-broken-symlink-handling.txt5
-rw-r--r--Makefile26
-rw-r--r--README.md2
-rw-r--r--docs/architecture/psa-migration/psa-limitations.md7
-rw-r--r--docs/use-psa-crypto.md25
-rw-r--r--doxygen/input/doc_mainpage.h2
-rw-r--r--doxygen/mbedtls.doxyfile2
-rw-r--r--include/mbedtls/build_info.h10
-rw-r--r--include/mbedtls/check_config.h10
-rw-r--r--include/mbedtls/mbedtls_config.h34
-rw-r--r--include/mbedtls/pk.h4
-rw-r--r--include/mbedtls/ssl.h17
-rw-r--r--library/CMakeLists.txt6
-rw-r--r--library/Makefile4
-rw-r--r--library/bignum.c204
-rw-r--r--library/bignum_core.c116
-rw-r--r--library/bignum_core.h162
-rw-r--r--library/bignum_mod.c138
-rw-r--r--library/bignum_mod.h201
-rw-r--r--library/bignum_mod_raw.c64
-rw-r--r--library/bignum_mod_raw.h152
-rw-r--r--library/ecp.c129
-rw-r--r--library/lms.c47
-rw-r--r--library/pk.c12
-rw-r--r--library/pk_wrap.c8
-rw-r--r--library/pkcs7.c45
-rw-r--r--library/ssl_client.c12
-rw-r--r--library/ssl_misc.h40
-rw-r--r--library/ssl_tls.c99
-rw-r--r--library/ssl_tls12_client.c11
-rw-r--r--library/ssl_tls12_server.c6
-rw-r--r--library/ssl_tls13_client.c16
-rw-r--r--programs/fuzz/Makefile4
-rw-r--r--programs/ssl/ssl_client2.c96
-rw-r--r--programs/ssl/ssl_server2.c95
-rw-r--r--programs/test/benchmark.c2
-rw-r--r--programs/test/cmake_package_install/CMakeLists.txt2
-rwxr-xr-xscripts/code_style.py37
-rwxr-xr-xscripts/config.py1
-rwxr-xr-xscripts/lcov.sh81
-rw-r--r--scripts/mbedtls_dev/bignum_common.py55
-rw-r--r--scripts/mbedtls_dev/bignum_core.py36
-rw-r--r--scripts/mbedtls_dev/bignum_data.py3
-rw-r--r--scripts/mbedtls_dev/bignum_mod.py75
-rw-r--r--scripts/mbedtls_dev/bignum_mod_raw.py122
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/Makefile1
-rwxr-xr-xtests/compat-in-docker.sh4
-rw-r--r--tests/docker/bionic/Dockerfile4
-rw-r--r--tests/include/test/bignum_helpers.h118
-rw-r--r--tests/include/test/helpers.h67
-rwxr-xr-xtests/make-in-docker.sh4
-rwxr-xr-xtests/opt-testcases/tls13-misc.sh62
-rwxr-xr-xtests/scripts/all-in-docker.sh4
-rwxr-xr-xtests/scripts/all.sh31
-rwxr-xr-xtests/scripts/basic-build-test.sh27
-rwxr-xr-xtests/scripts/basic-in-docker.sh4
-rwxr-xr-xtests/scripts/check-generated-files.sh10
-rwxr-xr-xtests/scripts/check_names.py5
-rwxr-xr-xtests/scripts/depends.py1
-rwxr-xr-xtests/scripts/docker_env.sh4
-rwxr-xr-xtests/scripts/generate_bignum_tests.py1
-rwxr-xr-xtests/scripts/generate_test_code.py68
-rwxr-xr-xtests/scripts/test_generate_test_code.py198
-rw-r--r--tests/src/bignum_helpers.c142
-rw-r--r--tests/src/helpers.c87
-rwxr-xr-xtests/ssl-opt-in-docker.sh4
-rwxr-xr-xtests/ssl-opt.sh213
-rw-r--r--tests/suites/helpers.function1
-rw-r--r--tests/suites/test_suite_bignum.function210
-rw-r--r--tests/suites/test_suite_bignum.misc.data170
-rw-r--r--tests/suites/test_suite_bignum_core.function101
-rw-r--r--tests/suites/test_suite_bignum_core.misc.data63
-rw-r--r--tests/suites/test_suite_bignum_mod.function380
-rw-r--r--tests/suites/test_suite_bignum_mod.misc.data (renamed from tests/suites/test_suite_bignum_mod.data)70
-rw-r--r--tests/suites/test_suite_bignum_mod_raw.function237
-rw-r--r--tests/suites/test_suite_bignum_random.data340
-rw-r--r--tests/suites/test_suite_bignum_random.function496
-rw-r--r--tests/suites/test_suite_ecjpake.data16
-rw-r--r--tests/suites/test_suite_ecp.data46
-rw-r--r--tests/suites/test_suite_ecp.function21
-rw-r--r--tests/suites/test_suite_pk.data8
-rw-r--r--tests/suites/test_suite_pkcs7.data2
-rw-r--r--tests/suites/test_suite_psa_crypto.function7
-rw-r--r--tests/suites/test_suite_ssl.data8
-rw-r--r--tests/suites/test_suite_ssl.function97
-rw-r--r--tests/suites/test_suite_version.data4
-rw-r--r--tests/suites/test_suite_x509parse.data10
-rw-r--r--tests/suites/test_suite_x509parse.function7
141 files changed, 4758 insertions, 1309 deletions
diff --git a/.pylintrc b/.pylintrc
index 10c93f8..f395fb9 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -1,5 +1,6 @@
[MASTER]
init-hook='import sys; sys.path.append("scripts")'
+min-similarity-lines=10
[BASIC]
# We're ok with short funtion argument names.
diff --git a/.uncrustify.cfg b/.uncrustify.cfg
index ac9173e..7ce0905 100644
--- a/.uncrustify.cfg
+++ b/.uncrustify.cfg
@@ -187,8 +187,8 @@ sp_before_comma = remove
# No space before the ':' in a case statement
sp_before_case_colon = remove
-# No space after a cast - '(char) x' -> '(char)x'
-sp_after_cast = remove
+# Must have space after a cast - '(char)x' -> '(char) x'
+sp_after_cast = add
# No space between 'sizeof' and '('
sp_sizeof_paren = remove
diff --git a/BRANCHES.md b/BRANCHES.md
index 6240023..c7a6082 100644
--- a/BRANCHES.md
+++ b/BRANCHES.md
@@ -101,6 +101,6 @@ The following branches are currently maintained:
- [`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.0>.
+ <https://github.com/Mbed-TLS/mbedtls/releases/tag/v2.28.2>.
Users are urged to always use the latest version of a maintained branch.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 59a960a..519604b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -304,22 +304,15 @@ if(ENABLE_TESTING)
# additional convenience targets for Unix only
if(UNIX)
- ADD_CUSTOM_TARGET(covtest
- COMMAND make test
- COMMAND programs/test/selftest
- COMMAND tests/compat.sh
- COMMAND tests/ssl-opt.sh
- )
-
+ # For coverage testing:
+ # 1. Build with:
+ # cmake -D CMAKE_BUILD_TYPE=Coverage /path/to/source && make
+ # 2. Run the relevant tests for the part of the code you're interested in.
+ # For the reference coverage measurement, see
+ # tests/scripts/basic-build-test.sh
+ # 3. Run scripts/lcov.sh to generate an HTML report.
ADD_CUSTOM_TARGET(lcov
- COMMAND rm -rf Coverage
- COMMAND lcov --capture --initial --directory library/CMakeFiles/mbedtls.dir -o files.info
- COMMAND lcov --capture --directory library/CMakeFiles/mbedtls.dir -o tests.info
- COMMAND lcov --add-tracefile files.info --add-tracefile tests.info -o all.info
- COMMAND lcov --remove all.info -o final.info '*.h'
- COMMAND gendesc tests/Descriptions.txt -o descriptions
- COMMAND genhtml --title "mbed TLS" --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage final.info
- COMMAND rm -f files.info tests.info all.info final.info descriptions
+ COMMAND scripts/lcov.sh
)
ADD_CUSTOM_TARGET(memcheck
@@ -350,12 +343,12 @@ if(NOT DISABLE_PACKAGE_CONFIG_AND_INSTALL)
write_basic_package_version_file(
"cmake/MbedTLSConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
- VERSION 3.2.1)
+ VERSION 3.3.0)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfigVersion.cmake"
- DESTINATION "cmake")
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/MbedTLS")
export(
EXPORT MbedTLSTargets
@@ -365,7 +358,7 @@ if(NOT DISABLE_PACKAGE_CONFIG_AND_INSTALL)
install(
EXPORT MbedTLSTargets
NAMESPACE MbedTLS::
- DESTINATION "cmake"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/MbedTLS"
FILE "MbedTLSTargets.cmake")
if(CMAKE_VERSION VERSION_GREATER 3.15 OR CMAKE_VERSION VERSION_EQUAL 3.15)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d19fe57..fc79e49 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -32,13 +32,9 @@ Backwards Compatibility
The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches, as described in [BRANCHES.md](BRANCHES.md).
-To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change. If there is an API change, the contribution, if accepted, will be merged only when there will be a major release.
+To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change. If there is an API change, the contribution, if accepted, will be merged only when there is a major release.
-Where changes to an existing interface are necessary, functions in the public interface which need to be changed, are marked as 'deprecated'. This is done with the preprocessor symbols `MBEDTLS_DEPRECATED_WARNING` and `MBEDTLS_DEPRECATED_REMOVED`. Then, a new function with a new name but similar if not identical behaviour to the original function containing the necessary changes should be created alongside the existing deprecated function.
-
-When a build is made with the deprecation preprocessor symbols defined, a compiler warning will be generated to warn a user that the function will be removed at some point in the future, notifying users that they should change from the older deprecated function to the newer function at their own convenience.
-
-Therefore, no changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. As described above, if a function needs to be changed, a new function needs to be created alongside it, with a new name, and whatever change is necessary, such as a new parameter or the addition of a return value.
+No changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. Where changes to an existing interface are necessary, functions in the public interface which need to be changed are marked as 'deprecated'. If there is a strong reason to replace an existing function with one that has a slightly different interface (different prototype, or different documented behavior), create a new function with a new name with the desired interface. Keep the old function, but mark it as deprecated.
Periodically, the library will remove deprecated functions from the library which will be a breaking change in the API, but such changes will be made only in a planned, structured way that gives sufficient notice to users of the library.
diff --git a/ChangeLog b/ChangeLog
index cb277dc..1404d36 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,209 @@
Mbed TLS ChangeLog (Sorted per branch, date)
+= Mbed TLS 3.3.0 branch released 2022-12-14
+
+Default behavior changes
+ * Previously the macro MBEDTLS_SSL_DTLS_CONNECTION_ID implemented version 05
+ of the IETF draft, and was marked experimental and disabled by default.
+ It is now no longer experimental, and implements the final version from
+ RFC 9146, which is not interoperable with the draft-05 version.
+ If you need to communicate with peers that use earlier versions of
+ Mbed TLS, then you need to define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT
+ to 1, but then you won't be able to communicate with peers that use the
+ standard (non-draft) version.
+ If you need to interoperate with both classes of peers with the
+ same build of Mbed TLS, please let us know about your situation on the
+ mailing list or GitHub.
+
+Requirement changes
+ * When building with PSA drivers using generate_driver_wrappers.py, or
+ when building the library from the development branch rather than
+ from a release, the Python module jsonschema is now necessary, in
+ addition to jinja2. The official list of required Python modules is
+ maintained in scripts/basic.requirements.txt and may change again
+ in the future.
+
+New deprecations
+ * Deprecate mbedtls_asn1_free_named_data().
+ Use mbedtls_asn1_free_named_data_list()
+ or mbedtls_asn1_free_named_data_list_shallow().
+
+Features
+ * Support rsa_pss_rsae_* signature algorithms in TLS 1.2.
+ * make: enable building unversioned shared library, with e.g.:
+ "SHARED=1 SOEXT_TLS=so SOEXT_X509=so SOEXT_CRYPTO=so make lib"
+ resulting in library names like "libmbedtls.so" rather than
+ "libmbedcrypto.so.11".
+ * Expose the EC J-PAKE functionality through the Draft PSA PAKE Crypto API.
+ Only the ECC primitive with secp256r1 curve and SHA-256 hash algorithm
+ are supported in this implementation.
+ * Some modules can now use PSA drivers for hashes, including with no
+ built-in implementation present, but only in some configurations.
+ - RSA OAEP and PSS (PKCS#1 v2.1), PKCS5, PKCS12 and EC J-PAKE now use
+ hashes from PSA when (and only when) MBEDTLS_MD_C is disabled.
+ - PEM parsing of encrypted files now uses MD-5 from PSA when (and only
+ when) MBEDTLS_MD5_C is disabled.
+ See the documentation of the corresponding macros in mbedtls_config.h for
+ details.
+ Note that some modules are not able to use hashes from PSA yet, including
+ the entropy module. As a consequence, for now the only way to build with
+ all hashes only provided by drivers (no built-in hash) is to use
+ MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG.
+ * When MBEDTLS_USE_PSA_CRYPTO is enabled, X.509, TLS 1.2 and TLS 1.3 now
+ properly negotiate/accept hashes based on their availability in PSA.
+ As a consequence, they now work in configurations where the built-in
+ implementations of (some) hashes are excluded and those hashes are only
+ provided by PSA drivers. (See previous entry for limitation on RSA-PSS
+ though: that module only use hashes from PSA when MBEDTLS_MD_C is off).
+ * Add support for opaque keys as the private keys associated to certificates
+ for authentication in TLS 1.3.
+ * Add the LMS post-quantum-safe stateful-hash asymmetric signature scheme.
+ Signature verification is production-ready, but generation is for testing
+ purposes only. This currently only supports one parameter set
+ (LMS_SHA256_M32_H10), meaning that each private key can be used to sign
+ 1024 messages. As such, it is not intended for use in TLS, but instead
+ for verification of assets transmitted over an insecure channel,
+ particularly firmware images.
+ * Add the LM-OTS post-quantum-safe one-time signature scheme, which is
+ required for LMS. This can be used independently, but each key can only
+ be used to sign one message so is impractical for most circumstances.
+ * Mbed TLS now supports TLS 1.3 key establishment via pre-shared keys.
+ The pre-shared keys can be provisioned externally or via the ticket
+ mechanism (session resumption).
+ The ticket mechanism is supported when the configuration option
+ MBEDTLS_SSL_SESSION_TICKETS is enabled.
+ New options MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_xxx_ENABLED
+ control the support for the three possible TLS 1.3 key exchange modes.
+ * cert_write: support for setting extended key usage attributes. A
+ corresponding new public API call has been added in the library,
+ mbedtls_x509write_crt_set_ext_key_usage().
+ * cert_write: support for writing certificate files in either PEM
+ or DER format.
+ * The PSA driver wrapper generator generate_driver_wrappers.py now
+ supports a subset of the driver description language, including
+ the following entry points: import_key, export_key, export_public_key,
+ get_builtin_key, copy_key.
+ * The new functions mbedtls_asn1_free_named_data_list() and
+ mbedtls_asn1_free_named_data_list_shallow() simplify the management
+ of memory in named data lists in X.509 structures.
+ * The TLS 1.2 EC J-PAKE key exchange can now use the PSA Crypto API.
+ Additional PSA key slots will be allocated in the process of such key
+ exchange for builds that enable MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED and
+ MBEDTLS_USE_PSA_CRYPTO.
+ * Add support for DTLS Connection ID as defined by RFC 9146, controlled by
+ MBEDTLS_SSL_DTLS_CONNECTION_ID (enabled by default) and configured with
+ mbedtls_ssl_set_cid().
+ * Add a driver dispatch layer for raw key agreement, enabling alternative
+ implementations of raw key agreement through the key_agreement driver
+ entry point. This entry point is specified in the proposed PSA driver
+ interface, but had not yet been implemented.
+ * Add an ad-hoc key derivation function handling EC J-PAKE to PMS
+ calculation that can be used to derive the session secret in TLS 1.2,
+ as described in draft-cragie-tls-ecjpake-01. This can be achieved by
+ using PSA_ALG_TLS12_ECJPAKE_TO_PMS as the key derivation algorithm.
+
+Security
+ * Fix potential heap buffer overread and overwrite in DTLS if
+ MBEDTLS_SSL_DTLS_CONNECTION_ID is enabled and
+ MBEDTLS_SSL_CID_IN_LEN_MAX > 2 * MBEDTLS_SSL_CID_OUT_LEN_MAX.
+ * An adversary with access to precise enough information about memory
+ accesses (typically, an untrusted operating system attacking a secure
+ enclave) could recover an RSA private key after observing the victim
+ performing a single private-key operation if the window size used for the
+ exponentiation was 3 or smaller. Found and reported by Zili KOU,
+ Wenjian HE, Sharad Sinha, and Wei ZHANG. See "Cache Side-channel Attacks
+ and Defenses of the Sliding Window Algorithm in TEEs" - Design, Automation
+ and Test in Europe 2023.
+
+Bugfix
+ * Refactor mbedtls_aes_context to support shallow-copying. Fixes #2147.
+ * Fix an issue with in-tree CMake builds in releases with GEN_FILES
+ turned off: if a shipped file was missing from the working directory,
+ it could be turned into a symbolic link to itself.
+ * Fix a long-standing build failure when building x86 PIC code with old
+ gcc (4.x). The code will be slower, but will compile. We do however
+ recommend upgrading to a more recent compiler instead. Fixes #1910.
+ * Fix support for little-endian Microblaze when MBEDTLS_HAVE_ASM is defined.
+ Contributed by Kazuyuki Kimura to fix #2020.
+ * Use double quotes to include private header file psa_crypto_cipher.h.
+ Fixes 'file not found with <angled> include' error
+ when building with Xcode.
+ * Fix handling of broken symlinks when loading certificates using
+ mbedtls_x509_crt_parse_path(). Instead of returning an error as soon as a
+ broken link is encountered, skip the broken link and continue parsing
+ other certificate files. Contributed by Eduardo Silva in #2602.
+ * Fix an interoperability failure between an Mbed TLS client with both
+ TLS 1.2 and TLS 1.3 support, and a TLS 1.2 server that supports
+ rsa_pss_rsae_* signature algorithms. This failed because Mbed TLS
+ advertised support for PSS in both TLS 1.2 and 1.3, but only
+ actually supported PSS in TLS 1.3.
+ * Fix a compilation error when using CMake with an IAR toolchain.
+ Fixes #5964.
+ * Fix a build error due to a missing prototype warning when
+ MBEDTLS_DEPRECATED_REMOVED is enabled.
+ * Fix mbedtls_ctr_drbg_free() on an initialized but unseeded context. When
+ MBEDTLS_AES_ALT is enabled, it could call mbedtls_aes_free() on an
+ uninitialized context.
+ * Fix a build issue on Windows using CMake where the source and build
+ directories could not be on different drives. Fixes #5751.
+ * Fix bugs and missing dependencies when building and testing
+ configurations with only one encryption type enabled in TLS 1.2.
+ * Provide the missing definition of mbedtls_setbuf() in some configurations
+ with MBEDTLS_PLATFORM_C disabled. Fixes #6118, #6196.
+ * Fix compilation errors when trying to build with
+ PSA drivers for AEAD (GCM, CCM, Chacha20-Poly1305).
+ * Fix memory leak in ssl_parse_certificate_request() caused by
+ mbedtls_x509_get_name() not freeing allocated objects in case of error.
+ Change mbedtls_x509_get_name() to clean up allocated objects on error.
+ * Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not
+ MBEDTLS_USE_PSA_CRYPTO or MBEDTLS_PK_WRITE_C. Fixes #6408.
+ * Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not
+ MBEDTLS_PK_PARSE_C. Fixes #6409.
+ * Fix ECDSA verification, where it was not always validating the
+ public key. This bug meant that it was possible to verify a
+ signature with an invalid public key, in some cases. Reported by
+ Guido Vranken using Cryptofuzz in #4420.
+ * Fix a possible null pointer dereference if a memory allocation fails
+ in TLS PRF code. Reported by Michael Madsen in #6516.
+ * Fix TLS 1.3 session resumption. Fixes #6488.
+ * Add a configuration check to exclude optional client authentication
+ in TLS 1.3 (where it is forbidden).
+ * Fix a bug in which mbedtls_x509_crt_info() would produce non-printable
+ bytes when parsing certificates containing a binary RFC 4108
+ HardwareModuleName as a Subject Alternative Name extension. Hardware
+ serial numbers are now rendered in hex format. Fixes #6262.
+ * Fix bug in error reporting in dh_genprime.c where upon failure,
+ the error code returned by mbedtls_mpi_write_file() is overwritten
+ and therefore not printed.
+ * In the bignum module, operations of the form (-A) - (+A) or (-A) - (-A)
+ with A > 0 created an unintended representation of the value 0 which was
+ not processed correctly by some bignum operations. Fix this. This had no
+ consequence on cryptography code, but might affect applications that call
+ bignum directly and use negative numbers.
+ * Fix a bug whereby the list of signature algorithms sent as part of
+ the TLS 1.2 server certificate request would get corrupted, meaning the
+ first algorithm would not get sent and an entry consisting of two random
+ bytes would be sent instead. Found by Serban Bejan and Dudek Sebastian.
+ * Fix undefined behavior (typically harmless in practice) of
+ mbedtls_mpi_add_mpi(), mbedtls_mpi_add_abs() and mbedtls_mpi_add_int()
+ when both operands are 0 and the left operand is represented with 0 limbs.
+ * Fix undefined behavior (typically harmless in practice) when some bignum
+ functions receive the most negative value of mbedtls_mpi_sint. Credit
+ to OSS-Fuzz. Fixes #6597.
+ * Fix undefined behavior (typically harmless in practice) in PSA ECB
+ encryption and decryption.
+ * Move some SSL-specific code out of libmbedcrypto where it had been placed
+ accidentally.
+ * Fix a build error when compiling the bignum module for some Arm platforms.
+ Fixes #6089, #6124, #6217.
+
+Changes
+ * Add the ability to query PSA_WANT_xxx macros to query_compile_time_config.
+ * Calling AEAD tag-specific functions for non-AEAD algorithms (which
+ should not be done - they are documented for use only by AES-GCM and
+ ChaCha20+Poly1305) now returns MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE
+ instead of success (0).
+
= Mbed TLS 3.2.1 branch released 2022-07-12
Bugfix
@@ -249,7 +453,7 @@ Bugfix
make to break on a clean checkout. Fixes #5340.
* Work around an MSVC ARM64 compiler bug causing incorrect behaviour
in mbedtls_mpi_exp_mod(). Reported by Tautvydas Žilys in #5467.
- * Removed the prompt to exit from all windows build programs that was causing
+ * Removed the prompt to exit from all windows build programs, which was causing
issues in CI/CD environments.
Changes
diff --git a/ChangeLog.d/LMS.txt b/ChangeLog.d/LMS.txt
deleted file mode 100644
index 785bfcf..0000000
--- a/ChangeLog.d/LMS.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Features
- * Add the LMS post-quantum-safe stateful-hash asymmetric signature scheme.
- Signature verification is production-ready, but generation is for testing
- purposes only. This currently only supports one parameter set
- (LMS_SHA256_M32_H10), meaning that each private key can be used to sign
- 1024 messages. As such, it is not intended for use in TLS, but instead
- for verification of assets transmitted over an insecure channel,
- particularly firmware images.
- * Add the LM-OTS post-quantum-safe one-time signature scheme, which is
- required for LMS. This can be used independently, but each key can only
- be used to sign one message so is impractical for most circumstances.
diff --git a/ChangeLog.d/add-rsa-pss-rsae-support-for-tls12.txt b/ChangeLog.d/add-rsa-pss-rsae-support-for-tls12.txt
deleted file mode 100644
index 0d40968..0000000
--- a/ChangeLog.d/add-rsa-pss-rsae-support-for-tls12.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Features
- * Support rsa_pss_rsae_* signature algorithms in TLS 1.2.
-Bugfix
- * Fix an interoperability failure between an Mbed TLS client with both
- TLS 1.2 and TLS 1.3 support, and a TLS 1.2 server that supports
- rsa_pss_rsae_* signature algorithms. This failed because Mbed TLS
- advertised support for PSS in both TLS 1.2 and 1.3, but only
- actually supported PSS in TLS 1.3.
diff --git a/ChangeLog.d/bn_mul-fix-x86-pic-compilation-for-gcc-4.txt b/ChangeLog.d/bn_mul-fix-x86-pic-compilation-for-gcc-4.txt
deleted file mode 100644
index 1d59c22..0000000
--- a/ChangeLog.d/bn_mul-fix-x86-pic-compilation-for-gcc-4.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix a long-standing build failure when building x86 PIC code with old
- gcc (4.x). The code will be slower, but will compile. We do however
- recommend upgrading to a more recent compiler instead. Fixes #1910.
diff --git a/ChangeLog.d/cert_write-set-extended-key-usages.txt b/ChangeLog.d/cert_write-set-extended-key-usages.txt
deleted file mode 100644
index 18b7b04..0000000
--- a/ChangeLog.d/cert_write-set-extended-key-usages.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Features
- * cert_write: support for setting extended key usage attributes. A
- corresponding new public API call has been added in the library,
- mbedtls_x509write_crt_set_ext_key_usage().
- * cert_write: support for writing certificate files in either PEM
- or DER format.
diff --git a/ChangeLog.d/cmake-install.txt b/ChangeLog.d/cmake-install.txt
new file mode 100644
index 0000000..d8eb72e
--- /dev/null
+++ b/ChangeLog.d/cmake-install.txt
@@ -0,0 +1,3 @@
+Changes
+ * Install the .cmake files into CMAKE_INSTALL_LIBDIR/cmake/MbedTLS,
+ typically /usr/lib/cmake/MbedTLS.
diff --git a/ChangeLog.d/driver-only-hashes.txt b/ChangeLog.d/driver-only-hashes.txt
deleted file mode 100644
index 6ccd199..0000000
--- a/ChangeLog.d/driver-only-hashes.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Features
- * Some modules can now use PSA drivers for hashes, including with no
- built-in implementation present, but only in some configurations.
- - RSA OAEP and PSS (PKCS#1 v2.1), PKCS5, PKCS12 and EC J-PAKE now use
- hashes from PSA when (and only when) MBEDTLS_MD_C is disabled.
- - PEM parsing of encrypted files now uses MD-5 from PSA when (and only
- when) MBEDTLS_MD5_C is disabled.
- See the documentation of the corresponding macros in mbedtls_config.h for
- details.
- Note that some modules are not able to use hashes from PSA yet, including
- the entropy module. As a consequence, for now the only way to build with
- all hashes only provided by drivers (no built-in hash) is to use
- MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG.
- * When MBEDTLS_USE_PSA_CRYPTO is enabled, X.509, TLS 1.2 and TLS 1.3 now
- properly negotiate/accept hashes based on their availability in PSA.
- As a consequence, they now work in configurations where the built-in
- implementations of (some) hashes are excluded and those hashes are only
- provided by PSA drivers. (See previous entry for limitation on RSA-PSS
- though: that module only use hashes from PSA when MBEDTLS_MD_C is off).
diff --git a/ChangeLog.d/dtls-connection-id.txt b/ChangeLog.d/dtls-connection-id.txt
deleted file mode 100644
index 840f837..0000000
--- a/ChangeLog.d/dtls-connection-id.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Features
- * Add support for DTLS Connection ID as defined by RFC 9146, controlled by
- MBEDTLS_SSL_DTLS_CONNECTION_ID (enabled by default) and configured with
- mbedtls_ssl_set_cid().
-
-Default behavior changes
- * Previously the macro MBEDTLS_SSL_DTLS_CONNECTION_ID implemented version 05
- of the IETF draft, and was marked experimental and disabled by default.
- It is now no longer experimental, and implements the final version from
- RFC 9146, which is not interoperable with the draft-05 version.
- If you need to communicate with peers that use earlier versions of
- Mbed TLS, then you need to define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT
- to 1, but then you won't be able to communicate with peers that use the
- standard (non-draft) version.
- If you need to interoperate with both classes of peers with the
- same build of Mbed TLS, please let us know about your situation on the
- mailing list or GitHub.
diff --git a/ChangeLog.d/ecdsa-verify-fixes.txt b/ChangeLog.d/ecdsa-verify-fixes.txt
deleted file mode 100644
index b41b046..0000000
--- a/ChangeLog.d/ecdsa-verify-fixes.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
- * Fix ECDSA verification, where it was not always validating the
- public key. This bug meant that it was possible to verify a
- signature with an invalid public key, in some cases. Reported by
- Guido Vranken using Cryptofuzz in #4420.
diff --git a/ChangeLog.d/ecjpake-in-tls.txt b/ChangeLog.d/ecjpake-in-tls.txt
deleted file mode 100644
index b84caab..0000000
--- a/ChangeLog.d/ecjpake-in-tls.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Features
- * The TLS 1.2 EC J-PAKE key exchange can now use the PSA Crypto API.
- Additional PSA key slots will be allocated in the process of such key
- exchange for builds that enable MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED and
- MBEDTLS_USE_PSA_CRYPTO.
diff --git a/ChangeLog.d/ecjpake_to_pms.txt b/ChangeLog.d/ecjpake_to_pms.txt
deleted file mode 100644
index 4dd2075..0000000
--- a/ChangeLog.d/ecjpake_to_pms.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-API changes
- * Add an ad-hoc key derivation function handling ECJPAKE to PMS
- calculation that can be used to derive the session secret in TLS 1.2,
- as described in draft-cragie-tls-ecjpake-01. This can be achieved by
- using PSA_ALG_TLS12_ECJPAKE_TO_PMS as the key derivation algorithm.
diff --git a/ChangeLog.d/extend-query_compile_time_config-to-psa_want.txt b/ChangeLog.d/extend-query_compile_time_config-to-psa_want.txt
deleted file mode 100644
index 99b2ec4..0000000
--- a/ChangeLog.d/extend-query_compile_time_config-to-psa_want.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Changes
- * Add the ability to query PSA_WANT_xxx macros to query_compile_time_config.
diff --git a/ChangeLog.d/fix-aes-shallow-copying.txt b/ChangeLog.d/fix-aes-shallow-copying.txt
deleted file mode 100644
index 0c119d6..0000000
--- a/ChangeLog.d/fix-aes-shallow-copying.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Bugfix
- * Refactor mbedtls_aes_context to support shallow-copying. Fixes #2147.
diff --git a/ChangeLog.d/fix-ctr-drbg-may-free-invalid-aes-context.txt b/ChangeLog.d/fix-ctr-drbg-may-free-invalid-aes-context.txt
deleted file mode 100644
index fe62c28..0000000
--- a/ChangeLog.d/fix-ctr-drbg-may-free-invalid-aes-context.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix mbedtls_ctr_drbg_free() on an initialized but unseeded context. When
- MBEDTLS_AES_ALT is enabled, it could call mbedtls_aes_free() on an
- uninitialized context.
diff --git a/ChangeLog.d/fix-gettimeofday-overflow.txt b/ChangeLog.d/fix-gettimeofday-overflow.txt
new file mode 100644
index 0000000..b7e10d2
--- /dev/null
+++ b/ChangeLog.d/fix-gettimeofday-overflow.txt
@@ -0,0 +1,3 @@
+Bugfix
+ * Fix possible integer overflow in mbedtls_timing_hardclock(), which
+ could cause a crash in programs/test/benchmark.
diff --git a/ChangeLog.d/fix-possible-false-success-in-mbedtls_cipher_check_tag.txt b/ChangeLog.d/fix-possible-false-success-in-mbedtls_cipher_check_tag.txt
deleted file mode 100644
index 1f9e0aa..0000000
--- a/ChangeLog.d/fix-possible-false-success-in-mbedtls_cipher_check_tag.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Changes
- * Calling AEAD tag-specific functions for non-AEAD algorithms (which
- should not be done - they are documented for use only by AES-GCM and
- ChaCha20+Poly1305) now returns MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE
- instead of success (0).
diff --git a/ChangeLog.d/fix-tls12server-sent-sigalgs.txt b/ChangeLog.d/fix-tls12server-sent-sigalgs.txt
deleted file mode 100644
index b74c6ec..0000000
--- a/ChangeLog.d/fix-tls12server-sent-sigalgs.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
- * Fix a bug whereby the list of signature algorithms sent as part of
- the TLS 1.2 server certificate request would get corrupted, meaning the
- first algorithm would not get sent and an entry consisting of two random
- bytes would be sent instead. Found by Serban Bejan and Dudek Sebastian.
diff --git a/ChangeLog.d/fix_aead_psa_driver_build.txt b/ChangeLog.d/fix_aead_psa_driver_build.txt
deleted file mode 100644
index a6d11d3..0000000
--- a/ChangeLog.d/fix_aead_psa_driver_build.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix compilation errors when trying to build with
- PSA drivers for AEAD (GCM, CCM, Chacha20-Poly1305).
diff --git a/ChangeLog.d/fix_arm_compile_erorr.txt b/ChangeLog.d/fix_arm_compile_erorr.txt
deleted file mode 100644
index 28c1d45..0000000
--- a/ChangeLog.d/fix_arm_compile_erorr.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix a build error when compiling the bignum module for some Arm platforms.
- Fixes #6089, #6124, #6217.
diff --git a/ChangeLog.d/fix_build_error_for_mbedtls_deprecated_removed.txt b/ChangeLog.d/fix_build_error_for_mbedtls_deprecated_removed.txt
deleted file mode 100644
index f0fa000..0000000
--- a/ChangeLog.d/fix_build_error_for_mbedtls_deprecated_removed.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix a build error due to a missing prototype warning when
- MBEDTLS_DEPRECATED_REMOVED is enabled.
diff --git a/ChangeLog.d/fix_build_tls1_2_with_single_encryption_type.txt b/ChangeLog.d/fix_build_tls1_2_with_single_encryption_type.txt
deleted file mode 100644
index c7d2691..0000000
--- a/ChangeLog.d/fix_build_tls1_2_with_single_encryption_type.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix bugs and missing dependencies when building and testing
- configurations with only one encryption type enabled in TLS 1.2.
diff --git a/ChangeLog.d/fix_cmake_gen_files.txt b/ChangeLog.d/fix_cmake_gen_files.txt
deleted file mode 100644
index cdec6e8..0000000
--- a/ChangeLog.d/fix_cmake_gen_files.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix an issue with in-tree CMake builds in releases with GEN_FILES
- turned off: if a shipped file was missing from the working directory,
- it could be turned into a symbolic link to itself.
diff --git a/ChangeLog.d/fix_cmake_using_iar_toolchain.txt b/ChangeLog.d/fix_cmake_using_iar_toolchain.txt
deleted file mode 100644
index 9ec6e0d..0000000
--- a/ChangeLog.d/fix_cmake_using_iar_toolchain.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix a compilation error when using CMake with an IAR toolchain.
- Fixes #5964.
diff --git a/ChangeLog.d/fix_dh_genprime_error_reporting.txt b/ChangeLog.d/fix_dh_genprime_error_reporting.txt
deleted file mode 100644
index 1c98947..0000000
--- a/ChangeLog.d/fix_dh_genprime_error_reporting.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix bug in error reporting in dh_genprime.c where upon failure,
- the error code returned by mbedtls_mpi_write_file() is overwritten
- and therefore not printed.
diff --git a/ChangeLog.d/fix_hard_link_across_drives.txt b/ChangeLog.d/fix_hard_link_across_drives.txt
deleted file mode 100644
index 46d05c0..0000000
--- a/ChangeLog.d/fix_hard_link_across_drives.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix a build issue on Windows using CMake where the source and build
- directories could not be on different drives. Fixes #5751.
diff --git a/ChangeLog.d/fix_psa_crypto_cipher_h_include.txt b/ChangeLog.d/fix_psa_crypto_cipher_h_include.txt
deleted file mode 100644
index bf2e65d..0000000
--- a/ChangeLog.d/fix_psa_crypto_cipher_h_include.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Use double quotes to include private header file psa_crypto_cipher.h.
- Fixes 'file not found with <angled> include' error
- when building with Xcode.
diff --git a/ChangeLog.d/fix_tls13_session_resumption_fail_when_hostname_is_not_localhost.txt b/ChangeLog.d/fix_tls13_session_resumption_fail_when_hostname_is_not_localhost.txt
deleted file mode 100644
index 9f5c649..0000000
--- a/ChangeLog.d/fix_tls13_session_resumption_fail_when_hostname_is_not_localhost.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix TLS 1.3 session resumption. Fixes #6488.
- * Add a configuration check to exclude optional client authentication
- in TLS 1.3 (where it is forbidden).
diff --git a/ChangeLog.d/fix_x509_get_name_mem_leak.txt b/ChangeLog.d/fix_x509_get_name_mem_leak.txt
deleted file mode 100644
index 358d1af..0000000
--- a/ChangeLog.d/fix_x509_get_name_mem_leak.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix memory leak in ssl_parse_certificate_request() caused by
- mbedtls_x509_get_name() not freeing allocated objects in case of error.
- Change mbedtls_x509_get_name() to clean up allocated objects on error.
diff --git a/ChangeLog.d/fix_x509_info_hwmodulename.txt b/ChangeLog.d/fix_x509_info_hwmodulename.txt
deleted file mode 100644
index 8b227ce..0000000
--- a/ChangeLog.d/fix_x509_info_hwmodulename.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
- * Fix a bug in which mbedtls_x509_crt_info() would produce non-printable
- bytes when parsing certificates containing a binary RFC 4108
- HardwareModuleName as a Subject Alternative Name extension. Hardware
- serial numbers are now rendered in hex format. Fixes #6262.
diff --git a/ChangeLog.d/fix_zeroization.txt b/ChangeLog.d/fix_zeroization.txt
deleted file mode 100644
index 8b00dcc..0000000
--- a/ChangeLog.d/fix_zeroization.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix a possible null pointer dereference if a memory allocation fails
- in TLS PRF code. Reported by Michael Madsen in #6516.
diff --git a/ChangeLog.d/mbedtls_asn1_type_free.txt b/ChangeLog.d/mbedtls_asn1_type_free.txt
deleted file mode 100644
index 3459bbe..0000000
--- a/ChangeLog.d/mbedtls_asn1_type_free.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Features
- * The new functions mbedtls_asn1_free_named_data_list() and
- mbedtls_asn1_free_named_data_list_shallow() simplify the management
- of memory in named data lists in X.509 structures.
-New deprecations
- * Deprecate mbedtls_asn1_free_named_data().
- Use mbedtls_asn1_free_named_data_list()
- or mbedtls_asn1_free_named_data_list_shallow().
diff --git a/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt b/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt
new file mode 100644
index 0000000..44253dd
--- /dev/null
+++ b/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt
@@ -0,0 +1,6 @@
+Features
+ * Add support for reading points in compressed format
+ (MBEDTLS_ECP_PF_COMPRESSED) with mbedtls_ecp_point_read_binary()
+ (and callers) for Short Weierstrass curves with prime p where p = 3 mod 4
+ (all mbedtls MBEDTLS_ECP_DP_SECP* and MBEDTLS_ECP_DP_BP* curves
+ except MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1)
diff --git a/ChangeLog.d/move-ssl-modules.txt b/ChangeLog.d/move-ssl-modules.txt
deleted file mode 100644
index f00e5ad..0000000
--- a/ChangeLog.d/move-ssl-modules.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Move some SSL-specific code out of libmbedcrypto where it had been placed
- accidentally.
diff --git a/ChangeLog.d/mpi-add-0-ub.txt b/ChangeLog.d/mpi-add-0-ub.txt
deleted file mode 100644
index 9f131a4..0000000
--- a/ChangeLog.d/mpi-add-0-ub.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix undefined behavior (typically harmless in practice) of
- mbedtls_mpi_add_mpi(), mbedtls_mpi_add_abs() and mbedtls_mpi_add_int()
- when both operands are 0 and the left operand is represented with 0 limbs.
diff --git a/ChangeLog.d/mpi-most-negative-sint.txt b/ChangeLog.d/mpi-most-negative-sint.txt
deleted file mode 100644
index 5e775c4..0000000
--- a/ChangeLog.d/mpi-most-negative-sint.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
- * Fix undefined behavior (typically harmless in practice) when some bignum
- functions receive the most negative value of mbedtls_mpi_sint. Credit
- to OSS-Fuzz. Fixes #6597.
diff --git a/ChangeLog.d/muladdc_microblaze.txt b/ChangeLog.d/muladdc_microblaze.txt
deleted file mode 100644
index 70fdff0..0000000
--- a/ChangeLog.d/muladdc_microblaze.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix support for little-endian Microblaze when MBEDTLS_HAVE_ASM is defined.
- Contributed by Kazuyuki Kimura to fix #2020.
diff --git a/ChangeLog.d/negative-zero-from-add.txt b/ChangeLog.d/negative-zero-from-add.txt
deleted file mode 100644
index 107d858..0000000
--- a/ChangeLog.d/negative-zero-from-add.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Bugfix
- * In the bignum module, operations of the form (-A) - (+A) or (-A) - (-A)
- with A > 0 created an unintended representation of the value 0 which was
- not processed correctly by some bignum operations. Fix this. This had no
- consequence on cryptography code, but might affect applications that call
- bignum directly and use negative numbers.
diff --git a/ChangeLog.d/nonversioned-library-soname.txt b/ChangeLog.d/nonversioned-library-soname.txt
deleted file mode 100644
index 8d83a2d..0000000
--- a/ChangeLog.d/nonversioned-library-soname.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Features
- * make: enable building unversioned shared library, with e.g.:
- "SHARED=1 SOEXT_TLS=so SOEXT_X509=so SOEXT_CRYPTO=so make lib"
- resulting in library names like "libmbedtls.so" rather than
- "libmbedcrypto.so.11".
diff --git a/ChangeLog.d/pk-sign-restartable.txt b/ChangeLog.d/pk-sign-restartable.txt
new file mode 100644
index 0000000..35da2be
--- /dev/null
+++ b/ChangeLog.d/pk-sign-restartable.txt
@@ -0,0 +1,5 @@
+Changes
+ * When MBEDTLS_USE_PSA_CRYPTO and MBEDTLS_ECDSA_DETERMINISTIC are both
+ defined, mbedtls_pk_sign() now use deterministic ECDSA for ECDSA
+ signatures. This aligns the behaviour with MBEDTLS_USE_PSA_CRYPTO to
+ the behaviour without it, where deterministic ECDSA was already used.
diff --git a/ChangeLog.d/platform-setbuf.txt b/ChangeLog.d/platform-setbuf.txt
deleted file mode 100644
index 844f70c..0000000
--- a/ChangeLog.d/platform-setbuf.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Provide the missing definition of mbedtls_setbuf() in some configurations
- with MBEDTLS_PLATFORM_C disabled. Fixes #6118, #6196.
diff --git a/ChangeLog.d/psa-ecb-ub.txt b/ChangeLog.d/psa-ecb-ub.txt
deleted file mode 100644
index 9d725ac..0000000
--- a/ChangeLog.d/psa-ecb-ub.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
- * Fix undefined behavior (typically harmless in practice) in PSA ECB
- encryption and decryption.
diff --git a/ChangeLog.d/psa_crypto_code_gen_1_1.txt b/ChangeLog.d/psa_crypto_code_gen_1_1.txt
deleted file mode 100644
index e10a81c..0000000
--- a/ChangeLog.d/psa_crypto_code_gen_1_1.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Features
- * The PSA driver wrapper generator generate_driver_wrappers.py now
- supports a subset of the driver description language, including
- the following entry points: import_key, export_key, export_public_key,
- get_builtin_key, copy_key.
-
-Requirement changes
- * When building with PSA drivers using generate_driver_wrappers.py, or
- when building the library from the development branch rather than
- from a release, the Python module jsonschema is now necessary, in
- addition to jinja2. The official list of required Python modules is
- maintained in scripts/basic.requirements.txt and may change again
- in the future.
diff --git a/ChangeLog.d/psa_crypto_pake.txt b/ChangeLog.d/psa_crypto_pake.txt
deleted file mode 100644
index e0ae046..0000000
--- a/ChangeLog.d/psa_crypto_pake.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
- * Expose the EC J-PAKE functionality through the Draft PSA PAKE Crypto API.
- Only the ECC primitive with secp256r1 curve and SHA-256 hash algorithm
- are supported in this implementation.
diff --git a/ChangeLog.d/psa_driver_wrapper_for_raw_key_agreement.txt b/ChangeLog.d/psa_driver_wrapper_for_raw_key_agreement.txt
deleted file mode 100644
index b9c78a6..0000000
--- a/ChangeLog.d/psa_driver_wrapper_for_raw_key_agreement.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Features
- * Add a driver dispatch layer for raw key agreement, enabling alternative
- implementations of raw key agreement through the key_agreement driver
- entry point. This entry point is specified in the proposed PSA driver
- interface, but had not yet been implemented.
diff --git a/ChangeLog.d/psa_rsa_needs_pk.txt b/ChangeLog.d/psa_rsa_needs_pk.txt
deleted file mode 100644
index 995963d..0000000
--- a/ChangeLog.d/psa_rsa_needs_pk.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
- * Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not
- MBEDTLS_USE_PSA_CRYPTO or MBEDTLS_PK_WRITE_C. Fixes #6408.
- * Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not
- MBEDTLS_PK_PARSE_C. Fixes #6409.
diff --git a/ChangeLog.d/tls13-misc.txt b/ChangeLog.d/tls13-misc.txt
deleted file mode 100644
index 6733173..0000000
--- a/ChangeLog.d/tls13-misc.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Features
- * Mbed TLS now supports TLS 1.3 key establishment via pre-shared keys.
- The pre-shared keys can be provisioned externally or via the ticket
- mechanism (session resumption).
- The ticket mechanism is supported when the configuration option
- MBEDTLS_SSL_SESSION_TICKETS is enabled.
- New options MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_xxx_ENABLED
- control the support for the three possible TLS 1.3 key exchange modes.
diff --git a/ChangeLog.d/tls13_sig_alg_selection.txt b/ChangeLog.d/tls13_sig_alg_selection.txt
deleted file mode 100644
index 8857750..0000000
--- a/ChangeLog.d/tls13_sig_alg_selection.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
- * Add support for opaque keys as the private keys associated to certificates
- for authentication in TLS 1.3.
diff --git a/ChangeLog.d/x509-broken-symlink-handling.txt b/ChangeLog.d/x509-broken-symlink-handling.txt
deleted file mode 100644
index 52288dc..0000000
--- a/ChangeLog.d/x509-broken-symlink-handling.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
- * Fix handling of broken symlinks when loading certificates using
- mbedtls_x509_crt_parse_path(). Instead of returning an error as soon as a
- broken link is encountered, skip the broken link and continue parsing
- other certificate files. Contributed by Eduardo Silva in #2602.
diff --git a/Makefile b/Makefile
index 5b2ad16..2f1be65 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ PERL ?= perl
.SILENT:
-.PHONY: all no_test programs lib tests install uninstall clean test check covtest lcov apidoc apidoc_clean
+.PHONY: all no_test programs lib tests install uninstall clean test check lcov apidoc apidoc_clean
all: programs tests
$(MAKE) post_build
@@ -136,23 +136,15 @@ check: lib tests
test: check
ifndef WINDOWS
-# note: for coverage testing, build with:
-# make CFLAGS='--coverage -g3 -O0'
-covtest:
- $(MAKE) check
- programs/test/selftest
- tests/compat.sh
- tests/ssl-opt.sh
-
+# For coverage testing:
+# 1. Build with:
+# make CFLAGS='--coverage -g3 -O0' LDFLAGS='--coverage'
+# 2. Run the relevant tests for the part of the code you're interested in.
+# For the reference coverage measurement, see
+# tests/scripts/basic-build-test.sh
+# 3. Run scripts/lcov.sh to generate an HTML report.
lcov:
- rm -rf Coverage
- lcov --capture --initial --directory library -o files.info
- lcov --rc lcov_branch_coverage=1 --capture --directory library -o tests.info
- lcov --rc lcov_branch_coverage=1 --add-tracefile files.info --add-tracefile tests.info -o all.info
- lcov --rc lcov_branch_coverage=1 --remove all.info -o final.info '*.h'
- gendesc tests/Descriptions.txt -o descriptions
- genhtml --title "mbed TLS" --description-file descriptions --keep-descriptions --legend --branch-coverage -o Coverage final.info
- rm -f files.info tests.info all.info final.info descriptions
+ scripts/lcov.sh
apidoc:
mkdir -p apidoc
diff --git a/README.md b/README.md
index 8a23bd2..cc70f56 100644
--- a/README.md
+++ b/README.md
@@ -245,6 +245,8 @@ For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, ad
- `tests/scripts/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on.
- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc).
+Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start).
+
Porting Mbed TLS
----------------
diff --git a/docs/architecture/psa-migration/psa-limitations.md b/docs/architecture/psa-migration/psa-limitations.md
index e565b28..c368023 100644
--- a/docs/architecture/psa-migration/psa-limitations.md
+++ b/docs/architecture/psa-migration/psa-limitations.md
@@ -17,8 +17,11 @@ Restartable ECC operations
There is currently no support for that in PSA at all, but it will be added at
some point, see <https://github.com/orgs/Mbed-TLS/projects/1#column-18816849>.
-Currently, `MBEDTLS_USE_PSA_CRYPTO` is simply incompatible with
-`MBEDTLS_ECP_RESTARTABLE`.
+Currently, when `MBEDTLS_USE_PSA_CRYPTO` and `MBEDTLS_ECP_RESTARTABLE` are
+both enabled, some operations that should be restartable are not (ECDH in TLS
+1.2 clients using ECDHE-ECDSA), as they are using PSA instead, and some
+operations that should use PSA do not (signature generation & verification) as
+they use the legacy API instead, in order to get restartable behaviour.
Things that are in the API but not implemented yet
--------------------------------------------------
diff --git a/docs/use-psa-crypto.md b/docs/use-psa-crypto.md
index 11442ed..fc5317a 100644
--- a/docs/use-psa-crypto.md
+++ b/docs/use-psa-crypto.md
@@ -7,9 +7,6 @@ operations, and enables new APIs for using keys handled by PSA Crypto.
General considerations
----------------------
-**Compile-time:** enabling `MBEDTLS_USE_PSA_CRYPTO` requires
-`MBEDTLS_ECP_RESTARTABLE` to be disabled.
-
**Application code:** when this option is enabled, you need to call
`psa_crypto_init()` before calling any function from the SSL/TLS, X.509 or PK
module.
@@ -86,29 +83,33 @@ is enabled, no change required on the application side.
Current exceptions:
-- finite-field (non-EC) Diffie-Hellman (used in key exchanges: DHE-RSA,
- DHE-PSK)
+- Finite-field (non-EC) Diffie-Hellman (used in key exchanges: DHE-RSA,
+ DHE-PSK).
+- Restartable operations when `MBEDTLS_ECP_RESTARTABLE` is also enabled (see
+ the documentation of that option).
Other than the above exceptions, all crypto operations are based on PSA when
`MBEDTLS_USE_PSA_CRYPTO` is enabled.
### X.509: most crypto operations based on PSA
-Current exception:
+Current exceptions:
-- verification of RSA-PSS signatures with a salt length that is different from
- the hash length.
+- Restartable operations when `MBEDTLS_ECP_RESTARTABLE` is also enabled (see
+ the documentation of that option).
Other than the above exception, all crypto operations are based on PSA when
`MBEDTLS_USE_PSA_CRYPTO` is enabled.
### PK layer: most crypto operations based on PSA
-Current exception:
+Current exceptions:
-- verification of RSA-PSS signatures with a salt length that is different from
- the hash length, or with an MGF hash that's different from the message hash.
+- Verification of RSA-PSS signatures with an MGF hash that's different from
+ the message hash.
+- Restartable operations when `MBEDTLS_ECP_RESTARTABLE` is also enabled (see
+ the documentation of that option).
-Other than the above exception, all crypto operations are based on PSA when
+Other than the above exceptions, all crypto operations are based on PSA when
`MBEDTLS_USE_PSA_CRYPTO` is enabled.
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index c05042b..7c6464f 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -22,7 +22,7 @@
*/
/**
- * @mainpage mbed TLS v3.2.1 source code documentation
+ * @mainpage mbed TLS v3.3.0 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 f722d28..0c744da 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -1,4 +1,4 @@
-PROJECT_NAME = "mbed TLS v3.2.1"
+PROJECT_NAME = "mbed TLS v3.3.0"
OUTPUT_DIRECTORY = ../apidoc/
FULL_PATH_NAMES = NO
OPTIMIZE_OUTPUT_FOR_C = YES
diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h
index 362ce2f..049a120 100644
--- a/include/mbedtls/build_info.h
+++ b/include/mbedtls/build_info.h
@@ -37,17 +37,17 @@
* Major, Minor, Patchlevel
*/
#define MBEDTLS_VERSION_MAJOR 3
-#define MBEDTLS_VERSION_MINOR 2
-#define MBEDTLS_VERSION_PATCH 1
+#define MBEDTLS_VERSION_MINOR 3
+#define MBEDTLS_VERSION_PATCH 0
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x03020100
-#define MBEDTLS_VERSION_STRING "3.2.1"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 3.2.1"
+#define MBEDTLS_VERSION_NUMBER 0x03030000
+#define MBEDTLS_VERSION_STRING "3.3.0"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 3.3.0"
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
#define _CRT_SECURE_NO_DEPRECATE 1
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 5760c9f..677be87 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -117,15 +117,19 @@
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE) && \
- ( defined(MBEDTLS_USE_PSA_CRYPTO) || \
- defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \
+ ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \
defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \
defined(MBEDTLS_ECDSA_SIGN_ALT) || \
defined(MBEDTLS_ECDSA_VERIFY_ALT) || \
defined(MBEDTLS_ECDSA_GENKEY_ALT) || \
defined(MBEDTLS_ECP_INTERNAL_ALT) || \
defined(MBEDTLS_ECP_ALT) )
-#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation"
+#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation"
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE) && \
+ !defined(MBEDTLS_ECP_C)
+#error "MBEDTLS_ECP_RESTARTABLE defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 14dc150..092152d 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -690,11 +690,42 @@
* This is useful in non-threaded environments if you want to avoid blocking
* for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
*
- * Uncomment this macro to enable restartable ECC computations.
+ * This option:
+ * - Adds xxx_restartable() variants of existing operations in the
+ * following modules, with corresponding restart context types:
+ * - ECP (for Short Weierstrass curves only): scalar multiplication (mul),
+ * linear combination (muladd);
+ * - ECDSA: signature generation & verification;
+ * - PK: signature generation & verification;
+ * - X509: certificate chain verification.
+ * - Adds mbedtls_ecdh_enable_restart() in the ECDH module.
+ * - Changes the behaviour of TLS 1.2 clients (not servers) when using the
+ * ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC
+ * computations restartable:
+ * - ECDH operations from the key exchange, only for Short Weierstass
+ * curves, only when MBEDTLS_USE_PSA_CRYPTO is not enabled.
+ * - verification of the server's key exchange signature;
+ * - verification of the server's certificate chain;
+ * - generation of the client's signature if client authentication is used,
+ * with an ECC key/certificate.
+ *
+ * \note In the cases above, the usual SSL/TLS functions, such as
+ * mbedtls_ssl_handshake(), can now return
+ * MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS.
+ *
+ * \note When this option and MBEDTLS_USE_PSA_CRYPTO are both enabled,
+ * restartable operations in PK, X.509 and TLS (see above) are not
+ * using PSA. On the other hand, ECDH computations in TLS are using
+ * PSA, and are not restartable. These are temporary limitations that
+ * should be lifted in the future.
*
* \note This option only works with the default software implementation of
* elliptic curve functionality. It is incompatible with
* MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT.
+ *
+ * Requires: MBEDTLS_ECP_C
+ *
+ * Uncomment this macro to enable restartable ECC computations.
*/
//#define MBEDTLS_ECP_RESTARTABLE
@@ -1923,7 +1954,6 @@
* before calling any function from the SSL/TLS, X.509 or PK modules.
*
* Requires: MBEDTLS_PSA_CRYPTO_C.
- * Conflicts with: MBEDTLS_ECP_RESTARTABLE
*
* Uncomment this to enable internal use of PSA Crypto and new associated APIs.
*/
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index db0bfac..386ec42 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -496,7 +496,9 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
*
* \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point
* to a mbedtls_pk_rsassa_pss_options structure,
- * otherwise it must be NULL.
+ * otherwise it must be NULL. Note that if
+ * #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not
+ * verified as PSA_ALG_RSA_PSS_ANY_SALT is used.
*/
int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 3f48377..7751560 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -3899,6 +3899,23 @@ void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf,
int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
const unsigned char *pw,
size_t pw_len );
+
+/**
+ * \brief Set the EC J-PAKE opaque password for current handshake.
+ *
+ * \note The key must remain valid until the handshake is over.
+ *
+ * \note The SSL context needs to be already set up. The right place
+ * to call this function is between \c mbedtls_ssl_setup() or
+ * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake().
+ *
+ * \param ssl SSL context
+ * \param pwd EC J-PAKE opaque password
+ *
+ * \return 0 on success, or a negative error code.
+ */
+int mbedtls_ssl_set_hs_ecjpake_password_opaque( mbedtls_ssl_context *ssl,
+ mbedtls_svc_key_id_t pwd );
#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_ALPN)
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 8106dab..c9714bb 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -282,7 +282,7 @@ endif(USE_STATIC_MBEDTLS_LIBRARY)
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 3.2.1 SOVERSION 12)
+ set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.3.0 SOVERSION 13)
target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
if(TARGET everest)
@@ -290,11 +290,11 @@ if(USE_SHARED_MBEDTLS_LIBRARY)
endif()
add_library(${mbedx509_target} SHARED ${src_x509})
- set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.2.1 SOVERSION 4)
+ set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.3.0 SOVERSION 4)
target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
add_library(${mbedtls_target} SHARED ${src_tls})
- set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.2.1 SOVERSION 18)
+ set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.3.0 SOVERSION 19)
target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
endif(USE_SHARED_MBEDTLS_LIBRARY)
diff --git a/library/Makefile b/library/Makefile
index 5073517..dd16d06 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -47,9 +47,9 @@ LOCAL_CFLAGS += -fPIC -fpic
endif
endif
-SOEXT_TLS?=so.18
+SOEXT_TLS?=so.19
SOEXT_X509?=so.4
-SOEXT_CRYPTO?=so.12
+SOEXT_CRYPTO?=so.13
# Set AR_DASH= (empty string) to use an ar implementation that does not accept
# the - prefix for command line options (e.g. llvm-ar)
diff --git a/library/bignum.c b/library/bignum.c
index a68957a..fc4ddf6 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1590,11 +1590,11 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
mbedtls_mpi *prec_RR )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t wbits, wsize, one = 1;
+ size_t window_bitsize;
size_t i, j, nblimbs;
size_t bufsize, nbits;
mbedtls_mpi_uint ei, mm, state;
- mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
+ mbedtls_mpi RR, T, W[ (size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
int neg;
MPI_VALIDATE_RET( X != NULL );
@@ -1623,21 +1623,59 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
i = mbedtls_mpi_bitlen( E );
- wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+ window_bitsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
- if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
- wsize = MBEDTLS_MPI_WINDOW_SIZE;
+ if( window_bitsize > MBEDTLS_MPI_WINDOW_SIZE )
+ window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
#endif
+ const size_t w_table_used_size = (size_t) 1 << window_bitsize;
+
+ /*
+ * This function is not constant-trace: its memory accesses depend on the
+ * exponent value. To defend against timing attacks, callers (such as RSA
+ * and DHM) should use exponent blinding. However this is not enough if the
+ * adversary can find the exponent in a single trace, so this function
+ * takes extra precautions against adversaries who can observe memory
+ * access patterns.
+ *
+ * This function performs a series of multiplications by table elements and
+ * squarings, and we want the prevent the adversary from finding out which
+ * table element was used, and from distinguishing between multiplications
+ * 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.
+ *
+ * This way, all multiplications take the form of a lookup-and-multiply.
+ * The number of lookup-and-multiply operations inside each iteration of
+ * the main loop still depends on the bits of the exponent, but since the
+ * other operations in the loop don't have an easily recognizable memory
+ * trace, an adversary is unlikely to be able to observe the exact
+ * patterns.
+ *
+ * An adversary may still be able to recover the exponent if they can
+ * 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!
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[x_index], j ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
@@ -1686,28 +1724,36 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
mpi_montmul( &W[1], &RR, N, mm, &T );
/*
- * X = R^2 * R^-1 mod N = R mod N
+ * W[x_index] = R^2 * R^-1 mod N = R mod N
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
- mpi_montred( X, N, mm, &T );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[x_index], &RR ) );
+ mpi_montred( &W[x_index], N, mm, &T );
- if( wsize > 1 )
+
+ if( window_bitsize > 1 )
{
/*
- * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+ * W[i] = W[1] ^ i
+ *
+ * The first bit of the sliding window is always 1 and therefore we
+ * only need to store the second half of the table.
+ *
+ * (There are two special elements in the table: W[0] for the
+ * accumulator/result and W[1] for A in Montgomery form. Both of these
+ * are already set at this point.)
*/
- j = one << ( wsize - 1 );
+ j = w_table_used_size / 2;
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
- for( i = 0; i < wsize - 1; i++ )
+ for( i = 0; i < window_bitsize - 1; i++ )
mpi_montmul( &W[j], &W[j], N, mm, &T );
/*
* W[i] = W[i - 1] * W[1]
*/
- for( i = j + 1; i < ( one << wsize ); i++ )
+ for( i = j + 1; i < w_table_used_size; i++ )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
@@ -1719,7 +1765,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
nblimbs = E->n;
bufsize = 0;
nbits = 0;
- wbits = 0;
+ size_t exponent_bits_in_window = 0;
state = 0;
while( 1 )
@@ -1747,9 +1793,10 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
if( ei == 0 && state == 1 )
{
/*
- * out of window, square X
+ * out of window, square W[x_index]
*/
- mpi_montmul( X, X, N, mm, &T );
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size, x_index ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
continue;
}
@@ -1759,25 +1806,30 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
state = 2;
nbits++;
- wbits |= ( ei << ( wsize - nbits ) );
+ exponent_bits_in_window |= ( ei << ( window_bitsize - nbits ) );
- if( nbits == wsize )
+ if( nbits == window_bitsize )
{
/*
- * X = X^wsize R^-1 mod N
+ * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
*/
- for( i = 0; i < wsize; i++ )
- mpi_montmul( X, X, N, mm, &T );
+ for( i = 0; i < window_bitsize; i++ )
+ {
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size,
+ x_index ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
+ }
/*
- * X = X * W[wbits] R^-1 mod N
+ * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
*/
- MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
- mpi_montmul( X, &WW, N, mm, &T );
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size,
+ exponent_bits_in_window ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
state--;
nbits = 0;
- wbits = 0;
+ exponent_bits_in_window = 0;
}
}
@@ -1786,31 +1838,45 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
*/
for( i = 0; i < nbits; i++ )
{
- mpi_montmul( X, X, N, mm, &T );
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size, x_index ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
- wbits <<= 1;
+ exponent_bits_in_window <<= 1;
- if( ( wbits & ( one << wsize ) ) != 0 )
- mpi_montmul( X, &W[1], N, mm, &T );
+ if( ( exponent_bits_in_window & ( (size_t) 1 << window_bitsize ) ) != 0 )
+ {
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, w_table_used_size, 1 ) );
+ mpi_montmul( &W[x_index], &WW, N, mm, &T );
+ }
}
/*
- * X = A^E * R * R^-1 mod N = A^E mod N
+ * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
*/
- mpi_montred( X, N, mm, &T );
+ mpi_montred( &W[x_index], N, mm, &T );
if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
{
- X->s = -1;
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
+ W[x_index].s = -1;
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &W[x_index], N, &W[x_index] ) );
}
+ /*
+ * Load the result in the output variable.
+ */
+ mbedtls_mpi_copy( X, &W[x_index] );
+
cleanup:
- for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
+ /* The first bit of the sliding window is always 1 and therefore the first
+ * half of the table was unused. */
+ for( i = w_table_used_size/2; i < w_table_used_size; i++ )
mbedtls_mpi_free( &W[i] );
- mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
+ mbedtls_mpi_free( &W[x_index] );
+ mbedtls_mpi_free( &W[1] );
+ mbedtls_mpi_free( &T );
+ mbedtls_mpi_free( &Apos );
mbedtls_mpi_free( &WW );
if( prec_RR == NULL || prec_RR->p == NULL )
@@ -1966,75 +2032,19 @@ int mbedtls_mpi_random( mbedtls_mpi *X,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
- int count;
- unsigned lt_lower = 1, lt_upper = 0;
- size_t n_bits = mbedtls_mpi_bitlen( N );
- size_t n_bytes = ( n_bits + 7 ) / 8;
- mbedtls_mpi lower_bound;
-
if( min < 0 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
- /*
- * When min == 0, each try has at worst a probability 1/2 of failing
- * (the msb has a probability 1/2 of being 0, and then the result will
- * be < N), so after 30 tries failure probability is a most 2**(-30).
- *
- * When N is just below a power of 2, as is the case when generating
- * a random scalar on most elliptic curves, 1 try is enough with
- * overwhelming probability. When N is just above a power of 2,
- * as when generating a random scalar on secp224k1, each try has
- * a probability of failing that is almost 1/2.
- *
- * The probabilities are almost the same if min is nonzero but negligible
- * compared to N. This is always the case when N is crypto-sized, but
- * it's convenient to support small N for testing purposes. When N
- * is small, use a higher repeat count, otherwise the probability of
- * failure is macroscopic.
- */
- count = ( n_bytes > 4 ? 30 : 250 );
-
- mbedtls_mpi_init( &lower_bound );
-
/* Ensure that target MPI has exactly the same number of limbs
* as the upper bound, even if the upper bound has leading zeros.
- * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
- MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
-
- /*
- * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
- * when f_rng is a suitably parametrized instance of HMAC_DRBG:
- * - use the same byte ordering;
- * - keep the leftmost n_bits bits of the generated octet string;
- * - try until result is in the desired range.
- * This also avoids any bias, which is especially important for ECDSA.
- */
- do
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_core_fill_random( X->p, X->n,
- n_bytes,
- f_rng, p_rng ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
-
- if( --count == 0 )
- {
- ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
- goto cleanup;
- }
-
- MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
- }
- while( lt_lower != 0 || lt_upper == 0 );
+ * This is necessary for mbedtls_mpi_core_random. */
+ int ret = mbedtls_mpi_resize_clear( X, N->n );
+ if( ret != 0 )
+ return( ret );
-cleanup:
- mbedtls_mpi_free( &lower_bound );
- return( ret );
+ return( mbedtls_mpi_core_random( X->p, min, N->p, X->n, f_rng, p_rng ) );
}
/*
diff --git a/library/bignum_core.c b/library/bignum_core.c
index 1ce8457..bda62f2 100644
--- a/library/bignum_core.c
+++ b/library/bignum_core.c
@@ -134,6 +134,27 @@ void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
}
}
+/* Whether min <= A, in constant time.
+ * A_limbs must be at least 1. */
+unsigned mbedtls_mpi_core_uint_le_mpi( mbedtls_mpi_uint min,
+ const mbedtls_mpi_uint *A,
+ size_t A_limbs )
+{
+ /* min <= least significant limb? */
+ unsigned min_le_lsl = 1 ^ mbedtls_ct_mpi_uint_lt( A[0], min );
+
+ /* limbs other than the least significant one are all zero? */
+ mbedtls_mpi_uint msll_mask = 0;
+ for( size_t i = 1; i < A_limbs; i++ )
+ msll_mask |= A[i];
+ /* The most significant limbs of A are not all zero iff msll_mask != 0. */
+ unsigned msll_nonzero = mbedtls_ct_mpi_uint_mask( msll_mask ) & 1;
+
+ /* min <= A iff the lowest limb of A is >= min or the other limbs
+ * are not all zero. */
+ return( min_le_lsl | msll_nonzero );
+}
+
void mbedtls_mpi_core_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
@@ -561,6 +582,67 @@ cleanup:
return( ret );
}
+int mbedtls_mpi_core_random( mbedtls_mpi_uint *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_uint *N,
+ size_t limbs,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ unsigned ge_lower = 1, lt_upper = 0;
+ size_t n_bits = mbedtls_mpi_core_bitlen( N, limbs );
+ size_t n_bytes = ( n_bits + 7 ) / 8;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ /*
+ * When min == 0, each try has at worst a probability 1/2 of failing
+ * (the msb has a probability 1/2 of being 0, and then the result will
+ * be < N), so after 30 tries failure probability is a most 2**(-30).
+ *
+ * When N is just below a power of 2, as is the case when generating
+ * a random scalar on most elliptic curves, 1 try is enough with
+ * overwhelming probability. When N is just above a power of 2,
+ * as when generating a random scalar on secp224k1, each try has
+ * a probability of failing that is almost 1/2.
+ *
+ * The probabilities are almost the same if min is nonzero but negligible
+ * compared to N. This is always the case when N is crypto-sized, but
+ * it's convenient to support small N for testing purposes. When N
+ * is small, use a higher repeat count, otherwise the probability of
+ * failure is macroscopic.
+ */
+ int count = ( n_bytes > 4 ? 30 : 250 );
+
+ /*
+ * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
+ * when f_rng is a suitably parametrized instance of HMAC_DRBG:
+ * - use the same byte ordering;
+ * - keep the leftmost n_bits bits of the generated octet string;
+ * - try until result is in the desired range.
+ * This also avoids any bias, which is especially important for ECDSA.
+ */
+ do
+ {
+ MBEDTLS_MPI_CHK( mbedtls_mpi_core_fill_random( X, limbs,
+ n_bytes,
+ f_rng, p_rng ) );
+ mbedtls_mpi_core_shift_r( X, limbs, 8 * n_bytes - n_bits );
+
+ if( --count == 0 )
+ {
+ ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+ goto cleanup;
+ }
+
+ ge_lower = mbedtls_mpi_core_uint_le_mpi( min, X, limbs );
+ lt_upper = mbedtls_mpi_core_lt_ct( X, N, limbs );
+ }
+ while( ge_lower == 0 || lt_upper == 0 );
+
+cleanup:
+ return( ret );
+}
+
/* BEGIN MERGE SLOT 1 */
static size_t exp_mod_get_window_size( size_t Ebits )
@@ -742,6 +824,40 @@ mbedtls_mpi_uint mbedtls_mpi_core_sub_int( mbedtls_mpi_uint *X,
return( c );
}
+mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct( const mbedtls_mpi_uint *A,
+ size_t limbs )
+{
+ mbedtls_mpi_uint bits = 0;
+
+ for( size_t i = 0; i < limbs; i++ )
+ bits |= A[i];
+
+ return( bits );
+}
+
+void mbedtls_mpi_core_to_mont_rep( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_uint *A,
+ const mbedtls_mpi_uint *N,
+ size_t AN_limbs,
+ mbedtls_mpi_uint mm,
+ const mbedtls_mpi_uint *rr,
+ mbedtls_mpi_uint *T )
+{
+ mbedtls_mpi_core_montmul( X, A, rr, AN_limbs, N, AN_limbs, mm, T );
+}
+
+void mbedtls_mpi_core_from_mont_rep( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_uint *A,
+ const mbedtls_mpi_uint *N,
+ size_t AN_limbs,
+ mbedtls_mpi_uint mm,
+ mbedtls_mpi_uint *T )
+{
+ const mbedtls_mpi_uint Rinv = 1; /* 1/R in Mont. rep => 1 */
+
+ mbedtls_mpi_core_montmul( X, A, &Rinv, 1, N, AN_limbs, mm, T );
+}
+
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
diff --git a/library/bignum_core.h b/library/bignum_core.h
index b7af4d0..771f208 100644
--- a/library/bignum_core.h
+++ b/library/bignum_core.h
@@ -129,6 +129,22 @@ size_t mbedtls_mpi_core_bitlen( const mbedtls_mpi_uint *A, size_t A_limbs );
void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
size_t A_limbs );
+/** \brief Compare a machine integer with an MPI.
+ *
+ * This function operates in constant time with respect
+ * to the values of \p min and \p A.
+ *
+ * \param min A machine integer.
+ * \param[in] A An MPI.
+ * \param A_limbs The number of limbs of \p A.
+ * This must be at least 1.
+ *
+ * \return 1 if \p min is less than or equal to \p A, otherwise 0.
+ */
+unsigned mbedtls_mpi_core_uint_le_mpi( mbedtls_mpi_uint min,
+ const mbedtls_mpi_uint *A,
+ size_t A_limbs );
+
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether assignment was done or not.
@@ -496,12 +512,53 @@ int mbedtls_mpi_core_fill_random( mbedtls_mpi_uint *X, size_t X_limbs,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note There are `N - min` possible outputs. The lower bound
+ * \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X The destination MPI, with \p limbs limbs.
+ * It must not be aliased with \p N or otherwise overlap it.
+ * \param min The minimum value to return.
+ * \param N The upper bound of the range, exclusive, with \p limbs limbs.
+ * In other words, this is one plus the maximum value to return.
+ * \p N must be strictly larger than \p min.
+ * \param limbs The number of limbs of \p N and \p X.
+ * This must not be 0.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ * unable to find a suitable value within a limited number
+ * of attempts. This has a negligible probability if \p N
+ * is significantly larger than \p min, which is the case
+ * for all usual cryptographic applications.
+ */
+int mbedtls_mpi_core_random( mbedtls_mpi_uint *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_uint *N,
+ size_t limbs,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
/* BEGIN MERGE SLOT 1 */
/**
* \brief Returns the number of limbs of working memory required for
* a call to `mbedtls_mpi_core_exp_mod()`.
*
+ * \note This will always be at least
+ * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`,
+ * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`.
+ *
* \param AN_limbs The number of limbs in the input `A` and the modulus `N`
* (they must be the same size) that will be given to
* `mbedtls_mpi_core_exp_mod()`.
@@ -572,6 +629,111 @@ mbedtls_mpi_uint mbedtls_mpi_core_sub_int( mbedtls_mpi_uint *X,
mbedtls_mpi_uint b,
size_t limbs );
+/**
+ * \brief Determine if a given MPI has the value \c 0 in constant time with
+ * respect to the value (but not with respect to the number of limbs).
+ *
+ * \param[in] A The MPI to test.
+ * \param limbs Number of limbs in \p A.
+ *
+ * \return 0 if `A == 0`
+ * non-0 (may be any value) if `A != 0`.
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct( const mbedtls_mpi_uint *A,
+ size_t limbs );
+
+/**
+ * \brief Returns the number of limbs of working memory required for
+ * a call to `mbedtls_mpi_core_montmul()`.
+ *
+ * \param AN_limbs The number of limbs in the input `A` and the modulus `N`
+ * (they must be the same size) that will be given to
+ * `mbedtls_mpi_core_montmul()` or one of the other functions
+ * that specifies this as the amount of working memory needed.
+ *
+ * \return The number of limbs of working memory required by
+ * `mbedtls_mpi_core_montmul()` (or other similar function).
+ */
+static inline size_t mbedtls_mpi_core_montmul_working_limbs( size_t AN_limbs )
+{
+ return( 2 * AN_limbs + 1 );
+}
+
+/** Convert an MPI into Montgomery form.
+ *
+ * \p X may be aliased to \p A, but may not otherwise overlap it.
+ *
+ * \p X may not alias \p N (it is in canonical form, so must be stricly less
+ * than \p N). Nor may it alias or overlap \p rr (this is unlikely to be
+ * required in practice.)
+ *
+ * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is
+ * an alternative to calling `mbedtls_mpi_mod_raw_to_mont_rep()` when we
+ * don't want to allocate memory.
+ *
+ * \param[out] X The result of the conversion.
+ * Must have the same number of limbs as \p A.
+ * \param[in] A The MPI to convert into Montgomery form.
+ * Must have the same number of limbs as the modulus.
+ * \param[in] N The address of the modulus, which gives the size of
+ * the base `R` = 2^(biL*N->limbs).
+ * \param[in] AN_limbs The number of limbs in \p X, \p A, \p N and \p rr.
+ * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL.
+ * This can be determined by calling
+ * `mbedtls_mpi_core_montmul_init()`.
+ * \param[in] rr The residue for `2^{2*n*biL} mod N`.
+ * \param[in,out] T Temporary storage of size at least
+ * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`
+ * limbs.
+ * Its initial content is unused and
+ * its final content is indeterminate.
+ * It must not alias or otherwise overlap any of the
+ * other parameters.
+ */
+void mbedtls_mpi_core_to_mont_rep( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_uint *A,
+ const mbedtls_mpi_uint *N,
+ size_t AN_limbs,
+ mbedtls_mpi_uint mm,
+ const mbedtls_mpi_uint *rr,
+ mbedtls_mpi_uint *T );
+
+/** Convert an MPI from Montgomery form.
+ *
+ * \p X may be aliased to \p A, but may not otherwise overlap it.
+ *
+ * \p X may not alias \p N (it is in canonical form, so must be stricly less
+ * than \p N).
+ *
+ * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is
+ * an alternative to calling `mbedtls_mpi_mod_raw_from_mont_rep()` when we
+ * don't want to allocate memory.
+ *
+ * \param[out] X The result of the conversion.
+ * Must have the same number of limbs as \p A.
+ * \param[in] A The MPI to convert from Montgomery form.
+ * Must have the same number of limbs as the modulus.
+ * \param[in] N The address of the modulus, which gives the size of
+ * the base `R` = 2^(biL*N->limbs).
+ * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N.
+ * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL.
+ * This can be determined by calling
+ * `mbedtls_mpi_core_montmul_init()`.
+ * \param[in,out] T Temporary storage of size at least
+ * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`
+ * limbs.
+ * Its initial content is unused and
+ * its final content is indeterminate.
+ * It must not alias or otherwise overlap any of the
+ * other parameters.
+ */
+void mbedtls_mpi_core_from_mont_rep( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_uint *A,
+ const mbedtls_mpi_uint *N,
+ size_t AN_limbs,
+ mbedtls_mpi_uint mm,
+ mbedtls_mpi_uint *T );
+
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
diff --git a/library/bignum_mod.c b/library/bignum_mod.c
index 7cf2fb2..bd67241 100644
--- a/library/bignum_mod.c
+++ b/library/bignum_mod.c
@@ -79,7 +79,7 @@ void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m )
if (m->rep.mont.rr != NULL)
{
mbedtls_platform_zeroize( (mbedtls_mpi_uint *) m->rep.mont.rr,
- m->limbs );
+ m->limbs * sizeof(mbedtls_mpi_uint) );
mbedtls_free( (mbedtls_mpi_uint *)m->rep.mont.rr );
m->rep.mont.rr = NULL;
}
@@ -176,6 +176,28 @@ exit:
/* BEGIN MERGE SLOT 2 */
+int mbedtls_mpi_mod_mul( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_residue *B,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ if( N->limbs == 0 )
+ return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+ if( X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs )
+ return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+ mbedtls_mpi_uint *T = mbedtls_calloc( N->limbs * 2 + 1, ciL );
+ if( T == NULL )
+ return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+
+ mbedtls_mpi_mod_raw_mul( X->p, A->p, B->p, N, T );
+
+ mbedtls_free( T );
+
+ return( 0 );
+}
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
@@ -191,6 +213,95 @@ int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X,
return( 0 );
}
+
+static int mbedtls_mpi_mod_inv_mont( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_modulus *N,
+ mbedtls_mpi_uint *working_memory )
+{
+ /* Input already in Montgomery form, so there's little to do */
+ mbedtls_mpi_mod_raw_inv_prime( X->p, A->p,
+ N->p, N->limbs,
+ N->rep.mont.rr,
+ working_memory );
+ return( 0 );
+}
+
+static int mbedtls_mpi_mod_inv_non_mont( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_modulus *N,
+ mbedtls_mpi_uint *working_memory )
+{
+ /* Need to convert input into Montgomery form */
+
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ mbedtls_mpi_mod_modulus Nmont;
+ mbedtls_mpi_mod_modulus_init( &Nmont );
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_modulus_setup( &Nmont, N->p, N->limbs,
+ MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+ /* We'll use X->p to hold the Montgomery form of the input A->p */
+ mbedtls_mpi_core_to_mont_rep( X->p, A->p, Nmont.p, Nmont.limbs,
+ Nmont.rep.mont.mm, Nmont.rep.mont.rr,
+ working_memory );
+
+ mbedtls_mpi_mod_raw_inv_prime( X->p, X->p,
+ Nmont.p, Nmont.limbs,
+ Nmont.rep.mont.rr,
+ working_memory );
+
+ /* And convert back from Montgomery form */
+
+ mbedtls_mpi_core_from_mont_rep( X->p, X->p, Nmont.p, Nmont.limbs,
+ Nmont.rep.mont.mm, working_memory );
+
+cleanup:
+ mbedtls_mpi_mod_modulus_free( &Nmont );
+ return( ret );
+}
+
+int mbedtls_mpi_mod_inv( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ if( X->limbs != N->limbs || A->limbs != N->limbs )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+ /* Zero has the same value regardless of Montgomery form or not */
+ if( mbedtls_mpi_core_check_zero_ct( A->p, A->limbs ) == 0 )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+ size_t working_limbs =
+ mbedtls_mpi_mod_raw_inv_prime_working_limbs( N->limbs );
+
+ mbedtls_mpi_uint *working_memory = mbedtls_calloc( working_limbs,
+ sizeof(mbedtls_mpi_uint) );
+ if( working_memory == NULL )
+ return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ switch( N->int_rep )
+ {
+ case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+ ret = mbedtls_mpi_mod_inv_mont( X, A, N, working_memory );
+ break;
+ case MBEDTLS_MPI_MOD_REP_OPT_RED:
+ ret = mbedtls_mpi_mod_inv_non_mont( X, A, N, working_memory );
+ break;
+ default:
+ ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+ break;
+ }
+
+ mbedtls_platform_zeroize( working_memory,
+ working_limbs * sizeof(mbedtls_mpi_uint) );
+ mbedtls_free( working_memory );
+
+ return ret;
+}
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
@@ -198,11 +309,33 @@ int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X,
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
+int mbedtls_mpi_mod_add( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_residue *B,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ if( X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);
+
+ return( 0 );
+}
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
+int mbedtls_mpi_mod_random( mbedtls_mpi_mod_residue *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_mod_modulus *N,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ if( X->limbs != N->limbs )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ return( mbedtls_mpi_mod_raw_random( X->p, min, N, f_rng, p_rng ) );
+}
+
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
@@ -226,8 +359,7 @@ int mbedtls_mpi_mod_read( mbedtls_mpi_mod_residue *r,
r->limbs = m->limbs;
- if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
- ret = mbedtls_mpi_mod_raw_to_mont_rep( r->p, m );
+ ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep( r->p, m );
cleanup:
return ( ret );
diff --git a/library/bignum_mod.h b/library/bignum_mod.h
index 0a8f4d3..1b1e920 100644
--- a/library/bignum_mod.h
+++ b/library/bignum_mod.h
@@ -2,6 +2,63 @@
* Modular bignum functions
*
* This module implements operations on integers modulo some fixed modulus.
+ *
+ * The functions in this module obey the following conventions unless
+ * explicitly indicated otherwise:
+ *
+ * - **Modulus parameters**: the modulus is passed as a pointer to a structure
+ * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an
+ * array of limbs storing the bignum value of the modulus. The modulus must
+ * be odd and is assumed to have no leading zeroes. The modulus is usually
+ * named \c N and is usually input-only. Functions which take a parameter
+ * of type \c const #mbedtls_mpi_mod_modulus* must not modify its value.
+ * - **Bignum parameters**: Bignums are passed as pointers to an array of
+ * limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type
+ * #mbedtls_mpi_uint. Residues must be initialized before use, and must be
+ * associated with the modulus \c N. Unless otherwise specified:
+ * - Bignum parameters called \c A, \c B, ... are inputs and are not
+ * modified by the function. Functions which take a parameter of
+ * type \c const #mbedtls_mpi_mod_residue* must not modify its value.
+ * - Bignum parameters called \c X, \c Y, ... are outputs or input-output.
+ * The initial bignum value of output-only parameters is ignored, but
+ * they must be set up and associated with the modulus \c N. Some
+ * functions (typically constant-flow) require that the limbs in an
+ * output residue are initialized.
+ * - Bignum parameters called \c p are inputs used to set up a modulus or
+ * residue. These must be pointers to an array of limbs.
+ * - \c T is a temporary storage area. The initial content of such a
+ * parameter is ignored and the final content is unspecified.
+ * - Some functions use different names, such as \c r for the residue.
+ * - **Bignum sizes**: bignum sizes are always expressed in limbs. Both
+ * #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \c limbs
+ * member storing its size. All bignum parameters must have the same
+ * number of limbs as the modulus. All bignum sizes must be at least 1 and
+ * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is
+ * undefined.
+ * - **Bignum representation**: the representation of inputs and outputs is
+ * specified by the \c int_rep field of the modulus.
+ * - **Parameter ordering**: for bignum parameters, outputs come before inputs.
+ * The modulus is passed after residues. Temporaries come last.
+ * - **Aliasing**: in general, output bignums may be aliased to one or more
+ * inputs. Modulus values may not be aliased to any other parameter. Outputs
+ * may not be aliased to one another. Temporaries may not be aliased to any
+ * other parameter.
+ * - **Overlap**: apart from aliasing of residue pointers (where two residue
+ * arguments are equal pointers), overlap is not supported and may result
+ * in undefined behavior.
+ * - **Error handling**: functions generally check compatibility of input
+ * sizes. Most functions will not check that input values are in canonical
+ * form (i.e. that \c A < \c N), this is only checked during setup of a
+ * residue structure.
+ * - **Modular representatives**: all functions expect inputs to be in the
+ * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1].
+ * Residues are set up with an associated modulus, and operations are only
+ * guaranteed to work if the modulus is associated with all residue
+ * parameters. If a residue is passed with a modulus other than the one it
+ * is associated with, then it may be out of range. If an input is out of
+ * range, outputs are fully unspecified, though bignum values out of range
+ * should not cause buffer overflows (beware that this is not extensively
+ * tested).
*/
/*
@@ -30,12 +87,23 @@
#include "mbedtls/bignum.h"
#endif
-/* Skip 1 as it is slightly easier to accidentally pass to functions. */
+/** How residues associated with a modulus are represented.
+ *
+ * This also determines which fields of the modulus structure are valid and
+ * what their contents are (see #mbedtls_mpi_mod_modulus).
+ */
typedef enum
{
+ /** Representation not chosen (makes the modulus structure invalid). */
MBEDTLS_MPI_MOD_REP_INVALID = 0,
+ /* Skip 1 as it is slightly easier to accidentally pass to functions. */
+ /** Montgomery representation. */
MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,
- MBEDTLS_MPI_MOD_REP_OPT_RED
+ /** TODO: document this.
+ *
+ * Residues are in canonical representation.
+ */
+ MBEDTLS_MPI_MOD_REP_OPT_RED,
} mbedtls_mpi_mod_rep_selector;
/* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to
@@ -67,7 +135,9 @@ typedef struct {
mbedtls_mpi_mod_rep_selector int_rep; // selector to signal the active member of the union
union rep
{
+ /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */
mbedtls_mpi_mont_struct mont;
+ /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */
mbedtls_mpi_opt_red_struct ored;
} rep;
} mbedtls_mpi_mod_modulus;
@@ -160,6 +230,40 @@ void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m );
/* BEGIN MERGE SLOT 2 */
+/** \brief Multiply two residues, returning the residue modulo the specified
+ * modulus.
+ *
+ * \note Currently handles the case when `N->int_rep` is
+ * MBEDTLS_MPI_MOD_REP_MONTGOMERY.
+ *
+ * The size of the operation is determined by \p N. \p A, \p B and \p X must
+ * all be associated with the modulus \p N and must all have the same number
+ * of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise. They may not alias \p N (since they must be in canonical
+ * form, they cannot == \p N).
+ *
+ * \param[out] X The address of the result MPI. Must have the same
+ * number of limbs as \p N.
+ * On successful completion, \p X contains the result of
+ * the multiplication `A * B * R^-1` mod N where
+ * `R = 2^(biL * N->limbs)`.
+ * \param[in] A The address of the first MPI.
+ * \param[in] B The address of the second MPI.
+ * \param[in] N The address of the modulus. Used to perform a modulo
+ * operation on the result of the multiplication.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not
+ * have the same number of limbs or \p N is invalid.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedtls_mpi_mod_mul( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_residue *B,
+ const mbedtls_mpi_mod_modulus *N );
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
@@ -192,6 +296,35 @@ int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_residue *B,
const mbedtls_mpi_mod_modulus *N );
+
+/**
+ * \brief Perform modular inversion of an MPI with respect to a modulus \p N.
+ *
+ * \p A and \p X must be associated with the modulus \p N and will therefore
+ * have the same number of limbs as \p N.
+ *
+ * \p X may be aliased to \p A.
+ *
+ * \warning Currently only supports prime moduli, but does not check for them.
+ *
+ * \param[out] X The modular inverse of \p A with respect to \p N.
+ * \param[in] A The number to calculate the modular inverse of.
+ * Must not be 0.
+ * \param[in] N The modulus to use.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A and \p N do not
+ * have the same number of limbs.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A is zero.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough
+ * memory (needed for conversion to and from Mongtomery form
+ * when not in Montgomery form already, and for temporary use
+ * by the inversion calculation itself).
+ */
+
+int mbedtls_mpi_mod_inv( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_modulus *N );
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
@@ -199,11 +332,73 @@ int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X,
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
-
+/**
+ * \brief Perform a fixed-size modular addition.
+ *
+ * Calculate `A + B modulo N`.
+ *
+ * \p A, \p B and \p X must all be associated with the modulus \p N and must
+ * all have the same number of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise.
+ *
+ * \note This function does not check that \p A or \p B are in canonical
+ * form (that is, are < \p N) - that will have been done by
+ * mbedtls_mpi_mod_residue_setup().
+ *
+ * \param[out] X The address of the result residue. Must be initialized.
+ * Must have the same number of limbs as the modulus \p N.
+ * \param[in] A The address of the first input residue.
+ * \param[in] B The address of the second input residue.
+ * \param[in] N The address of the modulus. Used to perform a modulo
+ * operation on the result of the addition.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
+ * have the correct number of limbs.
+ */
+int mbedtls_mpi_mod_add( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_residue *B,
+ const mbedtls_mpi_mod_modulus *N );
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note There are `N - min` possible outputs. The lower bound
+ * \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X The destination residue.
+ * \param min The minimum value to return. It must be strictly smaller
+ * than \b N.
+ * \param N The modulus.
+ * This is the upper bound of the output range, exclusive.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ * unable to find a suitable value within a limited number
+ * of attempts. This has a negligible probability if \p N
+ * is significantly larger than \p min, which is the case
+ * for all usual cryptographic applications.
+ */
+int mbedtls_mpi_mod_random( mbedtls_mpi_mod_residue *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_mod_modulus *N,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c
index c98a1c1..18599c3 100644
--- a/library/bignum_mod_raw.c
+++ b/library/bignum_mod_raw.c
@@ -120,6 +120,16 @@ void mbedtls_mpi_mod_raw_sub( mbedtls_mpi_uint *X,
(void) mbedtls_mpi_core_add_if( X, N->p, N->limbs, (unsigned) c );
}
+void mbedtls_mpi_mod_raw_mul( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_uint *A,
+ const mbedtls_mpi_uint *B,
+ const mbedtls_mpi_mod_modulus *N,
+ mbedtls_mpi_uint *T )
+{
+ mbedtls_mpi_core_montmul( X, A, B, N->limbs, N->p, N->limbs,
+ N->rep.mont.mm, T );
+}
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
@@ -176,6 +186,48 @@ void mbedtls_mpi_mod_raw_add( mbedtls_mpi_uint *X,
/* BEGIN MERGE SLOT 6 */
+int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
+ mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ switch( N->int_rep )
+ {
+ case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+ return( mbedtls_mpi_mod_raw_to_mont_rep( X, N ) );
+ case MBEDTLS_MPI_MOD_REP_OPT_RED:
+ return( 0 );
+ default:
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ }
+}
+
+int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
+ mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ switch( N->int_rep )
+ {
+ case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+ return( mbedtls_mpi_mod_raw_from_mont_rep( X, N ) );
+ case MBEDTLS_MPI_MOD_REP_OPT_RED:
+ return( 0 );
+ default:
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ }
+}
+
+int mbedtls_mpi_mod_raw_random( mbedtls_mpi_uint *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_mod_modulus *N,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret = mbedtls_mpi_core_random( X, min, N->p, N->limbs, f_rng, p_rng );
+ if( ret != 0 )
+ return( ret );
+ return( mbedtls_mpi_mod_raw_canonical_to_modulus_rep( X, N ) );
+}
+
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
@@ -183,13 +235,13 @@ int mbedtls_mpi_mod_raw_to_mont_rep( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m )
{
mbedtls_mpi_uint *T;
- const size_t t_limbs = m->limbs * 2 + 1;
+ const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs( m->limbs );
if( ( T = (mbedtls_mpi_uint *) mbedtls_calloc( t_limbs, ciL ) ) == NULL )
return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
- mbedtls_mpi_core_montmul( X, X, m->rep.mont.rr, m->limbs, m->p, m->limbs,
- m->rep.mont.mm, T );
+ mbedtls_mpi_core_to_mont_rep( X, X, m->p, m->limbs,
+ m->rep.mont.mm, m->rep.mont.rr, T );
mbedtls_platform_zeroize( T, t_limbs * ciL );
mbedtls_free( T );
@@ -199,15 +251,13 @@ int mbedtls_mpi_mod_raw_to_mont_rep( mbedtls_mpi_uint *X,
int mbedtls_mpi_mod_raw_from_mont_rep( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m )
{
- const mbedtls_mpi_uint one = 1;
- const size_t t_limbs = m->limbs * 2 + 1;
+ const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs( m->limbs );
mbedtls_mpi_uint *T;
if( ( T = (mbedtls_mpi_uint *) mbedtls_calloc( t_limbs, ciL ) ) == NULL )
return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
- mbedtls_mpi_core_montmul( X, X, &one, 1, m->p, m->limbs,
- m->rep.mont.mm, T );
+ mbedtls_mpi_core_from_mont_rep( X, X, m->p, m->limbs, m->rep.mont.mm, T );
mbedtls_platform_zeroize( T, t_limbs * ciL );
mbedtls_free( T );
diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h
index f9968ba..ea3207f 100644
--- a/library/bignum_mod_raw.h
+++ b/library/bignum_mod_raw.h
@@ -11,6 +11,51 @@
* the wrong size. The functions in bignum_mod.h provide a higher-level
* interface that includes protections against accidental misuse, at the
* expense of code size and sometimes more cumbersome memory management.
+ *
+ * The functions in this module obey the following conventions unless
+ * explicitly indicated otherwise:
+ * - **Modulus parameters**: the modulus is passed as a pointer to a structure
+ * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an
+ * array of limbs storing the bignum value of the modulus. The modulus must
+ * be odd and is assumed to have no leading zeroes. The modulus is usually
+ * named \c N and is usually input-only.
+ * - **Bignum parameters**: Bignums are passed as pointers to an array of
+ * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:
+ * - Bignum parameters called \c A, \c B, ... are inputs, and are not
+ * modified by the function.
+ * - Bignum parameters called \c X, \c Y are outputs or input-output.
+ * The initial content of output-only parameters is ignored.
+ * - \c T is a temporary storage area. The initial content of such a
+ * parameter is ignored and the final content is unspecified.
+ * - **Bignum sizes**: bignum sizes are usually expressed by the \c limbs
+ * member of the modulus argument. All bignum parameters must have the same
+ * number of limbs as the modulus. All bignum sizes must be at least 1 and
+ * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is
+ * undefined.
+ * - **Bignum representation**: the representation of inputs and outputs is
+ * specified by the \c int_rep field of the modulus for arithmetic
+ * functions. Utility functions may allow for different representation.
+ * - **Parameter ordering**: for bignum parameters, outputs come before inputs.
+ * The modulus is passed after other bignum input parameters. Temporaries
+ * come last.
+ * - **Aliasing**: in general, output bignums may be aliased to one or more
+ * inputs. Modulus values may not be aliased to any other parameter. Outputs
+ * may not be aliased to one another. Temporaries may not be aliased to any
+ * other parameter.
+ * - **Overlap**: apart from aliasing of limb array pointers (where two
+ * arguments are equal pointers), overlap is not supported and may result
+ * in undefined behavior.
+ * - **Error handling**: This is a low-level module. Functions generally do not
+ * try to protect against invalid arguments such as nonsensical sizes or
+ * null pointers. Note that passing bignums with a different size than the
+ * modulus may lead to buffer overflows. Some functions which allocate
+ * memory or handle reading/writing of bignums will return an error if
+ * memory allocation fails or if buffer sizes are invalid.
+ * - **Modular representatives**: all functions expect inputs to be in the
+ * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. If
+ * an input is out of range, outputs are fully unspecified, though bignum
+ * values out of range should not cause buffer overflows (beware that this is
+ * not extensively tested).
*/
/*
@@ -170,6 +215,41 @@ void mbedtls_mpi_mod_raw_sub( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *B,
const mbedtls_mpi_mod_modulus *N );
+/** \brief Multiply two MPIs, returning the residue modulo the specified
+ * modulus.
+ *
+ * \note Currently handles the case when `N->int_rep` is
+ * MBEDTLS_MPI_MOD_REP_MONTGOMERY.
+ *
+ * The size of the operation is determined by \p N. \p A, \p B and \p X must
+ * all be associated with the modulus \p N and must all have the same number
+ * of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise. They may not alias \p N (since they must be in canonical
+ * form, they cannot == \p N).
+ *
+ * \param[out] X The address of the result MPI. Must have the same
+ * number of limbs as \p N.
+ * On successful completion, \p X contains the result of
+ * the multiplication `A * B * R^-1` mod N where
+ * `R = 2^(biL * N->limbs)`.
+ * \param[in] A The address of the first MPI.
+ * \param[in] B The address of the second MPI.
+ * \param[in] N The address of the modulus. Used to perform a modulo
+ * operation on the result of the multiplication.
+ * \param[in,out] T Temporary storage of size at least 2 * N->limbs + 1
+ * limbs. Its initial content is unused and
+ * its final content is indeterminate.
+ * It must not alias or otherwise overlap any of the
+ * other parameters.
+ */
+void mbedtls_mpi_mod_raw_mul( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_uint *A,
+ const mbedtls_mpi_uint *B,
+ const mbedtls_mpi_mod_modulus *N,
+ mbedtls_mpi_uint *T );
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
@@ -178,6 +258,10 @@ void mbedtls_mpi_mod_raw_sub( mbedtls_mpi_uint *X,
* \brief Returns the number of limbs of working memory required for
* a call to `mbedtls_mpi_mod_raw_inv_prime()`.
*
+ * \note This will always be at least
+ * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`,
+ * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`.
+ *
* \param AN_limbs The number of limbs in the input `A` and the modulus `N`
* (they must be the same size) that will be given to
* `mbedtls_mpi_mod_raw_inv_prime()`.
@@ -252,6 +336,74 @@ void mbedtls_mpi_mod_raw_add( mbedtls_mpi_uint *X,
/* BEGIN MERGE SLOT 6 */
+/** Convert an MPI from canonical representation (little-endian limb array)
+ * to the representation associated with the modulus.
+ *
+ * \param[in,out] X The limb array to convert.
+ * It must have as many limbs as \p N.
+ * It is converted in place.
+ * If this function returns an error, the content of \p X
+ * is unspecified.
+ * \param[in] N The modulus structure.
+ *
+ *\ return \c 0 if successful.
+ * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
+ */
+int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
+ mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *N );
+
+/** Convert an MPI from the representation associated with the modulus
+ * to canonical representation (little-endian limb array).
+ *
+ * \param[in,out] X The limb array to convert.
+ * It must have as many limbs as \p N.
+ * It is converted in place.
+ * If this function returns an error, the content of \p X
+ * is unspecified.
+ * \param[in] N The modulus structure.
+ *
+ *\ return \c 0 if successful.
+ * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
+ */
+int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
+ mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *N );
+
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note There are `N - min` possible outputs. The lower bound
+ * \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X The destination MPI, in canonical representation modulo \p N.
+ * It must not be aliased with \p N or otherwise overlap it.
+ * \param min The minimum value to return. It must be strictly smaller
+ * than \b N.
+ * \param N The modulus.
+ * This is the upper bound of the output range, exclusive.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ * unable to find a suitable value within a limited number
+ * of attempts. This has a negligible probability if \p N
+ * is significantly larger than \p min, which is the case
+ * for all usual cryptographic applications.
+ */
+int mbedtls_mpi_mod_raw_random( mbedtls_mpi_uint *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_mod_modulus *N,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
diff --git a/library/ecp.c b/library/ecp.c
index cd7d554..b6ed60a 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -754,6 +754,13 @@ cleanup:
return( ret );
}
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+static int mbedtls_ecp_sw_derive_y( const mbedtls_ecp_group *grp,
+ const mbedtls_mpi *X,
+ mbedtls_mpi *Y,
+ int parity_bit );
+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+
/*
* Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748)
*/
@@ -795,16 +802,29 @@ int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
}
- if( buf[0] != 0x04 )
- return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
-
- if( ilen != 2 * plen + 1 )
+ if( ilen < 1 + plen )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y,
- buf + 1 + plen, plen ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+
+ if( buf[0] == 0x04 )
+ {
+ /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */
+ if( ilen != 1 + plen * 2 )
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ return( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
+ }
+ else if( buf[0] == 0x02 || buf[0] == 0x03 )
+ {
+ /* format == MBEDTLS_ECP_PF_COMPRESSED */
+ if( ilen != 1 + plen )
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ return( mbedtls_ecp_sw_derive_y( grp, &pt->X, &pt->Y,
+ ( buf[0] & 1 ) ) );
+ }
+ else
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
}
#endif
@@ -1191,6 +1211,86 @@ cleanup:
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( (X), (Y), (cond) ) )
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+
+/*
+ * Computes the right-hand side of the Short Weierstrass equation
+ * RHS = X^3 + A X + B
+ */
+static int ecp_sw_rhs( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *rhs,
+ const mbedtls_mpi *X )
+{
+ int ret;
+
+ /* Compute X^3 + A X + B as X (X^2 + A) + B */
+ MPI_ECP_SQR( rhs, X );
+
+ /* Special case for A = -3 */
+ if( grp->A.p == NULL )
+ {
+ MPI_ECP_SUB_INT( rhs, rhs, 3 );
+ }
+ else
+ {
+ MPI_ECP_ADD( rhs, rhs, &grp->A );
+ }
+
+ MPI_ECP_MUL( rhs, rhs, X );
+ MPI_ECP_ADD( rhs, rhs, &grp->B );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Derive Y from X and a parity bit
+ */
+static int mbedtls_ecp_sw_derive_y( const mbedtls_ecp_group *grp,
+ const mbedtls_mpi *X,
+ mbedtls_mpi *Y,
+ int parity_bit )
+{
+ /* w = y^2 = x^3 + ax + b
+ * y = sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4)
+ *
+ * Note: this method for extracting square root does not validate that w
+ * was indeed a square so this function will return garbage in Y if X
+ * does not correspond to a point on the curve.
+ */
+
+ /* Check prerequisite p = 3 mod 4 */
+ if( mbedtls_mpi_get_bit( &grp->P, 0 ) != 1 ||
+ mbedtls_mpi_get_bit( &grp->P, 1 ) != 1 )
+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+
+ int ret;
+ mbedtls_mpi exp;
+ mbedtls_mpi_init( &exp );
+
+ /* use Y to store intermediate result, actually w above */
+ MBEDTLS_MPI_CHK( ecp_sw_rhs( grp, Y, X ) );
+
+ /* w = y^2 */ /* Y contains y^2 intermediate result */
+ /* exp = ((p+1)/4) */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &exp, &grp->P, 1 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &exp, 2 ) );
+ /* sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( Y, Y /*y^2*/, &exp, &grp->P, NULL ) );
+
+ /* check parity bit match or else invert Y */
+ /* This quick inversion implementation is valid because Y != 0 for all
+ * Short Weierstrass curves supported by mbedtls, as each supported curve
+ * has an order that is a large prime, so each supported curve does not
+ * have any point of order 2, and a point with Y == 0 would be of order 2 */
+ if( mbedtls_mpi_get_bit( Y, 0 ) != parity_bit )
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( Y, &grp->P, Y ) );
+
+cleanup:
+
+ mbedtls_mpi_free( &exp );
+ return( ret );
+}
+
/*
* For curves in short Weierstrass form, we do all the internal operations in
* Jacobian coordinates.
@@ -2611,23 +2711,10 @@ static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_
/*
* YY = Y^2
- * RHS = X (X^2 + A) + B = X^3 + A X + B
+ * RHS = X^3 + A X + B
*/
MPI_ECP_SQR( &YY, &pt->Y );
- MPI_ECP_SQR( &RHS, &pt->X );
-
- /* Special case for A = -3 */
- if( grp->A.p == NULL )
- {
- MPI_ECP_SUB_INT( &RHS, &RHS, 3 );
- }
- else
- {
- MPI_ECP_ADD( &RHS, &RHS, &grp->A );
- }
-
- MPI_ECP_MUL( &RHS, &RHS, &pt->X );
- MPI_ECP_ADD( &RHS, &RHS, &grp->B );
+ MBEDTLS_MPI_CHK( ecp_sw_rhs( grp, &RHS, &pt->X ) );
if( MPI_ECP_CMP( &YY, &RHS ) != 0 )
ret = MBEDTLS_ERR_ECP_INVALID_KEY;
diff --git a/library/lms.c b/library/lms.c
index 46ea567..78c7d26 100644
--- a/library/lms.c
+++ b/library/lms.c
@@ -65,10 +65,9 @@
/* Currently only support H=10 */
#define H_TREE_HEIGHT_MAX 10
-#define MERKLE_TREE_NODE_AM_MAX (1u << (H_TREE_HEIGHT_MAX + 1u))
-#define MERKLE_TREE_NODE_AM(type) (1u << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
-#define MERKLE_TREE_LEAF_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))
-#define MERKLE_TREE_INTERNAL_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))
+#define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
+#define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
+#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
#define D_CONST_LEN (2)
static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = {0x82, 0x82};
@@ -499,13 +498,21 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx,
unsigned int leaf_node_id,
unsigned char *path )
{
- unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX];
+ const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
unsigned int curr_node_id = leaf_node_id;
unsigned int adjacent_node_id;
+ unsigned char *tree = NULL;
unsigned int height;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- ret = calculate_merkle_tree( ctx, ( unsigned char * )tree );
+ tree = mbedtls_calloc( MERKLE_TREE_NODE_AM(ctx->params.type),
+ node_bytes );
+ if ( tree == NULL )
+ {
+ return MBEDTLS_ERR_LMS_ALLOC_FAILED;
+ }
+
+ ret = calculate_merkle_tree( ctx, tree );
if( ret != 0 )
{
goto exit;
@@ -516,9 +523,8 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx,
{
adjacent_node_id = curr_node_id ^ 1;
- memcpy( &path[height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
- &tree[adjacent_node_id],
- MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) );
+ memcpy( &path[height * node_bytes],
+ &tree[adjacent_node_id * node_bytes], node_bytes );
curr_node_id >>=1;
}
@@ -526,7 +532,9 @@ static int get_merkle_path( mbedtls_lms_private_t *ctx,
ret = 0;
exit:
- mbedtls_platform_zeroize( tree, sizeof( tree ) );
+ mbedtls_platform_zeroize( tree, node_bytes *
+ MERKLE_TREE_NODE_AM(ctx->params.type) );
+ mbedtls_free ( tree );
return( ret );
}
@@ -659,8 +667,9 @@ exit:
int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx,
const mbedtls_lms_private_t *priv_ctx )
{
- unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX];
+ const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type);
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char *tree = NULL;
if( ! priv_ctx->have_private_key )
{
@@ -679,25 +688,33 @@ int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx,
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
+ tree = mbedtls_calloc( MERKLE_TREE_NODE_AM(priv_ctx->params.type),
+ node_bytes );
+ if ( tree == NULL )
+ {
+ return MBEDTLS_ERR_LMS_ALLOC_FAILED;
+ }
+
memcpy( &ctx->params, &priv_ctx->params,
sizeof( mbedtls_lmots_parameters_t ) );
- ret = calculate_merkle_tree( priv_ctx, ( unsigned char * )tree );
+ ret = calculate_merkle_tree( priv_ctx, tree );
if( ret != 0 )
{
goto exit;
}
/* Root node is always at position 1, due to 1-based indexing */
- memcpy( ctx->T_1_pub_key, &tree[1],
- MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) );
+ memcpy( ctx->T_1_pub_key, &tree[node_bytes], node_bytes );
ctx->have_public_key = 1;
ret = 0;
exit:
- mbedtls_platform_zeroize( tree, sizeof( tree ) );
+ mbedtls_platform_zeroize( tree, node_bytes *
+ MERKLE_TREE_NODE_AM(priv_ctx->params.type) );
+ mbedtls_free ( tree );
return( ret );
}
diff --git a/library/pk.c b/library/pk.c
index 8dc19ef..a73fa56 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -482,12 +482,9 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
- if( pss_opts->mgf1_hash_id == md_alg &&
- ( (size_t) pss_opts->expected_salt_len == hash_len ||
- pss_opts->expected_salt_len == MBEDTLS_RSA_SALT_LEN_ANY ) )
+ if( pss_opts->mgf1_hash_id == md_alg )
{
- /* see RSA_PUB_DER_MAX_BYTES in pkwrite.c */
- unsigned char buf[ 38 + 2 * MBEDTLS_MPI_MAX_SIZE ];
+ unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
unsigned char *p;
int key_len;
size_t signature_length;
@@ -497,10 +494,7 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
psa_algorithm_t psa_md_alg = mbedtls_hash_info_psa_from_md( md_alg );
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- psa_algorithm_t psa_sig_alg =
- ( pss_opts->expected_salt_len == MBEDTLS_RSA_SALT_LEN_ANY ?
- PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg) :
- PSA_ALG_RSA_PSS(psa_md_alg) );
+ psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT( psa_md_alg );
p = buf + sizeof( buf );
key_len = mbedtls_pk_write_pubkey( &p, buf, ctx );
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 5de8fa6..ea7d726 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -1162,8 +1162,12 @@ static int ecdsa_sign_wrap( void *ctx_arg, mbedtls_md_type_t md_alg,
size_t key_len;
unsigned char buf[MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES];
unsigned char *p;
- psa_algorithm_t psa_sig_md =
- PSA_ALG_ECDSA( mbedtls_hash_info_psa_from_md( md_alg ) );
+ psa_algorithm_t psa_hash = mbedtls_hash_info_psa_from_md( md_alg );
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ psa_algorithm_t psa_sig_md = PSA_ALG_DETERMINISTIC_ECDSA( psa_hash );
+#else
+ psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA( psa_hash );
+#endif
size_t curve_bits;
psa_ecc_family_t curve =
mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits );
diff --git a/library/pkcs7.c b/library/pkcs7.c
index 5b22afa..9100980 100644
--- a/library/pkcs7.c
+++ b/library/pkcs7.c
@@ -253,6 +253,24 @@ static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
return( 0 );
}
+static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer )
+{
+ mbedtls_x509_name *name_cur;
+ mbedtls_x509_name *name_prv;
+
+ if( signer == NULL )
+ return;
+
+ name_cur = signer->issuer.next;
+ while( name_cur != NULL )
+ {
+ name_prv = name_cur;
+ name_cur = name_cur->next;
+ mbedtls_free( name_prv );
+ }
+ signer->issuer.next = NULL;
+}
+
/**
* SignerInfo ::= SEQUENCE {
* version Version;
@@ -329,33 +347,16 @@ static int pkcs7_get_signer_info( unsigned char **p, unsigned char *end,
ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
out:
- if( asn1_ret != 0 )
+ if( asn1_ret != 0 || ret != 0 )
+ {
+ pkcs7_free_signer_info( signer );
ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
asn1_ret );
- else if( ret != 0 )
- ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
+ }
return( ret );
}
-static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer )
-{
- mbedtls_x509_name *name_cur;
- mbedtls_x509_name *name_prv;
-
- if( signer == NULL )
- return;
-
- name_cur = signer->issuer.next;
- while( name_cur != NULL )
- {
- name_prv = name_cur;
- name_cur = name_cur->next;
- mbedtls_free( name_prv );
- }
- signer->issuer.next = NULL;
-}
-
/**
* SignerInfos ::= SET of SignerInfo
* Return number of signers added to the signed data,
@@ -387,7 +388,7 @@ static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end,
ret = pkcs7_get_signer_info( p, end_set, signers_set );
if( ret != 0 )
- goto cleanup;
+ return( ret );
count++;
mbedtls_pkcs7_signer_info *prev = signers_set;
diff --git a/library/ssl_client.c b/library/ssl_client.c
index 2c4ce43..e838845 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -518,18 +518,22 @@ static int ssl_write_client_hello_body( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
- unsigned char cookie_len = 0;
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
+ uint8_t cookie_len = 0;
+#else
+ uint16_t cookie_len = 0;
+#endif /* !MBEDTLS_SSL_PROTO_TLS1_3 */
if( handshake->cookie != NULL )
{
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
handshake->cookie,
- handshake->verify_cookie_len );
- cookie_len = handshake->verify_cookie_len;
+ handshake->cookie_len );
+ cookie_len = handshake->cookie_len;
}
MBEDTLS_SSL_CHK_BUF_PTR( p, end, cookie_len + 1 );
- *p++ = cookie_len;
+ *p++ = ( unsigned char )cookie_len;
if( cookie_len > 0 )
{
memcpy( p, handshake->cookie, cookie_len );
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 5808cab..8254964 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -846,19 +846,33 @@ struct mbedtls_ssl_handshake_params
} buffering;
#if defined(MBEDTLS_SSL_CLI_C) && \
- ( defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3) )
- unsigned char *cookie; /*!< HelloVerifyRequest cookie for DTLS
- * HelloRetryRequest cookie for TLS 1.3 */
+ ( defined(MBEDTLS_SSL_PROTO_DTLS) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_3) )
+ unsigned char *cookie; /*!< HelloVerifyRequest cookie for DTLS
+ * HelloRetryRequest cookie for TLS 1.3 */
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
+ /* RFC 6347 page 15
+ ...
+ opaque cookie<0..2^8-1>;
+ ...
+ */
+ uint8_t cookie_len;
+#else
+ /* RFC 8446 page 39
+ ...
+ opaque cookie<0..2^16-1>;
+ ...
+ If TLS1_3 is enabled, the max length is 2^16 - 1
+ */
+ uint16_t cookie_len; /*!< DTLS: HelloVerifyRequest cookie length
+ * TLS1_3: HelloRetryRequest cookie length */
+#endif
#endif /* MBEDTLS_SSL_CLI_C &&
- ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- unsigned char verify_cookie_len; /*!< Cli: HelloVerifyRequest cookie
- * length
- * Srv: flag for sending a cookie */
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
- uint16_t hrr_cookie_len; /*!< HelloRetryRequest cookie length */
-#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_3 */
+ ( MBEDTLS_SSL_PROTO_DTLS ||
+ MBEDTLS_SSL_PROTO_TLS1_3 ) */
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_DTLS)
+ unsigned char cookie_verify_result; /*!< Srv: flag for sending a cookie */
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
@@ -1135,7 +1149,7 @@ struct mbedtls_ssl_transform
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
uint8_t in_cid_len;
uint8_t out_cid_len;
- unsigned char in_cid [ MBEDTLS_SSL_CID_OUT_LEN_MAX ];
+ unsigned char in_cid [ MBEDTLS_SSL_CID_IN_LEN_MAX ];
unsigned char out_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ];
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 9bb9dc2..b757613 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1863,27 +1863,55 @@ void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl,
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-/*
- * Set EC J-PAKE password for current handshake
- */
+
#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static psa_status_t mbedtls_ssl_set_hs_ecjpake_password_common(
+ mbedtls_ssl_context *ssl,
+ mbedtls_svc_key_id_t pwd )
+{
+ psa_status_t status;
+ psa_pake_role_t psa_role;
+ psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
+
+ psa_pake_cs_set_algorithm( &cipher_suite, PSA_ALG_JPAKE );
+ psa_pake_cs_set_primitive( &cipher_suite,
+ PSA_PAKE_PRIMITIVE( PSA_PAKE_PRIMITIVE_TYPE_ECC,
+ PSA_ECC_FAMILY_SECP_R1,
+ 256) );
+ psa_pake_cs_set_hash( &cipher_suite, PSA_ALG_SHA_256 );
+
+ status = psa_pake_setup( &ssl->handshake->psa_pake_ctx, &cipher_suite );
+ if( status != PSA_SUCCESS )
+ return status;
+
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+ psa_role = PSA_PAKE_ROLE_SERVER;
+ else
+ psa_role = PSA_PAKE_ROLE_CLIENT;
+
+ status = psa_pake_set_role( &ssl->handshake->psa_pake_ctx, psa_role );
+ if( status != PSA_SUCCESS )
+ return status;
+
+ status = psa_pake_set_password_key( &ssl->handshake->psa_pake_ctx, pwd );
+ if( status != PSA_SUCCESS )
+ return status;
+
+ ssl->handshake->psa_pake_ctx_is_ok = 1;
+
+ return ( PSA_SUCCESS );
+}
+
int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
const unsigned char *pw,
size_t pw_len )
{
- psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- psa_pake_role_t psa_role;
psa_status_t status;
if( ssl->handshake == NULL || ssl->conf == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
- psa_role = PSA_PAKE_ROLE_SERVER;
- else
- psa_role = PSA_PAKE_ROLE_CLIENT;
-
/* Empty password is not valid */
if( ( pw == NULL) || ( pw_len == 0 ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -1897,21 +1925,8 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
- psa_pake_cs_set_algorithm( &cipher_suite, PSA_ALG_JPAKE );
- psa_pake_cs_set_primitive( &cipher_suite,
- PSA_PAKE_PRIMITIVE( PSA_PAKE_PRIMITIVE_TYPE_ECC,
- PSA_ECC_FAMILY_SECP_R1,
- 256) );
- psa_pake_cs_set_hash( &cipher_suite, PSA_ALG_SHA_256 );
-
- status = psa_pake_setup( &ssl->handshake->psa_pake_ctx, &cipher_suite );
- if( status != PSA_SUCCESS )
- {
- psa_destroy_key( ssl->handshake->psa_pake_password );
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
- }
-
- status = psa_pake_set_role( &ssl->handshake->psa_pake_ctx, psa_role );
+ status = mbedtls_ssl_set_hs_ecjpake_password_common( ssl,
+ ssl->handshake->psa_pake_password );
if( status != PSA_SUCCESS )
{
psa_destroy_key( ssl->handshake->psa_pake_password );
@@ -1919,17 +1934,27 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
}
- psa_pake_set_password_key( &ssl->handshake->psa_pake_ctx,
- ssl->handshake->psa_pake_password );
+ return( 0 );
+}
+
+int mbedtls_ssl_set_hs_ecjpake_password_opaque( mbedtls_ssl_context *ssl,
+ mbedtls_svc_key_id_t pwd )
+{
+ psa_status_t status;
+
+ if( ssl->handshake == NULL || ssl->conf == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ if( mbedtls_svc_key_id_is_null( pwd ) )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ status = mbedtls_ssl_set_hs_ecjpake_password_common( ssl, pwd );
if( status != PSA_SUCCESS )
{
- psa_destroy_key( ssl->handshake->psa_pake_password );
psa_pake_abort( &ssl->handshake->psa_pake_ctx );
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
}
- ssl->handshake->psa_pake_ctx_is_ok = 1;
-
return( 0 );
}
#else /* MBEDTLS_USE_PSA_CRYPTO */
@@ -1942,6 +1967,10 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
if( ssl->handshake == NULL || ssl->conf == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ /* Empty password is not valid */
+ if( ( pw == NULL) || ( pw_len == 0 ) )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
role = MBEDTLS_ECJPAKE_SERVER;
else
@@ -3996,7 +4025,15 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_pake_abort( &handshake->psa_pake_ctx );
- psa_destroy_key( handshake->psa_pake_password );
+ /*
+ * Opaque keys are not stored in the handshake's data and it's the user
+ * responsibility to destroy them. Clear ones, instead, are created by
+ * the TLS library and should be destroyed at the same level
+ */
+ if( ! mbedtls_svc_key_id_is_null( handshake->psa_pake_password ) )
+ {
+ psa_destroy_key( handshake->psa_pake_password );
+ }
handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT;
#else
mbedtls_ecjpake_free( &handshake->ecjpake_ctx );
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index 7a17452..76588d3 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -1137,7 +1137,12 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
{
const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
uint16_t dtls_legacy_version;
- unsigned char cookie_len;
+
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
+ uint8_t cookie_len;
+#else
+ uint16_t cookie_len;
+#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) );
@@ -1200,7 +1205,7 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
}
memcpy( ssl->handshake->cookie, p, cookie_len );
- ssl->handshake->verify_cookie_len = cookie_len;
+ ssl->handshake->cookie_len = cookie_len;
/* Start over at ClientHello */
ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
@@ -1284,7 +1289,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
/* We made it through the verification process */
mbedtls_free( ssl->handshake->cookie );
ssl->handshake->cookie = NULL;
- ssl->handshake->verify_cookie_len = 0;
+ ssl->handshake->cookie_len = 0;
}
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index eeb579a..5cdbcc0 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -1274,12 +1274,12 @@ read_record_header:
ssl->cli_id, ssl->cli_id_len ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) );
- ssl->handshake->verify_cookie_len = 1;
+ ssl->handshake->cookie_verify_result = 1;
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) );
- ssl->handshake->verify_cookie_len = 0;
+ ssl->handshake->cookie_verify_result = 0;
}
}
else
@@ -2244,7 +2244,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->handshake->verify_cookie_len != 0 )
+ ssl->handshake->cookie_verify_result != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 0109f77..839b954 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -553,7 +553,7 @@ static int ssl_tls13_parse_cookie_ext( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_BUF( 3, "cookie extension", p, cookie_len );
mbedtls_free( handshake->cookie );
- handshake->hrr_cookie_len = 0;
+ handshake->cookie_len = 0;
handshake->cookie = mbedtls_calloc( 1, cookie_len );
if( handshake->cookie == NULL )
{
@@ -564,7 +564,7 @@ static int ssl_tls13_parse_cookie_ext( mbedtls_ssl_context *ssl,
}
memcpy( handshake->cookie, p, cookie_len );
- handshake->hrr_cookie_len = cookie_len;
+ handshake->cookie_len = cookie_len;
return( 0 );
}
@@ -587,21 +587,21 @@ static int ssl_tls13_write_cookie_ext( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
handshake->cookie,
- handshake->hrr_cookie_len );
+ handshake->cookie_len );
- MBEDTLS_SSL_CHK_BUF_PTR( p, end, handshake->hrr_cookie_len + 6 );
+ MBEDTLS_SSL_CHK_BUF_PTR( p, end, handshake->cookie_len + 6 );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding cookie extension" ) );
MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_COOKIE, p, 0 );
- MBEDTLS_PUT_UINT16_BE( handshake->hrr_cookie_len + 2, p, 2 );
- MBEDTLS_PUT_UINT16_BE( handshake->hrr_cookie_len, p, 4 );
+ MBEDTLS_PUT_UINT16_BE( handshake->cookie_len + 2, p, 2 );
+ MBEDTLS_PUT_UINT16_BE( handshake->cookie_len, p, 4 );
p += 6;
/* Cookie */
- memcpy( p, handshake->cookie, handshake->hrr_cookie_len );
+ memcpy( p, handshake->cookie, handshake->cookie_len );
- *out_len = handshake->hrr_cookie_len + 6;
+ *out_len = handshake->cookie_len + 6;
mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_COOKIE );
diff --git a/programs/fuzz/Makefile b/programs/fuzz/Makefile
index 59a2bb7..8477aa8 100644
--- a/programs/fuzz/Makefile
+++ b/programs/fuzz/Makefile
@@ -1,7 +1,9 @@
MBEDTLS_TEST_PATH:=../../tests/src
MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c ${MBEDTLS_TEST_PATH}/drivers/*.c))
-LOCAL_CFLAGS = -I../../tests/include -I../../include -D_FILE_OFFSET_BITS=64
+CFLAGS ?= -O2
+WARNING_CFLAGS ?= -Wall -Wextra
+LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../../tests/include -I../../include -D_FILE_OFFSET_BITS=64
LOCAL_LDFLAGS = ${MBEDTLS_TEST_OBJS} \
-L../../library \
-lmbedtls$(SHARED_SUFFIX) \
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 6aa295d..02ee7cf 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -68,6 +68,7 @@ int main( void )
#define DFL_PSK_OPAQUE 0
#define DFL_PSK_IDENTITY "Client_identity"
#define DFL_ECJPAKE_PW NULL
+#define DFL_ECJPAKE_PW_OPAQUE 0
#define DFL_EC_MAX_OPS -1
#define DFL_FORCE_CIPHER 0
#define DFL_TLS1_3_KEX_MODES MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL
@@ -318,11 +319,17 @@ int main( void )
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
#define USAGE_ECJPAKE \
- " ecjpake_pw=%%s default: none (disabled)\n"
-#else
+ " ecjpake_pw=%%s default: none (disabled)\n" \
+ " ecjpake_pw_opaque=%%d default: 0 (disabled)\n"
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+#define USAGE_ECJPAKE \
+ " ecjpake_pw=%%s default: none (disabled)\n"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#else /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#define USAGE_ECJPAKE ""
-#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_ECP_RESTARTABLE)
#define USAGE_ECRESTART \
@@ -492,6 +499,9 @@ struct options
const char *psk; /* the pre-shared key */
const char *psk_identity; /* the pre-shared key identity */
const char *ecjpake_pw; /* the EC J-PAKE password */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ int ecjpake_pw_opaque; /* set to 1 to use the opaque method for setting the password */
+#endif
int ec_max_ops; /* EC consecutive operations limit */
int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
@@ -824,6 +834,10 @@ int main( int argc, char *argv[] )
MBEDTLS_TLS_SRTP_UNSET
};
#endif /* MBEDTLS_SSL_DTLS_SRTP */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+ defined(MBEDTLS_USE_PSA_CRYPTO)
+ mbedtls_svc_key_id_t ecjpake_pw_slot = MBEDTLS_SVC_KEY_ID_INIT; /* ecjpake password key slot */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -919,6 +933,9 @@ int main( int argc, char *argv[] )
#endif
opt.psk_identity = DFL_PSK_IDENTITY;
opt.ecjpake_pw = DFL_ECJPAKE_PW;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ opt.ecjpake_pw_opaque = DFL_ECJPAKE_PW_OPAQUE;
+#endif
opt.ec_max_ops = DFL_EC_MAX_OPS;
opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
@@ -1094,6 +1111,10 @@ int main( int argc, char *argv[] )
opt.psk_identity = q;
else if( strcmp( p, "ecjpake_pw" ) == 0 )
opt.ecjpake_pw = q;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ else if( strcmp( p, "ecjpake_pw_opaque" ) == 0 )
+ opt.ecjpake_pw_opaque = atoi( q );
+#endif
else if( strcmp( p, "ec_max_ops" ) == 0 )
opt.ec_max_ops = atoi( q );
else if( strcmp( p, "force_ciphersuite" ) == 0 )
@@ -2166,16 +2187,46 @@ int main( int argc, char *argv[] )
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( opt.ecjpake_pw != DFL_ECJPAKE_PW )
{
- if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,
- (const unsigned char *) opt.ecjpake_pw,
- strlen( opt.ecjpake_pw ) ) ) != 0 )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE )
{
- mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n",
- ret );
- goto exit;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+ psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE );
+ psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD );
+
+ status = psa_import_key( &attributes,
+ (const unsigned char *) opt.ecjpake_pw,
+ strlen( opt.ecjpake_pw ),
+ &ecjpake_pw_slot );
+ if( status != PSA_SUCCESS )
+ {
+ mbedtls_printf( " failed\n ! psa_import_key returned %d\n\n",
+ status );
+ goto exit;
+ }
+ if( ( ret = mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl,
+ ecjpake_pw_slot ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password_opaque returned %d\n\n", ret );
+ goto exit;
+ }
+ mbedtls_printf( "using opaque password\n");
+ }
+ else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ {
+ if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,
+ (const unsigned char *) opt.ecjpake_pw,
+ strlen( opt.ecjpake_pw ) ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret );
+ goto exit;
+ }
}
}
-#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
if( opt.context_crt_cb == 1 )
@@ -3276,6 +3327,31 @@ exit:
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED &&
MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+ defined(MBEDTLS_USE_PSA_CRYPTO)
+ /*
+ * In case opaque keys it's the user responsibility to keep the key valid
+ * for the duration of the handshake and destroy it at the end
+ */
+ if( ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE ) )
+ {
+ psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ /* Verify that the key is still valid before destroying it */
+ if( psa_get_key_attributes( ecjpake_pw_slot, &check_attributes ) !=
+ PSA_SUCCESS )
+ {
+ if( ret == 0 )
+ ret = 1;
+ mbedtls_printf( "The EC J-PAKE password key has unexpectedly been already destroyed\n" );
+ }
+ else
+ {
+ psa_destroy_key( ecjpake_pw_slot );
+ }
+ }
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
const char* message = mbedtls_test_helper_is_psa_leaking();
if( message )
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 00624b5..802beb2 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -98,6 +98,7 @@ int main( void )
#define DFL_PSK_LIST_OPAQUE 0
#define DFL_PSK_IDENTITY "Client_identity"
#define DFL_ECJPAKE_PW NULL
+#define DFL_ECJPAKE_PW_OPAQUE 0
#define DFL_PSK_LIST NULL
#define DFL_FORCE_CIPHER 0
#define DFL_TLS1_3_KEX_MODES MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL
@@ -419,11 +420,17 @@ int main( void )
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
#define USAGE_ECJPAKE \
- " ecjpake_pw=%%s default: none (disabled)\n"
-#else
+ " ecjpake_pw=%%s default: none (disabled)\n" \
+ " ecjpake_pw_opaque=%%d default: 0 (disabled)\n"
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+#define USAGE_ECJPAKE \
+ " ecjpake_pw=%%s default: none (disabled)\n"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#else /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#define USAGE_ECJPAKE ""
-#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_EARLY_DATA)
#define USAGE_EARLY_DATA \
@@ -631,6 +638,9 @@ struct options
const char *psk_identity; /* the pre-shared key identity */
char *psk_list; /* list of PSK id/key pairs for callback */
const char *ecjpake_pw; /* the EC J-PAKE password */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ int ecjpake_pw_opaque; /* set to 1 to use the opaque method for setting the password */
+#endif
int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
int tls13_kex_modes; /* supported TLS 1.3 key exchange modes */
@@ -1517,6 +1527,10 @@ int main( int argc, char *argv[] )
unsigned char *context_buf = NULL;
size_t context_buf_len = 0;
#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+ defined(MBEDTLS_USE_PSA_CRYPTO)
+ mbedtls_svc_key_id_t ecjpake_pw_slot = MBEDTLS_SVC_KEY_ID_INIT; /* ecjpake password key slot */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
uint16_t sig_alg_list[SIG_ALG_LIST_SIZE];
@@ -1675,6 +1689,9 @@ int main( int argc, char *argv[] )
opt.psk_identity = DFL_PSK_IDENTITY;
opt.psk_list = DFL_PSK_LIST;
opt.ecjpake_pw = DFL_ECJPAKE_PW;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ opt.ecjpake_pw_opaque = DFL_ECJPAKE_PW_OPAQUE;
+#endif
opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
opt.tls13_kex_modes = DFL_TLS1_3_KEX_MODES;
@@ -1879,6 +1896,10 @@ int main( int argc, char *argv[] )
opt.psk_list = q;
else if( strcmp( p, "ecjpake_pw" ) == 0 )
opt.ecjpake_pw = q;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ else if( strcmp( p, "ecjpake_pw_opaque" ) == 0 )
+ opt.ecjpake_pw_opaque = atoi( q );
+#endif
else if( strcmp( p, "force_ciphersuite" ) == 0 )
{
opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q );
@@ -3528,15 +3549,46 @@ reset:
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( opt.ecjpake_pw != DFL_ECJPAKE_PW )
{
- if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,
- (const unsigned char *) opt.ecjpake_pw,
- strlen( opt.ecjpake_pw ) ) ) != 0 )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE )
{
- mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret );
- goto exit;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+ psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE );
+ psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD );
+
+ status = psa_import_key( &attributes,
+ (const unsigned char *) opt.ecjpake_pw,
+ strlen( opt.ecjpake_pw ),
+ &ecjpake_pw_slot );
+ if( status != PSA_SUCCESS )
+ {
+ mbedtls_printf( " failed\n ! psa_import_key returned %d\n\n",
+ status );
+ goto exit;
+ }
+ if( ( ret = mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl,
+ ecjpake_pw_slot ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password_opaque returned %d\n\n", ret );
+ goto exit;
+ }
+ mbedtls_printf( "using opaque password\n");
+ }
+ else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ {
+ if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,
+ (const unsigned char *) opt.ecjpake_pw,
+ strlen( opt.ecjpake_pw ) ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret );
+ goto exit;
+ }
}
}
-#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
@@ -4422,6 +4474,31 @@ exit:
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED &&
MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+ defined(MBEDTLS_USE_PSA_CRYPTO)
+ /*
+ * In case opaque keys it's the user responsibility to keep the key valid
+ * for the duration of the handshake and destroy it at the end
+ */
+ if( ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE ) )
+ {
+ psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ /* Verify that the key is still valid before destroying it */
+ if( psa_get_key_attributes( ecjpake_pw_slot, &check_attributes ) !=
+ PSA_SUCCESS )
+ {
+ if( ret == 0 )
+ ret = 1;
+ mbedtls_printf( "The EC J-PAKE password key has unexpectedly been already destroyed\n" );
+ }
+ else
+ {
+ psa_destroy_key( ecjpake_pw_slot );
+ }
+ }
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
const char* message = mbedtls_test_helper_is_psa_leaking();
if( message )
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 6313c52..1ad2034 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -398,7 +398,7 @@ static unsigned long mbedtls_timing_hardclock( void )
}
gettimeofday( &tv_cur, NULL );
- return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
+ return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000U
+ ( tv_cur.tv_usec - tv_init.tv_usec ) );
}
#endif /* !HAVE_HARDCLOCK */
diff --git a/programs/test/cmake_package_install/CMakeLists.txt b/programs/test/cmake_package_install/CMakeLists.txt
index 711a1e5..fb5ad51 100644
--- a/programs/test/cmake_package_install/CMakeLists.txt
+++ b/programs/test/cmake_package_install/CMakeLists.txt
@@ -26,7 +26,7 @@ execute_process(
# Locate the package.
#
-set(MbedTLS_DIR "${MbedTLS_INSTALL_DIR}/cmake")
+list(INSERT CMAKE_PREFIX_PATH 0 "${MbedTLS_INSTALL_DIR}")
find_package(MbedTLS REQUIRED)
#
diff --git a/scripts/code_style.py b/scripts/code_style.py
index 68cd556..8e82b93 100755
--- a/scripts/code_style.py
+++ b/scripts/code_style.py
@@ -22,9 +22,10 @@ change of code style.
import argparse
import io
import os
+import re
import subprocess
import sys
-from typing import List
+from typing import FrozenSet, List
UNCRUSTIFY_SUPPORTED_VERSION = "0.75.1"
CONFIG_FILE = ".uncrustify.cfg"
@@ -32,10 +33,33 @@ UNCRUSTIFY_EXE = "uncrustify"
UNCRUSTIFY_ARGS = ["-c", CONFIG_FILE]
STDOUT_UTF8 = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
STDERR_UTF8 = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
+CHECK_GENERATED_FILES = "tests/scripts/check-generated-files.sh"
def print_err(*args):
print("Error: ", *args, file=STDERR_UTF8)
+# Match FILENAME(s) in "check SCRIPT (FILENAME...)"
+CHECK_CALL_RE = re.compile(r"\n\s*check\s+[^\s#$&*?;|]+([^\n#$&*?;|]+)",
+ re.ASCII)
+def list_generated_files() -> FrozenSet[str]:
+ """Return the names of generated files.
+
+ We don't reformat generated files, since the result might be different
+ from the output of the generator. Ideally the result of the generator
+ would conform to the code style, but this would be difficult, especially
+ with respect to the placement of line breaks in long logical lines.
+ """
+ # Parse check-generated-files.sh to get an up-to-date list of
+ # generated files. Read the file rather than calling it so that
+ # this script only depends on Git, Python and uncrustify, and not other
+ # tools such as sh or grep which might not be available on Windows.
+ # This introduces a limitation: check-generated-files.sh must have
+ # the expected format and must list the files explicitly, not through
+ # wildcards or command substitution.
+ content = open(CHECK_GENERATED_FILES, encoding="utf-8").read()
+ checks = re.findall(CHECK_CALL_RE, content)
+ return frozenset(word for s in checks for word in s.split())
+
def get_src_files() -> List[str]:
"""
Use git ls-files to get a list of the source files
@@ -52,11 +76,14 @@ def get_src_files() -> List[str]:
print_err("git ls-files returned: " + str(result.returncode))
return []
else:
+ generated_files = list_generated_files()
src_files = str(result.stdout, "utf-8").split()
- # Don't correct style for files in 3rdparty/
- src_files = list(filter( \
- lambda filename: not filename.startswith("3rdparty/"), \
- src_files))
+ # Don't correct style for third-party files (and, for simplicity,
+ # companion files in the same subtree), or for automatically
+ # generated files (we're correcting the templates instead).
+ src_files = [filename for filename in src_files
+ if not (filename.startswith("3rdparty/") or
+ filename in generated_files)]
return src_files
def get_uncrustify_version() -> str:
diff --git a/scripts/config.py b/scripts/config.py
index 7e58acd..a53c470 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -194,7 +194,6 @@ EXCLUDE_FROM_FULL = frozenset([
'MBEDTLS_DEPRECATED_WARNING', # conflicts with deprecated options
'MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED', # influences the use of ECDH in TLS
'MBEDTLS_ECP_NO_FALLBACK', # removes internal ECP implementation
- 'MBEDTLS_ECP_RESTARTABLE', # incompatible with USE_PSA_CRYPTO
'MBEDTLS_ENTROPY_FORCE_SHA256', # interacts with CTR_DRBG_128_BIT_KEY
'MBEDTLS_HAVE_SSE2', # hardware dependency
'MBEDTLS_MEMORY_BACKTRACE', # depends on MEMORY_BUFFER_ALLOC_C
diff --git a/scripts/lcov.sh b/scripts/lcov.sh
new file mode 100755
index 0000000..8d141ee
--- /dev/null
+++ b/scripts/lcov.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+help () {
+ cat <<EOF
+Usage: $0 [-r]
+Collect coverage statistics of library code into an HTML report.
+
+General instructions:
+1. Build the library with CFLAGS="--coverage -O0 -g3" and link the test
+ programs with LDFLAGS="--coverage".
+ This can be an out-of-tree build.
+ For example (in-tree):
+ make CFLAGS="--coverage -O0 -g3" LDFLAGS="--coverage"
+ Or (out-of-tree):
+ mkdir build-coverage && cd build-coverage &&
+ cmake -D CMAKE_BUILD_TYPE=Coverage .. && make
+2. Run whatever tests you want.
+3. Run this script from the parent of the directory containing the library
+ object files and coverage statistics files.
+4. Browse the coverage report in Coverage/index.html.
+5. After rework, run "$0 -r", then re-test and run "$0" to get a fresh report.
+
+Options
+ -r Reset traces. Run this before re-testing to get fresh measurements.
+EOF
+}
+
+# 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.
+
+set -eu
+
+# Collect stats and build a HTML report.
+lcov_library_report () {
+ rm -rf Coverage
+ mkdir Coverage Coverage/tmp
+ lcov --capture --initial --directory library -o Coverage/tmp/files.info
+ lcov --rc lcov_branch_coverage=1 --capture --directory library -o Coverage/tmp/tests.info
+ lcov --rc lcov_branch_coverage=1 --add-tracefile Coverage/tmp/files.info --add-tracefile Coverage/tmp/tests.info -o Coverage/tmp/all.info
+ lcov --rc lcov_branch_coverage=1 --remove Coverage/tmp/all.info -o Coverage/tmp/final.info '*.h'
+ gendesc tests/Descriptions.txt -o Coverage/tmp/descriptions
+ genhtml --title "mbed TLS" --description-file Coverage/tmp/descriptions --keep-descriptions --legend --branch-coverage -o Coverage Coverage/tmp/final.info
+ rm -f Coverage/tmp/*.info Coverage/tmp/descriptions
+ echo "Coverage report in: Coverage/index.html"
+}
+
+# Reset the traces to 0.
+lcov_reset_traces () {
+ # Location with plain make
+ rm -f library/*.gcda
+ # Location with CMake
+ rm -f library/CMakeFiles/*.dir/*.gcda
+}
+
+if [ $# -gt 0 ] && [ "$1" = "--help" ]; then
+ help
+ exit
+fi
+
+main=lcov_library_report
+while getopts r OPTLET; do
+ case $OPTLET in
+ r) main=lcov_reset_traces;;
+ *) help 2>&1; exit 120;;
+ esac
+done
+shift $((OPTIND - 1))
+
+"$main" "$@"
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
index 0339b1a..2422175 100644
--- a/scripts/mbedtls_dev/bignum_common.py
+++ b/scripts/mbedtls_dev/bignum_common.py
@@ -15,6 +15,7 @@
# limitations under the License.
from abc import abstractmethod
+import enum
from typing import Iterator, List, Tuple, TypeVar, Any
from itertools import chain
@@ -39,6 +40,11 @@ def invmod(a: int, n: int) -> int:
return b
raise ValueError("Not invertible")
+def invmod_positive(a: int, n: int) -> int:
+ """Return a non-negative inverse of a to modulo n."""
+ inv = invmod(a, n)
+ return inv if inv >= 0 else inv + n
+
def hex_to_int(val: str) -> int:
"""Implement the syntax accepted by mbedtls_test_read_mpi().
@@ -48,7 +54,7 @@ def hex_to_int(val: str) -> int:
return 0
return int(val, 16)
-def quote_str(val) -> str:
+def quote_str(val: str) -> str:
return "\"{}\"".format(val)
def bound_mpi(val: int, bits_in_limb: int) -> int:
@@ -134,7 +140,7 @@ class OperationCommon(test_data_generation.BaseTest):
def hex_digits(self) -> int:
return 2 * (self.limbs * self.bits_in_limb // 8)
- def format_arg(self, val) -> str:
+ def format_arg(self, val: str) -> str:
if self.input_style not in self.input_styles:
raise ValueError("Unknown input style!")
if self.input_style == "variable":
@@ -142,7 +148,7 @@ class OperationCommon(test_data_generation.BaseTest):
else:
return val.zfill(self.hex_digits)
- def format_result(self, res) -> str:
+ def format_result(self, res: int) -> str:
res_str = '{:x}'.format(res)
return quote_str(self.format_arg(res_str))
@@ -240,10 +246,29 @@ class OperationCommon(test_data_generation.BaseTest):
)
+class ModulusRepresentation(enum.Enum):
+ """Representation selector of a modulus."""
+ # Numerical values aligned with the type mbedtls_mpi_mod_rep_selector
+ INVALID = 0
+ MONTGOMERY = 2
+ OPT_RED = 3
+
+ def symbol(self) -> str:
+ """The C symbol for this representation selector."""
+ return 'MBEDTLS_MPI_MOD_REP_' + self.name
+
+ @classmethod
+ def supported_representations(cls) -> List['ModulusRepresentation']:
+ """Return all representations that are supported in positive test cases."""
+ return [cls.MONTGOMERY, cls.OPT_RED]
+
+
class ModOperationCommon(OperationCommon):
#pylint: disable=abstract-method
"""Target for bignum mod_raw test case generation."""
moduli = MODULI_DEFAULT # type: List[str]
+ montgomery_form_a = False
+ disallow_zero_a = False
def __init__(self, val_n: str, val_a: str, val_b: str = "0",
bits_in_limb: int = 64) -> None:
@@ -259,14 +284,36 @@ class ModOperationCommon(OperationCommon):
def from_montgomery(self, val: int) -> int:
return (val * self.r_inv) % self.int_n
+ def convert_from_canonical(self, canonical: int,
+ rep: ModulusRepresentation) -> int:
+ """Convert values from canonical representation to the given representation."""
+ if rep is ModulusRepresentation.MONTGOMERY:
+ return self.to_montgomery(canonical)
+ elif rep is ModulusRepresentation.OPT_RED:
+ return canonical
+ else:
+ raise ValueError('Modulus representation not supported: {}'
+ .format(rep.name))
+
@property
def boundary(self) -> int:
return self.int_n
@property
+ def arg_a(self) -> str:
+ if self.montgomery_form_a:
+ value_a = self.to_montgomery(self.int_a)
+ else:
+ value_a = self.int_a
+ return self.format_arg('{:x}'.format(value_a))
+
+ @property
def arg_n(self) -> str:
return self.format_arg(self.val_n)
+ def format_arg(self, val: str) -> str:
+ return super().format_arg(val).zfill(self.hex_digits)
+
def arguments(self) -> List[str]:
return [quote_str(self.arg_n)] + super().arguments()
@@ -287,6 +334,8 @@ class ModOperationCommon(OperationCommon):
def is_valid(self) -> bool:
if self.int_a >= self.int_n:
return False
+ if self.disallow_zero_a and self.int_a == 0:
+ return False
if self.arity == 2 and self.int_b >= self.int_n:
return False
return True
diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py
index 118a659..24d37cb 100644
--- a/scripts/mbedtls_dev/bignum_core.py
+++ b/scripts/mbedtls_dev/bignum_core.py
@@ -130,24 +130,20 @@ class BignumCoreAddAndAddIf(BignumCoreTarget, bignum_common.OperationCommon):
class BignumCoreSub(BignumCoreTarget, bignum_common.OperationCommon):
"""Test cases for bignum core sub."""
count = 0
+ input_style = "arch_split"
symbol = "-"
test_function = "mpi_core_sub"
test_name = "mbedtls_mpi_core_sub"
def result(self) -> List[str]:
if self.int_a >= self.int_b:
- result_4 = result_8 = self.int_a - self.int_b
+ result = self.int_a - self.int_b
carry = 0
else:
- bound_val = max(self.int_a, self.int_b)
- bound_4 = bignum_common.bound_mpi(bound_val, 32)
- result_4 = bound_4 + self.int_a - self.int_b
- bound_8 = bignum_common.bound_mpi(bound_val, 64)
- result_8 = bound_8 + self.int_a - self.int_b
+ result = self.limb_boundary + self.int_a - self.int_b
carry = 1
return [
- "\"{:x}\"".format(result_4),
- "\"{:x}\"".format(result_8),
+ self.format_result(result),
str(carry)
]
@@ -761,15 +757,7 @@ class BignumCoreExpMod(BignumCoreTarget, bignum_common.ModOperationCommon):
test_function = "mpi_core_exp_mod"
test_name = "Core modular exponentiation (Mongtomery form only)"
input_style = "fixed"
-
- def arguments(self) -> List[str]:
- # Input 'a' has to be given in Montgomery form
- mont_a = self.to_montgomery(self.int_a)
- arg_mont_a = self.format_arg('{:x}'.format(mont_a))
- return [bignum_common.quote_str(n) for n in [self.arg_n,
- arg_mont_a,
- self.arg_b]
- ] + self.result()
+ montgomery_form_a = True
def result(self) -> List[str]:
# Result has to be given in Montgomery form too
@@ -822,6 +810,20 @@ class BignumCoreSubInt(BignumCoreTarget, bignum_common.OperationCommon):
str(-borrow)
]
+class BignumCoreZeroCheckCT(BignumCoreTarget, bignum_common.OperationCommon):
+ """Test cases for bignum core zero check (constant flow)."""
+ count = 0
+ symbol = "== 0"
+ test_function = "mpi_core_check_zero_ct"
+ test_name = "mpi_core_check_zero_ct"
+ input_style = "variable"
+ arity = 1
+ suffix = True
+
+ def result(self) -> List[str]:
+ result = 1 if self.int_a == 0 else 0
+ return [str(result)]
+
# END MERGE SLOT 3
# BEGIN MERGE SLOT 4
diff --git a/scripts/mbedtls_dev/bignum_data.py b/scripts/mbedtls_dev/bignum_data.py
index 9658933..0a48e53 100644
--- a/scripts/mbedtls_dev/bignum_data.py
+++ b/scripts/mbedtls_dev/bignum_data.py
@@ -121,6 +121,9 @@ MODULI_DEFAULT = [
ONLY_PRIME_MODULI = [
"53", # safe prime
"8ac72304057392b5", # 9999999997777777333 (longer, not safe, prime)
+ # The next prime has a different R in Montgomery form depending on
+ # whether 32- or 64-bit MPIs are used.
+ "152d02c7e14af67fe0bf", # 99999999999999999991999
SAFE_PRIME_192_BIT_SEED_1, # safe prime
SAFE_PRIME_1024_BIT_SEED_3, # safe prime
]
diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py
index aa06fe8..a83e136 100644
--- a/scripts/mbedtls_dev/bignum_mod.py
+++ b/scripts/mbedtls_dev/bignum_mod.py
@@ -14,10 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from typing import Dict, List # pylint: disable=unused-import
+from typing import Dict, List
from . import test_data_generation
-from . import bignum_common # pylint: disable=unused-import
+from . import bignum_common
+from .bignum_data import ONLY_PRIME_MODULI
class BignumModTarget(test_data_generation.BaseTarget):
#pylint: disable=abstract-method, too-few-public-methods
@@ -30,6 +31,26 @@ class BignumModTarget(test_data_generation.BaseTarget):
# BEGIN MERGE SLOT 2
+class BignumModMul(bignum_common.ModOperationCommon,
+ BignumModTarget):
+ # pylint:disable=duplicate-code
+ """Test cases for bignum mpi_mod_mul()."""
+ symbol = "*"
+ test_function = "mpi_mod_mul"
+ test_name = "mbedtls_mpi_mod_mul"
+ input_style = "arch_split"
+ arity = 2
+
+ def arguments(self) -> List[str]:
+ return [self.format_result(self.to_montgomery(self.int_a)),
+ self.format_result(self.to_montgomery(self.int_b)),
+ bignum_common.quote_str(self.arg_n)
+ ] + self.result()
+
+ def result(self) -> List[str]:
+ result = (self.int_a * self.int_b) % self.int_n
+ return [self.format_result(self.to_montgomery(result))]
+
# END MERGE SLOT 2
# BEGIN MERGE SLOT 3
@@ -48,6 +69,42 @@ class BignumModSub(bignum_common.ModOperationCommon, BignumModTarget):
# generated cases
return [self.format_result(result), "0"]
+class BignumModInvNonMont(bignum_common.ModOperationCommon, BignumModTarget):
+ """Test cases for bignum mpi_mod_inv() - not in Montgomery form."""
+ moduli = ONLY_PRIME_MODULI # for now only prime moduli supported
+ symbol = "^ -1"
+ test_function = "mpi_mod_inv_non_mont"
+ test_name = "mbedtls_mpi_mod_inv non-Mont. form"
+ input_style = "fixed"
+ arity = 1
+ suffix = True
+ disallow_zero_a = True
+
+ def result(self) -> List[str]:
+ result = bignum_common.invmod_positive(self.int_a, self.int_n)
+ # To make negative tests easier, append 0 for success to the
+ # generated cases
+ return [self.format_result(result), "0"]
+
+class BignumModInvMont(bignum_common.ModOperationCommon, BignumModTarget):
+ """Test cases for bignum mpi_mod_inv() - Montgomery form."""
+ moduli = ONLY_PRIME_MODULI # for now only prime moduli supported
+ symbol = "^ -1"
+ test_function = "mpi_mod_inv_mont"
+ test_name = "mbedtls_mpi_mod_inv Mont. form"
+ input_style = "arch_split" # Mont. form requires arch_split
+ arity = 1
+ suffix = True
+ disallow_zero_a = True
+ montgomery_form_a = True
+
+ def result(self) -> List[str]:
+ result = bignum_common.invmod_positive(self.int_a, self.int_n)
+ mont_result = self.to_montgomery(result)
+ # To make negative tests easier, append 0 for success to the
+ # generated cases
+ return [self.format_result(mont_result), "0"]
+
# END MERGE SLOT 3
# BEGIN MERGE SLOT 4
@@ -55,6 +112,20 @@ class BignumModSub(bignum_common.ModOperationCommon, BignumModTarget):
# END MERGE SLOT 4
# BEGIN MERGE SLOT 5
+class BignumModAdd(bignum_common.ModOperationCommon, BignumModTarget):
+ """Test cases for bignum mpi_mod_add()."""
+ count = 0
+ symbol = "+"
+ test_function = "mpi_mod_add"
+ test_name = "mbedtls_mpi_mod_add"
+ input_style = "fixed"
+
+ def result(self) -> List[str]:
+ result = (self.int_a + self.int_b) % self.int_n
+ # To make negative tests easier, append "0" for success to the
+ # generated cases
+ return [self.format_result(result), "0"]
+
# END MERGE SLOT 5
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
index 6fc4c91..f9d9899 100644
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ b/scripts/mbedtls_dev/bignum_mod_raw.py
@@ -14,8 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from typing import Dict, List
+from typing import Iterator, List
+from . import test_case
from . import test_data_generation
from . import bignum_common
from .bignum_data import ONLY_PRIME_MODULI
@@ -50,6 +51,25 @@ class BignumModRawSub(bignum_common.ModOperationCommon,
result = (self.int_a - self.int_b) % self.int_n
return [self.format_result(result)]
+class BignumModRawMul(bignum_common.ModOperationCommon,
+ BignumModRawTarget):
+ """Test cases for bignum mpi_mod_raw_mul()."""
+ symbol = "*"
+ test_function = "mpi_mod_raw_mul"
+ test_name = "mbedtls_mpi_mod_raw_mul"
+ input_style = "arch_split"
+ arity = 2
+
+ def arguments(self) -> List[str]:
+ return [self.format_result(self.to_montgomery(self.int_a)),
+ self.format_result(self.to_montgomery(self.int_b)),
+ bignum_common.quote_str(self.arg_n)
+ ] + self.result()
+
+ def result(self) -> List[str]:
+ result = (self.int_a * self.int_b) % self.int_n
+ return [self.format_result(self.to_montgomery(result))]
+
# END MERGE SLOT 2
# BEGIN MERGE SLOT 3
@@ -61,24 +81,14 @@ class BignumModRawInvPrime(bignum_common.ModOperationCommon,
symbol = "^ -1"
test_function = "mpi_mod_raw_inv_prime"
test_name = "mbedtls_mpi_mod_raw_inv_prime (Montgomery form only)"
- input_style = "fixed"
+ input_style = "arch_split"
arity = 1
suffix = True
-
- @property
- def is_valid(self) -> bool:
- return self.int_a > 0 and self.int_a < self.int_n
-
- @property
- def arg_a(self) -> str:
- # Input has to be given in Montgomery form
- mont_a = self.to_montgomery(self.int_a)
- return self.format_arg('{:x}'.format(mont_a))
+ montgomery_form_a = True
+ disallow_zero_a = True
def result(self) -> List[str]:
- result = bignum_common.invmod(self.int_a, self.int_n)
- if result < 0:
- result += self.int_n
+ result = bignum_common.invmod_positive(self.int_a, self.int_n)
mont_result = self.to_montgomery(result)
return [self.format_result(mont_result)]
@@ -107,6 +117,88 @@ class BignumModRawAdd(bignum_common.ModOperationCommon,
# BEGIN MERGE SLOT 6
+class BignumModRawConvertRep(bignum_common.ModOperationCommon,
+ BignumModRawTarget):
+ # This is an abstract class, it's ok to have unimplemented methods.
+ #pylint: disable=abstract-method
+ """Test cases for representation conversion."""
+ symbol = ""
+ input_style = "arch_split"
+ arity = 1
+ rep = bignum_common.ModulusRepresentation.INVALID
+
+ def set_representation(self, r: bignum_common.ModulusRepresentation) -> None:
+ self.rep = r
+
+ def arguments(self) -> List[str]:
+ return ([bignum_common.quote_str(self.arg_n), self.rep.symbol(),
+ bignum_common.quote_str(self.arg_a)] +
+ self.result())
+
+ def description(self) -> str:
+ base = super().description()
+ mod_with_rep = 'mod({})'.format(self.rep.name)
+ return base.replace('mod', mod_with_rep, 1)
+
+ @classmethod
+ def test_cases_for_values(cls, rep: bignum_common.ModulusRepresentation,
+ n: str, a: str) -> Iterator[test_case.TestCase]:
+ """Emit test cases for the given values (if any).
+
+ This may emit no test cases if a isn't valid for the modulus n,
+ or multiple test cases if rep requires different data depending
+ on the limb size.
+ """
+ for bil in cls.limb_sizes:
+ test_object = cls(n, a, bits_in_limb=bil)
+ test_object.set_representation(rep)
+ # The class is set to having separate test cases for each limb
+ # size, because the Montgomery representation requires it.
+ # But other representations don't require it. So for other
+ # representations, emit a single test case with no dependency
+ # on the limb size.
+ if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
+ test_object.dependencies = \
+ [dep for dep in test_object.dependencies
+ if not dep.startswith('MBEDTLS_HAVE_INT')]
+ if test_object.is_valid:
+ yield test_object.create_test_case()
+ if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
+ # A single test case (emitted, or skipped due to invalidity)
+ # is enough, since this test case doesn't depend on the
+ # limb size.
+ break
+
+ # The parent class doesn't support non-bignum parameters. So we override
+ # test generation, in order to have the representation as a parameter.
+ @classmethod
+ def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
+
+ for rep in bignum_common.ModulusRepresentation.supported_representations():
+ for n in cls.moduli:
+ for a in cls.input_values:
+ yield from cls.test_cases_for_values(rep, n, a)
+
+class BignumModRawCanonicalToModulusRep(BignumModRawConvertRep):
+ """Test cases for mpi_mod_raw_canonical_to_modulus_rep."""
+ test_function = "mpi_mod_raw_canonical_to_modulus_rep"
+ test_name = "Rep canon->mod"
+
+ def result(self) -> List[str]:
+ return [self.format_result(self.convert_from_canonical(self.int_a, self.rep))]
+
+class BignumModRawModulusToCanonicalRep(BignumModRawConvertRep):
+ """Test cases for mpi_mod_raw_modulus_to_canonical_rep."""
+ test_function = "mpi_mod_raw_modulus_to_canonical_rep"
+ test_name = "Rep mod->canon"
+
+ @property
+ def arg_a(self) -> str:
+ return self.format_arg("{:x}".format(self.convert_from_canonical(self.int_a, self.rep)))
+
+ def result(self) -> List[str]:
+ return [self.format_result(self.int_a)]
+
# END MERGE SLOT 6
# BEGIN MERGE SLOT 7
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 71dd70b..4a7de82 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -243,6 +243,7 @@ if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/seedfile")
link_to_source(seedfile)
endif()
+ link_to_source(Descriptions.txt)
link_to_source(compat.sh)
link_to_source(context-info.sh)
link_to_source(data_files)
diff --git a/tests/Makefile b/tests/Makefile
index 2d2d70a..f037338 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -165,6 +165,7 @@ src/drivers/%.o : src/drivers/%.c
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
C_FILES := $(addsuffix .c,$(APPS))
+c: $(C_FILES)
# Wildcard target for test code generation:
# A .c file is generated for each .data file in the suites/ directory. Each .c
diff --git a/tests/compat-in-docker.sh b/tests/compat-in-docker.sh
index 3a1cd21..ad73582 100755
--- a/tests/compat-in-docker.sh
+++ b/tests/compat-in-docker.sh
@@ -6,6 +6,10 @@
# -------
# This runs compat.sh in a Docker container.
#
+# WARNING: the Dockerfile used by this script is no longer maintained! See
+# https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start
+# for the set of Docker images we use on the CI.
+#
# Notes for users
# ---------------
# If OPENSSL_CMD, GNUTLS_CLI, or GNUTLS_SERV are specified the path must
diff --git a/tests/docker/bionic/Dockerfile b/tests/docker/bionic/Dockerfile
index 28d33b7..d44cdff 100644
--- a/tests/docker/bionic/Dockerfile
+++ b/tests/docker/bionic/Dockerfile
@@ -4,6 +4,10 @@
# -------
# Defines a Docker container suitable to build and run all tests (all.sh),
# except for those that use a proprietary toolchain.
+#
+# WARNING: this Dockerfile is no longer maintained! See
+# https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start
+# for the set of Docker images we use on the CI.
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0
diff --git a/tests/include/test/bignum_helpers.h b/tests/include/test/bignum_helpers.h
new file mode 100644
index 0000000..164017e
--- /dev/null
+++ b/tests/include/test/bignum_helpers.h
@@ -0,0 +1,118 @@
+/**
+ * \file bignum_helpers.h
+ *
+ * \brief This file contains the prototypes of helper functions for
+ * bignum-related testing.
+ */
+
+/*
+ * 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 TEST_BIGNUM_HELPERS_H
+#define TEST_BIGNUM_HELPERS_H
+
+#include <mbedtls/build_info.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <mbedtls/bignum.h>
+#include <bignum_mod.h>
+
+/** Allocate and populate a core MPI from a test case argument.
+ *
+ * This function allocates exactly as many limbs as necessary to fit
+ * the length of the input. In other words, it preserves leading zeros.
+ *
+ * The limb array is allocated with mbedtls_calloc() and must later be
+ * freed with mbedtls_free().
+ *
+ * \param[in,out] pX The address where a pointer to the allocated limb
+ * array will be stored.
+ * \c *pX must be null on entry.
+ * On exit, \c *pX is null on error or if the number
+ * of limbs is 0.
+ * \param[out] plimbs The address where the number of limbs will be stored.
+ * \param[in] input The test argument to read.
+ * It is interpreted as a hexadecimal representation
+ * of a non-negative integer.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
+ const char *input );
+
+/** Read a modulus from a hexadecimal string.
+ *
+ * This function allocates exactly as many limbs as necessary to fit
+ * the length of the input. In other words, it preserves leading zeros.
+ *
+ * The limb array is allocated with mbedtls_calloc() and must later be
+ * freed with mbedtls_free(). You can do that by calling
+ * mbedtls_test_mpi_mod_modulus_free_with_limbs().
+ *
+ * \param[in,out] N A modulus structure. It must be initialized, but
+ * not set up.
+ * \param[in] s The null-terminated hexadecimal string to read from.
+ * \param int_rep The desired representation of residues.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi_modulus( mbedtls_mpi_mod_modulus *N,
+ const char *s,
+ mbedtls_mpi_mod_rep_selector int_rep );
+
+/** Free a modulus and its limbs.
+ *
+ * \param[in] N A modulus structure such that there is no other
+ * reference to `N->p`.
+ */
+void mbedtls_test_mpi_mod_modulus_free_with_limbs( mbedtls_mpi_mod_modulus *N );
+
+/** Read an MPI from a hexadecimal string.
+ *
+ * Like mbedtls_mpi_read_string(), but with tighter guarantees around
+ * edge cases.
+ *
+ * - This function guarantees that if \p s begins with '-' then the sign
+ * bit of the result will be negative, even if the value is 0.
+ * When this function encounters such a "negative 0", it
+ * increments #mbedtls_test_case_uses_negative_0.
+ * - The size of the result is exactly the minimum number of limbs needed
+ * to fit the digits in the input. In particular, this function constructs
+ * a bignum with 0 limbs for an empty string, and a bignum with leading 0
+ * limbs if the string has sufficiently many leading 0 digits.
+ * This is important so that the "0 (null)" and "0 (1 limb)" and
+ * "leading zeros" test cases do what they claim.
+ *
+ * \param[out] X The MPI object to populate. It must be initialized.
+ * \param[in] s The null-terminated hexadecimal string to read from.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s );
+
+/** Nonzero if the current test case had an input parsed with
+ * mbedtls_test_read_mpi() that is a negative 0 (`"-"`, `"-0"`, `"-00"`, etc.,
+ * constructing a result with the sign bit set to -1 and the value being
+ * all-limbs-0, which is not a valid representation in #mbedtls_mpi but is
+ * tested for robustness).
+ */
+extern unsigned mbedtls_test_case_uses_negative_0;
+
+#endif /* MBEDTLS_BIGNUM_C */
+
+#endif /* TEST_BIGNUM_HELPERS_H */
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index 5f9bde6..b64bfcb 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -216,6 +216,17 @@ void mbedtls_test_hexify( unsigned char *obuf,
int len );
/**
+ * \brief Convert hexadecimal digit to an integer.
+ *
+ * \param c The digit to convert (`'0'` to `'9'`, `'A'` to `'F'` or
+ * `'a'` to `'f'`).
+ * \param[out] uc On success, the value of the digit (0 to 15).
+ *
+ * \return 0 on success, -1 if \p c is not a hexadecimal digit.
+ */
+int mbedtls_test_ascii2uc(const char c, unsigned char *uc);
+
+/**
* Allocate and zeroize a buffer.
*
* If the size if zero, a pointer to a zeroized 1-byte buffer is returned.
@@ -269,60 +280,4 @@ void mbedtls_test_err_add_check( int high, int low,
const char *file, int line);
#endif
-#if defined(MBEDTLS_BIGNUM_C)
-/** Allocate and populate a core MPI from a test case argument.
- *
- * This function allocates exactly as many limbs as necessary to fit
- * the length of the input. In other words, it preserves leading zeros.
- *
- * The limb array is allocated with mbedtls_calloc() and must later be
- * freed with mbedtls_free().
- *
- * \param[in,out] pX The address where a pointer to the allocated limb
- * array will be stored.
- * \c *pX must be null on entry.
- * On exit, \c *pX is null on error or if the number
- * of limbs is 0.
- * \param[out] plimbs The address where the number of limbs will be stored.
- * \param[in] input The test argument to read.
- * It is interpreted as a hexadecimal representation
- * of a non-negative integer.
- *
- * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
- */
-int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
- const char *input );
-
-/** Read an MPI from a hexadecimal string.
- *
- * Like mbedtls_mpi_read_string(), but with tighter guarantees around
- * edge cases.
- *
- * - This function guarantees that if \p s begins with '-' then the sign
- * bit of the result will be negative, even if the value is 0.
- * When this function encounters such a "negative 0", it
- * increments #mbedtls_test_case_uses_negative_0.
- * - The size of the result is exactly the minimum number of limbs needed
- * to fit the digits in the input. In particular, this function constructs
- * a bignum with 0 limbs for an empty string, and a bignum with leading 0
- * limbs if the string has sufficiently many leading 0 digits.
- * This is important so that the "0 (null)" and "0 (1 limb)" and
- * "leading zeros" test cases do what they claim.
- *
- * \param[out] X The MPI object to populate. It must be initialized.
- * \param[in] s The null-terminated hexadecimal string to read from.
- *
- * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
- */
-int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s );
-
-/** Nonzero if the current test case had an input parsed with
- * mbedtls_test_read_mpi() that is a negative 0 (`"-"`, `"-0"`, `"-00"`, etc.,
- * constructing a result with the sign bit set to -1 and the value being
- * all-limbs-0, which is not a valid representation in #mbedtls_mpi but is
- * tested for robustness).
- */
-extern unsigned mbedtls_test_case_uses_negative_0;
-#endif /* MBEDTLS_BIGNUM_C */
-
#endif /* TEST_HELPERS_H */
diff --git a/tests/make-in-docker.sh b/tests/make-in-docker.sh
index 77dc8ab..0ee08dc 100755
--- a/tests/make-in-docker.sh
+++ b/tests/make-in-docker.sh
@@ -8,6 +8,10 @@
#
# See also:
# - scripts/docker_env.sh for general Docker prerequisites and other information.
+#
+# WARNING: the Dockerfile used by this script is no longer maintained! See
+# https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start
+# for the set of Docker images we use on the CI.
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0
diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh
index ed42848..710fb34 100755
--- a/tests/opt-testcases/tls13-misc.sh
+++ b/tests/opt-testcases/tls13-misc.sh
@@ -56,11 +56,8 @@ run_test "TLS 1.3: PSK: No valid ciphersuite. O->m" \
-s "No matched ciphersuite"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
- MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
run_test "TLS 1.3 m->m: Multiple PSKs: valid ticket, reconnect with ticket" \
"$P_SRV force_version=tls13 tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70 tickets=8" \
"$P_CLI force_version=tls13 tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70 reco_mode=1 reconnect=1" \
@@ -73,11 +70,8 @@ run_test "TLS 1.3 m->m: Multiple PSKs: valid ticket, reconnect with ticket" \
-S "ticket is not authentic"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
- MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
run_test "TLS 1.3 m->m: Multiple PSKs: invalid ticket, reconnect with PSK" \
"$P_SRV force_version=tls13 tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70 tickets=8 dummy_ticket=1" \
"$P_CLI force_version=tls13 tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70 reco_mode=1 reconnect=1" \
@@ -90,11 +84,9 @@ run_test "TLS 1.3 m->m: Multiple PSKs: invalid ticket, reconnect with PSK" \
-s "ticket is not authentic"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
- MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED \
- MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
run_test "TLS 1.3 m->m: Session resumption failure, ticket authentication failed." \
"$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=8 dummy_ticket=1" \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
@@ -111,11 +103,9 @@ run_test "TLS 1.3 m->m: Session resumption failure, ticket authentication failed
-S "Ticket age outside tolerance window"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
- MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED \
- MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
run_test "TLS 1.3 m->m: Session resumption failure, ticket expired." \
"$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=8 dummy_ticket=2" \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
@@ -132,11 +122,9 @@ run_test "TLS 1.3 m->m: Session resumption failure, ticket expired." \
-S "Ticket age outside tolerance window"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
- MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED \
- MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
run_test "TLS 1.3 m->m: Session resumption failure, invalid start time." \
"$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=8 dummy_ticket=3" \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
@@ -153,11 +141,9 @@ run_test "TLS 1.3 m->m: Session resumption failure, invalid start time." \
-S "Ticket age outside tolerance window"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
- MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED \
- MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
run_test "TLS 1.3 m->m: Session resumption failure, ticket expired. too old" \
"$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=8 dummy_ticket=4" \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
@@ -174,11 +160,9 @@ run_test "TLS 1.3 m->m: Session resumption failure, ticket expired. too old" \
-S "Ticket age outside tolerance window"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
- MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED \
- MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
run_test "TLS 1.3 m->m: Session resumption failure, age outside tolerance window, too young." \
"$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=8 dummy_ticket=5" \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
@@ -195,11 +179,9 @@ run_test "TLS 1.3 m->m: Session resumption failure, age outside tolerance window
-s "Ticket age outside tolerance window"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
- MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED \
- MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-requires_any_configs_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED \
- MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
run_test "TLS 1.3 m->m: Session resumption failure, age outside tolerance window, too old." \
"$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=8 dummy_ticket=6" \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
diff --git a/tests/scripts/all-in-docker.sh b/tests/scripts/all-in-docker.sh
index 8c9ff47..7c03d91 100755
--- a/tests/scripts/all-in-docker.sh
+++ b/tests/scripts/all-in-docker.sh
@@ -6,6 +6,10 @@
# -------
# This runs all.sh (except for armcc) in a Docker container.
#
+# WARNING: the Dockerfile used by this script is no longer maintained! See
+# https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start
+# for the set of Docker images we use on the CI.
+#
# Notes for users
# ---------------
# See docker_env.sh for prerequisites and other information.
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 1460ecd..d166f77 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -870,14 +870,8 @@ component_check_test_cases () {
else
opt=''
fi
- tests/scripts/check_test_cases.py $opt
+ tests/scripts/check_test_cases.py -q $opt
unset opt
-
- # Check that no tests are explicitely disabled when USE_PSA_CRYPTO is set
- # as a matter of policy to ensure there is no missed testing
- msg "Check: explicitely disabled test with USE_PSA_CRYPTO" # < 1s
- not grep -n 'depends_on:.*!MBEDTLS_USE_PSA_CRYPTO' tests/suites/*.function tests/suites/*.data
- not grep -n '^ *requires_config_disabled.*MBEDTLS_USE_PSA_CRYPTO' tests/ssl-opt.sh tests/opt-testcases/*.sh
}
component_check_doxygen_warnings () {
@@ -1457,10 +1451,14 @@ component_test_tls1_2_ecjpake_compatibility() {
make -C programs ssl/ssl_server2 ssl/ssl_client2
make -C programs test/udp_proxy test/query_compile_time_config
- msg "test: server w/o USE_PSA - client w/ USE_PSA"
- P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f ECJPAKE
- msg "test: client w/o USE_PSA - server w/ USE_PSA"
- P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f ECJPAKE
+ msg "test: server w/o USE_PSA - client w/ USE_PSA, text password"
+ P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: working, TLS"
+ msg "test: server w/o USE_PSA - client w/ USE_PSA, opaque password"
+ P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: opaque password client only, working, TLS"
+ msg "test: client w/o USE_PSA - server w/ USE_PSA, text password"
+ P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: working, TLS"
+ msg "test: client w/o USE_PSA - server w/ USE_PSA, opaque password"
+ P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: opaque password server only, working, TLS"
rm s2_no_use_psa c2_no_use_psa
}
@@ -1889,10 +1887,13 @@ component_test_depends_py_pkalgs_psa () {
component_build_module_alt () {
msg "build: MBEDTLS_XXX_ALT" # ~30s
scripts/config.py full
- # Disable options that are incompatible with some ALT implementations.
+
+ # Disable options that are incompatible with some ALT implementations:
# aesni.c and padlock.c reference mbedtls_aes_context fields directly.
scripts/config.py unset MBEDTLS_AESNI_C
scripts/config.py unset MBEDTLS_PADLOCK_C
+ # MBEDTLS_ECP_RESTARTABLE is documented as incompatible.
+ scripts/config.py unset MBEDTLS_ECP_RESTARTABLE
# You can only have one threading implementation: alt or pthread, not both.
scripts/config.py unset MBEDTLS_THREADING_PTHREAD
# The SpecifiedECDomain parsing code accesses mbedtls_ecp_group fields
@@ -1904,10 +1905,12 @@ component_build_module_alt () {
# MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*
scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
+
# Enable all MBEDTLS_XXX_ALT for whole modules. Do not enable
# MBEDTLS_XXX_YYY_ALT which are for single functions.
scripts/config.py set-all 'MBEDTLS_([A-Z0-9]*|NIST_KW)_ALT'
scripts/config.py unset MBEDTLS_DHM_ALT #incompatible with MBEDTLS_DEBUG_C
+
# We can only compile, not link, since we don't have any implementations
# suitable for testing with the dummy alt headers.
make CC=gcc CFLAGS='-Werror -Wall -Wextra -I../tests/include/alt-dummy' lib
@@ -1928,7 +1931,6 @@ component_test_no_use_psa_crypto_full_cmake_asan() {
# full minus MBEDTLS_USE_PSA_CRYPTO: run the same set of tests as basic-build-test.sh
msg "build: cmake, full config minus MBEDTLS_USE_PSA_CRYPTO, ASan"
scripts/config.py full
- scripts/config.py set MBEDTLS_ECP_RESTARTABLE # not using PSA, so enable restartable ECC
scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
@@ -1943,6 +1945,9 @@ component_test_no_use_psa_crypto_full_cmake_asan() {
msg "test: main suites (full minus MBEDTLS_USE_PSA_CRYPTO)"
make test
+ # Note: ssl-opt.sh has some test cases that depend on
+ # MBEDTLS_ECP_RESTARTABLE && !MBEDTLS_USE_PSA_CRYPTO
+ # This is the only component where those tests are not skipped.
msg "test: ssl-opt.sh (full minus MBEDTLS_USE_PSA_CRYPTO)"
tests/ssl-opt.sh
diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh
index a96254f..3dc8a73 100755
--- a/tests/scripts/basic-build-test.sh
+++ b/tests/scripts/basic-build-test.sh
@@ -243,35 +243,16 @@ rm -f "tests/basic-build-test-$$.ok"
echo
- # Step 4e - Coverage
- echo "Coverage"
-
- LINES_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/ lines......: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* lines)/\1/p')
- LINES_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/ lines......: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) lines)/\1/p')
- FUNCS_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/ functions..: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* functions)$/\1/p')
- FUNCS_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/ functions..: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) functions)$/\1/p')
- BRANCHES_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/ branches...: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* branches)$/\1/p')
- BRANCHES_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/ branches...: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) branches)$/\1/p')
-
- LINES_PERCENT=$((1000*$LINES_TESTED/$LINES_TOTAL))
- LINES_PERCENT="$(($LINES_PERCENT/10)).$(($LINES_PERCENT-($LINES_PERCENT/10)*10))"
-
- FUNCS_PERCENT=$((1000*$FUNCS_TESTED/$FUNCS_TOTAL))
- FUNCS_PERCENT="$(($FUNCS_PERCENT/10)).$(($FUNCS_PERCENT-($FUNCS_PERCENT/10)*10))"
-
- BRANCHES_PERCENT=$((1000*$BRANCHES_TESTED/$BRANCHES_TOTAL))
- BRANCHES_PERCENT="$(($BRANCHES_PERCENT/10)).$(($BRANCHES_PERCENT-($BRANCHES_PERCENT/10)*10))"
+ # Step 4e - Coverage report
+ echo "Coverage statistics:"
+ sed -n '1,/^Overall coverage/d; /%/p' cov-$TEST_OUTPUT
+ echo
rm unit-test-$TEST_OUTPUT
rm sys-test-$TEST_OUTPUT
rm compat-test-$TEST_OUTPUT
rm cov-$TEST_OUTPUT
- echo "Lines Tested : $LINES_TESTED of $LINES_TOTAL $LINES_PERCENT%"
- echo "Functions Tested : $FUNCS_TESTED of $FUNCS_TOTAL $FUNCS_PERCENT%"
- echo "Branches Tested : $BRANCHES_TESTED of $BRANCHES_TOTAL $BRANCHES_PERCENT%"
- echo
-
# Mark the report generation as having succeeded. This must be the
# last thing in the report generation.
touch "basic-build-test-$$.ok"
diff --git a/tests/scripts/basic-in-docker.sh b/tests/scripts/basic-in-docker.sh
index 1f65710..02cafb0 100755
--- a/tests/scripts/basic-in-docker.sh
+++ b/tests/scripts/basic-in-docker.sh
@@ -9,6 +9,10 @@
# in the default configuration, partial test runs in the reference
# configurations, and some dependency tests.
#
+# WARNING: the Dockerfile used by this script is no longer maintained! See
+# https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start
+# for the set of Docker images we use on the CI.
+#
# Notes for users
# ---------------
# See docker_env.sh for prerequisites and other information.
diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh
index 3006ec7..946794c 100755
--- a/tests/scripts/check-generated-files.sh
+++ b/tests/scripts/check-generated-files.sh
@@ -116,6 +116,16 @@ check()
fi
}
+# Note: if the format of calls to the "check" function changes, update
+# scripts/code_style.py accordingly. For generated C source files (*.h or *.c),
+# the format must be "check SCRIPT FILENAME...". For other source files,
+# any shell syntax is permitted (including e.g. command substitution).
+
+# Note: Instructions to generate those files are replicated in:
+# - **/Makefile (to (re)build them with make)
+# - **/CMakeLists.txt (to (re)build them with cmake)
+# - scripts/make_generated_files.bat (to generate them under Windows)
+
check scripts/generate_errors.pl library/error.c
check scripts/generate_query_config.pl programs/test/query_config.c
check scripts/generate_driver_wrappers.py library/psa_crypto_driver_wrappers.c
diff --git a/tests/scripts/check_names.py b/tests/scripts/check_names.py
index 13b6c2d..7398f3c 100755
--- a/tests/scripts/check_names.py
+++ b/tests/scripts/check_names.py
@@ -444,8 +444,11 @@ class CodeParser():
# Match typedefs and brackets only when they are at the
# beginning of the line -- if they are indented, they might
# be sub-structures within structs, etc.
+ optional_c_identifier = r"([_a-zA-Z][_a-zA-Z0-9]*)?"
if (state == states.OUTSIDE_KEYWORD and
- re.search(r"^(typedef +)?enum +{", line)):
+ re.search(r"^(typedef +)?enum " + \
+ optional_c_identifier + \
+ r" *{", line)):
state = states.IN_BRACES
elif (state == states.OUTSIDE_KEYWORD and
re.search(r"^(typedef +)?enum", line)):
diff --git a/tests/scripts/depends.py b/tests/scripts/depends.py
index 51a8ef2..d4fe4fd 100755
--- a/tests/scripts/depends.py
+++ b/tests/scripts/depends.py
@@ -228,6 +228,7 @@ REVERSE_DEPENDENCIES = {
'MBEDTLS_ECP_C': ['MBEDTLS_ECDSA_C',
'MBEDTLS_ECDH_C',
'MBEDTLS_ECJPAKE_C',
+ 'MBEDTLS_ECP_RESTARTABLE',
'MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED',
'MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED',
'MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED',
diff --git a/tests/scripts/docker_env.sh b/tests/scripts/docker_env.sh
index be96c72..3dbc41d 100755
--- a/tests/scripts/docker_env.sh
+++ b/tests/scripts/docker_env.sh
@@ -9,6 +9,10 @@
# thus making it easier to get set up as well as isolating test dependencies
# (which include legacy/insecure configurations of openssl and gnutls).
#
+# WARNING: the Dockerfile used by this script is no longer maintained! See
+# https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start
+# for the set of Docker images we use on the CI.
+#
# Notes for users
# ---------------
# This script expects a Linux x86_64 system with a recent version of Docker
diff --git a/tests/scripts/generate_bignum_tests.py b/tests/scripts/generate_bignum_tests.py
index 0b84711..6ee6ab3 100755
--- a/tests/scripts/generate_bignum_tests.py
+++ b/tests/scripts/generate_bignum_tests.py
@@ -60,7 +60,6 @@ from abc import ABCMeta
from typing import List
import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import test_case
from mbedtls_dev import test_data_generation
from mbedtls_dev import bignum_common
# Import modules containing additional test classes
diff --git a/tests/scripts/generate_test_code.py b/tests/scripts/generate_test_code.py
index 938f24c..f19d30b 100755
--- a/tests/scripts/generate_test_code.py
+++ b/tests/scripts/generate_test_code.py
@@ -220,25 +220,17 @@ class FileWrapper(io.FileIO):
:param file_name: File path to open.
"""
- super(FileWrapper, self).__init__(file_name, 'r')
+ super().__init__(file_name, 'r')
self._line_no = 0
- def next(self):
+ def __next__(self):
"""
- Python 2 iterator method. This method overrides base class's
- next method and extends the next method to count the line
- numbers as each line is read.
-
- It works for both Python 2 and Python 3 by checking iterator
- method name in the base iterator object.
+ This method overrides base class's __next__ method and extends it
+ method to count the line numbers as each line is read.
:return: Line read from file.
"""
- parent = super(FileWrapper, self)
- if hasattr(parent, '__next__'):
- line = parent.__next__() # Python 3
- else:
- line = parent.next() # Python 2 # pylint: disable=no-member
+ line = super().__next__()
if line is not None:
self._line_no += 1
# Convert byte array to string with correct encoding and
@@ -246,9 +238,6 @@ class FileWrapper(io.FileIO):
return line.decode(sys.getdefaultencoding()).rstrip() + '\n'
return None
- # Python 3 iterator method
- __next__ = next
-
def get_line_no(self):
"""
Gives current line number.
@@ -530,6 +519,50 @@ def generate_function_code(name, code, local_vars, args_dispatch,
gen_dependencies(dependencies)
return preprocessor_check_start + code + preprocessor_check_end
+COMMENT_START_REGEX = re.compile(r'/[*/]')
+
+def skip_comments(line, stream):
+ """Remove comments in line.
+
+ If the line contains an unfinished comment, read more lines from stream
+ until the line that contains the comment.
+
+ :return: The original line with inner comments replaced by spaces.
+ Trailing comments and whitespace may be removed completely.
+ """
+ pos = 0
+ while True:
+ opening = COMMENT_START_REGEX.search(line, pos)
+ if not opening:
+ break
+ if line[opening.start(0) + 1] == '/': # //...
+ continuation = line
+ # Count the number of line breaks, to keep line numbers aligned
+ # in the output.
+ line_count = 1
+ while continuation.endswith('\\\n'):
+ # This errors out if the file ends with an unfinished line
+ # comment. That's acceptable to not complicate the code further.
+ continuation = next(stream)
+ line_count += 1
+ return line[:opening.start(0)].rstrip() + '\n' * line_count
+ # Parsing /*...*/, looking for the end
+ closing = line.find('*/', opening.end(0))
+ while closing == -1:
+ # This errors out if the file ends with an unfinished block
+ # comment. That's acceptable to not complicate the code further.
+ line += next(stream)
+ closing = line.find('*/', opening.end(0))
+ pos = closing + 2
+ # Replace inner comment by spaces. There needs to be at least one space
+ # for things like 'int/*ihatespaces*/foo'. Go further and preserve the
+ # width of the comment and line breaks, this way positions in error
+ # messages remain correct.
+ line = (line[:opening.start(0)] +
+ re.sub(r'.', r' ', line[opening.start(0):pos]) +
+ line[pos:])
+ # Strip whitespace at the end of lines (it's irrelevant to error messages).
+ return re.sub(r' +(\n|\Z)', r'\1', line)
def parse_function_code(funcs_f, dependencies, suite_dependencies):
"""
@@ -549,6 +582,7 @@ def parse_function_code(funcs_f, dependencies, suite_dependencies):
# across multiple lines. Here we try to find the start of
# arguments list, then remove '\n's and apply the regex to
# detect function start.
+ line = skip_comments(line, funcs_f)
up_to_arg_list_start = code + line[:line.find('(') + 1]
match = re.match(TEST_FUNCTION_VALIDATION_REGEX,
up_to_arg_list_start.replace('\n', ' '), re.I)
@@ -557,7 +591,7 @@ def parse_function_code(funcs_f, dependencies, suite_dependencies):
name = match.group('func_name')
if not re.match(FUNCTION_ARG_LIST_END_REGEX, line):
for lin in funcs_f:
- line += lin
+ line += skip_comments(lin, funcs_f)
if re.search(FUNCTION_ARG_LIST_END_REGEX, line):
break
args, local_vars, args_dispatch = parse_function_arguments(
diff --git a/tests/scripts/test_generate_test_code.py b/tests/scripts/test_generate_test_code.py
index 9bf66f1..d23d742 100755
--- a/tests/scripts/test_generate_test_code.py
+++ b/tests/scripts/test_generate_test_code.py
@@ -682,12 +682,12 @@ exit:
@patch("generate_test_code.gen_dependencies")
@patch("generate_test_code.gen_function_wrapper")
@patch("generate_test_code.parse_function_arguments")
- def test_functio_name_on_newline(self, parse_function_arguments_mock,
- gen_function_wrapper_mock,
- gen_dependencies_mock,
- gen_dispatch_mock):
+ def test_function_name_on_newline(self, parse_function_arguments_mock,
+ gen_function_wrapper_mock,
+ gen_dependencies_mock,
+ gen_dispatch_mock):
"""
- Test when exit label is present.
+ Test with line break before the function name.
:return:
"""
parse_function_arguments_mock.return_value = ([], '', [])
@@ -727,6 +727,194 @@ exit:
'''
self.assertEqual(code, expected)
+ @patch("generate_test_code.gen_dispatch")
+ @patch("generate_test_code.gen_dependencies")
+ @patch("generate_test_code.gen_function_wrapper")
+ @patch("generate_test_code.parse_function_arguments")
+ def test_case_starting_with_comment(self, parse_function_arguments_mock,
+ gen_function_wrapper_mock,
+ gen_dependencies_mock,
+ gen_dispatch_mock):
+ """
+ Test with comments before the function signature
+ :return:
+ """
+ parse_function_arguments_mock.return_value = ([], '', [])
+ gen_function_wrapper_mock.return_value = ''
+ gen_dependencies_mock.side_effect = gen_dependencies
+ gen_dispatch_mock.side_effect = gen_dispatch
+ data = '''/* comment */
+/* more
+ * comment */
+// this is\\
+still \\
+a comment
+void func()
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+/* END_CASE */
+'''
+ stream = StringIOWrapper('test_suite_ut.function', data)
+ _, _, code, _ = parse_function_code(stream, [], [])
+
+ expected = '''#line 1 "test_suite_ut.function"
+
+
+
+
+
+
+void test_func()
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+'''
+ self.assertEqual(code, expected)
+
+ @patch("generate_test_code.gen_dispatch")
+ @patch("generate_test_code.gen_dependencies")
+ @patch("generate_test_code.gen_function_wrapper")
+ @patch("generate_test_code.parse_function_arguments")
+ def test_comment_in_prototype(self, parse_function_arguments_mock,
+ gen_function_wrapper_mock,
+ gen_dependencies_mock,
+ gen_dispatch_mock):
+ """
+ Test with comments in the function prototype
+ :return:
+ """
+ parse_function_arguments_mock.return_value = ([], '', [])
+ gen_function_wrapper_mock.return_value = ''
+ gen_dependencies_mock.side_effect = gen_dependencies
+ gen_dispatch_mock.side_effect = gen_dispatch
+ data = '''
+void func( int x, // (line \\
+ comment)
+ int y /* lone closing parenthesis) */ )
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+/* END_CASE */
+'''
+ stream = StringIOWrapper('test_suite_ut.function', data)
+ _, _, code, _ = parse_function_code(stream, [], [])
+
+ expected = '''#line 1 "test_suite_ut.function"
+
+void test_func( int x,
+
+ int y )
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+'''
+ self.assertEqual(code, expected)
+
+ @patch("generate_test_code.gen_dispatch")
+ @patch("generate_test_code.gen_dependencies")
+ @patch("generate_test_code.gen_function_wrapper")
+ @patch("generate_test_code.parse_function_arguments")
+ def test_line_comment_in_block_comment(self, parse_function_arguments_mock,
+ gen_function_wrapper_mock,
+ gen_dependencies_mock,
+ gen_dispatch_mock):
+ """
+ Test with line comment in block comment.
+ :return:
+ """
+ parse_function_arguments_mock.return_value = ([], '', [])
+ gen_function_wrapper_mock.return_value = ''
+ gen_dependencies_mock.side_effect = gen_dependencies
+ gen_dispatch_mock.side_effect = gen_dispatch
+ data = '''
+void func( int x /* // */ )
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+/* END_CASE */
+'''
+ stream = StringIOWrapper('test_suite_ut.function', data)
+ _, _, code, _ = parse_function_code(stream, [], [])
+
+ expected = '''#line 1 "test_suite_ut.function"
+
+void test_func( int x )
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+'''
+ self.assertEqual(code, expected)
+
+ @patch("generate_test_code.gen_dispatch")
+ @patch("generate_test_code.gen_dependencies")
+ @patch("generate_test_code.gen_function_wrapper")
+ @patch("generate_test_code.parse_function_arguments")
+ def test_block_comment_in_line_comment(self, parse_function_arguments_mock,
+ gen_function_wrapper_mock,
+ gen_dependencies_mock,
+ gen_dispatch_mock):
+ """
+ Test with block comment in line comment.
+ :return:
+ """
+ parse_function_arguments_mock.return_value = ([], '', [])
+ gen_function_wrapper_mock.return_value = ''
+ gen_dependencies_mock.side_effect = gen_dependencies
+ gen_dispatch_mock.side_effect = gen_dispatch
+ data = '''
+// /*
+void func( int x )
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+/* END_CASE */
+'''
+ stream = StringIOWrapper('test_suite_ut.function', data)
+ _, _, code, _ = parse_function_code(stream, [], [])
+
+ expected = '''#line 1 "test_suite_ut.function"
+
+
+void test_func( int x )
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+'''
+ self.assertEqual(code, expected)
+
class ParseFunction(TestCase):
"""
diff --git a/tests/src/bignum_helpers.c b/tests/src/bignum_helpers.c
new file mode 100644
index 0000000..d6ec9bd
--- /dev/null
+++ b/tests/src/bignum_helpers.c
@@ -0,0 +1,142 @@
+/**
+ * \file bignum_helpers.c
+ *
+ * \brief This file contains the prototypes of helper functions for
+ * bignum-related testing.
+ */
+
+/*
+ * 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.
+ */
+
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#include <test/bignum_helpers.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mbedtls/bignum.h>
+#include <bignum_core.h>
+#include <bignum_mod.h>
+#include <bignum_mod_raw.h>
+
+#include <test/helpers.h>
+#include <test/macros.h>
+
+int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
+ const char *input )
+{
+ /* Sanity check */
+ if( *pX != NULL )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+ size_t hex_len = strlen( input );
+ size_t byte_len = ( hex_len + 1 ) / 2;
+ *plimbs = CHARS_TO_LIMBS( byte_len );
+
+ /* A core bignum is not allowed to be empty. Forbid it as test data,
+ * this way static analyzers have a chance of knowing we don't expect
+ * the bignum functions to support empty inputs. */
+ if( *plimbs == 0 )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+ *pX = mbedtls_calloc( *plimbs, sizeof( **pX ) );
+ if( *pX == NULL )
+ return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+ unsigned char *byte_start = ( unsigned char * ) *pX;
+ if( byte_len % sizeof( mbedtls_mpi_uint ) != 0 )
+ {
+ byte_start += sizeof( mbedtls_mpi_uint ) - byte_len % sizeof( mbedtls_mpi_uint );
+ }
+ if( ( hex_len & 1 ) != 0 )
+ {
+ /* mbedtls_test_unhexify wants an even number of hex digits */
+ TEST_ASSERT( mbedtls_test_ascii2uc( *input, byte_start ) == 0 );
+ ++byte_start;
+ ++input;
+ --byte_len;
+ }
+ TEST_ASSERT( mbedtls_test_unhexify( byte_start,
+ byte_len,
+ input,
+ &byte_len ) == 0 );
+
+ mbedtls_mpi_core_bigendian_to_host( *pX, *plimbs );
+ return( 0 );
+
+exit:
+ mbedtls_free( *pX );
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+}
+
+int mbedtls_test_read_mpi_modulus( mbedtls_mpi_mod_modulus *N,
+ const char *s,
+ mbedtls_mpi_mod_rep_selector int_rep )
+{
+ mbedtls_mpi_uint *p = NULL;
+ size_t limbs = 0;
+ if( N->limbs != 0 )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ int ret = mbedtls_test_read_mpi_core( &p, &limbs, s );
+ if( ret != 0 )
+ return( ret );
+ ret = mbedtls_mpi_mod_modulus_setup( N, p, limbs, int_rep );
+ if( ret != 0 )
+ mbedtls_free( p );
+ return( ret );
+}
+
+void mbedtls_test_mpi_mod_modulus_free_with_limbs( mbedtls_mpi_mod_modulus *N )
+{
+ mbedtls_free( (mbedtls_mpi_uint*) N->p );
+ mbedtls_mpi_mod_modulus_free( N );
+}
+
+int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s )
+{
+ int negative = 0;
+ /* Always set the sign bit to -1 if the input has a minus sign, even for 0.
+ * This creates an invalid representation, which mbedtls_mpi_read_string()
+ * avoids but we want to be able to create that in test data. */
+ if( s[0] == '-' )
+ {
+ ++s;
+ negative = 1;
+ }
+ /* mbedtls_mpi_read_string() currently retains leading zeros.
+ * It always allocates at least one limb for the value 0. */
+ if( s[0] == 0 )
+ {
+ mbedtls_mpi_free( X );
+ return( 0 );
+ }
+ int ret = mbedtls_mpi_read_string( X, 16, s );
+ if( ret != 0 )
+ return( ret );
+ if( negative )
+ {
+ if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
+ ++mbedtls_test_case_uses_negative_0;
+ X->s = -1;
+ }
+ return( 0 );
+}
+
+#endif /* MBEDTLS_BIGNUM_C */
+
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index 7c83714..be5c465 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -48,7 +48,7 @@ void mbedtls_test_platform_teardown( void )
#endif /* MBEDTLS_PLATFORM_C */
}
-static int ascii2uc(const char c, unsigned char *uc)
+int mbedtls_test_ascii2uc(const char c, unsigned char *uc)
{
if( ( c >= '0' ) && ( c <= '9' ) )
*uc = c - '0';
@@ -207,10 +207,10 @@ int mbedtls_test_unhexify( unsigned char *obuf,
while( *ibuf != 0 )
{
- if ( ascii2uc( *(ibuf++), &uc ) != 0 )
+ if ( mbedtls_test_ascii2uc( *(ibuf++), &uc ) != 0 )
return( -1 );
- if ( ascii2uc( *(ibuf++), &uc2 ) != 0 )
+ if ( mbedtls_test_ascii2uc( *(ibuf++), &uc2 ) != 0 )
return( -1 );
*(obuf++) = ( uc << 4 ) | uc2;
@@ -350,84 +350,3 @@ void mbedtls_test_err_add_check( int high, int low,
}
}
#endif /* MBEDTLS_TEST_HOOKS */
-
-#if defined(MBEDTLS_BIGNUM_C)
-#include "bignum_core.h"
-
-int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
- const char *input )
-{
- /* Sanity check */
- if( *pX != NULL )
- return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
- size_t hex_len = strlen( input );
- size_t byte_len = ( hex_len + 1 ) / 2;
- *plimbs = CHARS_TO_LIMBS( byte_len );
-
- /* A core bignum is not allowed to be empty. Forbid it as test data,
- * this way static analyzers have a chance of knowing we don't expect
- * the bignum functions to support empty inputs. */
- if( *plimbs == 0 )
- return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
- *pX = mbedtls_calloc( *plimbs, sizeof( **pX ) );
- if( *pX == NULL )
- return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
-
- unsigned char *byte_start = ( unsigned char * ) *pX;
- if( byte_len % sizeof( mbedtls_mpi_uint ) != 0 )
- {
- byte_start += sizeof( mbedtls_mpi_uint ) - byte_len % sizeof( mbedtls_mpi_uint );
- }
- if( ( hex_len & 1 ) != 0 )
- {
- /* mbedtls_test_unhexify wants an even number of hex digits */
- TEST_ASSERT( ascii2uc( *input, byte_start ) == 0 );
- ++byte_start;
- ++input;
- --byte_len;
- }
- TEST_ASSERT( mbedtls_test_unhexify( byte_start,
- byte_len,
- input,
- &byte_len ) == 0 );
-
- mbedtls_mpi_core_bigendian_to_host( *pX, *plimbs );
- return( 0 );
-
-exit:
- mbedtls_free( *pX );
- return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-}
-
-int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s )
-{
- int negative = 0;
- /* Always set the sign bit to -1 if the input has a minus sign, even for 0.
- * This creates an invalid representation, which mbedtls_mpi_read_string()
- * avoids but we want to be able to create that in test data. */
- if( s[0] == '-' )
- {
- ++s;
- negative = 1;
- }
- /* mbedtls_mpi_read_string() currently retains leading zeros.
- * It always allocates at least one limb for the value 0. */
- if( s[0] == 0 )
- {
- mbedtls_mpi_free( X );
- return( 0 );
- }
- int ret = mbedtls_mpi_read_string( X, 16, s );
- if( ret != 0 )
- return( ret );
- if( negative )
- {
- if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
- ++mbedtls_test_case_uses_negative_0;
- X->s = -1;
- }
- return( 0 );
-}
-#endif
diff --git a/tests/ssl-opt-in-docker.sh b/tests/ssl-opt-in-docker.sh
index e7bb01d..c8c6697 100755
--- a/tests/ssl-opt-in-docker.sh
+++ b/tests/ssl-opt-in-docker.sh
@@ -6,6 +6,10 @@
# -------
# This runs ssl-opt.sh in a Docker container.
#
+# WARNING: the Dockerfile used by this script is no longer maintained! See
+# https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start
+# for the set of Docker images we use on the CI.
+#
# Notes for users
# ---------------
# If OPENSSL_CMD, GNUTLS_CLI, or GNUTLS_SERV are specified, the path must
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 1fe8bae..0d4ce6e 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -7986,6 +7986,8 @@ run_test "ECJPAKE: server not configured" \
-C "found ecjpake_kkpp extension" \
-s "SSL - The handshake negotiation failed"
+# Note: if the name of this test is changed, then please adjust the corresponding
+# filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh")
requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
run_test "ECJPAKE: working, TLS" \
@@ -8004,6 +8006,73 @@ run_test "ECJPAKE: working, TLS" \
-S "SSL - The handshake negotiation failed" \
-S "SSL - Verification of the message MAC failed"
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test "ECJPAKE: opaque password client+server, working, TLS" \
+ "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \
+ "$P_CLI debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1\
+ force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \
+ 0 \
+ -c "add ciphersuite: c0ff" \
+ -c "adding ecjpake_kkpp extension" \
+ -c "using opaque password" \
+ -s "using opaque password" \
+ -C "re-using cached ecjpake parameters" \
+ -s "found ecjpake kkpp extension" \
+ -S "skip ecjpake kkpp extension" \
+ -S "ciphersuite mismatch: ecjpake not configured" \
+ -s "server hello, ecjpake kkpp extension" \
+ -c "found ecjpake_kkpp extension" \
+ -S "SSL - The handshake negotiation failed" \
+ -S "SSL - Verification of the message MAC failed"
+
+# Note: if the name of this test is changed, then please adjust the corresponding
+# filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh")
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test "ECJPAKE: opaque password client only, working, TLS" \
+ "$P_SRV debug_level=3 ecjpake_pw=bla" \
+ "$P_CLI debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1\
+ force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \
+ 0 \
+ -c "add ciphersuite: c0ff" \
+ -c "adding ecjpake_kkpp extension" \
+ -c "using opaque password" \
+ -S "using opaque password" \
+ -C "re-using cached ecjpake parameters" \
+ -s "found ecjpake kkpp extension" \
+ -S "skip ecjpake kkpp extension" \
+ -S "ciphersuite mismatch: ecjpake not configured" \
+ -s "server hello, ecjpake kkpp extension" \
+ -c "found ecjpake_kkpp extension" \
+ -S "SSL - The handshake negotiation failed" \
+ -S "SSL - Verification of the message MAC failed"
+
+# Note: if the name of this test is changed, then please adjust the corresponding
+# filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh")
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test "ECJPAKE: opaque password server only, working, TLS" \
+ "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \
+ "$P_CLI debug_level=3 ecjpake_pw=bla\
+ force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \
+ 0 \
+ -c "add ciphersuite: c0ff" \
+ -c "adding ecjpake_kkpp extension" \
+ -C "using opaque password" \
+ -s "using opaque password" \
+ -C "re-using cached ecjpake parameters" \
+ -s "found ecjpake kkpp extension" \
+ -S "skip ecjpake kkpp extension" \
+ -S "ciphersuite mismatch: ecjpake not configured" \
+ -s "server hello, ecjpake kkpp extension" \
+ -c "found ecjpake_kkpp extension" \
+ -S "SSL - The handshake negotiation failed" \
+ -S "SSL - Verification of the message MAC failed"
+
server_needs_more_time 1
requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
@@ -8015,6 +8084,20 @@ run_test "ECJPAKE: password mismatch, TLS" \
-C "re-using cached ecjpake parameters" \
-s "SSL - Verification of the message MAC failed"
+server_needs_more_time 1
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test "ECJPAKE_OPAQUE_PW: opaque password mismatch, TLS" \
+ "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \
+ "$P_CLI debug_level=3 ecjpake_pw=bad ecjpake_pw_opaque=1 \
+ force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \
+ 1 \
+ -c "using opaque password" \
+ -s "using opaque password" \
+ -C "re-using cached ecjpake parameters" \
+ -s "SSL - Verification of the message MAC failed"
+
requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
run_test "ECJPAKE: working, DTLS" \
@@ -8395,10 +8478,12 @@ run_test "EC restart: TLS, max_ops=65535" \
-C "mbedtls_ecdh_make_public.*4b00" \
-C "mbedtls_pk_sign.*4b00"
+# With USE_PSA disabled we expect full restartable behaviour.
requires_config_enabled MBEDTLS_ECP_RESTARTABLE
requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test "EC restart: TLS, max_ops=1000" \
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: TLS, max_ops=1000 (no USE_PSA)" \
"$P_SRV curves=secp256r1 auth_mode=required" \
"$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
key_file=data_files/server5.key crt_file=data_files/server5.crt \
@@ -8409,6 +8494,25 @@ run_test "EC restart: TLS, max_ops=1000" \
-c "mbedtls_ecdh_make_public.*4b00" \
-c "mbedtls_pk_sign.*4b00"
+# With USE_PSA enabled we expect only partial restartable behaviour:
+# everything except ECDH (where TLS calls PSA directly).
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: TLS, max_ops=1000 (USE_PSA)" \
+ "$P_SRV curves=secp256r1 auth_mode=required" \
+ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+ key_file=data_files/server5.key crt_file=data_files/server5.crt \
+ debug_level=1 ec_max_ops=1000" \
+ 0 \
+ -c "x509_verify_cert.*4b00" \
+ -c "mbedtls_pk_verify.*4b00" \
+ -C "mbedtls_ecdh_make_public.*4b00" \
+ -c "mbedtls_pk_sign.*4b00"
+
+# This works the same with & without USE_PSA as we never get to ECDH:
+# we abort as soon as we determined the cert is bad.
requires_config_enabled MBEDTLS_ECP_RESTARTABLE
requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
@@ -8428,10 +8532,12 @@ run_test "EC restart: TLS, max_ops=1000, badsign" \
-c "! mbedtls_ssl_handshake returned" \
-c "X509 - Certificate verification failed"
+# With USE_PSA disabled we expect full restartable behaviour.
requires_config_enabled MBEDTLS_ECP_RESTARTABLE
requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test "EC restart: TLS, max_ops=1000, auth_mode=optional badsign" \
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: TLS, max_ops=1000, auth_mode=optional badsign (no USE_PSA)" \
"$P_SRV curves=secp256r1 auth_mode=required \
crt_file=data_files/server5-badsign.crt \
key_file=data_files/server5.key" \
@@ -8447,10 +8553,34 @@ run_test "EC restart: TLS, max_ops=1000, auth_mode=optional badsign" \
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed"
+# With USE_PSA enabled we expect only partial restartable behaviour:
+# everything except ECDH (where TLS calls PSA directly).
requires_config_enabled MBEDTLS_ECP_RESTARTABLE
requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test "EC restart: TLS, max_ops=1000, auth_mode=none badsign" \
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: TLS, max_ops=1000, auth_mode=optional badsign (USE_PSA)" \
+ "$P_SRV curves=secp256r1 auth_mode=required \
+ crt_file=data_files/server5-badsign.crt \
+ key_file=data_files/server5.key" \
+ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+ key_file=data_files/server5.key crt_file=data_files/server5.crt \
+ debug_level=1 ec_max_ops=1000 auth_mode=optional" \
+ 0 \
+ -c "x509_verify_cert.*4b00" \
+ -c "mbedtls_pk_verify.*4b00" \
+ -C "mbedtls_ecdh_make_public.*4b00" \
+ -c "mbedtls_pk_sign.*4b00" \
+ -c "! The certificate is not correctly signed by the trusted CA" \
+ -C "! mbedtls_ssl_handshake returned" \
+ -C "X509 - Certificate verification failed"
+
+# With USE_PSA disabled we expect full restartable behaviour.
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: TLS, max_ops=1000, auth_mode=none badsign (no USE_PSA)" \
"$P_SRV curves=secp256r1 auth_mode=required \
crt_file=data_files/server5-badsign.crt \
key_file=data_files/server5.key" \
@@ -8466,10 +8596,34 @@ run_test "EC restart: TLS, max_ops=1000, auth_mode=none badsign" \
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed"
+# With USE_PSA enabled we expect only partial restartable behaviour:
+# everything except ECDH (where TLS calls PSA directly).
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: TLS, max_ops=1000, auth_mode=none badsign (USE_PSA)" \
+ "$P_SRV curves=secp256r1 auth_mode=required \
+ crt_file=data_files/server5-badsign.crt \
+ key_file=data_files/server5.key" \
+ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+ key_file=data_files/server5.key crt_file=data_files/server5.crt \
+ debug_level=1 ec_max_ops=1000 auth_mode=none" \
+ 0 \
+ -C "x509_verify_cert.*4b00" \
+ -c "mbedtls_pk_verify.*4b00" \
+ -C "mbedtls_ecdh_make_public.*4b00" \
+ -c "mbedtls_pk_sign.*4b00" \
+ -C "! The certificate is not correctly signed by the trusted CA" \
+ -C "! mbedtls_ssl_handshake returned" \
+ -C "X509 - Certificate verification failed"
+
+# With USE_PSA disabled we expect full restartable behaviour.
requires_config_enabled MBEDTLS_ECP_RESTARTABLE
requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test "EC restart: DTLS, max_ops=1000" \
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: DTLS, max_ops=1000 (no USE_PSA)" \
"$P_SRV curves=secp256r1 auth_mode=required dtls=1" \
"$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
key_file=data_files/server5.key crt_file=data_files/server5.crt \
@@ -8480,10 +8634,29 @@ run_test "EC restart: DTLS, max_ops=1000" \
-c "mbedtls_ecdh_make_public.*4b00" \
-c "mbedtls_pk_sign.*4b00"
+# With USE_PSA enabled we expect only partial restartable behaviour:
+# everything except ECDH (where TLS calls PSA directly).
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: DTLS, max_ops=1000 (USE_PSA)" \
+ "$P_SRV curves=secp256r1 auth_mode=required dtls=1" \
+ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+ key_file=data_files/server5.key crt_file=data_files/server5.crt \
+ dtls=1 debug_level=1 ec_max_ops=1000" \
+ 0 \
+ -c "x509_verify_cert.*4b00" \
+ -c "mbedtls_pk_verify.*4b00" \
+ -C "mbedtls_ecdh_make_public.*4b00" \
+ -c "mbedtls_pk_sign.*4b00"
+
+# With USE_PSA disabled we expect full restartable behaviour.
requires_config_enabled MBEDTLS_ECP_RESTARTABLE
requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test "EC restart: TLS, max_ops=1000 no client auth" \
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: TLS, max_ops=1000 no client auth (no USE_PSA)" \
"$P_SRV curves=secp256r1" \
"$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
debug_level=1 ec_max_ops=1000" \
@@ -8493,13 +8666,35 @@ run_test "EC restart: TLS, max_ops=1000 no client auth" \
-c "mbedtls_ecdh_make_public.*4b00" \
-C "mbedtls_pk_sign.*4b00"
+
+# With USE_PSA enabled we expect only partial restartable behaviour:
+# everything except ECDH (where TLS calls PSA directly).
requires_config_enabled MBEDTLS_ECP_RESTARTABLE
requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test "EC restart: TLS, max_ops=1000, ECDHE-PSK" \
- "$P_SRV curves=secp256r1 psk=abc123" \
- "$P_CLI force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 \
- psk=abc123 debug_level=1 ec_max_ops=1000" \
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+run_test "EC restart: TLS, max_ops=1000 no client auth (USE_PSA)" \
+ "$P_SRV curves=secp256r1" \
+ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+ debug_level=1 ec_max_ops=1000" \
+ 0 \
+ -c "x509_verify_cert.*4b00" \
+ -c "mbedtls_pk_verify.*4b00" \
+ -C "mbedtls_ecdh_make_public.*4b00" \
+ -C "mbedtls_pk_sign.*4b00"
+
+# Restartable is only for ECDHE-ECDSA, with another ciphersuite we expect no
+# restartable behaviour at all (not even client auth).
+# This is the same as "EC restart: TLS, max_ops=1000" except with ECDHE-RSA,
+# and all 4 assertions negated.
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test "EC restart: TLS, max_ops=1000, ECDHE-RSA" \
+ "$P_SRV curves=secp256r1 auth_mode=required" \
+ "$P_CLI force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 \
+ key_file=data_files/server5.key crt_file=data_files/server5.crt \
+ debug_level=1 ec_max_ops=1000" \
0 \
-C "x509_verify_cert.*4b00" \
-C "mbedtls_pk_verify.*4b00" \
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index fe33f9b..8249564 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -5,6 +5,7 @@
#include <test/helpers.h>
#include <test/macros.h>
#include <test/random.h>
+#include <test/bignum_helpers.h>
#include <test/psa_crypto_helpers.h>
#include <stdlib.h>
diff --git a/tests/suites/test_suite_bignum.function b/tests/suites/test_suite_bignum.function
index 55bb2f5..01af2ff 100644
--- a/tests/suites/test_suite_bignum.function
+++ b/tests/suites/test_suite_bignum.function
@@ -2,6 +2,7 @@
#include "mbedtls/bignum.h"
#include "mbedtls/entropy.h"
#include "constant_time_internal.h"
+#include "bignum_core.h"
#include "test/constant_flow.h"
#if MBEDTLS_MPI_MAX_BITS > 792
@@ -89,50 +90,6 @@ static int f_rng_bytes_left( void *state, unsigned char *buf, size_t len )
return( 0 );
}
-/* Test whether bytes represents (in big-endian base 256) a number b that
- * is significantly above a power of 2. That is, b must not have a long run
- * of unset bits after the most significant bit.
- *
- * Let n be the bit-size of b, i.e. the integer such that 2^n <= b < 2^{n+1}.
- * This function returns 1 if, when drawing a number between 0 and b,
- * the probability that this number is at least 2^n is not negligible.
- * This probability is (b - 2^n) / b and this function checks that this
- * number is above some threshold A. The threshold value is heuristic and
- * based on the needs of mpi_random_many().
- */
-static int is_significantly_above_a_power_of_2( data_t *bytes )
-{
- const uint8_t *p = bytes->x;
- size_t len = bytes->len;
- unsigned x;
-
- /* Skip leading null bytes */
- while( len > 0 && p[0] == 0 )
- {
- ++p;
- --len;
- }
- /* 0 is not significantly above a power of 2 */
- if( len == 0 )
- return( 0 );
- /* Extract the (up to) 2 most significant bytes */
- if( len == 1 )
- x = p[0];
- else
- x = ( p[0] << 8 ) | p[1];
-
- /* Shift the most significant bit of x to position 8 and mask it out */
- while( ( x & 0xfe00 ) != 0 )
- x >>= 1;
- x &= 0x00ff;
-
- /* At this point, x = floor((b - 2^n) / 2^(n-8)). b is significantly above
- * a power of 2 iff x is significantly above 0 compared to 2^8.
- * Testing x >= 2^4 amounts to picking A = 1/16 in the function
- * description above. */
- return( x >= 0x10 );
-}
-
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -1295,170 +1252,6 @@ exit:
/* END_CASE */
/* BEGIN_CASE */
-void mpi_random_many( int min, data_t *bound_bytes, int iterations )
-{
- /* Generate numbers in the range 1..bound-1. Do it iterations times.
- * This function assumes that the value of bound is at least 2 and
- * that iterations is large enough that a one-in-2^iterations chance
- * effectively never occurs.
- */
-
- mbedtls_mpi upper_bound;
- size_t n_bits;
- mbedtls_mpi result;
- size_t b;
- /* If upper_bound is small, stats[b] is the number of times the value b
- * has been generated. Otherwise stats[b] is the number of times a
- * value with bit b set has been generated. */
- size_t *stats = NULL;
- size_t stats_len;
- int full_stats;
- size_t i;
-
- mbedtls_mpi_init( &upper_bound );
- mbedtls_mpi_init( &result );
-
- TEST_EQUAL( 0, mbedtls_mpi_read_binary( &upper_bound,
- bound_bytes->x, bound_bytes->len ) );
- n_bits = mbedtls_mpi_bitlen( &upper_bound );
- /* Consider a bound "small" if it's less than 2^5. This value is chosen
- * to be small enough that the probability of missing one value is
- * negligible given the number of iterations. It must be less than
- * 256 because some of the code below assumes that "small" values
- * fit in a byte. */
- if( n_bits <= 5 )
- {
- full_stats = 1;
- stats_len = bound_bytes->x[bound_bytes->len - 1];
- }
- else
- {
- full_stats = 0;
- stats_len = n_bits;
- }
- ASSERT_ALLOC( stats, stats_len );
-
- for( i = 0; i < (size_t) iterations; i++ )
- {
- mbedtls_test_set_step( i );
- TEST_EQUAL( 0, mbedtls_mpi_random( &result, min, &upper_bound,
- mbedtls_test_rnd_std_rand, NULL ) );
-
- TEST_ASSERT( sign_is_valid( &result ) );
- TEST_ASSERT( mbedtls_mpi_cmp_mpi( &result, &upper_bound ) < 0 );
- TEST_ASSERT( mbedtls_mpi_cmp_int( &result, min ) >= 0 );
- if( full_stats )
- {
- uint8_t value;
- TEST_EQUAL( 0, mbedtls_mpi_write_binary( &result, &value, 1 ) );
- TEST_ASSERT( value < stats_len );
- ++stats[value];
- }
- else
- {
- for( b = 0; b < n_bits; b++ )
- stats[b] += mbedtls_mpi_get_bit( &result, b );
- }
- }
-
- if( full_stats )
- {
- for( b = min; b < stats_len; b++ )
- {
- mbedtls_test_set_step( 1000000 + b );
- /* Assert that each value has been reached at least once.
- * This is almost guaranteed if the iteration count is large
- * enough. This is a very crude way of checking the distribution.
- */
- TEST_ASSERT( stats[b] > 0 );
- }
- }
- else
- {
- int statistically_safe_all_the_way =
- is_significantly_above_a_power_of_2( bound_bytes );
- for( b = 0; b < n_bits; b++ )
- {
- mbedtls_test_set_step( 1000000 + b );
- /* Assert that each bit has been set in at least one result and
- * clear in at least one result. Provided that iterations is not
- * too small, it would be extremely unlikely for this not to be
- * the case if the results are uniformly distributed.
- *
- * As an exception, the top bit may legitimately never be set
- * if bound is a power of 2 or only slightly above.
- */
- if( statistically_safe_all_the_way || b != n_bits - 1 )
- {
- TEST_ASSERT( stats[b] > 0 );
- }
- TEST_ASSERT( stats[b] < (size_t) iterations );
- }
- }
-
-exit:
- mbedtls_mpi_free( &upper_bound );
- mbedtls_mpi_free( &result );
- mbedtls_free( stats );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void mpi_random_sizes( int min, data_t *bound_bytes, int nlimbs, int before )
-{
- mbedtls_mpi upper_bound;
- mbedtls_mpi result;
-
- mbedtls_mpi_init( &upper_bound );
- mbedtls_mpi_init( &result );
-
- if( before != 0 )
- {
- /* Set result to sign(before) * 2^(|before|-1) */
- TEST_ASSERT( mbedtls_mpi_lset( &result, before > 0 ? 1 : -1 ) == 0 );
- if( before < 0 )
- before = - before;
- TEST_ASSERT( mbedtls_mpi_shift_l( &result, before - 1 ) == 0 );
- }
-
- TEST_EQUAL( 0, mbedtls_mpi_grow( &result, nlimbs ) );
- TEST_EQUAL( 0, mbedtls_mpi_read_binary( &upper_bound,
- bound_bytes->x, bound_bytes->len ) );
- TEST_EQUAL( 0, mbedtls_mpi_random( &result, min, &upper_bound,
- mbedtls_test_rnd_std_rand, NULL ) );
- TEST_ASSERT( sign_is_valid( &result ) );
- TEST_ASSERT( mbedtls_mpi_cmp_mpi( &result, &upper_bound ) < 0 );
- TEST_ASSERT( mbedtls_mpi_cmp_int( &result, min ) >= 0 );
-
-exit:
- mbedtls_mpi_free( &upper_bound );
- mbedtls_mpi_free( &result );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void mpi_random_fail( int min, data_t *bound_bytes, int expected_ret )
-{
- mbedtls_mpi upper_bound;
- mbedtls_mpi result;
- int actual_ret;
-
- mbedtls_mpi_init( &upper_bound );
- mbedtls_mpi_init( &result );
-
- TEST_EQUAL( 0, mbedtls_mpi_read_binary( &upper_bound,
- bound_bytes->x, bound_bytes->len ) );
- actual_ret = mbedtls_mpi_random( &result, min, &upper_bound,
- mbedtls_test_rnd_std_rand, NULL );
- TEST_EQUAL( expected_ret, actual_ret );
-
-exit:
- mbedtls_mpi_free( &upper_bound );
- mbedtls_mpi_free( &result );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
void most_negative_mpi_sint( )
{
/* Ad hoc tests for n = -p = -2^(biL-1) as a mbedtls_mpi_sint. We
@@ -1481,7 +1274,6 @@ void most_negative_mpi_sint( )
mbedtls_mpi_init( &R );
mbedtls_mpi_init( &X );
- const size_t biL = 8 * sizeof( mbedtls_mpi_sint );
mbedtls_mpi_uint most_positive_plus_1 = (mbedtls_mpi_uint) 1 << ( biL - 1 );
const mbedtls_mpi_sint most_positive = most_positive_plus_1 - 1;
const mbedtls_mpi_sint most_negative = - most_positive - 1;
diff --git a/tests/suites/test_suite_bignum.misc.data b/tests/suites/test_suite_bignum.misc.data
index dc6830e..5eda4c1 100644
--- a/tests/suites/test_suite_bignum.misc.data
+++ b/tests/suites/test_suite_bignum.misc.data
@@ -1788,176 +1788,6 @@ mpi_fill_random:16:15:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
Fill random: MAX_SIZE bytes, RNG failure after MAX_SIZE-1 bytes
mpi_fill_random:MBEDTLS_MPI_MAX_SIZE:MBEDTLS_MPI_MAX_SIZE-1:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
-MPI random in range: 1..2
-mpi_random_many:1:"02":1000
-
-MPI random in range: 1..3
-mpi_random_many:1:"03":1000
-
-MPI random in range: 1..4
-mpi_random_many:1:"04":1000
-
-MPI random in range: 1..5
-mpi_random_many:1:"05":1000
-
-MPI random in range: 1..6
-mpi_random_many:1:"06":1000
-
-MPI random in range: 1..7
-mpi_random_many:1:"07":1000
-
-MPI random in range: 1..8
-mpi_random_many:1:"08":1000
-
-MPI random in range: 1..9
-mpi_random_many:1:"09":1000
-
-MPI random in range: 1..10
-mpi_random_many:1:"0a":1000
-
-MPI random in range: 1..11
-mpi_random_many:1:"0b":1000
-
-MPI random in range: 1..12
-mpi_random_many:1:"0c":1000
-
-MPI random in range: 1..255
-mpi_random_many:1:"ff":200
-
-MPI random in range: 1..256
-mpi_random_many:1:"0100":200
-
-MPI random in range: 1..257
-mpi_random_many:1:"0101":200
-
-MPI random in range: 1..272
-mpi_random_many:1:"0110":200
-
-MPI random in range: 1..2^64-1
-mpi_random_many:1:"ffffffffffffffff":100
-
-MPI random in range: 1..2^64
-mpi_random_many:1:"010000000000000000":100
-
-MPI random in range: 1..2^64+1
-mpi_random_many:1:"010000000000000001":100
-
-MPI random in range: 1..2^64+2^63
-mpi_random_many:1:"018000000000000000":100
-
-MPI random in range: 1..2^65-1
-mpi_random_many:1:"01ffffffffffffffff":100
-
-MPI random in range: 1..2^65
-mpi_random_many:1:"020000000000000000":100
-
-MPI random in range: 1..2^65+1
-mpi_random_many:1:"020000000000000001":100
-
-MPI random in range: 1..2^65+2^64
-mpi_random_many:1:"030000000000000000":100
-
-MPI random in range: 1..2^66+2^65
-mpi_random_many:1:"060000000000000000":100
-
-MPI random in range: 1..2^71-1
-mpi_random_many:1:"7fffffffffffffffff":100
-
-MPI random in range: 1..2^71
-mpi_random_many:1:"800000000000000000":100
-
-MPI random in range: 1..2^71+1
-mpi_random_many:1:"800000000000000001":100
-
-MPI random in range: 1..2^71+2^70
-mpi_random_many:1:"c00000000000000000":100
-
-MPI random in range: 1..2^72-1
-mpi_random_many:1:"ffffffffffffffffff":100
-
-MPI random in range: 1..2^72
-mpi_random_many:1:"01000000000000000000":100
-
-MPI random in range: 1..2^72+1
-mpi_random_many:1:"01000000000000000001":100
-
-MPI random in range: 1..2^72+2^71
-mpi_random_many:1:"01800000000000000000":100
-
-MPI random in range: 0..1
-mpi_random_many:0:"04":10000
-
-MPI random in range: 0..4
-mpi_random_many:0:"04":10000
-
-MPI random in range: 2..4
-mpi_random_many:2:"04":10000
-
-MPI random in range: 3..4
-mpi_random_many:3:"04":10000
-
-MPI random in range: smaller result
-mpi_random_sizes:1:"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb":1:0
-
-MPI random in range: same size result (32-bit limbs)
-mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":2:0
-
-MPI random in range: same size result (64-bit limbs)
-mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":1:0
-
-MPI random in range: larger result
-mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":3:0
-
-## The "0 limb in upper bound" tests rely on the fact that
-## mbedtls_mpi_read_binary() bases the size of the MPI on the size of
-## the input, without first checking for leading zeros. If this was
-## not the case, the tests would still pass, but would not exercise
-## the advertised behavior.
-MPI random in range: leading 0 limb in upper bound #0
-mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":0:0
-
-MPI random in range: leading 0 limb in upper bound #1
-mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":1:0
-
-MPI random in range: leading 0 limb in upper bound #2
-mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":2:0
-
-MPI random in range: leading 0 limb in upper bound #3
-mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":3:0
-
-MPI random in range: leading 0 limb in upper bound #4
-mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":4:0
-
-MPI random in range: previously small >0
-mpi_random_sizes:1:"1234567890":4:1
-
-MPI random in range: previously small <0
-mpi_random_sizes:1:"1234567890":4:-1
-
-MPI random in range: previously large >0
-mpi_random_sizes:1:"1234":4:65
-
-MPI random in range: previously large <0
-mpi_random_sizes:1:"1234":4:-65
-
-MPI random bad arguments: min < 0
-mpi_random_fail:-1:"04":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
-MPI random bad arguments: min = N = 0
-mpi_random_fail:0:"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
-MPI random bad arguments: min = N = 1
-mpi_random_fail:1:"01":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
-MPI random bad arguments: min > N = 0
-mpi_random_fail:1:"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
-MPI random bad arguments: min > N = 1
-mpi_random_fail:2:"01":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
-MPI random bad arguments: min > N = 1, 0 limb in upper bound
-mpi_random_fail:2:"000000000000000001":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
Most negative mbedtls_mpi_sint
most_negative_mpi_sint:
diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function
index 7bf03fb..47f9013 100644
--- a/tests/suites/test_suite_bignum_core.function
+++ b/tests/suites/test_suite_bignum_core.function
@@ -345,6 +345,56 @@ exit:
/* END_CASE */
/* BEGIN_CASE */
+void mpi_core_uint_le_mpi( char *input_A )
+{
+ mbedtls_mpi_uint *A = NULL;
+ size_t A_limbs = 0;
+
+ TEST_EQUAL( mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ), 0 );
+
+ int is_large = 0; /* nonzero limbs beyond the lowest-order one? */
+ for( size_t i = 1; i < A_limbs; i++ )
+ {
+ if( A[i] != 0 )
+ {
+ is_large = 1;
+ break;
+ }
+ }
+
+ TEST_CF_SECRET( A, A_limbs * sizeof( *A ) );
+
+ TEST_EQUAL( mbedtls_mpi_core_uint_le_mpi( 0, A, A_limbs ), 1 );
+ TEST_EQUAL( mbedtls_mpi_core_uint_le_mpi( A[0], A, A_limbs ), 1 );
+
+ if( is_large )
+ {
+ TEST_EQUAL( mbedtls_mpi_core_uint_le_mpi( A[0] + 1,
+ A, A_limbs ), 1 );
+ TEST_EQUAL( mbedtls_mpi_core_uint_le_mpi( (mbedtls_mpi_uint)( -1 ) >> 1,
+ A, A_limbs ), 1 );
+ TEST_EQUAL( mbedtls_mpi_core_uint_le_mpi( (mbedtls_mpi_uint)( -1 ),
+ A, A_limbs ), 1 );
+ }
+ else
+ {
+ TEST_EQUAL( mbedtls_mpi_core_uint_le_mpi( A[0] + 1,
+ A, A_limbs ),
+ A[0] + 1 <= A[0] );
+ TEST_EQUAL( mbedtls_mpi_core_uint_le_mpi( (mbedtls_mpi_uint)( -1 ) >> 1,
+ A, A_limbs ),
+ (mbedtls_mpi_uint)( -1 ) >> 1 <= A[0] );
+ TEST_EQUAL( mbedtls_mpi_core_uint_le_mpi( (mbedtls_mpi_uint)( -1 ),
+ A, A_limbs ),
+ (mbedtls_mpi_uint)( -1 ) <= A[0] );
+ }
+
+exit:
+ mbedtls_free( A );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void mpi_core_cond_assign( char * input_X,
char * input_Y,
int input_bytes )
@@ -533,10 +583,9 @@ exit:
/* BEGIN_CASE */
void mpi_core_sub( char * input_A, char * input_B,
- char * input_X4, char * input_X8,
- int carry )
+ char * input_X, int carry )
{
- mbedtls_mpi A, B, X4, X8;
+ mbedtls_mpi A, B, X;
mbedtls_mpi_uint *a = NULL;
mbedtls_mpi_uint *b = NULL;
mbedtls_mpi_uint *x = NULL; /* expected */
@@ -544,29 +593,23 @@ void mpi_core_sub( char * input_A, char * input_B,
mbedtls_mpi_init( &A );
mbedtls_mpi_init( &B );
- mbedtls_mpi_init( &X4 );
- mbedtls_mpi_init( &X8 );
+ mbedtls_mpi_init( &X );
TEST_EQUAL( 0, mbedtls_test_read_mpi( &A, input_A ) );
TEST_EQUAL( 0, mbedtls_test_read_mpi( &B, input_B ) );
- TEST_EQUAL( 0, mbedtls_test_read_mpi( &X4, input_X4 ) );
- TEST_EQUAL( 0, mbedtls_test_read_mpi( &X8, input_X8 ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi( &X, input_X ) );
/* All of the inputs are +ve (or zero) */
TEST_EQUAL( 1, A.s );
TEST_EQUAL( 1, B.s );
- TEST_EQUAL( 1, X4.s );
- TEST_EQUAL( 1, X8.s );
+ TEST_EQUAL( 1, X.s );
/* Get the number of limbs we will need */
size_t limbs = MAX( A.n, B.n );
size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
- /* We only need to work with X4 or X8, depending on sizeof(mbedtls_mpi_uint) */
- mbedtls_mpi *X = ( sizeof(mbedtls_mpi_uint) == 4 ) ? &X4 : &X8;
-
/* The result shouldn't have more limbs than the longest input */
- TEST_LE_U( X->n, limbs );
+ TEST_LE_U( X.n, limbs );
/* Now let's get arrays of mbedtls_mpi_uints, rather than MPI structures */
@@ -582,7 +625,7 @@ void mpi_core_sub( char * input_A, char * input_B,
*/
memcpy( a, A.p, A.n * sizeof(mbedtls_mpi_uint) );
memcpy( b, B.p, B.n * sizeof(mbedtls_mpi_uint) );
- memcpy( x, X->p, X->n * sizeof(mbedtls_mpi_uint) );
+ memcpy( x, X.p, X.n * sizeof(mbedtls_mpi_uint) );
/* 1a) r = a - b => we should get the correct carry */
TEST_EQUAL( carry, mbedtls_mpi_core_sub( r, a, b, limbs ) );
@@ -621,8 +664,7 @@ exit:
mbedtls_mpi_free( &A );
mbedtls_mpi_free( &B );
- mbedtls_mpi_free( &X4 );
- mbedtls_mpi_free( &X8 );
+ mbedtls_mpi_free( &X );
}
/* END_CASE */
@@ -806,7 +848,9 @@ void mpi_core_montmul( int limbs_AN4, int limbs_B4,
TEST_EQUAL( 0, mbedtls_mpi_grow( X, limbs_AN ) );
TEST_EQUAL( 0, mbedtls_mpi_grow( &B, limbs_B ) );
- TEST_EQUAL( 0, mbedtls_mpi_grow( &T, limbs_AN * 2 + 1 ) );
+ size_t working_limbs = mbedtls_mpi_core_montmul_working_limbs( limbs_AN );
+ TEST_EQUAL( working_limbs, limbs_AN * 2 + 1 );
+ TEST_EQUAL( 0, mbedtls_mpi_grow( &T, working_limbs ) );
/* Calculate the Montgomery constant (this is unit tested separately) */
mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init( N.p );
@@ -1091,6 +1135,10 @@ void mpi_core_exp_mod( char * input_N, char * input_A,
TEST_LE_U( min_expected_working_limbs, working_limbs );
TEST_LE_U( working_limbs, max_expected_working_limbs );
+ /* Should also be at least mbedtls_mpi_core_montmul_working_limbs() */
+ TEST_LE_U( mbedtls_mpi_core_montmul_working_limbs( N_limbs ),
+ working_limbs );
+
ASSERT_ALLOC( T, working_limbs );
mbedtls_mpi_core_exp_mod( Y, A, N, N_limbs, E, E_limbs, R2, T );
@@ -1170,6 +1218,25 @@ exit:
}
/* END_CASE */
+/* BEGIN_CASE */
+void mpi_core_check_zero_ct( char *input_X, int expected_is_zero )
+{
+ mbedtls_mpi_uint *X = NULL;
+ size_t X_limbs;
+
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+
+ TEST_CF_SECRET( X, X_limbs * sizeof( mbedtls_mpi_uint ) );
+
+ mbedtls_mpi_uint check = mbedtls_mpi_core_check_zero_ct( X, X_limbs );
+ int is_zero = (check == 0);
+ TEST_EQUAL( is_zero, expected_is_zero );
+
+exit:
+ mbedtls_free( X );
+}
+/* END_CASE */
+
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
diff --git a/tests/suites/test_suite_bignum_core.misc.data b/tests/suites/test_suite_bignum_core.misc.data
index 62480e4..81a767a 100644
--- a/tests/suites/test_suite_bignum_core.misc.data
+++ b/tests/suites/test_suite_bignum_core.misc.data
@@ -242,6 +242,69 @@ mpi_core_lt_ct:"11FFFFFFFFFFFFFFFF":"FF1111111111111111":1
mbedtls_mpi_core_lt_ct: x>y (alternating limbs)
mpi_core_lt_ct:"FF1111111111111111":"11FFFFFFFFFFFFFFFF":0
+Test mbedtls_mpi_core_uint_le_mpi: 0 (1 limb)
+mpi_core_uint_le_mpi:"00"
+
+Test mbedtls_mpi_core_uint_le_mpi: 0 (>=2 limbs)
+mpi_core_uint_le_mpi:"000000000000000000"
+
+Test mbedtls_mpi_core_uint_le_mpi: 1 (1 limb)
+mpi_core_uint_le_mpi:"01"
+
+Test mbedtls_mpi_core_uint_le_mpi: 1 (>=2 limbs)
+mpi_core_uint_le_mpi:"000000000000000001"
+
+Test mbedtls_mpi_core_uint_le_mpi: 42 (1 limb)
+mpi_core_uint_le_mpi:"2a"
+
+Test mbedtls_mpi_core_uint_le_mpi: 42 (>=2 limbs)
+mpi_core_uint_le_mpi:"000000000000000042"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^31-1
+mpi_core_uint_le_mpi:"7fffffff"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^31-1 with leading zero limb
+mpi_core_uint_le_mpi:"00000000007fffffff"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^32-1
+mpi_core_uint_le_mpi:"ffffffff"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^32-1 with leading zero limb
+mpi_core_uint_le_mpi:"0000000000ffffffff"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^32
+mpi_core_uint_le_mpi:"10000000"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^32 with leading zero limb
+mpi_core_uint_le_mpi:"000000000010000000"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^32+1
+mpi_core_uint_le_mpi:"10000001"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^32+1 with leading zero limb
+mpi_core_uint_le_mpi:"000000000010000001"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^63-1
+mpi_core_uint_le_mpi:"7fffffffffffffff"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^63-1 with leading zero limb
+mpi_core_uint_le_mpi:"007fffffffffffffff"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^64-1
+mpi_core_uint_le_mpi:"ffffffffffffffff"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^64-1 with leading zero limb
+mpi_core_uint_le_mpi:"00ffffffffffffffff"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^64
+mpi_core_uint_le_mpi:"010000000000000000"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^64+1
+mpi_core_uint_le_mpi:"010000000000000001"
+
+Test mbedtls_mpi_core_uint_le_mpi: 2^64+2
+mpi_core_uint_le_mpi:"010000000000000002"
+
mbedtls_mpi_core_cond_assign: 1 limb
mpi_core_cond_assign:"FFFFFFFF":"11111111":4
diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function
index 0d2e232..8ab8ccf 100644
--- a/tests/suites/test_suite_bignum_mod.function
+++ b/tests/suites/test_suite_bignum_mod.function
@@ -2,6 +2,7 @@
#include "mbedtls/bignum.h"
#include "mbedtls/entropy.h"
#include "bignum_mod.h"
+#include "bignum_mod_raw.h"
#include "constant_time_internal.h"
#include "test/constant_flow.h"
@@ -102,13 +103,152 @@ exit:
/* BEGIN MERGE SLOT 2 */
+/* BEGIN_CASE */
+void mpi_mod_mul( char * input_A,
+ char * input_B,
+ char * input_N,
+ char * result )
+{
+ mbedtls_mpi_uint *X = NULL;
+
+ mbedtls_mpi_mod_residue rA = { NULL, 0 };
+ mbedtls_mpi_mod_residue rB = { NULL, 0 };
+ mbedtls_mpi_mod_residue rR = { NULL, 0 };
+ mbedtls_mpi_mod_residue rX = { NULL, 0 };
+
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ TEST_EQUAL( test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ),
+ 0 );
+
+ TEST_EQUAL( test_read_residue( &rA, &m, input_A, 0 ), 0 );
+ TEST_EQUAL( test_read_residue( &rB, &m, input_B, 0 ), 0 );
+ TEST_EQUAL( test_read_residue( &rR, &m, result, 0 ), 0 );
+
+ const size_t limbs = m.limbs;
+ const size_t bytes = limbs * sizeof( mbedtls_mpi_uint );
+
+ TEST_EQUAL( rA.limbs, limbs );
+ TEST_EQUAL( rB.limbs, limbs );
+ TEST_EQUAL( rR.limbs, limbs );
+
+ ASSERT_ALLOC( X, limbs );
+
+ TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &rX, &m, X, limbs ), 0 );
+
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* alias X to A */
+ memcpy( rX.p, rA.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rB, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* alias X to B */
+ memcpy( rX.p, rB.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rX, &m ), 0);
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* A == B: alias A and B */
+ if( memcmp( rA.p, rB.p, bytes ) == 0 )
+ {
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rA, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* X, A, B all aliased together */
+ memcpy( rX.p, rA.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rX, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+ }
+
+ /* A != B: test B * A */
+ else
+ {
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rB, &rA, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* B * A: alias X to A */
+ memcpy( rX.p, rA.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rB, &rX, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* B + A: alias X to B */
+ memcpy( rX.p, rB.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rA, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+ }
+
+exit:
+ mbedtls_free( rA.p );
+ mbedtls_free( rB.p );
+ mbedtls_free( rR.p );
+ mbedtls_free( X );
+ mbedtls_free( (mbedtls_mpi_uint *) m.p );
+
+ mbedtls_mpi_mod_modulus_free( &m );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_mul_neg( char * input_A,
+ char * input_B,
+ char * input_N,
+ char * result,
+ int exp_ret )
+{
+ mbedtls_mpi_uint *X = NULL;
+
+ mbedtls_mpi_mod_residue rA = { NULL, 0 };
+ mbedtls_mpi_mod_residue rB = { NULL, 0 };
+ mbedtls_mpi_mod_residue rR = { NULL, 0 };
+ mbedtls_mpi_mod_residue rX = { NULL, 0 };
+
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ mbedtls_mpi_mod_modulus fake_m;
+ mbedtls_mpi_mod_modulus_init( &fake_m );
+
+ TEST_EQUAL( test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ),
+ 0 );
+
+ TEST_EQUAL( test_read_residue( &rA, &m, input_A, 1 ), 0 );
+ TEST_EQUAL( test_read_residue( &rB, &m, input_B, 1 ), 0 );
+ TEST_EQUAL( test_read_residue( &rR, &m, result, 1 ), 0 );
+
+ const size_t limbs = m.limbs;
+
+ ASSERT_ALLOC( X, limbs );
+
+ TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &rX, &m, X, limbs ), 0 );
+ rX.limbs = rR.limbs;
+
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &m ), exp_ret );
+
+ /* Check when m is not initialized */
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &fake_m ),
+ MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+exit:
+ mbedtls_free( rA.p );
+ mbedtls_free( rB.p );
+ mbedtls_free( rR.p );
+ mbedtls_free( X );
+ mbedtls_free( (mbedtls_mpi_uint *) m.p );
+
+ mbedtls_mpi_mod_modulus_free( &m );
+ mbedtls_mpi_mod_modulus_free( &fake_m );
+}
+/* END_CASE */
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* BEGIN_CASE */
void mpi_mod_sub( char * input_N,
char * input_A, char * input_B,
- char * input_D, int oret )
+ char * input_D, int expected_ret )
{
mbedtls_mpi_mod_residue a = { NULL, 0 };
mbedtls_mpi_mod_residue b = { NULL, 0 };
@@ -125,46 +265,51 @@ void mpi_mod_sub( char * input_N,
/* test_read_residue() normally checks that inputs have the same number of
* limbs as the modulus. For negative testing we can ask it to skip this
* with a non-zero final parameter. */
- TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, oret != 0 ) );
- TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, oret != 0 ) );
- TEST_EQUAL( 0, test_read_residue( &d, &m, input_D, oret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, expected_ret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, expected_ret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &d, &m, input_D, expected_ret != 0 ) );
size_t limbs = m.limbs;
size_t bytes = limbs * sizeof( *X_raw );
- /* One spare limb for negative testing */
- ASSERT_ALLOC( X_raw, limbs + 1 );
-
- if( oret == 0 )
+ if( expected_ret == 0 )
{
- /* Sneak in a couple of negative tests on known-good data */
+ /* Negative test with too many limbs in output */
+ ASSERT_ALLOC( X_raw, limbs + 1 );
- /* First, negative test with too many limbs in output */
x.p = X_raw;
x.limbs = limbs + 1;
TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
- /* Then negative test with too few limbs in output */
+ mbedtls_free( X_raw );
+ X_raw = NULL;
+
+ /* Negative test with too few limbs in output */
if( limbs > 1 )
{
+ ASSERT_ALLOC( X_raw, limbs - 1 );
+
x.p = X_raw;
x.limbs = limbs - 1;
TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
+
+ mbedtls_free( X_raw );
+ X_raw = NULL;
}
/* Negative testing with too many/too few limbs in a and b is covered by
- * manually-written test cases with oret != 0. */
-
- /* Back to the normally-scheduled programme */
+ * manually-written test cases with expected_ret != 0. */
}
+ ASSERT_ALLOC( X_raw, limbs );
+
TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &m, X_raw, limbs ) );
/* a - b => Correct result, or expected error */
- TEST_EQUAL( oret, mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
- if( oret != 0 )
+ TEST_EQUAL( expected_ret, mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
+ if( expected_ret != 0 )
goto exit;
TEST_COMPARE_MPI_RESIDUES( x, d );
@@ -203,6 +348,106 @@ exit:
mbedtls_free( X_raw );
}
/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_inv_mont( char * input_N,
+ char * input_A, char * input_I,
+ int expected_ret )
+{
+ mbedtls_mpi_mod_residue a = { NULL, 0 }; /* argument */
+ mbedtls_mpi_mod_residue i = { NULL, 0 }; /* expected inverse wrt N */
+ mbedtls_mpi_mod_residue x = { NULL, 0 }; /* output */
+ mbedtls_mpi_uint *X_raw = NULL;
+
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+
+ TEST_EQUAL( 0,
+ test_read_modulus( &N, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ) );
+
+ /* test_read_residue() normally checks that inputs have the same number of
+ * limbs as the modulus. For negative testing we can ask it to skip this
+ * with a non-zero final parameter. */
+ TEST_EQUAL( 0, test_read_residue( &a, &N, input_A, expected_ret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &i, &N, input_I, expected_ret != 0 ) );
+
+ size_t limbs = N.limbs;
+ size_t bytes = limbs * sizeof( *X_raw );
+
+ ASSERT_ALLOC( X_raw, limbs );
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &N, X_raw, limbs ) );
+
+ TEST_EQUAL( expected_ret, mbedtls_mpi_mod_inv( &x, &a, &N ) );
+ if( expected_ret == 0 )
+ {
+ TEST_COMPARE_MPI_RESIDUES( x, i );
+
+ /* a^-1: alias x to a => Correct result */
+ memcpy( x.p, a.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_inv( &x, &x, &N ) );
+ TEST_COMPARE_MPI_RESIDUES( x, i );
+ }
+
+exit:
+ mbedtls_free( (void *)N.p ); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
+ mbedtls_mpi_mod_modulus_free( &N );
+
+ mbedtls_free( a.p );
+ mbedtls_free( i.p );
+ mbedtls_free( X_raw );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_inv_non_mont( char * input_N,
+ char * input_A, char * input_I,
+ int expected_ret )
+{
+ mbedtls_mpi_mod_residue a = { NULL, 0 }; /* argument */
+ mbedtls_mpi_mod_residue i = { NULL, 0 }; /* expected inverse wrt N */
+ mbedtls_mpi_mod_residue x = { NULL, 0 }; /* output */
+ mbedtls_mpi_uint *X_raw = NULL;
+
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+
+ TEST_EQUAL( 0,
+ test_read_modulus( &N, MBEDTLS_MPI_MOD_REP_OPT_RED, input_N ) );
+
+ /* test_read_residue() normally checks that inputs have the same number of
+ * limbs as the modulus. For negative testing we can ask it to skip this
+ * with a non-zero final parameter. */
+ TEST_EQUAL( 0, test_read_residue( &a, &N, input_A, expected_ret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &i, &N, input_I, expected_ret != 0 ) );
+
+ size_t limbs = N.limbs;
+ size_t bytes = limbs * sizeof( *X_raw );
+
+ ASSERT_ALLOC( X_raw, limbs );
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &N, X_raw, limbs ) );
+
+ TEST_EQUAL( expected_ret, mbedtls_mpi_mod_inv( &x, &a, &N ) );
+ if( expected_ret == 0 )
+ {
+ TEST_COMPARE_MPI_RESIDUES( x, i );
+
+ /* a^-1: alias x to a => Correct result */
+ memcpy( x.p, a.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_inv( &x, &x, &N ) );
+ TEST_COMPARE_MPI_RESIDUES( x, i );
+ }
+
+exit:
+ mbedtls_free( (void *)N.p ); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
+ mbedtls_mpi_mod_modulus_free( &N );
+
+ mbedtls_free( a.p );
+ mbedtls_free( i.p );
+ mbedtls_free( X_raw );
+}
+/* END_CASE */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
@@ -210,7 +455,110 @@ exit:
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
+/* BEGIN_CASE */
+void mpi_mod_add( char * input_N,
+ char * input_A, char * input_B,
+ char * input_S, int expected_ret )
+{
+ mbedtls_mpi_mod_residue a = { NULL, 0 };
+ mbedtls_mpi_mod_residue b = { NULL, 0 };
+ mbedtls_mpi_mod_residue s = { NULL, 0 };
+ mbedtls_mpi_mod_residue x = { NULL, 0 };
+ mbedtls_mpi_uint *X_raw = NULL;
+
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ TEST_EQUAL( 0,
+ test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ) );
+
+ /* test_read_residue() normally checks that inputs have the same number of
+ * limbs as the modulus. For negative testing we can ask it to skip this
+ * with a non-zero final parameter. */
+ TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, expected_ret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, expected_ret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &s, &m, input_S, expected_ret != 0 ) );
+ size_t limbs = m.limbs;
+ size_t bytes = limbs * sizeof( *X_raw );
+
+ if( expected_ret == 0 )
+ {
+ /* Negative test with too many limbs in output */
+ ASSERT_ALLOC( X_raw, limbs + 1 );
+
+ x.p = X_raw;
+ x.limbs = limbs + 1;
+ TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+ mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
+
+ mbedtls_free( X_raw );
+ X_raw = NULL;
+
+ /* Negative test with too few limbs in output */
+ if( limbs > 1 )
+ {
+ ASSERT_ALLOC( X_raw, limbs - 1 );
+
+ x.p = X_raw;
+ x.limbs = limbs - 1;
+ TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+ mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
+
+ mbedtls_free( X_raw );
+ X_raw = NULL;
+ }
+
+ /* Negative testing with too many/too few limbs in a and b is covered by
+ * manually-written test cases with oret != 0. */
+ }
+
+ /* Allocate correct number of limbs for X_raw */
+ ASSERT_ALLOC( X_raw, limbs );
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &m, X_raw, limbs ) );
+
+ /* A + B => Correct result or expected error */
+ TEST_EQUAL( expected_ret, mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
+ if( expected_ret != 0 )
+ goto exit;
+
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ /* a + b: alias x to a => Correct result */
+ memcpy( x.p, a.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &x, &b, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ /* a + b: alias x to b => Correct result */
+ memcpy( x.p, b.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &a, &x, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ if ( memcmp( a.p, b.p, bytes ) == 0 )
+ {
+ /* a == b: alias a and b */
+
+ /* a + a => Correct result */
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &a, &a, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ /* a + a: x, a, b all aliased together => Correct result */
+ memcpy( x.p, a.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &x, &x, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+ }
+
+exit:
+ mbedtls_free( (void *)m.p ); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
+ mbedtls_mpi_mod_modulus_free( &m );
+
+ mbedtls_free( a.p );
+ mbedtls_free( b.p );
+ mbedtls_free( s.p );
+ mbedtls_free( X_raw );
+}
+/* END_CASE */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
diff --git a/tests/suites/test_suite_bignum_mod.data b/tests/suites/test_suite_bignum_mod.misc.data
index 501d9d7..e369211 100644
--- a/tests/suites/test_suite_bignum_mod.data
+++ b/tests/suites/test_suite_bignum_mod.misc.data
@@ -12,7 +12,14 @@ mpi_mod_setup:MBEDTLS_MPI_MOD_REP_MONTGOMERY:0
# END MERGE SLOT 1
# BEGIN MERGE SLOT 2
+Test mpi_mod_mul #1 N->limbs != A->limbs
+mpi_mod_mul_neg:"1":"00000000000000000000000000000000":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+Test mpi_mod_mul #2 N->limbs != B->limbs
+mpi_mod_mul_neg:"1234567890abcdef1234567890abcdef":"0":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mpi_mod_mul #3 N->limbs != X->limbs
+mpi_mod_mul_neg:"1234567890abcdef1234567890abcdef":"00000000000000000000000000000000":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
# END MERGE SLOT 2
# BEGIN MERGE SLOT 3
@@ -38,6 +45,50 @@ mpi_mod_sub:"014320a022ccb75bdf470ddf25":"a99c71c7":"00033b2e3c9fd0803ce8000f93"
mpi_mod_sub with second input too short
mpi_mod_sub:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"e8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+mbedtls_mpi_mod_inv non-Mont. form - base case for negative testing (N, A, A^-1)
+mpi_mod_inv_non_mont:"000000000000152d02c7e14af67fe0bf":"00000000000000000000000000000038":"000000000000097418193b6f2e0b5fc3":0
+
+mbedtls_mpi_mod_inv non-Mont. form - A == 0
+mpi_mod_inv_non_mont:"000000000000152d02c7e14af67fe0bf":"00000000000000000000000000000000":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mbedtls_mpi_mod_inv non-Mont. form - A too long
+mpi_mod_inv_non_mont:"000000000000152d02c7e14af67fe0bf":"0000000000000000000000000000000000000038":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mbedtls_mpi_mod_inv non-Mont. form - A too short
+mpi_mod_inv_non_mont:"000000000000152d02c7e14af67fe0bf":"0000000000000038":"000000000000097418193b6f2e0b5fc3":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mbedtls_mpi_mod_inv 32-bit Mont. form - base case for negative testing, A = 1 (N, mont(A), mont(A^-1))
+depends_on:MBEDTLS_HAVE_INT32
+mpi_mod_inv_mont:"000000000000152d02c7e14af67fe0bf":"0000000000000d71d51539b9c02b7b28":"0000000000000d71d51539b9c02b7b28":0
+
+mbedtls_mpi_mod_inv 32-bit Mont. form - A == 0
+depends_on:MBEDTLS_HAVE_INT32
+mpi_mod_inv_mont:"000000000000152d02c7e14af67fe0bf":"00000000000000000000000000000000":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mbedtls_mpi_mod_inv 32-bit Mont. form - A too long
+depends_on:MBEDTLS_HAVE_INT32
+mpi_mod_inv_mont:"000000000000152d02c7e14af67fe0bf":"000000000000000000000d71d51539b9c02b7b28":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mbedtls_mpi_mod_inv 32-bit Mont. form - A too short
+depends_on:MBEDTLS_HAVE_INT32
+mpi_mod_inv_mont:"000000000000152d02c7e14af67fe0bf":"00000d71d51539b9c02b7b28":"0000000000000d71d51539b9c02b7b28":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mbedtls_mpi_mod_inv 64-bit Mont. form - base case for negative testing, A = 1 (N, mont(A), mont(A^-1))
+depends_on:MBEDTLS_HAVE_INT64
+mpi_mod_inv_mont:"0000000000000000000000000000152d02c7e14af67fe0bf":"000000000000000000000000000009545642424381c611fb":"000000000000000000000000000009545642424381c611fb":0
+
+mbedtls_mpi_mod_inv 64-bit Mont. form - A == 0
+depends_on:MBEDTLS_HAVE_INT64
+mpi_mod_inv_mont:"0000000000000000000000000000152d02c7e14af67fe0bf":"000000000000000000000000000000000000000000000000":"000000000000000000000000000009545642424381c611fb":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mbedtls_mpi_mod_inv 64-bit Mont. form - A too long
+depends_on:MBEDTLS_HAVE_INT64
+mpi_mod_inv_mont:"0000000000000000000000000000152d02c7e14af67fe0bf":"0000000000000000000000000000000000000000000009545642424381c611fb":"000000000000000000000000000009545642424381c611fb":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mbedtls_mpi_mod_inv 64-bit Mont. form - A too short
+depends_on:MBEDTLS_HAVE_INT64
+mpi_mod_inv_mont:"0000000000000000000000000000152d02c7e14af67fe0bf":"00000000000009545642424381c611fb":"000000000000000000000000000009545642424381c611fb":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
# END MERGE SLOT 3
# BEGIN MERGE SLOT 4
@@ -45,7 +96,26 @@ mpi_mod_sub:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"e8000f93"
# END MERGE SLOT 4
# BEGIN MERGE SLOT 5
+mpi_mod_add base case for negative testing (N, a, b all >= 1 limb)
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"00033b3096f574ee9a919c815a":0
+
+mpi_mod_add with modulus too long/both inputs too short
+mpi_mod_add:"0000000014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with first input too long
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"0000000000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with second input too long
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"000000000033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with both inputs too long
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"0000000000000025a55a46e5da99c71c7":"000000000033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with first input too short
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"a99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+mpi_mod_add with second input too short
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"e8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
# END MERGE SLOT 5
# BEGIN MERGE SLOT 6
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index 83e1f54..4a658e1 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -345,6 +345,101 @@ exit:
}
/* END_CASE */
+/* BEGIN_CASE */
+void mpi_mod_raw_mul( char * input_A,
+ char * input_B,
+ char * input_N,
+ char * result )
+{
+ mbedtls_mpi_uint *A = NULL;
+ mbedtls_mpi_uint *B = NULL;
+ mbedtls_mpi_uint *N = NULL;
+ mbedtls_mpi_uint *X = NULL;
+ mbedtls_mpi_uint *R = NULL;
+ mbedtls_mpi_uint *T = NULL;
+ size_t limbs_A;
+ size_t limbs_B;
+ size_t limbs_N;
+ size_t limbs_R;
+
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ TEST_EQUAL( mbedtls_test_read_mpi_core( &A, &limbs_A, input_A ), 0 );
+ TEST_EQUAL( mbedtls_test_read_mpi_core( &B, &limbs_B, input_B ), 0 );
+ TEST_EQUAL( mbedtls_test_read_mpi_core( &N, &limbs_N, input_N ), 0 );
+ TEST_EQUAL( mbedtls_test_read_mpi_core( &R, &limbs_R, result ), 0 );
+
+ const size_t limbs = limbs_N;
+ const size_t bytes = limbs * sizeof( mbedtls_mpi_uint );
+
+ TEST_EQUAL( limbs_A, limbs );
+ TEST_EQUAL( limbs_B, limbs );
+ TEST_EQUAL( limbs_R, limbs );
+
+ ASSERT_ALLOC( X, limbs );
+
+ TEST_EQUAL( mbedtls_mpi_mod_modulus_setup(
+ &m, N, limbs,
+ MBEDTLS_MPI_MOD_REP_MONTGOMERY ), 0 );
+
+ const size_t limbs_T = limbs * 2 + 1;
+ ASSERT_ALLOC( T, limbs_T );
+
+ mbedtls_mpi_mod_raw_mul( X, A, B, &m, T );
+ ASSERT_COMPARE( X, bytes, R, bytes );
+
+ /* alias X to A */
+ memcpy( X, A, bytes );
+ mbedtls_mpi_mod_raw_mul( X, X, B, &m, T );
+ ASSERT_COMPARE( X, bytes, R, bytes );
+
+ /* alias X to B */
+ memcpy( X, B, bytes );
+ mbedtls_mpi_mod_raw_mul( X, A, X, &m, T );
+ ASSERT_COMPARE( X, bytes, R, bytes );
+
+ /* A == B: alias A and B */
+ if( memcmp( A, B, bytes ) == 0 )
+ {
+ mbedtls_mpi_mod_raw_mul( X, A, A, &m, T );
+ ASSERT_COMPARE( X, bytes, R, bytes );
+
+ /* X, A, B all aliased together */
+ memcpy( X, A, bytes );
+ mbedtls_mpi_mod_raw_mul( X, X, X, &m, T );
+ ASSERT_COMPARE( X, bytes, R, bytes );
+ }
+
+ /* A != B: test B * A */
+ else
+ {
+ mbedtls_mpi_mod_raw_mul( X, B, A, &m, T );
+ ASSERT_COMPARE( X, bytes, R, bytes );
+
+ /* B * A: alias X to A */
+ memcpy( X, A, bytes );
+ mbedtls_mpi_mod_raw_mul( X, B, X, &m, T );
+ ASSERT_COMPARE( X, bytes, R, bytes );
+
+ /* B + A: alias X to B */
+ memcpy( X, B, bytes );
+ mbedtls_mpi_mod_raw_mul( X, X, A, &m, T );
+ ASSERT_COMPARE( X, bytes, R, bytes );
+ }
+
+exit:
+ mbedtls_free( A );
+ mbedtls_free( B );
+ mbedtls_free( X );
+ mbedtls_free( R );
+ mbedtls_free( T );
+
+ mbedtls_mpi_mod_modulus_free( &m );
+ mbedtls_free( N );
+}
+/* END_CASE */
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
@@ -394,6 +489,10 @@ void mpi_mod_raw_inv_prime( char * input_N, char * input_A, char * input_X )
TEST_LE_U( min_expected_working_limbs, working_limbs );
TEST_LE_U( working_limbs, max_expected_working_limbs );
+ /* Should also be at least mbedtls_mpi_core_montmul_working_limbs() */
+ TEST_LE_U( mbedtls_mpi_core_montmul_working_limbs( N_limbs ),
+ working_limbs );
+
ASSERT_ALLOC( T, working_limbs );
mbedtls_mpi_mod_raw_inv_prime( Y, A, N, N_limbs, R2, T );
@@ -520,7 +619,59 @@ exit:
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
+/* BEGIN_CASE */
+void mpi_mod_raw_canonical_to_modulus_rep( const char *input_N, int rep,
+ const char *input_A,
+ const char *input_X )
+{
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+ mbedtls_mpi_uint *A = NULL;
+ size_t A_limbs = 0;;
+ mbedtls_mpi_uint *X = NULL;
+ size_t X_limbs = 0;
+
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_modulus( &N, input_N, rep ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_raw_canonical_to_modulus_rep( A, &N ) );
+ ASSERT_COMPARE( A, A_limbs * sizeof( mbedtls_mpi_uint ),
+ X, X_limbs * sizeof( mbedtls_mpi_uint ) );
+
+exit:
+ mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+ mbedtls_free( A );
+ mbedtls_free( X );
+}
+/* END_CASE */
+/* BEGIN_CASE */
+void mpi_mod_raw_modulus_to_canonical_rep( const char *input_N, int rep,
+ const char *input_A,
+ const char *input_X )
+{
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+ mbedtls_mpi_uint *A = NULL;
+ size_t A_limbs = 0;
+ mbedtls_mpi_uint *X = NULL;
+ size_t X_limbs = 0;
+
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_modulus( &N, input_N, rep ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_raw_modulus_to_canonical_rep( A, &N ) );
+ ASSERT_COMPARE( A, A_limbs * sizeof( mbedtls_mpi_uint ),
+ X, X_limbs * sizeof( mbedtls_mpi_uint ) );
+
+exit:
+ mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+ mbedtls_free( A );
+ mbedtls_free( X );
+}
+/* END_CASE */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
@@ -529,8 +680,10 @@ void mpi_mod_raw_to_mont_rep( char * input_N, char * input_A, char * input_X )
{
mbedtls_mpi_uint *N = NULL;
mbedtls_mpi_uint *A = NULL;
+ mbedtls_mpi_uint *R = NULL; /* for result of low-level conversion */
mbedtls_mpi_uint *X = NULL;
- size_t n_limbs, a_limbs, x_limbs, x_bytes;
+ mbedtls_mpi_uint *T = NULL;
+ size_t n_limbs, a_limbs, x_limbs;
mbedtls_mpi_mod_modulus m;
mbedtls_mpi_mod_modulus_init( &m );
@@ -539,23 +692,50 @@ void mpi_mod_raw_to_mont_rep( char * input_N, char * input_A, char * input_X )
TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &a_limbs, input_A ) );
TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &x_limbs, input_X ) );
- x_bytes = x_limbs * sizeof(mbedtls_mpi_uint);
- /* Test that input does not require more limbs than modulo */
- TEST_LE_U(a_limbs, n_limbs);
+ /* Number to convert must have same number of limbs as modulus */
+ TEST_EQUAL(a_limbs, n_limbs);
+
+ /* Higher-level conversion is in-place, so expected result must have the
+ * same number of limbs too */
+ TEST_EQUAL(x_limbs, n_limbs);
+
+ size_t limbs = n_limbs;
+ size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
- MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+ MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+ /* 1. Test low-level function first */
+
+ /* It has separate output, and requires temporary working storage */
+ size_t temp_limbs = mbedtls_mpi_core_montmul_working_limbs( limbs );
+ ASSERT_ALLOC( T, temp_limbs );
+ ASSERT_ALLOC( R, limbs );
+ mbedtls_mpi_core_to_mont_rep( R, A, N, n_limbs,
+ m.rep.mont.mm, m.rep.mont.rr, T );
+ /* Test that the low-level function gives the required value */
+ ASSERT_COMPARE( R, bytes, X, bytes );
+
+ /* Test when output is aliased to input */
+ memcpy( R, A, bytes );
+ mbedtls_mpi_core_to_mont_rep( R, R, N, n_limbs,
+ m.rep.mont.mm, m.rep.mont.rr, T );
+ ASSERT_COMPARE( R, bytes, X, bytes );
+
+ /* 2. Test higher-level cannonical to Montgomery conversion */
- /* Convert from cannonical into Montgomery representation */
TEST_EQUAL(0, mbedtls_mpi_mod_raw_to_mont_rep( A, &m ) );
/* The result matches expected value */
- ASSERT_COMPARE( A, x_bytes, X, x_bytes );
+ ASSERT_COMPARE( A, bytes, X, bytes );
+
exit:
mbedtls_mpi_mod_modulus_free( &m );
+ mbedtls_free( T );
mbedtls_free( N );
mbedtls_free( A );
+ mbedtls_free( R );
mbedtls_free( X );
}
/* END_CASE */
@@ -565,8 +745,10 @@ void mpi_mod_raw_from_mont_rep( char * input_N, char * input_A, char * input_X )
{
mbedtls_mpi_uint *N = NULL;
mbedtls_mpi_uint *A = NULL;
+ mbedtls_mpi_uint *R = NULL; /* for result of low-level conversion */
mbedtls_mpi_uint *X = NULL;
- size_t n_limbs, a_limbs, x_limbs, x_bytes;
+ mbedtls_mpi_uint *T = NULL;
+ size_t n_limbs, a_limbs, x_limbs;
mbedtls_mpi_mod_modulus m;
mbedtls_mpi_mod_modulus_init( &m );
@@ -575,23 +757,50 @@ void mpi_mod_raw_from_mont_rep( char * input_N, char * input_A, char * input_X )
TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &a_limbs, input_A ) );
TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &x_limbs, input_X ) );
- x_bytes = x_limbs * sizeof(mbedtls_mpi_uint);
- /* Test that input does not require more limbs than modulo */
- TEST_LE_U(a_limbs, n_limbs);
+ /* Number to convert must have same number of limbs as modulus */
+ TEST_EQUAL(a_limbs, n_limbs);
+
+ /* Higher-level conversion is in-place, so expected result must have the
+ * same number of limbs too */
+ TEST_EQUAL(x_limbs, n_limbs);
+
+ size_t limbs = n_limbs;
+ size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
- MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+ MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+ /* 1. Test low-level function first */
+
+ /* It has separate output, and requires temporary working storage */
+ size_t temp_limbs = mbedtls_mpi_core_montmul_working_limbs( limbs );
+ ASSERT_ALLOC( T, temp_limbs );
+ ASSERT_ALLOC( R, limbs );
+ mbedtls_mpi_core_from_mont_rep( R, A, N, n_limbs,
+ m.rep.mont.mm, T );
+ /* Test that the low-level function gives the required value */
+ ASSERT_COMPARE( R, bytes, X, bytes );
+
+ /* Test when output is aliased to input */
+ memcpy( R, A, bytes );
+ mbedtls_mpi_core_from_mont_rep( R, R, N, n_limbs,
+ m.rep.mont.mm, T );
+ ASSERT_COMPARE( R, bytes, X, bytes );
+
+ /* 2. Test higher-level Montgomery to cannonical conversion */
- /* Convert from Montgomery into cannonical representation */
TEST_EQUAL(0, mbedtls_mpi_mod_raw_from_mont_rep( A, &m ) );
/* The result matches expected value */
- ASSERT_COMPARE( A, x_bytes, X, x_bytes );
+ ASSERT_COMPARE( A, bytes, X, bytes );
+
exit:
mbedtls_mpi_mod_modulus_free( &m );
+ mbedtls_free( T );
mbedtls_free( N );
mbedtls_free( A );
+ mbedtls_free( R );
mbedtls_free( X );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_bignum_random.data b/tests/suites/test_suite_bignum_random.data
new file mode 100644
index 0000000..ee5e397
--- /dev/null
+++ b/tests/suites/test_suite_bignum_random.data
@@ -0,0 +1,340 @@
+MPI core random basic: 0..1
+mpi_core_random_basic:0:"01":0
+
+MPI core random basic: 0..2
+mpi_core_random_basic:0:"02":0
+
+MPI core random basic: 1..2
+mpi_core_random_basic:1:"02":0
+
+MPI core random basic: 2^30..2^31
+mpi_core_random_basic:0x40000000:"80000000":0
+
+MPI core random basic: 0..2^128
+mpi_core_random_basic:0x40000000:"0100000000000000000000000000000000":0
+
+MPI core random basic: 2^30..2^129
+mpi_core_random_basic:0x40000000:"0200000000000000000000000000000000":0
+
+# Use the same data values for mpi_core_random_basic->NOT_ACCEPTABLE
+# and for mpi_XXX_random_values where we want to return NOT_ACCEPTABLE
+# but this isn't checked at runtime.
+MPI core random basic: 2^28-1..2^28+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x0fffffff:"10000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+MPI random legacy=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x0fffffff:"10000001"
+
+MPI random mod=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x0fffffff:"10000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x0fffffff:"10000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI core random basic: 2^29-1..2^29+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x1fffffff:"20000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+MPI random legacy=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x1fffffff:"20000001"
+
+MPI random mod=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x1fffffff:"20000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x1fffffff:"20000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI core random basic: 2^30-1..2^30+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x3fffffff:"40000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+MPI random legacy=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x3fffffff:"40000001"
+
+MPI random mod=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x3fffffff:"40000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x3fffffff:"40000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI core random basic: 2^31-1..2^31+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x7fffffff:"80000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+MPI random legacy=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x7fffffff:"80000001"
+
+MPI random mod=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x7fffffff:"80000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x7fffffff:"80000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random in range: 1..2
+mpi_random_many:1:"02":1000
+
+MPI random in range: 1..3
+mpi_random_many:1:"03":1000
+
+MPI random in range: 1..4
+mpi_random_many:1:"04":1000
+
+MPI random in range: 1..5
+mpi_random_many:1:"05":1000
+
+MPI random in range: 1..6
+mpi_random_many:1:"06":1000
+
+MPI random in range: 1..7
+mpi_random_many:1:"07":1000
+
+MPI random in range: 1..8
+mpi_random_many:1:"08":1000
+
+MPI random in range: 1..9
+mpi_random_many:1:"09":1000
+
+MPI random in range: 1..10
+mpi_random_many:1:"0a":1000
+
+MPI random in range: 1..11
+mpi_random_many:1:"0b":1000
+
+MPI random in range: 1..12
+mpi_random_many:1:"0c":1000
+
+MPI random in range: 1..255
+mpi_random_many:1:"ff":200
+
+MPI random in range: 1..256
+mpi_random_many:1:"0100":200
+
+MPI random in range: 1..257
+mpi_random_many:1:"0101":200
+
+MPI random in range: 1..272
+mpi_random_many:1:"0110":200
+
+MPI random in range: 1..2^64-1
+mpi_random_many:1:"ffffffffffffffff":100
+
+MPI random in range: 1..2^64
+mpi_random_many:1:"010000000000000000":100
+
+MPI random in range: 1..2^64+1
+mpi_random_many:1:"010000000000000001":100
+
+MPI random in range: 1..2^64+2^63
+mpi_random_many:1:"018000000000000000":100
+
+MPI random in range: 1..2^65-1
+mpi_random_many:1:"01ffffffffffffffff":100
+
+MPI random in range: 1..2^65
+mpi_random_many:1:"020000000000000000":100
+
+MPI random in range: 1..2^65+1
+mpi_random_many:1:"020000000000000001":100
+
+MPI random in range: 1..2^65+2^64
+mpi_random_many:1:"030000000000000000":100
+
+MPI random in range: 1..2^66+2^65
+mpi_random_many:1:"060000000000000000":100
+
+MPI random in range: 1..2^71-1
+mpi_random_many:1:"7fffffffffffffffff":100
+
+MPI random in range: 1..2^71
+mpi_random_many:1:"800000000000000000":100
+
+MPI random in range: 1..2^71+1
+mpi_random_many:1:"800000000000000001":100
+
+MPI random in range: 1..2^71+2^70
+mpi_random_many:1:"c00000000000000000":100
+
+MPI random in range: 1..2^72-1
+mpi_random_many:1:"ffffffffffffffffff":100
+
+MPI random in range: 1..2^72
+mpi_random_many:1:"01000000000000000000":100
+
+MPI random in range: 1..2^72+1
+mpi_random_many:1:"01000000000000000001":100
+
+MPI random in range: 1..2^72+2^71
+mpi_random_many:1:"01800000000000000000":100
+
+MPI random in range: 0..1
+mpi_random_many:0:"04":10000
+
+MPI random in range: 0..4
+mpi_random_many:0:"04":10000
+
+MPI random in range: 2..4
+mpi_random_many:2:"04":10000
+
+MPI random in range: 3..4
+mpi_random_many:3:"04":10000
+
+MPI random in range: smaller result
+mpi_random_sizes:1:"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb":1:0
+
+MPI random in range: same size result (32-bit limbs)
+mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":2:0
+
+MPI random in range: same size result (64-bit limbs)
+mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":1:0
+
+MPI random in range: larger result
+mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":3:0
+
+## The "0 limb in upper bound" tests rely on the fact that
+## mbedtls_mpi_read_binary() bases the size of the MPI on the size of
+## the input, without first checking for leading zeros. If this was
+## not the case, the tests would still pass, but would not exercise
+## the advertised behavior.
+MPI random in range: leading 0 limb in upper bound #0
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":0:0
+
+MPI random in range: leading 0 limb in upper bound #1
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":1:0
+
+MPI random in range: leading 0 limb in upper bound #2
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":2:0
+
+MPI random in range: leading 0 limb in upper bound #3
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":3:0
+
+MPI random in range: leading 0 limb in upper bound #4
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":4:0
+
+MPI random in range: previously small >0
+mpi_random_sizes:1:"1234567890":4:1
+
+MPI random in range: previously small <0
+mpi_random_sizes:1:"1234567890":4:-1
+
+MPI random in range: previously large >0
+mpi_random_sizes:1:"1234":4:65
+
+MPI random in range: previously large <0
+mpi_random_sizes:1:"1234":4:-65
+
+MPI random bad arguments: min < 0
+mpi_random_fail:-1:"04":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min = N = 0
+mpi_random_fail:0:"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min = N = 1
+mpi_random_fail:1:"01":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min > N = 0
+mpi_random_fail:1:"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min > N = 1
+mpi_random_fail:2:"01":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min > N = 1, 0 limb in upper bound
+mpi_random_fail:2:"000000000000000001":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random legacy=core: 0..1
+mpi_legacy_random_values:0:"01"
+
+MPI random legacy=core: 0..2
+mpi_legacy_random_values:0:"02"
+
+MPI random legacy=core: 1..2
+mpi_legacy_random_values:1:"02"
+
+MPI random legacy=core: 2^30..2^31
+mpi_legacy_random_values:0x40000000:"80000000"
+
+MPI random legacy=core: 2^31-1..2^32-1
+mpi_legacy_random_values:0x7fffffff:"ffffffff"
+
+MPI random legacy=core: 0..2^256
+mpi_legacy_random_values:0:"010000000000000000000000000000000000000000000000000000000000000000"
+
+MPI random legacy=core: 0..2^256+1
+mpi_legacy_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001"
+
+MPI random mod=core: 0..1 (Mont)
+mpi_mod_random_values:0:"01":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..1 (canon)
+mpi_mod_random_values:0:"01":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 0..3 (Mont)
+mpi_mod_random_values:0:"03":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..3 (canon)
+mpi_mod_random_values:0:"03":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 1..3 (Mont)
+mpi_mod_random_values:1:"03":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 1..3 (canon)
+mpi_mod_random_values:1:"03":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 2^30..2^31-1 (Mont)
+mpi_mod_random_values:0x40000000:"7fffffff":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^30..2^31-1 (canon)
+mpi_mod_random_values:0x40000000:"7fffffff":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 2^31-1..2^32-1 (Mont)
+mpi_mod_random_values:0x7fffffff:"ffffffff":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^31-1..2^32-1 (canon)
+mpi_mod_random_values:0x7fffffff:"ffffffff":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 0..2^256+1 (Mont)
+mpi_mod_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..2^256+1 (canon)
+mpi_mod_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod validation: 1 limb, good, 0..1
+mpi_mod_random_validation:0:"1":0:0
+
+MPI random mod validation: 1 limb, good, 1..3
+mpi_mod_random_validation:1:"3":0:0
+
+MPI random mod validation: 1 limb, good, 2..3
+mpi_mod_random_validation:2:"3":0:0
+
+MPI random mod validation: 1 limb, good, 3..5
+mpi_mod_random_validation:3:"5":0:0
+
+MPI random mod validation: 1 limb, good, 4..5
+mpi_mod_random_validation:4:"5":0:0
+
+MPI random mod validation: 1 limb, good, 5..7
+mpi_mod_random_validation:5:"7":0:0
+
+MPI random mod validation: 1 limb, good, 6..7
+mpi_mod_random_validation:6:"7":0:0
+
+MPI random mod validation: 1 limb, good, 0..0x123
+mpi_mod_random_validation:0:"123":0:0
+
+MPI random mod validation: 2+ limbs, good
+mpi_mod_random_validation:0:"01234567890123456789":0:0
+
+MPI random mod validation: 1 limb, output null
+mpi_mod_random_validation:0:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 1 limb, output too large
+mpi_mod_random_validation:0:"123":1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 2+ limbs, output too small
+mpi_mod_random_validation:0:"01234567890123456789":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 2+ limbs, output too large
+mpi_mod_random_validation:0:"01234567890123456789":1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: min == upper bound
+mpi_mod_random_validation:0x123:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: min > upper bound
+mpi_mod_random_validation:0x124:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_bignum_random.function b/tests/suites/test_suite_bignum_random.function
new file mode 100644
index 0000000..4709148
--- /dev/null
+++ b/tests/suites/test_suite_bignum_random.function
@@ -0,0 +1,496 @@
+/* BEGIN_HEADER */
+/* Dedicated test suite for mbedtls_mpi_core_random() and the upper-layer
+ * functions. Due to the complexity of how these functions are tested,
+ * we test all the layers in a single test suite, unlike the way other
+ * functions are tested with each layer in its own test suite.
+ *
+ * Test strategy
+ * =============
+ *
+ * There are three main goals for testing random() functions:
+ * - Parameter validation.
+ * - Correctness of outputs (well-formed, in range).
+ * - Distribution of outputs.
+ *
+ * We test parameter validation in a standard way, with unit tests with
+ * positive and negative cases:
+ * - mbedtls_mpi_core_random(): negative cases for mpi_core_random_basic.
+ * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): negative
+ * cases for mpi_mod_random_validation.
+ * - mbedtls_mpi_random(): mpi_random_fail.
+ *
+ * We test the correctness of outputs in positive tests:
+ * - mbedtls_mpi_core_random(): positive cases for mpi_core_random_basic,
+ * and mpi_random_many.
+ * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): tested indirectly
+ * via mpi_mod_random_values.
+ * - mbedtls_mpi_random(): mpi_random_sizes, plus indirectly via
+ * mpi_random_values.
+ *
+ * We test the distribution of outputs only for mbedtls_mpi_core_random(),
+ * in mpi_random_many, which runs the function multiple times. This also
+ * helps in validating the output range, through test cases with a small
+ * range where any output out of range would be very likely to lead to a
+ * test failure. For the other functions, we validate the distribution
+ * indirectly by testing that these functions consume the random generator
+ * in the same way as mbedtls_mpi_core_random(). This is done in
+ * mpi_mod_random_values and mpi_legacy_random_values.
+ */
+
+#include "mbedtls/bignum.h"
+#include "mbedtls/entropy.h"
+#include "bignum_core.h"
+#include "bignum_mod_raw.h"
+#include "constant_time_internal.h"
+
+/* This test suite only manipulates non-negative bignums. */
+static int sign_is_valid( const mbedtls_mpi *X )
+{
+ return( X->s == 1 );
+}
+
+/* A common initializer for test functions that should generate the same
+ * sequences for reproducibility and good coverage. */
+const mbedtls_test_rnd_pseudo_info rnd_pseudo_seed = {
+ /* 16-word key */
+ {'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
+ 'a', ' ', 's', 'e', 'e', 'd', '!', 0},
+ /* 2-word initial state, should be zero */
+ 0, 0};
+
+/* Test whether bytes represents (in big-endian base 256) a number b that
+ * is significantly above a power of 2. That is, b must not have a long run
+ * of unset bits after the most significant bit.
+ *
+ * Let n be the bit-size of b, i.e. the integer such that 2^n <= b < 2^{n+1}.
+ * This function returns 1 if, when drawing a number between 0 and b,
+ * the probability that this number is at least 2^n is not negligible.
+ * This probability is (b - 2^n) / b and this function checks that this
+ * number is above some threshold A. The threshold value is heuristic and
+ * based on the needs of mpi_random_many().
+ */
+static int is_significantly_above_a_power_of_2( data_t *bytes )
+{
+ const uint8_t *p = bytes->x;
+ size_t len = bytes->len;
+ unsigned x;
+
+ /* Skip leading null bytes */
+ while( len > 0 && p[0] == 0 )
+ {
+ ++p;
+ --len;
+ }
+ /* 0 is not significantly above a power of 2 */
+ if( len == 0 )
+ return( 0 );
+ /* Extract the (up to) 2 most significant bytes */
+ if( len == 1 )
+ x = p[0];
+ else
+ x = ( p[0] << 8 ) | p[1];
+
+ /* Shift the most significant bit of x to position 8 and mask it out */
+ while( ( x & 0xfe00 ) != 0 )
+ x >>= 1;
+ x &= 0x00ff;
+
+ /* At this point, x = floor((b - 2^n) / 2^(n-8)). b is significantly above
+ * a power of 2 iff x is significantly above 0 compared to 2^8.
+ * Testing x >= 2^4 amounts to picking A = 1/16 in the function
+ * description above. */
+ return( x >= 0x10 );
+}
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_BIGNUM_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void mpi_core_random_basic( int min, char *bound_bytes, int expected_ret )
+{
+ /* Same RNG as in mpi_random_values */
+ mbedtls_test_rnd_pseudo_info rnd = rnd_pseudo_seed;
+ size_t limbs;
+ mbedtls_mpi_uint *lower_bound = NULL;
+ mbedtls_mpi_uint *upper_bound = NULL;
+ mbedtls_mpi_uint *result = NULL;
+
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &upper_bound, &limbs,
+ bound_bytes ) );
+ ASSERT_ALLOC( lower_bound, limbs );
+ lower_bound[0] = min;
+ ASSERT_ALLOC( result, limbs );
+
+ TEST_EQUAL( expected_ret,
+ mbedtls_mpi_core_random( result, min, upper_bound, limbs,
+ mbedtls_test_rnd_pseudo_rand, &rnd ) );
+
+ if( expected_ret == 0 )
+ {
+ TEST_EQUAL( 0, mbedtls_mpi_core_lt_ct( result, lower_bound, limbs ) );
+ TEST_EQUAL( 1, mbedtls_mpi_core_lt_ct( result, upper_bound, limbs ) );
+ }
+
+exit:
+ mbedtls_free( lower_bound );
+ mbedtls_free( upper_bound );
+ mbedtls_free( result );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_legacy_random_values( int min, char *max_hex )
+{
+ /* Same RNG as in mpi_core_random_basic */
+ mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed;
+ mbedtls_test_rnd_pseudo_info rnd_legacy;
+ memcpy( &rnd_legacy, &rnd_core, sizeof( rnd_core ) );
+ mbedtls_mpi max_legacy;
+ mbedtls_mpi_init( &max_legacy );
+ mbedtls_mpi_uint *R_core = NULL;
+ mbedtls_mpi R_legacy;
+ mbedtls_mpi_init( &R_legacy );
+
+ TEST_EQUAL( 0, mbedtls_test_read_mpi( &max_legacy, max_hex ) );
+ size_t limbs = max_legacy.n;
+ ASSERT_ALLOC( R_core, limbs );
+
+ /* Call the legacy function and the core function with the same random
+ * stream. */
+ int core_ret = mbedtls_mpi_core_random( R_core, min, max_legacy.p, limbs,
+ mbedtls_test_rnd_pseudo_rand,
+ &rnd_core );
+ int legacy_ret = mbedtls_mpi_random( &R_legacy, min, &max_legacy,
+ mbedtls_test_rnd_pseudo_rand,
+ &rnd_legacy );
+
+ /* They must return the same status, and, on success, output the
+ * same number, with the same limb count. */
+ TEST_EQUAL( core_ret, legacy_ret );
+ if( core_ret == 0 )
+ {
+ ASSERT_COMPARE( R_core, limbs * ciL,
+ R_legacy.p, R_legacy.n * ciL );
+ }
+
+ /* Also check that they have consumed the RNG in the same way. */
+ /* This may theoretically fail on rare platforms with padding in
+ * the structure! If this is a problem in practice, change to a
+ * field-by-field comparison. */
+ ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ),
+ &rnd_legacy, sizeof( rnd_legacy ) );
+
+exit:
+ mbedtls_mpi_free( &max_legacy );
+ mbedtls_free( R_core );
+ mbedtls_mpi_free( &R_legacy );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_random_values( int min, char *max_hex, int rep )
+{
+ /* Same RNG as in mpi_core_random_basic */
+ mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed;
+ mbedtls_test_rnd_pseudo_info rnd_mod_raw;
+ memcpy( &rnd_mod_raw, &rnd_core, sizeof( rnd_core ) );
+ mbedtls_test_rnd_pseudo_info rnd_mod;
+ memcpy( &rnd_mod, &rnd_core, sizeof( rnd_core ) );
+ mbedtls_mpi_uint *R_core = NULL;
+ mbedtls_mpi_uint *R_mod_raw = NULL;
+ mbedtls_mpi_uint *R_mod_digits = NULL;
+ mbedtls_mpi_mod_residue R_mod;
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+
+ TEST_EQUAL( mbedtls_test_read_mpi_modulus( &N, max_hex, rep ), 0 );
+ ASSERT_ALLOC( R_core, N.limbs );
+ ASSERT_ALLOC( R_mod_raw, N.limbs );
+ ASSERT_ALLOC( R_mod_digits, N.limbs );
+ TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &R_mod, &N,
+ R_mod_digits, N.limbs ),
+ 0 );
+
+ /* Call the core and mod random() functions with the same random stream. */
+ int core_ret = mbedtls_mpi_core_random( R_core,
+ min, N.p, N.limbs,
+ mbedtls_test_rnd_pseudo_rand,
+ &rnd_core );
+ int mod_raw_ret = mbedtls_mpi_mod_raw_random( R_mod_raw,
+ min, &N,
+ mbedtls_test_rnd_pseudo_rand,
+ &rnd_mod_raw );
+ int mod_ret = mbedtls_mpi_mod_random( &R_mod,
+ min, &N,
+ mbedtls_test_rnd_pseudo_rand,
+ &rnd_mod );
+
+ /* They must return the same status, and, on success, output the
+ * same number, with the same limb count. */
+ TEST_EQUAL( core_ret, mod_raw_ret );
+ TEST_EQUAL( core_ret, mod_ret );
+ if( core_ret == 0 )
+ {
+ TEST_EQUAL( mbedtls_mpi_mod_raw_modulus_to_canonical_rep( R_mod_raw, &N ),
+ 0 );
+ ASSERT_COMPARE( R_core, N.limbs * ciL,
+ R_mod_raw, N.limbs * ciL );
+ TEST_EQUAL( mbedtls_mpi_mod_raw_modulus_to_canonical_rep( R_mod_digits, &N ),
+ 0 );
+ ASSERT_COMPARE( R_core, N.limbs * ciL,
+ R_mod_digits, N.limbs * ciL );
+ }
+
+ /* Also check that they have consumed the RNG in the same way. */
+ /* This may theoretically fail on rare platforms with padding in
+ * the structure! If this is a problem in practice, change to a
+ * field-by-field comparison. */
+ ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ),
+ &rnd_mod_raw, sizeof( rnd_mod_raw ) );
+ ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ),
+ &rnd_mod, sizeof( rnd_mod ) );
+
+exit:
+ mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+ mbedtls_free( R_core );
+ mbedtls_free( R_mod_raw );
+ mbedtls_free( R_mod_digits );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_random_many( int min, char *bound_hex, int iterations )
+{
+ /* Generate numbers in the range 1..bound-1. Do it iterations times.
+ * This function assumes that the value of bound is at least 2 and
+ * that iterations is large enough that a one-in-2^iterations chance
+ * effectively never occurs.
+ */
+
+ data_t bound_bytes = {NULL, 0};
+ mbedtls_mpi_uint *upper_bound = NULL;
+ size_t limbs;
+ size_t n_bits;
+ mbedtls_mpi_uint *result = NULL;
+ size_t b;
+ /* If upper_bound is small, stats[b] is the number of times the value b
+ * has been generated. Otherwise stats[b] is the number of times a
+ * value with bit b set has been generated. */
+ size_t *stats = NULL;
+ size_t stats_len;
+ int full_stats;
+ size_t i;
+
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &upper_bound, &limbs,
+ bound_hex ) );
+ ASSERT_ALLOC( result, limbs );
+
+ n_bits = mbedtls_mpi_core_bitlen( upper_bound, limbs );
+ /* Consider a bound "small" if it's less than 2^5. This value is chosen
+ * to be small enough that the probability of missing one value is
+ * negligible given the number of iterations. It must be less than
+ * 256 because some of the code below assumes that "small" values
+ * fit in a byte. */
+ if( n_bits <= 5 )
+ {
+ full_stats = 1;
+ stats_len = (uint8_t) upper_bound[0];
+ }
+ else
+ {
+ full_stats = 0;
+ stats_len = n_bits;
+ }
+ ASSERT_ALLOC( stats, stats_len );
+
+ for( i = 0; i < (size_t) iterations; i++ )
+ {
+ mbedtls_test_set_step( i );
+ TEST_EQUAL( 0, mbedtls_mpi_core_random( result,
+ min, upper_bound, limbs,
+ mbedtls_test_rnd_std_rand, NULL ) );
+
+ /* Temporarily use a legacy MPI for analysis, because the
+ * necessary auxiliary functions don't exist yet in core. */
+ mbedtls_mpi B = {1, limbs, upper_bound};
+ mbedtls_mpi R = {1, limbs, result};
+
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R, &B ) < 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_int( &R, min ) >= 0 );
+ if( full_stats )
+ {
+ uint8_t value;
+ TEST_EQUAL( 0, mbedtls_mpi_write_binary( &R, &value, 1 ) );
+ TEST_ASSERT( value < stats_len );
+ ++stats[value];
+ }
+ else
+ {
+ for( b = 0; b < n_bits; b++ )
+ stats[b] += mbedtls_mpi_get_bit( &R, b );
+ }
+ }
+
+ if( full_stats )
+ {
+ for( b = min; b < stats_len; b++ )
+ {
+ mbedtls_test_set_step( 1000000 + b );
+ /* Assert that each value has been reached at least once.
+ * This is almost guaranteed if the iteration count is large
+ * enough. This is a very crude way of checking the distribution.
+ */
+ TEST_ASSERT( stats[b] > 0 );
+ }
+ }
+ else
+ {
+ bound_bytes.len = limbs * sizeof( mbedtls_mpi_uint );
+ ASSERT_ALLOC( bound_bytes.x, bound_bytes.len );
+ mbedtls_mpi_core_write_be( upper_bound, limbs,
+ bound_bytes.x, bound_bytes.len );
+ int statistically_safe_all_the_way =
+ is_significantly_above_a_power_of_2( &bound_bytes );
+ for( b = 0; b < n_bits; b++ )
+ {
+ mbedtls_test_set_step( 1000000 + b );
+ /* Assert that each bit has been set in at least one result and
+ * clear in at least one result. Provided that iterations is not
+ * too small, it would be extremely unlikely for this not to be
+ * the case if the results are uniformly distributed.
+ *
+ * As an exception, the top bit may legitimately never be set
+ * if bound is a power of 2 or only slightly above.
+ */
+ if( statistically_safe_all_the_way || b != n_bits - 1 )
+ {
+ TEST_ASSERT( stats[b] > 0 );
+ }
+ TEST_ASSERT( stats[b] < (size_t) iterations );
+ }
+ }
+
+exit:
+ mbedtls_free( bound_bytes.x );
+ mbedtls_free( upper_bound );
+ mbedtls_free( result );
+ mbedtls_free( stats );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_random_sizes( int min, data_t *bound_bytes, int nlimbs, int before )
+{
+ mbedtls_mpi upper_bound;
+ mbedtls_mpi result;
+
+ mbedtls_mpi_init( &upper_bound );
+ mbedtls_mpi_init( &result );
+
+ if( before != 0 )
+ {
+ /* Set result to sign(before) * 2^(|before|-1) */
+ TEST_ASSERT( mbedtls_mpi_lset( &result, before > 0 ? 1 : -1 ) == 0 );
+ if( before < 0 )
+ before = - before;
+ TEST_ASSERT( mbedtls_mpi_shift_l( &result, before - 1 ) == 0 );
+ }
+
+ TEST_EQUAL( 0, mbedtls_mpi_grow( &result, nlimbs ) );
+ TEST_EQUAL( 0, mbedtls_mpi_read_binary( &upper_bound,
+ bound_bytes->x, bound_bytes->len ) );
+ TEST_EQUAL( 0, mbedtls_mpi_random( &result, min, &upper_bound,
+ mbedtls_test_rnd_std_rand, NULL ) );
+ TEST_ASSERT( sign_is_valid( &result ) );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &result, &upper_bound ) < 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_int( &result, min ) >= 0 );
+
+exit:
+ mbedtls_mpi_free( &upper_bound );
+ mbedtls_mpi_free( &result );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_random_validation( int min, char *bound_hex,
+ int result_limbs_delta,
+ int expected_ret )
+{
+ mbedtls_mpi_uint *result_digits = NULL;
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+
+ TEST_EQUAL( mbedtls_test_read_mpi_modulus( &N, bound_hex,
+ MBEDTLS_MPI_MOD_REP_OPT_RED ),
+ 0 );
+ size_t result_limbs = N.limbs + result_limbs_delta;
+ ASSERT_ALLOC( result_digits, result_limbs );
+ /* Build a reside that might not match the modulus, to test that
+ * the library function rejects that as expected. */
+ mbedtls_mpi_mod_residue result = {result_digits, result_limbs};
+
+ TEST_EQUAL( mbedtls_mpi_mod_random( &result, min, &N,
+ mbedtls_test_rnd_std_rand, NULL ),
+ expected_ret );
+ if( expected_ret == 0 )
+ {
+ /* Success should only be expected when the result has the same
+ * size as the modulus, otherwise it's a mistake in the test data. */
+ TEST_EQUAL( result_limbs, N.limbs );
+ /* Sanity check: check that the result is in range */
+ TEST_EQUAL( mbedtls_mpi_core_lt_ct( result_digits, N.p, N.limbs ),
+ 1 );
+ /* Check result >= min (changes result) */
+ TEST_EQUAL( mbedtls_mpi_core_sub_int( result_digits, result_digits, min,
+ result_limbs ),
+ 0 );
+ }
+
+ /* When the result has the right number of limbs, also test mod_raw
+ * (for which this is an unchecked precondition). */
+ if( result_limbs_delta == 0 )
+ {
+ TEST_EQUAL( mbedtls_mpi_mod_raw_random( result_digits, min, &N,
+ mbedtls_test_rnd_std_rand, NULL ),
+ expected_ret );
+ if( expected_ret == 0 )
+ {
+ TEST_EQUAL( mbedtls_mpi_core_lt_ct( result_digits, N.p, N.limbs ),
+ 1 );
+ TEST_EQUAL( mbedtls_mpi_core_sub_int( result_digits, result.p, min,
+ result_limbs ),
+ 0 );
+ }
+ }
+
+exit:
+ mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+ mbedtls_free( result_digits );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_random_fail( int min, data_t *bound_bytes, int expected_ret )
+{
+ mbedtls_mpi upper_bound;
+ mbedtls_mpi result;
+ int actual_ret;
+
+ mbedtls_mpi_init( &upper_bound );
+ mbedtls_mpi_init( &result );
+
+ TEST_EQUAL( 0, mbedtls_mpi_read_binary( &upper_bound,
+ bound_bytes->x, bound_bytes->len ) );
+ actual_ret = mbedtls_mpi_random( &result, min, &upper_bound,
+ mbedtls_test_rnd_std_rand, NULL );
+ TEST_EQUAL( expected_ret, actual_ret );
+
+exit:
+ mbedtls_mpi_free( &upper_bound );
+ mbedtls_mpi_free( &result );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_ecjpake.data b/tests/suites/test_suite_ecjpake.data
index 73808c9..c2ec782 100644
--- a/tests/suites/test_suite_ecjpake.data
+++ b/tests/suites/test_suite_ecjpake.data
@@ -35,7 +35,7 @@ ECJPAKE round one: KKP1: first point is zero
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"0100":MBEDTLS_ERR_ECP_INVALID_KEY
ECJPAKE round one: KKP1: unknown first point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP1: nothing after first point
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -50,7 +50,7 @@ ECJPAKE round one: KKP1: no second point data
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP1: unknown second point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP1: nothing after second point
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -83,7 +83,7 @@ ECJPAKE round one: KKP2: first point is zero
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb120100":MBEDTLS_ERR_ECP_INVALID_KEY
ECJPAKE round one: KKP2: unknown first point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP2: nothing after first point
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -98,7 +98,7 @@ ECJPAKE round one: KKP2: no second point data
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP2: unknown second point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP2: nothing after second point
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -149,7 +149,7 @@ ECJPAKE round two client: first point is zero
read_round_two_cli:"0300170100":MBEDTLS_ERR_ECP_INVALID_KEY
ECJPAKE round two client: unknown first point format
-read_round_two_cli:"03001741050fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_cli:"03001741050fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two client: nothing after first point
read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -164,7 +164,7 @@ ECJPAKE round two client: no second point data
read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a60104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two client: unknown second point format
-read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641055516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641055516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two client: nothing after second point
read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -203,7 +203,7 @@ ECJPAKE round two server: first point is zero
read_round_two_srv:"0100":MBEDTLS_ERR_ECP_INVALID_KEY
ECJPAKE round two server: unknown first point format
-read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two server: nothing after first point
read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -218,7 +218,7 @@ ECJPAKE round two server: no second point data
read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two server: unknown second point format
-read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two server: nothing after second point
read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 4c0ed1c..9311200 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -227,19 +227,51 @@ ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0000":"01":"01":"00":MBEDTLS_ERR_ECP_B
ECP read binary #2 (zero, invalid first byte)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
-ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"01":"01":"01":"00":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"01":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECP read binary #3 (zero, OK)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"00":"01":"01":"00":0
-ECP read binary #4 (non-zero, invalid ilen)
+ECP read binary #4 (non-zero, invalid ilen, too short)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"04001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+ECP read binary #4a (non-zero, invalid ilen, too short)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"03001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4b (non-zero, invalid ilen, too short)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"02001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4c (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"040011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4d (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"030011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4e (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"020011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
ECP read binary #5 (non-zero, invalid first byte)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
-ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #5a (non-zero, compressed format, invalid first byte)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #5b (non-zero, compressed format, parity 0, OK)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0248d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0
+
+ECP read binary #5c (non-zero, compressed format, parity 1, OK)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0348d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"93112b28345b7d1d7799611e49bea9d8290cb2d7afe1f9f3":"01":0
ECP read binary #6 (non-zero, OK)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
@@ -285,6 +317,14 @@ ECP read binary #16 (Curve448, non-canonical)
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_read_binary:MBEDTLS_ECP_DP_CURVE448:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"0":"1":0
+ECP read binary #17 (non-zero, compressed format, p != 3 mod 4, secp224r1)
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP224R1:"0200000000000000000000000000000000000000000000000000000000":"01":"01":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+
+ECP read binary #17a (non-zero, compressed format, p != 3 mod 4, secp224k1)
+depends_on:MBEDTLS_ECP_DP_SECP224K1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP224K1:"0200000000000000000000000000000000000000000000000000000000":"01":"01":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+
ECP tls read point #1 (zero, invalid length byte)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
mbedtls_ecp_tls_read_point:MBEDTLS_ECP_DP_SECP192R1:"0200":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 7d29e52..96b9f40 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -237,7 +237,7 @@ exit:
}
/* END_CASE */
-/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
void ecp_muladd_restart( int id, char *xR_str, char *yR_str,
char *u1_str, char *u2_str,
char *xQ_str, char *yQ_str,
@@ -642,6 +642,19 @@ void ecp_read_binary( int id, data_t * buf, char * x, char * y, char * z,
{
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Y, &Y ) == 0 );
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Z, &Z ) == 0 );
+
+ if( buf->x[0] == 0x04 &&
+ /* (reading compressed format supported only for
+ * Short Weierstrass curves with prime p where p = 3 mod 4) */
+ id != MBEDTLS_ECP_DP_SECP224R1 &&
+ id != MBEDTLS_ECP_DP_SECP224K1 )
+ {
+ /* re-encode in compressed format and test read again */
+ mbedtls_mpi_free( &P.Y );
+ buf->x[0] = 0x02 + mbedtls_mpi_get_bit( &Y, 0 );
+ TEST_ASSERT( mbedtls_ecp_point_read_binary( &grp, &P, buf->x, buf->len/2+1 ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Y, &Y ) == 0 );
+ }
}
}
@@ -703,8 +716,10 @@ void ecp_tls_write_read_point( int id )
memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
TEST_ASSERT( mbedtls_ecp_tls_write_point( &grp, &grp.G,
MBEDTLS_ECP_PF_COMPRESSED, &olen, buf, 256 ) == 0 );
- TEST_ASSERT( mbedtls_ecp_tls_read_point( &grp, &pt, &vbuf, olen )
- == MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+ TEST_ASSERT( mbedtls_ecp_tls_read_point( &grp, &pt, &vbuf, olen ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.X, &pt.X ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.Y, &pt.Y ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.Z, &pt.Z ) == 0 );
TEST_ASSERT( vbuf == buf + olen );
memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index bd5d31e..d796f6f 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -456,10 +456,14 @@ Verify ext RSA #4 (PKCS1 v2.1, salt_len = max, OK)
depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA
pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":MBEDTLS_MD_SHA256:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256:94:128:0
-Verify ext RSA #5 (PKCS1 v2.1, wrong salt_len)
-depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA
+Verify ext RSA #5a (PKCS1 v2.1, wrong salt_len) !USE_PSA
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA:!MBEDTLS_USE_PSA_CRYPTO
pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":MBEDTLS_MD_SHA256:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256:32:128:MBEDTLS_ERR_RSA_INVALID_PADDING
+Verify ext RSA #5b (PKCS1 v2.1, wrong salt_len) USE_PSA
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA:MBEDTLS_USE_PSA_CRYPTO
+pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":MBEDTLS_MD_SHA256:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256:32:128:0
+
Verify ext RSA #6 (PKCS1 v2.1, MGF1 alg != MSG hash alg)
depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA
pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":MBEDTLS_MD_NONE:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:128:0
diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data
index f3cbb62..571d5ad 100644
--- a/tests/suites/test_suite_pkcs7.data
+++ b/tests/suites/test_suite_pkcs7.data
@@ -68,7 +68,7 @@ pkcs7_parse:"data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-62139
pkcs7_get_signers_info_set error handling (4541044530479104)
depends_on:MBEDTLS_RIPEMD160_C
-pkcs7_parse:"data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+pkcs7_parse:"data_files/pkcs7_get_signers_info_set-leak-fuzz_pkcs7-4541044530479104.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO
PKCS7 Only Signed Data Parse Pass #15
depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index dbbac76..a4c19b8 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -1452,6 +1452,7 @@ exit:
/* END_CASE */
/* BEGIN_CASE */
+/* Construct and attempt to import a large unstructured key. */
void import_large_key( int type_arg, int byte_size_arg,
int expected_status_arg )
{
@@ -1508,6 +1509,9 @@ exit:
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ASN1_WRITE_C */
+/* Import an RSA key with a valid structure (but not valid numbers
+ * inside, beyond having sensible size and parity). This is expected to
+ * fail for large keys. */
void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg )
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
@@ -1553,6 +1557,7 @@ void import_export( data_t *data,
int expected_bits,
int export_size_delta,
int expected_export_status_arg,
+ /*whether reexport must give the original input exactly*/
int canonical_input )
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
@@ -1657,7 +1662,7 @@ exit:
/* BEGIN_CASE */
void import_export_public_key( data_t *data,
- int type_arg,
+ int type_arg, // key pair or public key
int alg_arg,
int lifetime_arg,
int export_size_delta,
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index a7f0501..1b5e44b 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -3539,3 +3539,11 @@ cookie_parsing:"16fefd0000000000000000002F010000de000000000000011efefd7b72727272
TLS 1.3 srv Certificate msg - wrong vector lengths
tls13_server_certificate_msg_invalid_vector_len
+
+EC-JPAKE set password
+depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+ssl_ecjpake_set_password:0
+
+EC-JPAKE set opaque password
+depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+ssl_ecjpake_set_password:1
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 624f8e0..274a894 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -2582,6 +2582,21 @@ int tweak_tls13_certificate_msg_vector_len(
return( 0 );
}
#endif /* MBEDTLS_TEST_HOOKS */
+
+#define ECJPAKE_TEST_PWD "bla"
+
+#if defined( MBEDTLS_USE_PSA_CRYPTO )
+#define ECJPAKE_TEST_SET_PASSWORD( exp_ret_val ) \
+ ret = ( use_opaque_arg ) ? \
+ mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl, pwd_slot ) : \
+ mbedtls_ssl_set_hs_ecjpake_password( &ssl, pwd_string, pwd_len ); \
+ TEST_EQUAL( ret, exp_ret_val )
+#else
+#define ECJPAKE_TEST_SET_PASSWORD( exp_ret_val ) \
+ ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, \
+ pwd_string, pwd_len ); \
+ TEST_EQUAL( ret, exp_ret_val )
+#endif
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -5997,3 +6012,85 @@ exit:
USE_PSA_DONE( );
}
/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+void ssl_ecjpake_set_password( int use_opaque_arg )
+{
+ mbedtls_ssl_context ssl;
+ mbedtls_ssl_config conf;
+#if defined( MBEDTLS_USE_PSA_CRYPTO )
+ mbedtls_svc_key_id_t pwd_slot = MBEDTLS_SVC_KEY_ID_INIT;
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+ (void) use_opaque_arg;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ unsigned char pwd_string[ sizeof(ECJPAKE_TEST_PWD) ] = "";
+ size_t pwd_len = 0;
+ int ret;
+
+ USE_PSA_INIT( );
+
+ mbedtls_ssl_init( &ssl );
+
+ /* test with uninitalized SSL context */
+ ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ mbedtls_ssl_config_init( &conf );
+
+ TEST_EQUAL( mbedtls_ssl_config_defaults( &conf,
+ MBEDTLS_SSL_IS_CLIENT,
+ MBEDTLS_SSL_TRANSPORT_STREAM,
+ MBEDTLS_SSL_PRESET_DEFAULT ), 0 );
+
+ TEST_EQUAL( mbedtls_ssl_setup( &ssl, &conf ), 0 );
+
+ /* test with empty password or unitialized password key (depending on use_opaque_arg) */
+ ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ pwd_len = strlen( ECJPAKE_TEST_PWD );
+ memcpy( pwd_string, ECJPAKE_TEST_PWD, pwd_len );
+
+#if defined( MBEDTLS_USE_PSA_CRYPTO )
+ if( use_opaque_arg )
+ {
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ /* First try with an invalid usage */
+ psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
+ psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE );
+ psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD );
+
+ PSA_ASSERT( psa_import_key( &attributes, pwd_string,
+ pwd_len, &pwd_slot ) );
+
+ ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+ /* check that the opaque key is still valid after failure */
+ TEST_EQUAL( psa_get_key_attributes( pwd_slot, &check_attributes ),
+ PSA_SUCCESS );
+
+ psa_destroy_key( pwd_slot );
+
+ /* Then set the correct usage */
+ psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+
+ PSA_ASSERT( psa_import_key( &attributes, pwd_string,
+ pwd_len, &pwd_slot ) );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ /* final check which should work without errors */
+ ECJPAKE_TEST_SET_PASSWORD( 0 );
+
+#if defined( MBEDTLS_USE_PSA_CRYPTO )
+ if( use_opaque_arg )
+ {
+ psa_destroy_key( pwd_slot );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ mbedtls_ssl_free( &ssl );
+ mbedtls_ssl_config_free( &conf );
+
+ USE_PSA_DONE( );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index f131029..ea6fc62 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:"3.2.1"
+check_compiletime_version:"3.3.0"
Check runtime library version
-check_runtime_version:"3.2.1"
+check_runtime_version:"3.3.0"
Check for MBEDTLS_VERSION_C
check_feature:"MBEDTLS_VERSION_C":0
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 5fcbf99..002f3dc 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -831,9 +831,13 @@ X509 CRT verification #67 (Valid, RSASSA-PSS, all defaults)
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
x509_verify:"data_files/server9-defaults.crt":"data_files/test-ca.crt":"data_files/crl-rsa-pss-sha1.pem":"NULL":0:0:"compat":"NULL"
-X509 CRT verification #68 (RSASSA-PSS, wrong salt_len)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_verify:"data_files/server9-bad-saltlen.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:"compat":"NULL"
+X509 CRT verification #68 (RSASSA-PSS, wrong salt_len, !USE_PSA)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:!MBEDTLS_USE_PSA_CRYPTO
+x509_verify:"data_files/server9-bad-saltlen.crt":"data_files/test-ca.crt":"data_files/crl-rsa-pss-sha1.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:"compat":"NULL"
+
+X509 CRT verification #68 (RSASSA-PSS, wrong salt_len, USE_PSA)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
+x509_verify:"data_files/server9-bad-saltlen.crt":"data_files/test-ca.crt":"data_files/crl-rsa-pss-sha1.pem":"NULL":0:0:"compat":"NULL"
X509 CRT verification #69 (RSASSA-PSS, wrong mgf_hash)
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index 2585720..388d45e 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -579,6 +579,8 @@ void x509_verify_restart( char *crt_file, char *ca_file,
mbedtls_x509_crt_init( &crt );
mbedtls_x509_crt_init( &ca );
+ USE_PSA_INIT( );
+
TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
TEST_ASSERT( mbedtls_x509_crt_parse_file( &ca, ca_file ) == 0 );
@@ -607,6 +609,7 @@ exit:
mbedtls_x509_crt_restart_free( &rs_ctx );
mbedtls_x509_crt_free( &crt );
mbedtls_x509_crt_free( &ca );
+ USE_PSA_DONE( );
}
/* END_CASE */
@@ -662,8 +665,8 @@ void x509_verify( char *crt_file, char *ca_file, char *crl_file,
res = mbedtls_x509_crt_verify_with_profile( &crt, &ca, &crl, profile, cn_name, &flags, f_vrfy, NULL );
- TEST_ASSERT( res == ( result ) );
- TEST_ASSERT( flags == (uint32_t)( flags_result ) );
+ TEST_EQUAL( res, result );
+ TEST_EQUAL( flags, (uint32_t) flags_result );
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
/* CRLs aren't supported with CA callbacks, so skip the CA callback