Merge remote-tracking branch 'development' into HEAD

This commit is contained in:
Gilles Peskine 2023-08-23 20:35:32 +02:00
commit f745e5b8de
383 changed files with 27896 additions and 11870 deletions

2
.gitignore vendored
View file

@ -1,5 +1,7 @@
# Random seed file created by test scripts and sample programs
seedfile
# MBEDTLS_PSA_INJECT_ENTROPY seed file created by the test framework
00000000ffffff52.psa_its
# CMake build artifacts:
CMakeCache.txt

View file

@ -32,6 +32,10 @@ jobs:
packages:
- clang-10
- gnutls-bin
env:
# Platform tests have an allocation that returns null
- ASAN_OPTIONS="allocator_may_return_null=1"
- MSAN_OPTIONS="allocator_may_return_null=1"
script:
# Do a manual build+test sequence rather than using all.sh,
# because there's no all.sh component that does what we want,
@ -89,6 +93,10 @@ jobs:
apt:
packages:
- gcc
env:
# Platform tests have an allocation that returns null
- ASAN_OPTIONS="allocator_may_return_null=1"
- MSAN_OPTIONS="allocator_may_return_null=1"
script:
# Do a manual build+test sequence rather than using all.sh.
#
@ -115,6 +123,10 @@ jobs:
packages:
- clang
- gnutls-bin
env:
# Platform tests have an allocation that returns null
- ASAN_OPTIONS="allocator_may_return_null=1"
- MSAN_OPTIONS="allocator_may_return_null=1"
script:
# Do a manual build+test sequence rather than using all.sh.
#
@ -129,6 +141,30 @@ jobs:
- tests/scripts/travis-log-failure.sh
- tests/context-info.sh
- name: Arm64 accelerators tests on arm64 host
os: linux
dist: focal
arch: arm64
addons:
apt:
packages:
- gcc
script:
# Do a manual build+test sequence rather than using all.sh.
#
# This is arm64 host only test for no runtime detection case. Internal
# and Open CI do not include Arm64 host, and they check if components
# are be tested. As result, it will always fail on `pre-test-check` in
# them.
- scripts/config.py unset MBEDTLS_AESNI_C
- scripts/config.py unset MBEDTLS_PADLOCK_C
- scripts/config.py set MBEDTLS_AESCE_C
- scripts/config.py set MBEDTLS_AES_USE_HARDWARE_ONLY
- make generated_files
- make
- programs/test/selftest aes | grep "using AESCE"
- tests/context-info.sh
after_failure:
- tests/scripts/travis-log-failure.sh

View file

@ -118,6 +118,10 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
FORCE)
endif()
# Make MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE into PATHs
set(MBEDTLS_CONFIG_FILE "" CACHE FILEPATH "Mbed TLS config file (overrides default).")
set(MBEDTLS_USER_CONFIG_FILE "" CACHE FILEPATH "Mbed TLS user config file (appended to default).")
# Create a symbolic link from ${base_name} in the binary directory
# to the corresponding path in the source directory.
# Note: Copies the file(s) on Windows.
@ -222,7 +226,9 @@ if(CMAKE_COMPILER_IS_CLANG)
endif(CMAKE_COMPILER_IS_CLANG)
if(CMAKE_COMPILER_IS_IAR)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts -Ohz")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts")
set(CMAKE_C_FLAGS_RELEASE "-Ohz")
set(CMAKE_C_FLAGS_DEBUG "--debug -On")
endif(CMAKE_COMPILER_IS_IAR)
if(CMAKE_COMPILER_IS_MSVC)
@ -297,6 +303,20 @@ if(ENABLE_TESTING OR ENABLE_PROGRAMS)
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/everest/include)
# Pass-through MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE
if(MBEDTLS_CONFIG_FILE)
target_compile_definitions(mbedtls_test
PUBLIC MBEDTLS_CONFIG_FILE="${MBEDTLS_CONFIG_FILE}")
target_compile_definitions(mbedtls_test_helpers
PUBLIC MBEDTLS_CONFIG_FILE="${MBEDTLS_CONFIG_FILE}")
endif()
if(MBEDTLS_USER_CONFIG_FILE)
target_compile_definitions(mbedtls_test
PUBLIC MBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}")
target_compile_definitions(mbedtls_test_helpers
PUBLIC MBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}")
endif()
endif()
if(ENABLE_PROGRAMS)
@ -354,7 +374,7 @@ if(NOT DISABLE_PACKAGE_CONFIG_AND_INSTALL)
write_basic_package_version_file(
"cmake/MbedTLSConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
VERSION 3.4.0)
VERSION 3.4.1)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfig.cmake"

View file

@ -84,8 +84,14 @@ Mbed TLS is well documented, but if you think documentation is needed, speak out
License and Copyright
---------------------
All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible. For licensing details, please see the [License section of the README](README.md#License).
Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license.
Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. This enables LTS (Long Term Support) branches of the software to be provided under either the Apache-2.0 or GPL-2.0-or-later licenses.
All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible.
The copyright on contributions is retained by the original authors of the code. Where possible for new files, this should be noted in a comment at the top of the file in the form: "Copyright The Mbed TLS Contributors".
When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and be subject to the same Apache 2.0 license. This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line.
When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and is submitted under both the Apache-2.0 AND GPL-2.0-or-later licenses.
This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line.

View file

@ -1,5 +1,13 @@
Mbed TLS ChangeLog (Sorted per branch, date)
= Mbed TLS 3.4.1 branch released 2023-08-04
Bugfix
* Fix builds on Windows with clang
Changes
* Update test data to avoid failures of unit tests after 2023-08-07.
= Mbed TLS 3.4.0 branch released 2023-03-28
Default behavior changes

View file

@ -21,6 +21,9 @@ We generally don't include changelog entries for:
* Performance improvements, unless they are particularly significant.
* Changes to parts of the code base that users don't interact with directly,
such as test code and test data.
* Fixes for compiler warnings. Releases typically contain a number of fixes
of this kind, so we will only mention them in the Changelog if they are
particularly significant.
Until Mbed TLS 2.24.0, we required changelog entries in more cases.
Looking at older changelog entries is good practice for how to write a

View file

@ -2,13 +2,17 @@ New deprecations
* PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and
MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR, where xxx is either ECC or RSA,
are now being deprecated in favor of PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_yyy and
MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR_yyy. Here yyy can be: USE, IMPORT,
EXPORT, GENERATE, DERIVE. The goal is to have a finer detail about the
capabilities of the PSA side for either key.
MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR_yyy. Here yyy can be: BASIC,
IMPORT, EXPORT, GENERATE, DERIVE. The goal is to have a finer detail about
the capabilities of the PSA side for either key.
Features
* New symbols PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_yyy and
MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR_yyy (where xxx is either ECC, RSA
or DH) were introduced in order to have finer accuracy in defining the
PSA capabilities for each key. These capabilities, named yyy above, can be
any of: USE, IMPORT, EXPORT, GENERATE, DERIVE.
any of: BASIC, IMPORT, EXPORT, GENERATE, DERIVE.
- DERIVE is only available for ECC keys, not for RSA or DH ones.
- implementations are free to enable more than what it was strictly
requested. For example BASIC internally enables IMPORT and EXPORT
(useful for testing purposes), but this might change in the future.

View file

@ -0,0 +1,6 @@
Features
* New configuration option MBEDTLS_AES_USE_HARDWARE_ONLY introduced. When
using CPU-accelerated AES (e.g., Arm Crypto Extensions), this option
disables the plain C implementation and the run-time detection for the
CPU feature, which reduces code size and avoids the vulnerability of the
plain C implementation.

View file

@ -0,0 +1,7 @@
Features
* Add getter (mbedtls_ssl_cache_get_timeout()) to access
`mbedtls_ssl_cache_context.timeout`.
* Add getter (mbedtls_ssl_get_hostname()) to access
`mbedtls_ssl_context.hostname`.
* Add getter (mbedtls_ssl_conf_get_endpoint()) to access
`mbedtls_ssl_config.endpoint`.

View file

@ -0,0 +1,2 @@
Features
* Add support for PBKDF2-CMAC through the PSA API.

View file

@ -0,0 +1,3 @@
Features
* Add a possibility to generate CSR's with RCF822 and directoryName subtype
of subjectAltName extension in x509 certificates.

View file

@ -1,4 +1,7 @@
Features
* AES performance improvements on 64-bit architectures. Uplift
varies by platform, toolchain, optimisation flags and mode,
in the 0 - 84% range. Aarch64, gcc and GCM/XTS benefit the most.
* AES performance improvements. Uplift varies by platform,
toolchain, optimisation flags and mode.
Aarch64, gcc -Os and CCM, GCM and XTS benefit the most.
On Aarch64, uplift is typically around 20 - 110%.
When compiling with gcc -Os on Aarch64, AES-XTS improves
by 4.5x.

View file

@ -0,0 +1,3 @@
Features
* Allow MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE to be set by
setting the CMake variable of the same name at configuration time.

View file

@ -5,3 +5,6 @@ Features
MBEDTLS_USE_PSA_CRYPTO. Restartable/interruptible ECDHE operations in
TLS 1.2 (ECDHE-ECDSA key exchange) are not supported in those builds yet,
as PSA does not have an API for restartable ECDH yet.
* When all of ECDH, ECDSA and EC J-PAKE are either disabled or provided by
a driver, it is possible to disable MBEDTLS_ECP_C and still get support
for ECC keys and algorithms in PSA. See docs/driver-only-builds.txt.

View file

@ -0,0 +1,3 @@
Changes
* Enforce minimum RSA key size when generating a key
to avoid accidental misuse.

View file

@ -0,0 +1,6 @@
Features
* Support for "opaque" (PSA-held) ECC keys in the PK module has been
extended: it is now possible to use mbedtls_pk_write_key_der(),
mbedtls_pk_write_key_pem(), mbedtls_pk_check_pair(), and
mbedtls_pk_verify() with opaque ECC keys (provided the PSA attributes
allow it).

View file

@ -0,0 +1,6 @@
Features
* Add support for FFDH key exchange in TLS 1.3.
This is automatically enabled as soon as PSA_WANT_ALG_FFDH
and the ephemeral or psk-ephemeral key exchange mode are enabled.
By default, all groups are offered; the list of groups can be
configured using the existing API function mbedtls_ssl_conf_groups().

View file

@ -0,0 +1,3 @@
Bugfix
* Fix some cases where mbedtls_mpi_mod_exp, RSA key construction or ECDSA
signature can silently return an incorrect result in low memory conditions.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix a potential corruption of the passed-in IV when mbedtls_aes_crypt_cbc()
is called with zero length and padlock is not enabled.

View file

@ -0,0 +1,4 @@
Bugfix
* Fix crypt_and_hash decryption fail when used with a stream cipher
mode of operation due to the input not being multiple of block size.
Resolves #7417.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix compile failure due to empty enum in cipher_wrap.c, when building
with a very minimal configuration. Fixes #7625.

View file

@ -0,0 +1,5 @@
Bugfix
* In TLS 1.3, fix handshake failure when a client in its ClientHello
proposes an handshake based on PSK only key exchange mode or at least
one of the key exchange modes using ephemeral keys to a server that
supports only the PSK key exchange mode.

View file

@ -0,0 +1,4 @@
Bugfix
* Fix a compilation failure in the constant_time module when
building for arm64_32 (e.g., for watchos). Reported by Paulo
Coutinho in #7787.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix a bug in which mbedtls_x509_string_to_names() would return success
when given a invalid name string if it did not contain '=' or ','.

View file

@ -0,0 +1,5 @@
Bugfix
* Fix compilation warnings in aes.c, which prevented the
example TF-M configuration in configs/ from building cleanly:
tfm_mbedcrypto_config_profile_medium.h with
crypto_config_profile_medium.h.

View file

@ -0,0 +1,3 @@
Features
* The documentation of mbedtls_ecp_group now describes the optimized
representation of A for some curves. Fixes #8045.

View file

@ -0,0 +1,2 @@
Bugfix
* Fix the build with MBEDTLS_PSA_INJECT_ENTROPY. Fixes #7516.

View file

@ -0,0 +1,3 @@
Features
* Improve mbedtls_x509_time performance and reduce memory use.
* Reduce syscalls to time() during certificate verification.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix CCM* with no tag being not supported in a build with CCM as the only
symmetric encryption algorithm and the PSA configuration enabled.

View file

@ -0,0 +1,3 @@
Bugfix
* Don't try to include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE when
MBEDTLS_PSA_CRYPTO_CONFIG is disabled.

View file

@ -0,0 +1,2 @@
Requirement changes
* Officially require Python 3.8 now that earlier versions are out of support.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix very high stack usage in SSL debug code. Reported by Maximilian
Gerhardt in #7804.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix a compilation error on some platforms when including mbedtls/ssl.h
with all TLS support disabled. Fixes #6628.

View file

@ -0,0 +1,4 @@
Changes
* Use heap memory to allocate DER encoded RSA private key.
This reduces stack usage significantly for RSA signature
operations when MBEDTLS_PSA_CRYPTO_C is defined.

View file

@ -0,0 +1,4 @@
Bugfix
* Fix x509 certificate generation to conform to RFC 5480 / RFC 5758 when
using ECC key. The certificate was rejected by some crypto frameworks.
Fixes #2924.

View file

@ -48,7 +48,7 @@ You need the following tools to build the library with the provided makefiles:
* GNU Make 3.82 or a build tool that CMake supports.
* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, IAR 8 and Visual Studio 2013. More recent versions should work. Slightly older versions may work.
* Python 3.6 to generate the test code, and to generate sample programs in the development branch.
* Python 3.8 to generate the test code. Python is also needed to integrate PSA drivers and to build the development branch (see next section).
* Perl to run the tests, and to generate some source files in the development branch.
* CMake 3.10.2 or later (if using CMake).
* Microsoft Visual Studio 2013 or later (if using Visual Studio).
@ -61,7 +61,7 @@ The source code of Mbed TLS includes some files that are automatically generated
The following tools are required:
* Perl, for some library source files and for Visual Studio build files.
* Python 3 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run:
* Python 3.8 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run:
```
python3 -m pip install --user -r scripts/basic.requirements.txt
```
@ -293,25 +293,28 @@ However, it does not aim to implement the whole specification; in particular it
The X.509 and TLS code can use PSA cryptography for most operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `mbedtls_config.h`. Note that TLS 1.3 uses PSA cryptography for most operations regardless of this option. See `docs/use-psa-crypto.md` for details.
### Upcoming features
### PSA drivers
Future releases of this library will include:
Mbed TLS supports drivers for cryptographic accelerators, secure elements and random generators. This is work in progress. Please note that the driver interfaces are not fully stable yet and may change without notice. We intend to preserve backward compatibility for application code (using the PSA Crypto API), but the code of the drivers may have to change in future minor releases of Mbed TLS.
* A driver programming interface, which makes it possible to use hardware accelerators instead of the default software implementation for chosen algorithms.
* Support for external keys to be stored and manipulated exclusively in a separate cryptoprocessor.
* A configuration mechanism to compile only the algorithms you need for your application.
* A wider set of cryptographic algorithms.
Please see the [PSA driver example and guide](docs/psa-driver-example-and-guide.md) for information on writing a driver.
When using drivers, you will generally want to enable two compilation options (see the reference manual for more information):
* `MBEDTLS_USE_PSA_CRYPTO` is necessary so that the X.509 and TLS code calls the PSA drivers rather than the built-in software implementation.
* `MBEDTLS_PSA_CRYPTO_CONFIG` allows you to enable PSA cryptographic mechanisms without including the code of the corresponding software implementation. This is not yet supported for all mechanisms.
License
-------
Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license. Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. This enables LTS (Long Term Support) branches of the software to be provided under either the Apache-2.0 OR GPL-2.0-or-later licenses.
Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license, and [the 'License and Copyright' section in the contributing guidelines](CONTRIBUTING.md#License-and-Copyright) for more information.
### Third-party code included in Mbed TLS
This project contains code from other projects. This code is located within the `3rdparty/` directory. The original license text is included within project subdirectories, and in source files. The projects are listed below:
* `3rdparty/everest/`: Files stem from [Project Everest](https://project-everest.github.io/) and are distributed under the Apache 2.0 license.
* `3rdparty/p256-m/p256-m/`: Files have been taken from the [p256-m](https://github.com/mpg/p256-m) repository. The code in the original repository is distributed under the Apache 2.0 license. It is also used by the project under the Apache 2.0 license. We do not plan to regularly update these files, so they may not contain fixes and improvements present in the upstream project.
* `3rdparty/p256-m/p256-m/`: Files have been taken from the [p256-m](https://github.com/mpg/p256-m) repository. The code in the original repository is distributed under the Apache 2.0 license. It is also used by Mbed TLS under the Apache 2.0 license. We do not plan to regularly update these files, so they may not contain fixes and improvements present in the upstream project.
Contributing
------------

View file

@ -0,0 +1,37 @@
/**
* \file configs/crypto-config-ccm-aes-sha256.h
*
* \brief PSA crypto configuration with only symmetric cryptography: CCM-AES,
* SHA-256, HMAC and key derivation
*/
/*
* 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 PSA_CRYPTO_CONFIG_H
#define PSA_CRYPTO_CONFIG_H
#define PSA_WANT_ALG_CCM 1
#define PSA_WANT_ALG_HMAC 1
#define PSA_WANT_ALG_SHA_256 1
#define PSA_WANT_ALG_TLS12_PRF 1
#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
#define PSA_WANT_KEY_TYPE_DERIVE 1
#define PSA_WANT_KEY_TYPE_HMAC 1
#define PSA_WANT_KEY_TYPE_AES 1
#define PSA_WANT_KEY_TYPE_RAW_DATA 1
#endif /* PSA_CRYPTO_CONFIG_H */

View file

@ -106,10 +106,33 @@
//#define PSA_WANT_KEY_TYPE_CAMELLIA 1
//#define PSA_WANT_KEY_TYPE_CHACHA20 1
//#define PSA_WANT_KEY_TYPE_DES 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1
#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
#define PSA_WANT_KEY_TYPE_RAW_DATA 1
//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1
//#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
/***********************************************************************
* Local edits below this delimiter
**********************************************************************/
/* Between Mbed TLS 3.4 and 3.5, the PSA_WANT_KEY_TYPE_RSA_KEY_PAIR macro
* (commented-out above) has been replaced with the following new macros: */
//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1
//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE 1 /* Not supported */
/* Between Mbed TLS 3.4 and 3.5, the following macros have been added: */
//#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1
//#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1
//#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1
//#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1
//#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE 1 // Not supported
#endif /* PROFILE_M_PSA_CRYPTO_CONFIG_H */

View file

@ -43,8 +43,11 @@ record() {
fi
}
# save current HEAD
HEAD=$(git branch --show-current)
# save current HEAD.
# Note: this can optionally be updated to
# HEAD=$(git branch --show-current)
# when using a Git version above 2.22
HEAD=$(git rev-parse --abbrev-ref HEAD)
# get the numbers before this PR for default and full
cleanup

View file

@ -0,0 +1,536 @@
# PSA storage resilience design
## Introduction
The PSA crypto subsystem includes a persistent key store. It is possible to create a persistent key and read it back later. This must work even if the underlying storage exhibits non-nominal behavior. In this document, _resilience_ means correct behavior of the key store even under if the underlying platform behaves in a non-nominal, but still partially controlled way.
At this point, we are only concerned about one specific form of resilience: to a system crash or power loss. That is, we assume that the underlying platform behaves nominally, except that occasionally it may restart. In the field, this can happen due to a sudden loss of power.
This document explores the problem space, defines a library design and a test design.
## Resilience goals for API functions
**Goal: PSA Crypto API functions are atomic and committing.**
_Atomic_ means that when an application calls an API function, as far as the application is concerned, at any given point in time, the system is either in a state where the function has not started yet, or in a state where the function has returned. The application never needs to worry about an intermediate state.
_Committing_ means that when a function returns, the data has been written to the persistent storage. As a consequence, if the system restarts during a sequence of storage modifications $M_1, M_2, \ldots, M_n$, we know that when the system restarts, a prefix of the sequence has been performed. For example, there will never be a situation where $M_2$ has been performed but not $M_1$.
The committing property is important not only for sequences of operations, but also when reporting the result of an operation to an external system. For example, if a key creation function in the PSA Crypto API reports to the application that a key has been created, and the application reports to a server that the key has been created, it is guaranteed that the key exists even if the system restarts.
## Assumptions on the underlying file storage
PSA relies on a PSA ITS (Internal Trusted Storage) interface, which exposes a simple API. There are two functions to modify files:
* `set()` writes a whole file (either creating it, or replacing the previous content).
* `remove()` removes a file (returning a specific error code if the file does not exist).
**Assumption: the underlying ITS functions are atomic and committing.**
Since the underlying functions are atomic, the content of a file is always a version that was previously passed to `set()`. We do not try to handle the case where a file might be partially written.
## Overview of API functions
For a transparent key, all key management operations (creation or destruction) on persistent keys rely on a single call to the underlying storage (`set()` for a key creation, `remove()` for a key destruction). This also holds for an opaque key stored in a secure element that does not have its own key store: in this case, the core stores a wrapped (i.e. encrypted) copy of the key material, but this does not impact how the core interacts with the storage. Other API functions do not modify the storage.
The following case requires extra work related to resilience:
* [Key management for stateful secure element keys](#designing-key-management-for-secure-element-keys).
As a consequence, apart from the listed cases, the API calls inherit directly from the [resilience properties of the underyling storage](#assumptions-on-the-underlying-file-storage). We do not need to take any special precautions in the library design, and we do not need to perform any testing of resilience for transparent keys.
(This section was last updated for Mbed TLS 3.4.0 implementing PSA Crypto API 1.1.)
## Designing key management for secure element keys
In this section, we use “(stateful) secure element key” to mean a key stored in a stateful secure element, i.e. a secure element that stores keys. This excludes keys in a stateleess secure element for which the core stores a wrapped copy of the key. We study the problem of how key management in stateful secure elements interacts with storage and explore the design space.
### Assumptions on stateful secure elements
**Assumption: driver calls for key management in stateful secure elements are atomic and committing.**
(For stateless secure elements, this assumption is vacuously true.)
### Dual management of keys: the problem
For a secure element key, key management requires a commitment on both sites. For example, consider a successful key creation operation:
1. The core sends a request to the secure element to create a key.
2. The secure element modifies its key store to create the key.
3. The secure element reports to the core that the key has been created.
4. The core reports to the application that the key has been created.
If the core loses power between steps 1 and 2, the key does not exist yet. This is fine from an application's perspective since the core has not committed to the key's existence, but the core needs to take care not to leave resources in storage that are related to the non-existent key. If the core loses power between steps 2 and 3, the key exists in the secure element. From an application's perspective, the core may either report that the key exists or that it does not exist, but in the latter case, the core needs to free the key in the secure element, to avoid leaving behind inaccessible resources.
As a consequence, the content of the storage cannot remain the same between the end of step 1 and the end of step 3, since the core must behave differently depending on whether step 2 has taken place.
Accomplishing a transaction across system boundaries is a well-known problem in database management, with a well-known solution: two-phase commit.
### Overview of two-phase commit with stateful secure elements
With a key in a stateful secure element, a successful creation process goes as follows (see [“Key management in a secure element with storage” in the driver interface specification](../../proposed/psa-driver-interface.html#key-management-in-a-secure-element-with-storage)):
1. The core calls the driver's `"allocate_key"` entry point.
2. The driver allocates a unique identifier _D_ for the key. This is unrelated to the key identifier _A_ used by the application interface. This step must not modify the state of the secure element.
3. The core updates the storage to indicate that key identifier _A_ has the identifier _D_ in the driver, and that _A_ is in a half-created state.
4. The core calls the driver's key creation entry point, passing it the driver's chosen identifier _D_.
5. The driver creates the key in the secure element. When this happens, it concludes the voting phase of the two-phase commit: effectively, the secure element decides to commit. (It is however possible to revert this commitment by giving the secure element the order to destroy the key.)
6. The core updates the storage to indicate that _A_ is now in a fully created state. This concludes the commit phase of the two-phase commit.
If there is a loss of power:
* Before step 3: the system state has not changed at all. As far as the world is concerned, the key creation attempt never happened.
* Between step 3 and step 6: upon restart, the core needs to find out whether the secure element completed step 5 or not, and reconcile the state of the storage with the state of the secure element.
* After step 6: the key has been created successfully.
Key destruction goes as follows:
1. The core updates the storage indicating that the key is being destroyed.
2. The core calls the driver's `"destroy_key"` entry point.
3. The secure element destroys the key.
4. The core updates the storage to indicate that the key has been destroyed.
If there is a loss of power:
* Before step 1: the system state has not changed at all. As far as the world is concerned, the key destruction attempt never happened.
* Between step 1 and step 4: upon restart, the core needs to find out whether the secure element completed step 3 or not, and reconcile the state of the storage with the state of the secure element.
* After step 4: the key has been destroyed successfully.
In both cases, upon restart, the core needs to perform a transaction recovery. When a power loss happens, the core decides whether to commit or abort the transaction.
Note that the analysis in this section assumes that the driver does not update its persistent state during a key management operation (or at least not in a way that is influences the key management process — for example, it might renew an authorization token).
### Optimization considerations for transactions
We assume that power failures are rare. Therefore we will primarily optimize for the normal case. Transaction recovery needs to be practical, but does not have to be fully optimized.
The main quantity we will optimize for is the number of storage updates in the nominal case. This is good for performance because storage writes are likely to dominate the runtime in some hardware configurations where storage writes are slow and communication with the secure element is fast, for key management operations that require a small amount of computation. In addition, minimizing the number of storage updates is good for the longevity of flash media.
#### Information available during recovery
The PSA ITS API does not support enumerating files in storage: an ITS call can only access one file identifier. Therefore transaction recovery cannot be done by traversing files whose name is or encodes the key identifier. It must start by traversing a small number of files whose names are independent of the key identifiers involved.
#### Minimum effort for a transaction
Per the [assumptions on the underlying file storage](#assumptions-on-the-underlying-file-storage), each atomic operation in the internal storage concerns a single file: either removing it, or setting its content. Furthermore there is no way to enumerate the files in storage.
A key creation function must transform the internal storage from a state where file `id` does not exist, to a state where file `id` exists and has its desired final content (containing the key attributes and the driver's key identifier). The situation is similar with key destruction, except that the initial and final states are exchanged. Neither the initial state nor the final state reference `id` otherwise.
For a key that is not in a stateful element, the transaction consists of a single write operation. As discussed previously, this is not possible with a stateful secure element because the state of the internal storage needs to change both before and after the state change in the secure element. No other single-write algorithm works.
If there is a power failure around the time of changing the state of the secure element, there must be information in the internal storage that indicates that key `id` has a transaction in progress. The file `id` cannot be used for this purpose because there is no way to enumerate all keys (and even if there was, it would not be practical). Therefore the transaction will need to modify some other file `t` with a fixed name (a name that doesn't depend on the key). Since the final system state should be identical to the initial state except for the file `id`, the minimum number of storage operations for a transaction is 3:
* Write (create or update) a file `t` referencing `id`.
* Write the final state of `id`.
* Restore `t` to its initial state.
The strategies discussed in the [overview above](#overview-of-two-phase-commit-with-stateful-secure-elements) follow this pattern, with `t` being the file containing the transaction list that the recovery consults. We have just proved that this pattern is optimal.
Note that this pattern requires the state of `id` to be modified only once. In particular, if a key management involves writing an intermediate state for `id` before modifying the secure element state and writing a different state after that, this will require a total of 4 updates to internal storage. Since we want to minimize the number of storage updates, we will not explore designs that involved updating `id` twice or more.
### Recovery strategies
When the core starts, it needs to know about transaction(s) that need to be resumed. This information will be stored in a persistent “transaction list”, with one entry per key. In this section, we explore recovery strategies, and we determine what the transaction list needs to contain as well as when it needs to be updated. Other sections will explore the format of the transaction list, as well as how many keys it needs to contain.
#### Exploring the recovery decision tree
There are four cases for recovery when a transaction is in progress. In each case, the core can either decide to commit the transaction (which may require replaying the interrupted part) or abort it (which may require a rewind in the secure element). It may call the secure element driver's `"get_key_attributes"` entry point to find out whether the key is present.
* Key creation, key not present in the secure element:
* Committing means replaying the driver call in the key creation. This requires all the input, for example the data to import. This seems impractical in general. Also, the second driver call require a new call to `"allocate_key"` which will in general changing the key's driver identifier, which complicates state management in the core. Given the likely complexity, we exclude this strategy.
* Aborting means removing any trace of the key creation.
* Key creation, key present in the secure element:
* Committing means finishing the update of the core's persistent state, as would have been done if the transaction had not been interrupted.
* Aborting means destroying the key in the secure element and removing any local storage used for that key.
* Key destruction, key not present in the secure element:
* Committing means finishing the update of the core's persistent state, as would have been done if the transaction had not been interrupted, by removing any remaining local storage used for that key.
* Aborting would mean re-creating the key in the secure element, which is impossible in general since the key material is no longer present.
* Key destruction, key present in the secure element:
* Committing means finishing the update of the core's persistent state, as would have been done if the transaction had not been interrupted, by removing any remaining local storage used for that key and destroying the key in the secure element.
* Aborting means keeping the key. This requires no action on the secure element, and is only practical locally if the local storage is intact.
#### Comparing recovery strategies
From the analysis above, assuming that all keys are treated in the same way, there are 4 possible strategies.
* [Always follow the state of the secure element](#exploring-the-follow-the-secure-element-strategy). This requires the secure element driver to have a `"get_key_attributes"` entry point. Recovery means resuming the operation where it left off. For key creation, this means that the key metadata needs to be saved before calling the secure element's key creation entry point.
* Minimize the information processing: [always destroy the key](#exploring-the-always-destroy-strategy), i.e. abort all key creations and commit all key destructions. This does not require querying the state of the secure element. This does not require any special precautions to preserve information about the key during the transaction. It simplifies recovery in that the recovery process might not even need to know whether it's recovering a key creation or a key destruction.
* Follow the state of the secure element for key creation, but always go ahead with key destruction. This requires the secure element driver to have a `"get_key_attributes"` entry point. Compared to always following the state of the secure element, this has the advantage of maximizing the chance that a command to destroy key material is effective. Compared to always destroying the key, this has a performance advantage if a key creation is interrupted. These do not seem like decisive advantages, so we will not consider this strategy further.
* Always abort key creation, but follow the state of the secure element for key destruction. I can't think of a good reason to choose this strategy.
Requiring the driver to have a `"get_key_attributes"` entry point is potentially problematic because some secure elements don't have room to store key attributes: a key slot always exists, and it's up to the user to remember what, if anything, they put in it. The driver has to remember anyway, so that it can find a free slot when creating a key. But with a recovery strategy that doesn't involve a `"get_key_attributes"` entry point, the driver design is easier: the driver doesn't need to protect the information about slots in use against a power failure, the core takes care of that.
#### Exploring the follow-the-secure-element strategy
Each entry in the transaction list contains the API key identifier, the key lifetime (or at least the location), the driver key identifier (not constant-size), and an indication of whether the key is being created or destroyed.
For key creation, we have all the information to store in the key file once the `"allocate_key"` call returns. We must store all the information that will go in the key file before calling the driver's key creation entry point. Therefore the normal sequence of operations is:
1. Call the driver's `"allocate_key"` entry point.
2. Add the key to the transaction list, indicating that it is being created.
3. Write the key file.
4. Call the driver's key creation entry point.
5. Remove the key from the transaction list.
During recovery, for each key in the transaction list that was being created:
* If the key exists in the secure element, just remove it from the transaction list.
* If the key does not exist in the secure element, first remove the key file if it is present, then remove the key from the transaction list.
For key destruction, we need to preserve the key file until after the key has been destroyed. Therefore the normal sequence of operations is:
1. Add the key to the transaction list, indicating that it is being destroyed.
2. Call the driver's `"destroy_key"` entry point.
3. Remove the key file.
4. Remove the key from the transaction list.
During recovery, for each key in the transaction list that was being created:
* If the key exists in the secure element, call the driver's `"destroy_key"` entry point, then remove the key file, and finally remote the key from the transaction lits.
* If the key does not exist in the secure element, remove the key file if it is still present, then remove the key from the transaction list.
#### Exploring the always-destroy strategy
Each entry in the transaction list contains the API key identifier, the key lifetime (or at least the location), and the driver key identifier (not constant-size).
For key creation, we do not need to store the key's metadata until it has been created in the secure element. Therefore the normal sequence of operations is:
1. Call the driver's `"allocate_key"` entry point.
2. Add the key to the transaction list.
3. Call the driver's key creation entry point.
4. Write the key file.
5. Remove the key from the transaction list.
For key destruction, we can remove the key file before contacting the secure element. Therefore the normal sequence of operations is:
1. Add the key to the transaction list.
2. Remove the key file.
3. Call the driver's `"destroy_key"` entry point.
4. Remove the key from the transaction list.
Recovery means removing all traces of all keys on the transaction list. This means following the destruction process, starting after the point where the key has been added to the transaction list, and ignoring any failure of a removal action if the item to remove does not exist:
1. Remove the key file, treating `DOES_NOT_EXIST` as a success.
2. Call the driver's `"destroy_key"` entry point, treating `DOES_NOT_EXIST` as a success.
3. Remove the key from the transaction list.
#### Always-destroy strategy with a simpler transaction file
We can modify the [always-destroy strategy](#exploring-the-always-destroy-strategy) to make the transaction file simpler: if we ensure that the key file always exists if the key exists in the secure element, then the transaction list does not need to include the driver key identifier: it can be read from the key file.
For key creation, we need to store the key's metadata before creating in the secure element. Therefore the normal sequence of operations is:
1. Call the driver's `"allocate_key"` entry point.
2. Add the key to the transaction list.
3. Write the key file.
4. Call the driver's key creation entry point.
5. Remove the key from the transaction list.
For key destruction, we need to contact the secure element before removing the key file. Therefore the normal sequence of operations is:
1. Add the key to the transaction list.
2. Call the driver's `"destroy_key"` entry point.
3. Remove the key file.
4. Remove the key from the transaction list.
Recovery means removing all traces of all keys on the transaction list. This means following the destruction process, starting after the point where the key has been added to the transaction list, and ignoring any failure of a removal action if the item to remove does not exist:
1. Load the driver key identifier from the key file. If the key file does not exist, skip to step 4.
2. Call the driver's `"destroy_key"` entry point, treating `DOES_NOT_EXIST` as a success.
3. Remove the key file, treating `DOES_NOT_EXIST` as a success.
4. Remove the key from the transaction list.
Compared with the basic always-destroy strategy:
* The transaction file handling is simpler since its entries have a fixed size.
* The flow of information is somewhat different from transparent keys and keys in stateless secure elements: we aren't just replacing “create the key material” by “tell the secure element to create the key material”, those happen at different times. But there's a different flow for stateful secure elements anyway, since the call to `"allocate_key"` has no analog in the stateless secure element or transparent cases.
#### Assisting secure element drivers with recovery
The actions of the secure element driver may themselves be non-atomic. So the driver must be given a chance to perform recovery.
To simplify the design of the driver, the core should guarantee that the driver will know if a transaction was in progress and the core cannot be sure about the state of the secure element. Merely calling a read-only entry point such as `"get_key_attributes"` does not provide enough information to the driver for it to know that it should actively perform recovery related to that key.
This gives an advantage to the “always destroy” strategy. Under this strategy, if the key might be in a transitional state, the core will request a key destruction from the driver. This means that, if the driver has per-key auxiliary data to clean up, it can bundle that as part of the key's destruction.
### Testing non-atomic processes
In this section, we discuss how to test non-atomic processes that must implement an atomic and committing interface. As discussed in [“Overview of API functions”](#overview-of-api-functions), this concerns key management in stateful secure elements.
#### Naive test strategy for non-atomic processes
Non-atomic processes consist of a series of atomic, committing steps.
Our general strategy to test them is as follows: every time there is a modification of persistent state, either in storage or in the (simulated) secure element, try both the nominal case and simulating a power loss. If a power loss occurs, restart the system (i.e. clean up and call `psa_crypto_init()`), and check that the system ends up in a consistent state.
Note that this creates a binary tree of possibilities: after each state modification, there may or may not be a restart, and after that different state modifications may occur, each of which may or may not be followed by a restart.
For example, consider testing of one key creation operation (see [“Overview of two-phase commit with stateful secure elements”](#overview-of-two-phase-commit-with-stateful-secure-elements), under the simplifying assumption that each storage update step, as well as the recovery after a restart, each make a single (atomic) storage modification and no secure element access. The nominal case consists of three state modifications: storage modification (start transaction), creation on the secure element, storage modification (commit transaction). We need to test the following sequences:
* Start transaction, restart, recovery.
* Start transaction, secure element operation, restart, recovery.
* Start transaction, secure element operation, commit transaction.
If, for example, recovery consists of two atomic steps, the tree of possibilities expands and may be infinite:
* Start transaction, restart, recovery step 1, restart, recovery step 1, recovery step 2.
* Start transaction, restart, recovery step 1, restart, recovery step 1, restart, recovery step 1, recovery step 2.
* Start transaction, restart, recovery step 1, restart, recovery step 1, restart, recovery step 1, restart, recovery step 1, recovery step 2.
* etc.
* Start transaction, secure element operation, restart, ...
* Start transaction, secure element operation, commit transaction.
In order to limit the possibilities, we need to make some assumptions about the recovery step. For example, if we have confidence that recovery step 1 is idempotent (i.e. doing it twice is the same as doing it once), we don't need to test what happens in execution sequences that take recovery step 1 more than twice in a row.
### Splitting normal behavior and transaction recovery
We introduce an abstraction level in transaction recovery:
* Normal operation must maintain a certain invariant on the state of the world (internal storage and secure element).
* Transaction recovery is defined over all states of the world that satisfy this invariant.
This separation of concerns greatly facilitates testing, since it is now split into two parts:
* During the testing of normal operation, we can use read-only invasive testing to ensure that the invariant is maintained. No modification of normal behavior (such as simulated power failures) is necessary.
* Testing of transaction recovery is independent of how the system state was reached. We only need to artificially construct a representative sample of system states that match the invariant. Transaction recovery is itself an operation that must respect the invariant, and so we do not need any special testing for the case of an interrupted recovery.
Another benefit of this approach is that it is easier to specify and test what happens if the library is updated on a device with leftovers from an interrupted transaction. We will require and test that the new version of the library supports recovery of the old library's states, without worrying how those states were reached.
#### Towards an invariant for transactions
As discussed in the section [“Recovery strategies”](#recovery-strategies), the information about active transactions is stored in a transaction list file. The name of the transaction list file does not depend on the identifiers of the keys in the list, but there may be more than one transaction list, for example one per secure element. If so, each transaction list can be considered independently.
When no transaction is in progress, the transaction list does not exist, or is empty. The empty case must be supported because this is the initial state of the filesystem. When no transaction is in progress, the state of the secure element must be consistent with references to keys in that secure element contained in key files. More generally, if a key is not in the transaction list, then the key must be present in the secure element if and only if the key file is in the internal storage.
For the purposes of the state invariant, it matters whether the transaction list file contains the driver key identifier, or if the driver key identifier is only stored in the key file. This is because the core needs to know the driver key id in order to access the secure element. If the transaction list does not contain the driver key identifier, and the key file does not exist, the key must not be present in the secure element.
We thus have two scenarios, each with their own invariant: one where the transaction list contains only key identifiers, and one where it also contains the secure element's key identifier (as well as the location of the secure element if this is not encoded in the name of the transaction list file).
#### Storage invariant if the transaction list contains application key identifiers only
Invariants:
* If the file `id` does not exist, then no resources corresponding to that key are in a secure element. This holds whether `id` is in the transaction list or not.
* If `id` is not in the transaction list and the file `id` exists and references a key in a stateful secure element, then the key is present in the secure element.
If `id` is in the transaction list and the file `id` exists, the key may or may not be present in the secure element.
The invariant imposes constraints on the [order of operations for the two-phase commit](#overview-of-two-phase-commit-with-stateful-secure-elements): key creation must create `id` before calling the secure element's key creation entry point, and key destruction must remove `id` after calling the secure element's key destruction entry point.
For recovery:
* If the file `id` does not exist, then nothing needs to be done for recovery, other than removing `id` from the transaction list.
* If the file `id` exists:
* It is correct to destroy the key in the secure element (treating a `DOES_NOT_EXIST` error as a success), then remove `id`.
* It is correct to check whether the key exists in the secure element, and if it does, keep it and keep `id`. If not, remove `id` from the internal storage.
#### Storage invariant if the transaction list contains driver key identifiers
Invariants:
* If `id` is not in the transaction list and the file `id` does not exist, then no resources corresponding to that key are in a secure element.
* If `id` is not in the transaction list and the file `id` exists, then the key is present in the secure element.
If `id` is in the transaction list, neither the state of `id` in the internal storage nor the state of the key in the secure element is known.
For recovery:
* If the file `id` does not exist, then destroy the key in the secure element (treating a `DOES_NOT_EXIST` error as a success).
* If the file `id` exists:
* It is correct to destroy the key in the secure element (treating a `DOES_NOT_EXIST` error as a success), then remove `id`.
* It is correct to check whether the key exists in the secure element, and if it does, keep it and keep `id`. If not, remove `id` from the internal storage.
#### Coverage of states that respect the invariant
For a given key, we have to consider three a priori independent boolean states:
* Whether the key file exists.
* Whether the key is in the secure element.
* Whether the key is in the transaction list.
There is full coverage for one key if we have tests of recovery for the states among these $2^3 = 8$ possibilities that satisfy the storage invariant.
In addition, testing should adequately cover the case of multiple keys in the transaction list. How much coverage is adequate depends on the layout of the list as well as white-box considerations of how the list is manipulated.
### Choice of a transaction design
#### Chosen transaction algorithm
Based on [“Optimization considerations for transactions”](#optimization-considerations-for-transactions), we choose a transaction algorithm that consists in the following operations:
1. Add the key identifier to the transaction list.
2. Call the secure element's key creation or destruction entry point.
3. Remove the key identifier from the transaction list.
In addition, before or after step 2, create or remove the key file in the internal storage.
In order to conveniently support multiple transactions at the same time, we pick the simplest possible layout for the transaction list: a simple array of key identifiers. Since the transaction list does not contain the driver key identifier:
* During key creation, create the key file in internal storage in the internal storage before calling the secure element's key creation entry point.
* During key destruction, call the secure element's key destruction entry point before removing the key file in internal storage.
This choice of algorithm does not require the secure element driver to have a `"get_key_attributes"` entry point.
#### Chosen storage invariant
The [storage invariant](#storage-invariant-if-the-transaction-list-contains-application-key-identifiers-only) is as follows:
* If the file `id` does not exist, then no resources corresponding to that key are in a secure element. This holds whether `id` is in the transaction list or not.
* If `id` is not in the transaction list and the file `id` exists and references a key in a stateful secure element, then the key is present in the secure element.
* If `id` is in the transaction list and a key exists by that identifier, the key's location is a stateful secure element.
#### Chosen recovery process
To [assist secure element drivers with recovery](#assisting-secure-element-drivers-with-recovery), we pick the [always-destroy recovery strategy with a simple transaction file](#always-destroy-strategy-with-a-simpler-transaction-file). The the recovery process is as follows:
* If the file `id` does not exist, then nothing needs to be done for recovery, other than removing `id` from the transaction list.
* If the file `id` exists, call the secure element's key destruction entry point (treating a `DOES_NOT_EXIST` error as a success), then remove `id`.
## Specification of key management in stateful secure elements
This section only concerns stateful secure elements as discussed in [“Designing key management for secure element keys”](#designing-key-management-for-secure-element-keys), i.e. secure elements with an `"allocate_key"` entry point. The design follows the general principle described in [“Overview of two-phase commit with stateful secure elements”](#overview-of-two-phase-commit-with-stateful-secure-elements) and the specific choices justified in [“Choice of a transaction design”](choice-of-a-transaction-design).
### Transaction list file manipulation
The transaction list is a simple array of key identifiers.
To add a key identifier to the list:
1. Load the current list from the transaction list if it exists and it is not already cached in memory.
2. Append the key identifier to the array.
3. Write the updated list file.
To remove a key identifier from the list:
1. Load the current list if it is not already cached in memory. It is an error if the file does not exist since it must contain this identifier.
2. Remove the key identifier from the array. If it wasn't the last element in array, move array elements to fill the hole.
3. If the list is now empty, remove the transaction list file. Otherwise write the updated list to the file.
### Key creation process in the core
Let _A_ be the application key identifier.
1. Call the driver's `"allocate_key"` entry point, obtaining the driver key identifier _D_ chosen by the driver.
2. Add _A_ [to the transaction list file](#transaction-list-file-manipulation).
3. Create the key file _A_ in the internal storage. Note that this is done at a different time from what happens when creating a transparent key or a key in a stateless secure element: in those cases, creating the key file happens after the actual creation of the key material.
4. Call the secure element's key creation entry point.
5. Remove _A_ [from the transaction list file](#transaction-list-file-manipulation).
If any step fails:
* If the secure element's key creation entry point has been called and succeeded, call the secure element's destroy entry point.
* If the key file has been created in the internal storage, remove it.
* Remove the key from the transaction list.
Note that this process is identical to key destruction, except that the key is already in the transaction list.
### Key destruction process in the core
Let _A_ be the application key identifier.
We assume that the key is loaded in a key slot in memory: the core needs to know the key's location in order to determine whether the key is in a stateful secure element, and if so to know the driver key identifier. A possible optimization would be to load only that information in local variables, without occupying a key store; this has the advantage that key destruction works even if the key store is full.
1. Add _A_ [to the transaction list file](#transaction-list-file-manipulation).
2. Call the secure element's `"destroy_key"` entry point.
3. Remove the key file _A_ from the internal storage.
4. Remove _A_ [from the transaction list file](#transaction-list-file-manipulation).
5. Free the corresponding key slot in memory.
If any step fails, remember the error but continue the process, to destroy the resources associated with the key as much as is practical.
### Transaction recovery
For each key _A_ in the transaction list file, if the file _A_ exists in the internal storage:
1. Load the key into a key slot in memory (to get its location and the driver key identifier, although we could get the location from the transaction list).
2. Call the secure element's `"destroy_key"` entry point.
3. Remove the key file _A_ from the internal storage.
4. Remove _A_ [from the transaction list file](#transaction-list-file-manipulation).
5. Free the corresponding key slot in memory.
The transaction list file can be processed in any order.
It is correct to update the transaction list after recovering each key, or to only delete the transaction list file once the recovery is over.
### Concrete format of the transaction list file
The transaction list file contains a [fixed header](#transaction-list-header-format) followed by a list of [fixed-size elements](#transaction-list-element-format).
The file uid is `PSA_CRYPTO_ITS_TRANSACTION_LIST_UID` = 0xffffff53.
#### Transaction list header format
* Version (2 bytes): 0x0003. (Chosen to differ from the first two bytes of a [dynamic secure element transaction file](#dynamic-secure-element-transaction-file), to reduce the risk of a mix-up.)
* Key name size (2 bytes): `sizeof(psa_storage_uid_t)`. Storing this size avoids reading bad data if Mbed TLS is upgraded to a different integration that names keys differently.
#### Transaction list element format
In practice, there will rarely be more than one active transaction at a time, so the size of an element is not critical for efficiency. Therefore, in addition to the key identifier which is required, we add some potentially useful information in case it becomes useful later. We do not put the driver key identifier because its size is not a constant.
* Key id: `sizeof(psa_storage_uid_t)` bytes.
* Key lifetime: 4 bytes (`sizeof(psa_key_lifetime_t)`). Currently unused during recovery.
* Operation type: 1 byte. Currently unused during recovery.
* 0: destroy key.
* 1: import key.
* 2: generate key.
* 3: derive key.
* 4: import key.
* Padding: 3 bytes. Reserved for future use. Currently unused during recovery.
#### Dynamic secure element transaction file
Note that the code base already references a “transaction file” (`PSA_CRYPTO_ITS_TRANSACTION_UID` = 0xffffff54), used by dynamic secure elements (feature enabled with `MBEDTLS_PSA_CRYPTO_SE_C`). This is a deprecated feature that has not been fully implemented: when this feature is enabled, the transaction file gets written during transactions, but if it exists when PSA crypto starts, `psa_crypto_init()` fails because [recovery has never been implemented](https://github.com/ARMmbed/mbed-crypto/issues/218).
For the new kind of secure element driver, we pick a different file name to avoid any mixup.
## Testing key management in secure elements
### Instrumentation for checking the storage invariant
#### Test hook locations
When `MBEDTLS_TEST_HOOKS` is enabled, each call to `psa_its_set()` or `psa_its_remove()` also calls a test hook, passing the file UID as an argument to the hook.
When a stateful secure element driver is present in the build, we use this hook to verify that the storage respects the [storage invariant](#chosen-storage-invariant). In addition, if there is some information about key ongoing operation (set explicitly by the test function as a global variable in the test framework), the hook tests that the content of the storage is compatible with the ongoing operation.
#### Test hook behavior
The storage invariant check cannot check all keys in storage, and does not need to (for example, it would be pointless to check anything about transparent keys). It checks the following keys:
* When invoked from the test hook on a key file: on that key.
* When invoked from the test hook on the transaction file: on all the keys listed in the transaction file.
* When invoked from a test secure element: on the specified key.
#### Test hook extra data
Some tests set global variables to indicate which persistent keys they manipulate. We instrument at least some of these tests to also indicate what operation is in progress on the key. See the GitHub issues or the source code for details.
### Testing of transaction recovery
When no secure element driver is present in the build, the presence of a transaction list file during initialization is an error.
#### Recovery testing process
When the stateful test secure element driver is present in the build, we run test cases on a representative selection of states of the internal storage and the test secure element. Each test case for transaction recovery has the following form:
1. Create the initial state:
* Create a transaction list file with a certain content.
* Create key files that we want to have in the test.
* Call the secure element test driver to create keys without going throught the PSA API.
2. Call `psa_crypto_init()`. Expect success if the initial state satisfies the [storage invariant](#chosen-storage-invariant) and failure otherwise.
3. On success, check that the expected keys exist, and that keys that are expected to have been destroyed by recovery do not exist.
4. Clean up the storage and the secure element test driver's state.
#### States to test recovery on
For a given key located in a secure element, the following combination of states are possible:
* Key file: present, absent.
* Key in secure element: present, absent.
* Key in the transaction file: no, creation (import), destruction.
We test all $2 \times 2 \times 3 = 12$ possibilities, each in its own test case. In each case, call the test function that checks the storage invariant and check that its result is as expected. Then, if the storage invariant is met, follow the [recovery testing process](#recovery-testing-process).
In addition, have at least one positive test case for each creation method other than import, to ensure that we don't reject a valid value.
Note: testing of a damaged filesystem (including a filesystem that doesn't meet the invariant) is out of scope of the present document.

View file

@ -0,0 +1,284 @@
Thread safety of the PSA subsystem
==================================
## Requirements
### Backward compatibility requirement
Code that is currently working must keep working. There can be an exception for code that uses features that are advertised as experimental; for example, it would be annoying but ok to add extra requirements for drivers.
(In this section, “currently” means Mbed TLS releases without proper concurrency management: 3.0.0, 3.1.0, and any other subsequent 3.x version.)
In particular, if you either protect all PSA calls with a mutex, or only ever call PSA functions from a single thread, your application currently works and must keep working. If your application currently builds and works with `MBEDTLS_PSA_CRYPTO_C` and `MBEDTLS_THREADING_C` enabled, it must keep building and working.
As a consequence, we must not add a new platform requirement beyond mutexes for the base case. It would be ok to add new platform requirements if they're only needed for PSA drivers, or if they're only performance improvements.
Tempting platform requirements that we cannot add to the default `MBEDTLS_THREADING_C` include:
* Releasing a mutex from a different thread than the one that acquired it. This isn't even guaranteed to work with pthreads.
* New primitives such as semaphores or condition variables.
### Correctness out of the box
If you build with `MBEDTLS_PSA_CRYPTO_C` and `MBEDTLS_THREADING_C`, the code must be functionally correct: no race conditions, deadlocks or livelocks.
The [PSA Crypto API specification](https://armmbed.github.io/mbed-crypto/html/overview/conventions.html#concurrent-calls) defines minimum expectations for concurrent calls. They must work as if they had been executed one at a time, except that the following cases have undefined behavior:
* Destroying a key while it's in use.
* Concurrent calls using the same operation object. (An operation object may not be used by more than one thread at a time. But it can move from one thread to another between calls.)
* Overlap of an output buffer with an input or output of a concurrent call.
* Modification of an input buffer during a call.
Note that while the specification does not define the behavior in such cases, Mbed TLS can be used as a crypto service. It's acceptable if an application can mess itself up, but it is not acceptable if an application can mess up the crypto service. As a consequence, destroying a key while it's in use may violate the security property that all key material is erased as soon as `psa_destroy_key` returns, but it may not cause data corruption or read-after-free inside the key store.
### No spinning
The code must not spin on a potentially non-blocking task. For example, this is proscribed:
```
lock(m);
while (!its_my_turn) {
unlock(m);
lock(m);
}
```
Rationale: this can cause battery drain, and can even be a livelock (spinning forever), e.g. if the thread that might unblock this one has a lower priority.
### Driver requirements
At the time of writing, the driver interface specification does not consider multithreaded environments.
We need to define clear policies so that driver implementers know what to expect. Here are two possible policies at two ends of the spectrum; what is desirable is probably somewhere in between.
* Driver entry points may be called concurrently from multiple threads, even if they're using the same key, and even including destroying a key while an operation is in progress on it.
* At most one driver entry point is active at any given time.
A more reasonable policy could be:
* By default, each driver only has at most one entry point active at any given time. In other words, each driver has its own exclusive lock.
* Drivers have an optional `"thread_safe"` boolean property. If true, it allows concurrent calls to this driver.
* Even with a thread-safe driver, the core never starts the destruction of a key while there are operations in progress on it, and never performs concurrent calls on the same multipart operation.
### Long-term performance requirements
In the short term, correctness is the important thing. We can start with a global lock.
In the medium to long term, performing a slow or blocking operation (for example, a driver call, or an RSA decryption) should not block other threads, even if they're calling the same driver or using the same key object.
We may want to go directly to a more sophisticated approach because when a system works with a global lock, it's typically hard to get rid of it to get more fine-grained concurrency.
### Key destruction long-term requirements
As noted above in [“Correctness out of the box”](#correctness-out-of-the-box), when a key is destroyed, it's ok if `psa_destroy_key` allows copies of the key to live until ongoing operations using the key return. In the long term, it would be good to guarantee that `psa_destroy_key` wipes all copies of the key material.
#### Summary of guarantees when `psa_destroy_key` returns
* The key identifier doesn't exist. Rationale: this is a functional requirement for persistent keys: the caller can immediately create a new key with the same identifier.
* The resources from the key have been freed. Rationale: in a low-resource condition, this may be necessary for the caller to re-create a similar key, which should be possible.
* The call must not block indefinitely, and in particular cannot wait for an event that is triggered by application code such as calling an abort function. Rationale: this may not strictly be a functional requirement, but it is an expectation `psa_destroy_key` does not block forever due to another thread, which could potentially be another process on a multi-process system.
* In the long term, no copy of the key material exists. Rationale: this is a security requirement. We do not have this requirement yet, but we need to document this as a security weakness, and we would like to become compliant.
## Resources to protect
Analysis of the behavior of the PSA key store as of Mbed TLS 9202ba37b19d3ea25c8451fd8597fce69eaa6867.
### Global variables
* `psa_crypto_slot_management::global_data.key_slots[i]`: see [“Key slots”](#key-slots).
* `psa_crypto_slot_management::global_data.key_slots_initialized`:
* `psa_initialize_key_slots`: modification.
* `psa_wipe_all_key_slots`: modification.
* `psa_get_empty_key_slot`: read.
* `psa_get_and_lock_key_slot`: read.
* `psa_crypto::global_data.rng`: depends on the RNG implementation. See [“Random generator”](#random-generator).
* `psa_generate_random`: query.
* `mbedtls_psa_crypto_configure_entropy_sources` (only if `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is enabled): setup. Only called from `psa_crypto_init` via `mbedtls_psa_random_init`, or from test code.
* `mbedtls_psa_crypto_free`: deinit.
* `psa_crypto_init`: seed (via `mbedtls_psa_random_seed`); setup via `mbedtls_psa_crypto_configure_entropy_sources.
* `psa_crypto::global_data.{initialized,rng_state}`: these are bit-fields and cannot be modified independently so they must be protected by the same mutex. The following functions access these fields:
* `mbedtls_psa_crypto_configure_entropy_sources` [`rng_state`] (only if `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is enabled): read. Only called from `psa_crypto_init` via `mbedtls_psa_random_init`, or from test code.
* `mbedtls_psa_crypto_free`: modification.
* `psa_crypto_init`: modification.
* Many functions via `GUARD_MODULE_INITIALIZED`: read.
### Key slots
#### Key slot array traversal
“Occupied key slot” is determined by `psa_is_key_slot_occupied` based on `slot->attr.type`.
The following functions traverse the key slot array:
* `psa_get_and_lock_key_slot_in_memory`: reads `slot->attr.id`.
* `psa_get_and_lock_key_slot_in_memory`: calls `psa_lock_key_slot` on one occupied slot.
* `psa_get_empty_key_slot`: calls `psa_is_key_slot_occupied`.
* `psa_get_empty_key_slot`: calls `psa_wipe_key_slot` and more modifications on one occupied slot with no active user.
* `psa_get_empty_key_slot`: calls `psa_lock_key_slot` and more modification on one unoccupied slot.
* `psa_wipe_all_key_slots`: writes to all slots.
* `mbedtls_psa_get_stats`: reads from all slots.
#### Key slot state
The following functions modify a slot's usage state:
* `psa_lock_key_slot`: writes to `slot->lock_count`.
* `psa_unlock_key_slot`: writes to `slot->lock_count`.
* `psa_wipe_key_slot`: writes to `slot->lock_count`.
* `psa_destroy_key`: reads `slot->lock_count`, calls `psa_lock_key_slot`.
* `psa_wipe_all_key_slots`: writes to all slots.
* `psa_get_empty_key_slot`: writes to `slot->lock_count` and calls `psa_wipe_key_slot` and `psa_lock_key_slot` on one occupied slot with no active user; calls `psa_lock_key_slot` on one unoccupied slot.
* `psa_close_key`: reads `slot->lock_count`; calls `psa_get_and_lock_key_slot_in_memory`, `psa_wipe_key_slot` and `psa_unlock_key_slot`.
* `psa_purge_key`: reads `slot->lock_count`; calls `psa_get_and_lock_key_slot_in_memory`, `psa_wipe_key_slot` and `psa_unlock_key_slot`.
**slot->attr access:**
`psa_crypto_core.h`:
* `psa_key_slot_set_flags` - writes to attr.flags
* `psa_key_slot_set_bits_in_flags` - writes to attr.flags
* `psa_key_slot_clear_bits` - writes to attr.flags
* `psa_is_key_slot_occupied` - reads attr.type (but see “[Determining whether a key slot is occupied](#determining-whether-a-key-slot-is-occupied)”)
* `psa_key_slot_get_flags` - reads attr.flags
`psa_crypto_slot_management.c`:
* `psa_get_and_lock_key_slot_in_memory` - reads attr.id
* `psa_get_empty_key_slot` - reads attr.lifetime
* `psa_load_persistent_key_into_slot` - passes attr pointer to psa_load_persistent_key
* `psa_load_persistent_key` - reads attr.id and passes pointer to psa_parse_key_data_from_storage
* `psa_parse_key_data_from_storage` - writes to many attributes
* `psa_get_and_lock_key_slot` - writes to attr.id, attr.lifetime, and attr.policy.usage
* `psa_purge_key` - reads attr.lifetime, calls psa_wipe_key_slot
* `mbedtls_psa_get_stats` - reads attr.lifetime, attr.id
`psa_crypto.c`:
* `psa_get_and_lock_key_slot_with_policy` - reads attr.type, attr.policy.
* `psa_get_and_lock_transparent_key_slot_with_policy` - reads attr.lifetime
* `psa_destroy_key` - reads attr.lifetime, attr.id
* `psa_get_key_attributes` - copies all publicly available attributes of a key
* `psa_export_key` - copies attributes
* `psa_export_public_key` - reads attr.type, copies attributes
* `psa_start_key_creation` - writes to the whole attr structure
* `psa_validate_optional_attributes` - reads attr.type, attr.bits
* `psa_import_key` - reads attr.bits
* `psa_copy_key` - reads attr.bits, attr.type, attr.lifetime, attr.policy
* `psa_mac_setup` - copies whole attr structure
* `psa_mac_compute_internal` - copies whole attr structure
* `psa_verify_internal` - copies whole attr structure
* `psa_sign_internal` - copies whole attr structure, reads attr.type
* `psa_assymmetric_encrypt` - reads attr.type
* `psa_assymetric_decrypt` - reads attr.type
* `psa_cipher_setup` - copies whole attr structure, reads attr.type
* `psa_cipher_encrypt` - copies whole attr structure, reads attr.type
* `psa_cipher_decrypt` - copies whole attr structure, reads attr.type
* `psa_aead_encrypt` - copies whole attr structure
* `psa_aead_decrypt` - copies whole attr structure
* `psa_aead_setup` - copies whole attr structure
* `psa_generate_derived_key_internal` - reads attr.type, writes to and reads from attr.bits, copies whole attr structure
* `psa_key_derivation_input_key` - reads attr.type
* `psa_key_agreement_raw_internal` - reads attr.type and attr.bits
#### Determining whether a key slot is occupied
`psa_is_key_slot_occupied` currently uses the `attr.type` field to determine whether a key slot is occupied. This works because we maintain the invariant that an occupied slot contains key material. With concurrency, it is desirable to allow a key slot to be reserved, but not yet contain key material or even metadata. When creating a key, determining the key type can be costly, for example when loading a persistent key from storage or (not yet implemented) when importing or unwrapping a key using an interface that determines the key type from the data that it parses. So we should not need to hold the global key store lock while the key type is undetermined.
Instead, `psa_is_key_slot_occupied` should use the key identifier to decide whether a slot is occupied. The key identifier is always readily available: when allocating a slot for a persistent key, it's an input of the function that allocates the key slot; when allocating a slot for a volatile key, the identifier is calculated from the choice of slot.
#### Key slot content
Other than what is used to determine the [“key slot state”](#key-slot-state), the contents of a key slot are only accessed as follows:
* Modification during key creation (between `psa_start_key_creation` and `psa_finish_key_creation` or `psa_fail_key_creation`).
* Destruction in `psa_wipe_key_slot`.
* Read in many functions, between calls to `psa_lock_key_slot` and `psa_unlock_key_slot`.
**slot->key access:**
* `psa_allocate_buffer_to_slot` - allocates key.data, sets key.bytes;
* `psa_copy_key_material_into_slot` - writes to key.data
* `psa_remove_key_data_from_memory` - writes and reads to/from key data
* `psa_get_key_attributes` - reads from key data
* `psa_export_key` - passes key data to psa_driver_wrapper_export_key
* `psa_export_public_key` - passes key data to psa_driver_wrapper_export_public_key
* `psa_finish_key_creation` - passes key data to psa_save_persistent_key
* `psa_validate_optional_attributes` - passes key data and bytes to mbedtls_psa_rsa_load_representation
* `psa_import_key` - passes key data to psa_driver_wrapper_import_key
* `psa_copy_key` - passes key data to psa_driver_wrapper_copy_key, psa_copy_key_material_into_slot
* `psa_mac_setup` - passes key data to psa_driver_wrapper_mac_sign_setup, psa_driver_wrapper_mac_verify_setup
* `psa_mac_compute_internal` - passes key data to psa_driver_wrapper_mac_compute
* `psa_sign_internal` - passes key data to psa_driver_wrapper_sign_message, psa_driver_wrapper_sign_hash
* `psa_verify_internal` - passes key data to psa_driver_wrapper_verify_message, psa_driver_wrapper_verify_hash
* `psa_asymmetric_encrypt` - passes key data to mbedtls_psa_rsa_load_representation
* `psa_asymmetric_decrypt` - passes key data to mbedtls_psa_rsa_load_representation
* `psa_cipher_setup ` - passes key data to psa_driver_wrapper_cipher_encrypt_setup and psa_driver_wrapper_cipher_decrypt_setup
* `psa_cipher_encrypt` - passes key data to psa_driver_wrapper_cipher_encrypt
* `psa_cipher_decrypt` - passes key data to psa_driver_wrapper_cipher_decrypt
* `psa_aead_encrypt` - passes key data to psa_driver_wrapper_aead_encrypt
* `psa_aead_decrypt` - passes key data to psa_driver_wrapper_aead_decrypt
* `psa_aead_setup` - passes key data to psa_driver_wrapper_aead_encrypt_setup and psa_driver_wrapper_aead_decrypt_setup
* `psa_generate_derived_key_internal` - passes key data to psa_driver_wrapper_import_key
* `psa_key_derivation_input_key` - passes key data to psa_key_derivation_input_internal
* `psa_key_agreement_raw_internal` - passes key data to mbedtls_psa_ecp_load_representation
* `psa_generate_key` - passes key data to psa_driver_wrapper_generate_key
### Random generator
The PSA RNG can be accessed both from various PSA functions, and from application code via `mbedtls_psa_get_random`.
With the built-in RNG implementations using `mbedtls_ctr_drbg_context` or `mbedtls_hmac_drbg_context`, querying the RNG with `mbedtls_xxx_drbg_random()` is thread-safe (protected by a mutex inside the RNG implementation), but other operations (init, free, seed) are not.
When `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is enabled, thread safety depends on the implementation.
### Driver resources
Depends on the driver. The PSA driver interface specification does not discuss whether drivers must support concurrent calls.
## Simple global lock strategy
Have a single mutex protecting all accesses to the key store and other global variables. In practice, this means every PSA API function needs to take the lock on entry and release on exit, except for:
* Hash function.
* Accessors for key attributes and other local structures.
Note that operation functions do need to take the lock, since they need to prevent the destruction of the key.
Note that this does not protect access to the RNG via `mbedtls_psa_get_random`, which is guaranteed to be thread-safe when `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is disabled.
This approach is conceptually simple, but requires extra instrumentation to every function and has bad performance in a multithreaded environment since a slow operation in one thread blocks unrelated operations on other threads.
## Global lock excluding slot content
Have a single mutex protecting all accesses to the key store and other global variables, except that it's ok to access the content of a key slot without taking the lock if one of the following conditions holds:
* The key slot is in a state that guarantees that the thread has exclusive access.
* The key slot is in a state that guarantees that no other thread can modify the slot content, and the accessing thread is only reading the slot.
Note that a thread must hold the global mutex when it reads or changes a slot's state.
### Slot states
For concurrency purposes, a slot can be in one of three states:
* UNUSED: no thread is currently accessing the slot. It may be occupied by a volatile key or a cached key.
* WRITING: a thread has exclusive access to the slot. This can only happen in specific circumstances as detailed below.
* READING: any thread may read from the slot.
A high-level view of state transitions:
* `psa_get_empty_key_slot`: UNUSED → WRITING.
* `psa_get_and_lock_key_slot_in_memory`: UNUSED or READING → READING. This function only accepts slots in the UNUSED or READING state. A slot with the correct id but in the WRITING state is considered free.
* `psa_unlock_key_slot`: READING → UNUSED or READING.
* `psa_finish_key_creation`: WRITING → READING.
* `psa_fail_key_creation`: WRITING → UNUSED.
* `psa_wipe_key_slot`: any → UNUSED. If the slot is READING or WRITING on entry, this function must wait until the writer or all readers have finished. (By the way, the WRITING state is possible if `mbedtls_psa_crypto_free` is called while a key creation is in progress.) See [“Destruction of a key in use”](#destruction of a key in use).
The current `state->lock_count` corresponds to the difference between UNUSED and READING: a slot is in use iff its lock count is nonzero, so `lock_count == 0` corresponds to UNUSED and `lock_count != 0` corresponds to READING.
There is currently no indication of when a slot is in the WRITING state. This only happens between a call to `psa_start_key_creation` and a call to one of `psa_finish_key_creation` or `psa_fail_key_creation`. This new state can be conveyed by a new boolean flag, or by setting `lock_count` to `~0`.
### Destruction of a key in use
Problem: a key slot is destroyed (by `psa_wipe_key_slot`) while it's in use (READING or WRITING).
TODO: how do we ensure that? This needs something more sophisticated than mutexes (concurrency number >2)! Even a per-slot mutex isn't enough (we'd need a reader-writer lock).
Solution: after some team discussion, we've decided to rely on a new threading abstraction which mimics C11 (i.e. `mbedtls_fff` where `fff` is the C11 function name, having the same parameters and return type, with default implementations for C11, pthreads and Windows). We'll likely use condition variables in addition to mutexes.

View file

@ -30,17 +30,23 @@ Each test case has a description which succinctly describes for a human audience
#### SSL test case descriptions
Each test case in `ssl-opt.sh` has a description which succinctly describes for a human audience what the test does. The test description is the first parameter to `run_tests`.
Each test case in `ssl-opt.sh` has a description which succinctly describes for a human audience what the test does. The test description is the first parameter to `run_test`.
The same rules and guidelines apply as for [unit test descriptions](#unit-test-descriptions). In addition, the description must be written on the same line as `run_test`, in double quotes, for the sake of `check_test_cases.py`.
### SSL cipher suite tests
Each test case in `compat.sh` has a description which succinctly describes for a human audience what the test does. The test description is `$TITLE` defined in `run_client`.
The same rules and guidelines apply as for [unit test descriptions](#unit-test-descriptions). In addition, failure cause in `compat.sh` is not classified as `ssl-opt.sh`, so the information of failed log files are followed as prompt.
## Running tests
### Outcome file
#### Generating an outcome file
Unit tests and `ssl-opt.sh` record the outcome of each test case in a **test outcome file**. This feature is enabled if the environment variable `MBEDTLS_TEST_OUTCOME_FILE` is set. Set it to the path of the desired file.
Unit tests, `ssl-opt.sh` and `compat.sh` record the outcome of each test case in a **test outcome file**. This feature is enabled if the environment variable `MBEDTLS_TEST_OUTCOME_FILE` is set. Set it to the path of the desired file.
If you run `all.sh --outcome-file test-outcome.csv`, this collects the outcome of all the test cases in `test-outcome.csv`.
@ -52,7 +58,7 @@ The outcome file has 6 fields:
* **Platform**: a description of the platform, e.g. `Linux-x86_64` or `Linux-x86_64-gcc7-msan`.
* **Configuration**: a unique description of the configuration (`mbedtls_config.h`).
* **Test suite**: `test_suite_xxx` or `ssl-opt`.
* **Test suite**: `test_suite_xxx`, `ssl-opt` or `compat`.
* **Test case**: the description of the test case.
* **Result**: one of `PASS`, `SKIP` or `FAIL`.
* **Cause**: more information explaining the result.

153
docs/driver-only-builds.md Normal file
View file

@ -0,0 +1,153 @@
This document explains how to create builds of Mbed TLS where some
cryptographic mechanisms are provided only by PSA drivers (that is, no
built-in implementation of those algorithms), from a user's perspective.
This is useful to save code size for people who are using either a hardware
accelerator, or an alternative software implementation that's more
aggressively optimized for code size than the default one in Mbed TLS.
General considerations
----------------------
This document assumes that you already have a working driver.
Otherwise, please see the [PSA driver example and
guide](psa-driver-example-and-guide.md) for information on writing a
driver.
In order to have some mechanism provided only by a driver, you'll want
the following compile-time configuration options enabled:
- `MBEDTLS_PSA_CRYPTO_C` (enabled by default) - this enables PSA Crypto.
- `MBEDTLS_USE_PSA_CRYPTO` (disabled by default) - this makes PK, X.509 and
TLS use PSA Crypto. You need to enable this if you're using PK, X.509 or TLS
and want them to have access to the algorithms provided by your driver. (See
[the dedicated document](use-psa-crypto.md) for details.)
- `MBEDTLS_PSA_CRYPTO_CONFIG` (disabled by default) - this enables
configuration of cryptographic algorithms using `PSA_WANT` macros in
`include/psa/crypto_config.h`. See [Conditional inclusion of cryptographic
mechanism through the PSA API in Mbed
TLS](proposed/psa-conditional-inclusion-c.md) for details.
In addition, for each mechanism you want provided only by your driver:
- Define the corresponding `PSA_WANT` macro in `psa/crypto_config.h` - this
means the algorithm will be available in the PSA Crypto API.
- Define the corresponding `MBEDTLS_PSA_ACCEL` in your build. This could be
defined in `psa/crypto_config.h` or your compiler's command line. This
informs the PSA code that an accelerator is available for this mechanism.
- Undefine / comment out the corresponding `MBEDTLS_xxx_C` macro in
`mbedtls/mbedtls_config.h`. This ensures the built-in implementation is not
included in the build.
For example, if you want SHA-256 to be provided only by a driver, you'll want
`PSA_WANT_ALG_SHA_256` and `MBEDTLS_PSA_ACCEL_SHA_256` defined, and
`MBEDTLS_SHA256_C` undefined.
In addition to these compile-time considerations, at runtime you'll need to
make sure you call `psa_crypto_init()` before any function that uses the
driver-only mechanisms. Note that this is already a requirement for any use of
the PSA Crypto API, as well as for use of the PK, X.509 and TLS modules when
`MBEDTLS_USE_PSA_CRYPTO` is enabled, so in most cases your application will
already be doing this.
Mechanisms covered
------------------
For now, only the following (families of) mechanisms are supported:
- hashes: SHA-3, SHA-2, SHA-1, MD5, etc.
- elliptic-curve cryptography (ECC): ECDH, ECDSA, EC J-PAKE, ECC key types.
- finite-field Diffie-Hellman: FFDH algorithm, DH key types.
Supported means that when those are provided only by drivers, everything
(including PK, X.509 and TLS if `MBEDTLS_USE_PSA_CRYPTO` is enabled) should
work in the same way as if the mechanisms where built-in, except as documented
in the "Limitations" sub-sections of the sections dedicated to each family
below.
In the near future (end of 2023), we are planning to also add support for
ciphers (AES) and AEADs (GCM, CCM, ChachaPoly).
Currently (mid-2023) we don't have plans to extend this to RSA. If
you're interested in driver-only support for RSA, please let us know.
Hashes
------
TODO
Elliptic-curve cryptography (ECC)
---------------------------------
Note: things are still evolving. This section describes the situation right
after #7452 has been merged. It will be updated again in #7757 when bignum is
done.
It is possible to have most ECC operations provided only by a driver:
- the ECDH, ECDSA and EC J-PAKE algorithms;
- key import, export, and random generation.
More precisely:
- you can enable `PSA_WANT_ALG_ECDH` without `MBEDTLS_ECDH_C` provided
`MBEDTLS_PSA_ACCEL_ALG_ECDH` is enabled;
- you can enable `PSA_WANT_ALG_ECDSA` without `MBEDTLS_ECDSA_C` provided
`MBEDTLS_PSA_ACCEL_ALG_ECDSA` is enabled;
- you can enable `PSA_WANT_ALG_JPAKE` without `MBEDTLS_ECJPAKE_C` provided
`MBEDTLS_PSA_ACCEL_ALG_JPAKE` is enabled.
In addition, if none of `MBEDTLS_ECDH_C`, `MBEDTLS_ECDSA_C`,
`MBEDTLS_ECJPAKE_C` are enabled, you can enable:
- `PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY`;
- `PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC`;
- `PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT`;
- `PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT`;
- `PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE`;
without `MBEDTLS_ECP_C` provided the corresponding
`MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx` are enabled.
[Coming soon] If `MBEDTLS_ECP_C` is disabled and `ecp.c` is fully removed (see
"Limitations regarding fully removing `ecp.c`" below), and you're not using
RSA or FFDH, then you can also disable `MBEDTLS_BIGNUM_C` for further code
size saving.
### Limitations regarding fully removing `ecp.c`
A limited subset of `ecp.c` will still be automatically re-enabled if any of
the following is enabled:
- `MBEDTLS_PK_PARSE_EC_COMPRESSED` - support for parsing ECC keys where the
public part is in compressed format;
- `MBEDTLS_PK_PARSE_EC_EXTENDED` - support for parsing ECC keys where the
curve is identified not by name, but by explicit parameters;
- `PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE` - support for deterministic
derivation of an ECC keypair with `psa_key_derivation_output_key()`.
Note: when any of the above options is enabled, a subset of `ecp.c` will
automatically be included in the build in order to support it. Therefore
you can still disable `MBEDTLS_ECP_C` in `mbedtls_config.h` and this will
result in some code size savings, but not as much as when none of the
above features are enabled.
We do have plans to support each of these with `ecp.c` fully removed in the
future, however there is no established timeline. If you're interested, please
let us know, so we can take it into consideration in our planning.
### Limitations regarding restartable / interruptible ECC operations
At the moment, there is not driver support for interruptible operations
(see `psa_sign_hash_start()` + `psa_sign_hash_complete()` etc.) so as a
consequence these are not supported in builds without `MBEDTLS_ECDSA_C`.
Similarly, there is no PSA support for interruptible ECDH operations so these
are not supported without `ECDH_C`. See also limitations regarding
restartable operations with `MBEDTLS_USE_PSA_CRYPTO` in [its
documentation](use-psa-crypto.md).
Again, we have plans to support this in the future but not with an established
timeline, please let us know if you're interested.
### Limitations regarding the selection of curves
TODO: apparently we don't really support having some curves built-in and
others driver-only... investigate and describe the situation. See also #7899.
Finite-field Diffie-Hellman
---------------------------
TODO

View file

@ -2,6 +2,7 @@ PSA Cryptoprocessor driver developer's guide
============================================
**This is a specification of work in progress. The implementation is not yet merged into Mbed TLS.**
For a description of the current state of drivers Mbed TLS, see our [PSA Cryptoprocessor driver development examples](../psa-driver-example-and-guide.html).
This document describes how to write drivers of cryptoprocessors such as accelerators and secure elements for the PSA cryptography subsystem of Mbed TLS.

View file

@ -2,6 +2,7 @@ Building Mbed TLS with PSA cryptoprocessor drivers
==================================================
**This is a specification of work in progress. The implementation is not yet merged into Mbed TLS.**
For a description of the current state of drivers Mbed TLS, see our [PSA Cryptoprocessor driver development examples](../psa-driver-example-and-guide.html).
This document describes how to build Mbed TLS with additional cryptoprocessor drivers that follow the PSA cryptoprocessor driver interface.

View file

@ -5,6 +5,8 @@ This document describes an interface for cryptoprocessor drivers in the PSA cryp
This specification is work in progress and should be considered to be in a beta stage. There is ongoing work to implement this interface in Mbed TLS, which is the reference implementation of the PSA Cryptography API. At this stage, Arm does not expect major changes, but minor changes are expected based on experience from the first implementation and on external feedback.
For a practical guide, with a description of the current state of drivers Mbed TLS, see our [PSA Cryptoprocessor driver development examples](../psa-driver-example-and-guide.html).
## Introduction
### Purpose of the driver interface

View file

@ -1,11 +1,11 @@
Migrating to an auto generated psa_crypto_driver_wrappers.c file
================================================================
**This is a specification of work in progress. The implementation is not yet merged into Mbed TLS.**
This document describes how to migrate to the auto generated psa_crypto_driver_wrappers.c file.
It is meant to give the library user migration guidelines while the Mbed TLS project tides over multiple minor revs of version 1.0, after which this will be merged into psa-driver-interface.md.
For a practical guide with a description of the current state of drivers Mbed TLS, see our [PSA Cryptoprocessor driver development examples](../psa-driver-example-and-guide.html).
## Introduction
The design of the Driver Wrappers code generation is based on the design proposal https://github.com/Mbed-TLS/mbedtls/pull/5067

View file

@ -29,8 +29,8 @@ Auto-generation of the driver wrapper is supported for the operation entry point
| Transparent Driver | Opaque Driver |
|---------------------|---------------------|
| `import_key` | `import_key` |
| `export_key` | `export_key` |
| `export_public_key` | `export_public_key` |
| | `export_key` |
| | `copy_key` |
| | `get_builtin_key` |

View file

@ -22,7 +22,7 @@
*/
/**
* @mainpage Mbed TLS v3.4.0 API Documentation
* @mainpage Mbed TLS v3.4.1 API Documentation
*
* This documentation describes the internal structure of Mbed TLS. It was
* automatically generated from specially formatted comment blocks in

View file

@ -1,4 +1,4 @@
PROJECT_NAME = "mbed TLS v3.4.0"
PROJECT_NAME = "mbed TLS v3.4.1"
OUTPUT_DIRECTORY = ../apidoc/
FULL_PATH_NAMES = NO
OPTIMIZE_OUTPUT_FOR_C = YES
@ -51,4 +51,5 @@ PREDEFINED = "MBEDTLS_CHECK_RETURN_CRITICAL=" \
"MBEDTLS_CHECK_RETURN_TYPICAL=" \
"MBEDTLS_CHECK_RETURN_OPTIONAL=" \
"MBEDTLS_PRINTF_ATTRIBUTE(a,b)=" \
"__DOXYGEN__" \

View file

@ -259,10 +259,6 @@ int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx,
* \brief This function performs an ARIA-CTR encryption or decryption
* operation.
*
* This function performs the operation defined in the \p mode
* parameter (encrypt/decrypt), on the input data buffer
* defined in the \p input parameter.
*
* Due to the nature of CTR, you must use the same key schedule
* for both encryption and decryption operations. Therefore, you
* must use the context initialized with mbedtls_aria_setkey_enc()

View file

@ -474,7 +474,7 @@ void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq);
* on a successful invocation.
* \param end The end of the ASN.1 SEQUENCE container.
* \param tag_must_mask A mask to be applied to the ASN.1 tags found within
* the SEQUENCE before comparing to \p tag_must_value.
* the SEQUENCE before comparing to \p tag_must_val.
* \param tag_must_val The required value of each ASN.1 tag found in the
* SEQUENCE, after masking with \p tag_must_mask.
* Mismatching tags lead to an error.
@ -483,7 +483,7 @@ void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq);
* while a value of \c 0xFF for \p tag_must_mask means
* that \p tag_must_val is the only allowed tag.
* \param tag_may_mask A mask to be applied to the ASN.1 tags found within
* the SEQUENCE before comparing to \p tag_may_value.
* the SEQUENCE before comparing to \p tag_may_val.
* \param tag_may_val The desired value of each ASN.1 tag found in the
* SEQUENCE, after masking with \p tag_may_mask.
* Mismatching tags will be silently ignored.

View file

@ -129,6 +129,7 @@
#endif /* !MBEDTLS_HAVE_INT64 */
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#define MBEDTLS_MPI_UINT_MAX UINT64_MAX
#elif defined(__GNUC__) && ( \
defined(__amd64__) || defined(__x86_64__) || \
defined(__ppc64__) || defined(__powerpc64__) || \
@ -141,6 +142,7 @@ typedef uint64_t mbedtls_mpi_uint;
#endif /* MBEDTLS_HAVE_INT64 */
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#define MBEDTLS_MPI_UINT_MAX UINT64_MAX
#if !defined(MBEDTLS_NO_UDBL_DIVISION)
/* mbedtls_t_udbl defined as 128-bit unsigned int */
typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
@ -156,6 +158,7 @@ typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
#endif /* !MBEDTLS_HAVE_INT64 */
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#define MBEDTLS_MPI_UINT_MAX UINT64_MAX
#if !defined(MBEDTLS_NO_UDBL_DIVISION)
/* mbedtls_t_udbl defined as 128-bit unsigned int */
typedef __uint128_t mbedtls_t_udbl;
@ -165,6 +168,7 @@ typedef __uint128_t mbedtls_t_udbl;
/* Force 64-bit integers with unknown compiler */
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#define MBEDTLS_MPI_UINT_MAX UINT64_MAX
#endif
#endif /* !MBEDTLS_HAVE_INT32 */
@ -175,6 +179,7 @@ typedef uint64_t mbedtls_mpi_uint;
#endif /* !MBEDTLS_HAVE_INT32 */
typedef int32_t mbedtls_mpi_sint;
typedef uint32_t mbedtls_mpi_uint;
#define MBEDTLS_MPI_UINT_MAX UINT32_MAX
#if !defined(MBEDTLS_NO_UDBL_DIVISION)
typedef uint64_t mbedtls_t_udbl;
#define MBEDTLS_HAVE_UDBL
@ -203,6 +208,12 @@ extern "C" {
* \brief MPI structure
*/
typedef struct mbedtls_mpi {
/** Pointer to limbs.
*
* This may be \c NULL if \c n is 0.
*/
mbedtls_mpi_uint *MBEDTLS_PRIVATE(p);
/** Sign: -1 if the mpi is negative, 1 otherwise.
*
* The number 0 must be represented with `s = +1`. Although many library
@ -214,16 +225,19 @@ typedef struct mbedtls_mpi {
* Note that this implies that calloc() or `... = {0}` does not create
* a valid MPI representation. You must call mbedtls_mpi_init().
*/
int MBEDTLS_PRIVATE(s);
signed short MBEDTLS_PRIVATE(s);
/** Total number of limbs in \c p. */
size_t MBEDTLS_PRIVATE(n);
/** Pointer to limbs.
*
* This may be \c NULL if \c n is 0.
unsigned short MBEDTLS_PRIVATE(n);
/* Make sure that MBEDTLS_MPI_MAX_LIMBS fits in n.
* Use the same limit value on all platforms so that we don't have to
* think about different behavior on the rare platforms where
* unsigned short can store values larger than the minimum required by
* the C language, which is 65535.
*/
mbedtls_mpi_uint *MBEDTLS_PRIVATE(p);
#if MBEDTLS_MPI_MAX_LIMBS > 65535
#error "MBEDTLS_MPI_MAX_LIMBS > 65535 is not supported"
#endif
}
mbedtls_mpi;
@ -530,7 +544,7 @@ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X,
* \param X The destination MPI. This must point to an initialized MPI.
* \param buf The input buffer. This must be a readable buffer of length
* \p buflen Bytes.
* \param buflen The length of the input buffer \p p in Bytes.
* \param buflen The length of the input buffer \p buf in Bytes.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
@ -545,7 +559,7 @@ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf,
* \param X The destination MPI. This must point to an initialized MPI.
* \param buf The input buffer. This must be a readable buffer of length
* \p buflen Bytes.
* \param buflen The length of the input buffer \p p in Bytes.
* \param buflen The length of the input buffer \p buf in Bytes.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
@ -985,8 +999,8 @@ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A,
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than
* or equal to one.
* \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse
* with respect to \p N.
* \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p A has no modular
* inverse with respect to \p N.
*/
int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *N);

View file

@ -38,16 +38,16 @@
*/
#define MBEDTLS_VERSION_MAJOR 3
#define MBEDTLS_VERSION_MINOR 4
#define MBEDTLS_VERSION_PATCH 0
#define MBEDTLS_VERSION_PATCH 1
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
#define MBEDTLS_VERSION_NUMBER 0x03040000
#define MBEDTLS_VERSION_STRING "3.4.0"
#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 3.4.0"
#define MBEDTLS_VERSION_NUMBER 0x03040100
#define MBEDTLS_VERSION_STRING "3.4.1"
#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 3.4.1"
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
#define _CRT_SECURE_NO_DEPRECATE 1
@ -59,6 +59,7 @@
#define inline __inline
#endif
/* X.509, TLS and non-PSA crypto configuration */
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/mbedtls_config.h"
#else
@ -80,6 +81,18 @@
#include MBEDTLS_USER_CONFIG_FILE
#endif
/* PSA crypto configuration */
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE)
#include MBEDTLS_PSA_CRYPTO_CONFIG_FILE
#else
#include "psa/crypto_config.h"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE)
#include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE
#endif
#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */
/* Auto-enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY if
* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH and MBEDTLS_CTR_DRBG_C defined
* to ensure a 128-bit key size in CTR_DRBG.
@ -161,6 +174,37 @@
#define MBEDTLS_PK_PARSE_EC_COMPRESSED
#endif
/* Helper symbol to state that there is support for ECDH, either through
* library implementation (ECDH_C) or through PSA. */
#if (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_ECDH)) || \
(!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C))
#define MBEDTLS_CAN_ECDH
#endif
/* PK module can achieve ECDSA functionalities by means of either software
* implementations (ECDSA_C) or through a PSA driver. The following defines
* are meant to list these capabilities in a general way which abstracts how
* they are implemented under the hood. */
#if !defined(MBEDTLS_USE_PSA_CRYPTO)
#if defined(MBEDTLS_ECDSA_C)
#define MBEDTLS_PK_CAN_ECDSA_SIGN
#define MBEDTLS_PK_CAN_ECDSA_VERIFY
#endif /* MBEDTLS_ECDSA_C */
#else /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(PSA_WANT_ALG_ECDSA)
#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)
#define MBEDTLS_PK_CAN_ECDSA_SIGN
#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */
#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
#define MBEDTLS_PK_CAN_ECDSA_VERIFY
#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
#endif /* PSA_WANT_ALG_ECDSA */
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
#define MBEDTLS_PK_CAN_ECDSA_SOME
#endif
/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT
* is defined as well to include all PSA code.
*/
@ -177,6 +221,14 @@
#define MBEDTLS_PK_PARSE_C
#endif
/* Helper symbol to state that the PK module has support for EC keys. This
* can either be provided through the legacy ECP solution or through the
* PSA friendly MBEDTLS_PK_USE_PSA_EC_DATA (see pk.h for its description). */
#if defined(MBEDTLS_ECP_C) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))
#define MBEDTLS_PK_HAVE_ECC_KEYS
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */
/* The following blocks make it easier to disable all of TLS,
* or of TLS 1.2 or 1.3 or DTLS, without having to manually disable all
* key exchanges, options and extensions related to them. */
@ -222,14 +274,10 @@
#undef MBEDTLS_SSL_EARLY_DATA
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
(defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED))
#define MBEDTLS_SSL_TLS1_2_SOME_ECC
#endif
/* Make sure all configuration symbols are set before including check_config.h,

View file

@ -220,7 +220,7 @@ int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx,
* *note Due to the nature of CTR mode, you should use the same
* key for both encryption and decryption. In particular, calls
* to this function should be preceded by a key-schedule via
* mbedtls_camellia_setkey_enc() regardless of whether \p mode
* mbedtls_camellia_setkey_enc() regardless of whether the mode
* is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
*
* \warning You must never reuse a nonce value with the same key. Doing so

View file

@ -35,7 +35,7 @@
#include <stdint.h>
#if defined(_WIN32)
#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900)
#if !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_C is required on Windows"
#endif
@ -51,7 +51,7 @@
!defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
#endif
#endif /* _WIN32 */
#endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */
#if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C)
#error "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS"
@ -275,22 +275,9 @@
#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites"
#endif
/* Helper for ECDSA dependencies, will be undefined at the end of the file */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if (defined(PSA_WANT_ALG_ECDSA) || \
defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)) && \
defined(MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_LEGACY)
#define MBEDTLS_PK_HAVE_ECDSA
#endif
#else /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_ECDSA_C)
#define MBEDTLS_PK_HAVE_ECDSA
#endif
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* Helper for JPAKE dependencies, will be undefined at the end of the file */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if defined(PSA_WANT_ALG_JPAKE) && defined(MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_LEGACY)
#if defined(PSA_WANT_ALG_JPAKE) && defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)
#define MBEDTLS_PK_HAVE_JPAKE
#endif
#else /* MBEDTLS_USE_PSA_CRYPTO */
@ -299,17 +286,6 @@
#endif
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* Helper for ECDH dependencies, will be undefined at the end of the file */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if defined(PSA_WANT_ALG_ECDH) && defined(MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_LEGACY)
#define MBEDTLS_PK_HAVE_ECDH
#endif
#else /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_ECDH_C)
#define MBEDTLS_PK_HAVE_ECDH
#endif
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* Helper for curve SECP256R1 */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if defined(PSA_WANT_ECC_SECP_R1_256)
@ -322,14 +298,14 @@
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \
( !defined(MBEDTLS_PK_HAVE_ECDH) || \
!defined(MBEDTLS_PK_HAVE_ECDSA) || \
( !defined(MBEDTLS_CAN_ECDH) || \
!defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
( !defined(MBEDTLS_PK_HAVE_ECDH) || !defined(MBEDTLS_RSA_C) || \
( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
#endif
@ -339,7 +315,7 @@
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \
!defined(MBEDTLS_PK_HAVE_ECDH)
!defined(MBEDTLS_CAN_ECDH)
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
#endif
@ -350,14 +326,14 @@
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
( !defined(MBEDTLS_PK_HAVE_ECDH) || !defined(MBEDTLS_RSA_C) || \
( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \
( !defined(MBEDTLS_PK_HAVE_ECDH) || \
!defined(MBEDTLS_PK_HAVE_ECDSA) || \
( !defined(MBEDTLS_CAN_ECDH) || \
!defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
#endif
@ -436,10 +412,6 @@
#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C)
#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites"
#endif
@ -449,7 +421,7 @@
#endif
#if defined(MBEDTLS_PK_C) && \
!defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_LIGHT)
!defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_PK_HAVE_ECC_KEYS)
#error "MBEDTLS_PK_C defined, but not all prerequisites"
#endif
@ -814,14 +786,15 @@
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
#if !( defined(PSA_WANT_ALG_ECDH) && defined(MBEDTLS_X509_CRT_PARSE_C) && \
( defined(MBEDTLS_PK_HAVE_ECDSA) || defined(MBEDTLS_PKCS1_V21) ) )
#if !( (defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)) && \
defined(MBEDTLS_X509_CRT_PARSE_C) && \
( defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || defined(MBEDTLS_PKCS1_V21) ) )
#error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites"
#endif
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
#if !( defined(PSA_WANT_ALG_ECDH) )
#if !( defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) )
#error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites"
#endif
#endif
@ -1009,15 +982,15 @@
#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \
#if defined(MBEDTLS_X509_USE_C) && \
(!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \
!defined(MBEDTLS_PK_PARSE_C) || \
( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) )
#error "MBEDTLS_X509_USE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \
#if defined(MBEDTLS_X509_CREATE_C) && \
(!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \
!defined(MBEDTLS_PK_PARSE_C) || \
( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) )
#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites"
@ -1122,16 +1095,14 @@
#if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \
( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \
( !defined(MBEDTLS_X509_CRT_PARSE_C) ) ||\
( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || ( !defined(MBEDTLS_BIGNUM_C) ) || \
( !defined(MBEDTLS_X509_CRT_PARSE_C) ) || \
( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || \
( !defined(MBEDTLS_MD_C) ) )
#error "MBEDTLS_PKCS7_C is defined, but not all prerequisites"
#endif
/* Undefine helper symbols */
#undef MBEDTLS_PK_HAVE_ECDSA
#undef MBEDTLS_PK_HAVE_JPAKE
#undef MBEDTLS_PK_HAVE_ECDH
#undef MBEDTLS_MD_HAVE_SHA256
#undef MBEDTLS_MD_HAVE_SHA384
#undef MBEDTLS_MD_HAVE_SHA512

View file

@ -270,45 +270,58 @@ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
* mbedtls_cipher_info_from_type(),
* mbedtls_cipher_info_from_values(),
* mbedtls_cipher_info_from_psa().
*
* \note Some fields store a value that has been right-shifted to save
* code-size, so should not be used directly. The accessor
* functions adjust for this and return the "natural" value.
*/
typedef struct mbedtls_cipher_info_t {
/** Full cipher identifier. For example,
* MBEDTLS_CIPHER_AES_256_CBC.
*/
mbedtls_cipher_type_t MBEDTLS_PRIVATE(type);
/** The cipher mode. For example, MBEDTLS_MODE_CBC. */
mbedtls_cipher_mode_t MBEDTLS_PRIVATE(mode);
/** The cipher key length, in bits. This is the
* default length for variable sized ciphers.
* Includes parity bits for ciphers like DES.
*/
unsigned int MBEDTLS_PRIVATE(key_bitlen);
/** Name of the cipher. */
const char *MBEDTLS_PRIVATE(name);
/** IV or nonce size, in Bytes.
/** The block size, in bytes. */
unsigned int MBEDTLS_PRIVATE(block_size) : 5;
/** IV or nonce size, in bytes (right shifted by #MBEDTLS_IV_SIZE_SHIFT).
* For ciphers that accept variable IV sizes,
* this is the recommended size.
*/
unsigned int MBEDTLS_PRIVATE(iv_size);
unsigned int MBEDTLS_PRIVATE(iv_size) : 3;
/** The cipher key length, in bits (right shifted by #MBEDTLS_KEY_BITLEN_SHIFT).
* This is the default length for variable sized ciphers.
* Includes parity bits for ciphers like DES.
*/
unsigned int MBEDTLS_PRIVATE(key_bitlen) : 4;
/** The cipher mode (as per mbedtls_cipher_mode_t).
* For example, MBEDTLS_MODE_CBC.
*/
unsigned int MBEDTLS_PRIVATE(mode) : 4;
/** Full cipher identifier (as per mbedtls_cipher_type_t).
* For example, MBEDTLS_CIPHER_AES_256_CBC.
*
* This could be 7 bits, but 8 bits retains byte alignment for the
* next field, which reduces code size to access that field.
*/
unsigned int MBEDTLS_PRIVATE(type) : 8;
/** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and
* MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the
* cipher supports variable IV or variable key sizes, respectively.
*/
int MBEDTLS_PRIVATE(flags);
unsigned int MBEDTLS_PRIVATE(flags) : 2;
/** The block size, in Bytes. */
unsigned int MBEDTLS_PRIVATE(block_size);
/** Struct for base cipher information and functions. */
const mbedtls_cipher_base_t *MBEDTLS_PRIVATE(base);
/** Index to LUT for base cipher information and functions. */
unsigned int MBEDTLS_PRIVATE(base_idx) : 5;
} mbedtls_cipher_info_t;
/* For internal use only.
* These are used to more compactly represent the fields above. */
#define MBEDTLS_KEY_BITLEN_SHIFT 6
#define MBEDTLS_IV_SIZE_SHIFT 2
/**
* Generic cipher context.
*/
@ -353,7 +366,7 @@ typedef struct mbedtls_cipher_context_t {
mbedtls_cmac_context_t *MBEDTLS_PRIVATE(cmac_ctx);
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
/** Indicates whether the cipher operations should be performed
* by Mbed TLS' own crypto library or an external implementation
* of the PSA Crypto API.
@ -362,7 +375,7 @@ typedef struct mbedtls_cipher_context_t {
* mbedtls_cipher_setup_psa().
*/
unsigned char MBEDTLS_PRIVATE(psa_enabled);
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
} mbedtls_cipher_context_t;
@ -439,7 +452,7 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type(
if (info == NULL) {
return MBEDTLS_CIPHER_NONE;
} else {
return info->MBEDTLS_PRIVATE(type);
return (mbedtls_cipher_type_t) info->MBEDTLS_PRIVATE(type);
}
}
@ -458,7 +471,7 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode(
if (info == NULL) {
return MBEDTLS_MODE_NONE;
} else {
return info->MBEDTLS_PRIVATE(mode);
return (mbedtls_cipher_mode_t) info->MBEDTLS_PRIVATE(mode);
}
}
@ -479,7 +492,7 @@ static inline size_t mbedtls_cipher_info_get_key_bitlen(
if (info == NULL) {
return 0;
} else {
return info->MBEDTLS_PRIVATE(key_bitlen);
return info->MBEDTLS_PRIVATE(key_bitlen) << MBEDTLS_KEY_BITLEN_SHIFT;
}
}
@ -492,7 +505,7 @@ static inline size_t mbedtls_cipher_info_get_key_bitlen(
*
* \return The cipher name, which is a human readable string,
* with static storage duration.
* \return \c NULL if \c info is \p NULL.
* \return \c NULL if \p info is \c NULL.
*/
static inline const char *mbedtls_cipher_info_get_name(
const mbedtls_cipher_info_t *info)
@ -521,7 +534,7 @@ static inline size_t mbedtls_cipher_info_get_iv_size(
return 0;
}
return (size_t) info->MBEDTLS_PRIVATE(iv_size);
return ((size_t) info->MBEDTLS_PRIVATE(iv_size)) << MBEDTLS_IV_SIZE_SHIFT;
}
/**
@ -541,7 +554,7 @@ static inline size_t mbedtls_cipher_info_get_block_size(
return 0;
}
return (size_t) info->MBEDTLS_PRIVATE(block_size);
return (size_t) (info->MBEDTLS_PRIVATE(block_size));
}
/**
@ -583,7 +596,7 @@ static inline int mbedtls_cipher_info_has_variable_iv_size(
}
/**
* \brief This function initializes a \p cipher_context as NONE.
* \brief This function initializes a \p ctx as NONE.
*
* \param ctx The context to be initialized. This must not be \c NULL.
*/
@ -682,7 +695,7 @@ static inline unsigned int mbedtls_cipher_get_block_size(
return 0;
}
return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size);
return (unsigned int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size);
}
/**
@ -702,7 +715,7 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(
return MBEDTLS_MODE_NONE;
}
return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode);
return (mbedtls_cipher_mode_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode);
}
/**
@ -727,7 +740,8 @@ static inline int mbedtls_cipher_get_iv_size(
return (int) ctx->MBEDTLS_PRIVATE(iv_size);
}
return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size);
return (int) (((int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size)) <<
MBEDTLS_IV_SIZE_SHIFT);
}
/**
@ -747,7 +761,7 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(
return MBEDTLS_CIPHER_NONE;
}
return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type);
return (mbedtls_cipher_type_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type);
}
/**
@ -776,7 +790,7 @@ static inline const char *mbedtls_cipher_get_name(
* \param ctx The context of the cipher. This must be initialized.
*
* \return The key length of the cipher in bits.
* \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been
* \return #MBEDTLS_KEY_LENGTH_NONE if \p ctx has not been
* initialized.
*/
static inline int mbedtls_cipher_get_key_bitlen(
@ -788,7 +802,8 @@ static inline int mbedtls_cipher_get_key_bitlen(
return MBEDTLS_KEY_LENGTH_NONE;
}
return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen);
return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen) <<
MBEDTLS_KEY_BITLEN_SHIFT;
}
/**
@ -975,7 +990,7 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx,
* \param ctx The generic cipher context. This must be initialized and
* bound to a key.
* \param output The buffer to write data to. This needs to be a writable
* buffer of at least \p block_size Bytes.
* buffer of at least block_size Bytes.
* \param olen The length of the data written to the \p output buffer.
* This may not be \c NULL.
*

View file

@ -30,24 +30,8 @@
#ifndef MBEDTLS_CONFIG_PSA_H
#define MBEDTLS_CONFIG_PSA_H
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE)
#include MBEDTLS_PSA_CRYPTO_CONFIG_FILE
#else
#include "psa/crypto_config.h"
#endif
#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */
#if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE)
#include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE
#endif
#include "psa/crypto_legacy.h"
#ifdef __cplusplus
extern "C" {
#endif
/****************************************************************/
@ -273,6 +257,7 @@ extern "C" {
#if defined(PSA_WANT_ALG_PBKDF2_HMAC)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC)
#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1
#define PSA_HAVE_SOFT_PBKDF2_HMAC
#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */
@ -438,13 +423,21 @@ extern "C" {
#define PSA_HAVE_SOFT_BLOCK_AEAD 1
#endif
#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128)
#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 1
#define PSA_HAVE_SOFT_PBKDF2_CMAC
#endif /* !MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128 */
#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */
#if defined(PSA_WANT_KEY_TYPE_AES)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
#define PSA_HAVE_SOFT_KEY_TYPE_AES 1
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */
#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
defined(PSA_HAVE_SOFT_BLOCK_MODE) || \
defined(PSA_HAVE_SOFT_BLOCK_AEAD)
defined(PSA_HAVE_SOFT_BLOCK_AEAD) || \
defined(PSA_HAVE_SOFT_PBKDF2_CMAC)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1
#define MBEDTLS_AES_C
#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */
@ -515,12 +508,18 @@ extern "C" {
#if defined(PSA_WANT_ALG_CMAC)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
defined(PSA_HAVE_SOFT_BLOCK_CIPHER) || \
defined(PSA_HAVE_SOFT_PBKDF2_CMAC)
#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1
#define MBEDTLS_CMAC_C
#endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */
#endif /* PSA_WANT_ALG_CMAC */
#if defined(PSA_HAVE_SOFT_PBKDF2_HMAC) || \
defined(PSA_HAVE_SOFT_PBKDF2_CMAC)
#define PSA_HAVE_SOFT_PBKDF2 1
#endif /* PSA_HAVE_SOFT_PBKDF2_HMAC || PSA_HAVE_SOFT_PBKDF2_CMAC */
#if defined(PSA_WANT_ALG_CTR)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
@ -743,10 +742,16 @@ extern "C" {
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
/* Normally we wouldn't enable this because it's not implemented in ecp.c,
* but since it used to be available any time ECP_C was enabled, let's enable
* it anyway for the sake of backwards compatibility */
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
/* See comment for PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE above. */
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
#endif /* MBEDTLS_ECP_C */
@ -828,14 +833,16 @@ extern "C" {
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1
#define PSA_WANT_ALG_RSA_PSS 1
#endif /* MBEDTLS_PKCS1_V21 */
#if defined(MBEDTLS_GENPRIME)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
#endif /* MBEDTLS_GENPRIME */
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1
#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1
#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
#endif /* MBEDTLS_RSA_C */
@ -1003,54 +1010,46 @@ extern "C" {
#define PSA_WANT_ALG_SOME_PAKE 1
#endif
/* Temporary internal migration helpers */
#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \
defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
#define MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_LEGACY
/* Even though KEY_PAIR symbols' feature several level of support (BASIC, IMPORT,
* EXPORT, GENERATE, DERIVE) we're not planning to have support only for BASIC
* without IMPORT/EXPORT since these last 2 features are strongly used in tests.
* In general it is allowed to include more feature than what is strictly
* requested.
* As a consequence IMPORT and EXPORT features will be automatically enabled
* as soon as the BASIC one is. */
#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
#endif
/* Temporary internal migration helpers */
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
#define MBEDTLS_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_LEGACY
/* See description above */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
#endif
/* Temporary internal migration helpers */
#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \
defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
#define MBEDTLS_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_LEGACY
/* See description above */
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
#endif
/* Temporary internal migration helpers */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_LEGACY
/* See description above */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
#endif
/* Temporary internal migration helpers */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_LEGACY
/* See description above */
#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC)
#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1
#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1
#endif
/* Temporary internal migration helpers */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_LEGACY
/* See description above */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1
#endif
/* These features are always enabled. */
@ -1059,8 +1058,4 @@ extern "C" {
#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1
#define PSA_WANT_KEY_TYPE_RAW_DATA 1
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CONFIG_PSA_H */

View file

@ -23,20 +23,22 @@
#include <stddef.h>
/** Constant-time buffer comparison without branches.
*
* This is equivalent to the standard memcmp function, but is likely to be
* compiled to code using bitwise operation rather than a branch.
* compiled to code using bitwise operations rather than a branch, such that
* the time taken is constant w.r.t. the data pointed to by \p a and \p b,
* and w.r.t. whether \p a and \p b are equal or not. It is not constant-time
* w.r.t. \p n .
*
* This function can be used to write constant-time code by replacing branches
* with bit operations using masks.
*
* \param a Pointer to the first buffer.
* \param b Pointer to the second buffer.
* \param n The number of bytes to compare in the buffer.
* \param a Pointer to the first buffer, containing at least \p n bytes. May not be NULL.
* \param b Pointer to the second buffer, containing at least \p n bytes. May not be NULL.
* \param n The number of bytes to compare.
*
* \return Zero if the content of the two buffer is the same,
* \return Zero if the contents of the two buffers are the same,
* otherwise non-zero.
*/
int mbedtls_ct_memcmp(const void *a,

View file

@ -280,7 +280,10 @@ void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,
const char *text, const mbedtls_x509_crt *crt);
#endif
#if defined(MBEDTLS_ECDH_C)
/* Note: the MBEDTLS_ECDH_C guard here is mandatory because this debug function
only works for the built-in implementation. */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \
defined(MBEDTLS_ECDH_C)
typedef enum {
MBEDTLS_DEBUG_ECDH_Q,
MBEDTLS_DEBUG_ECDH_QP,
@ -307,7 +310,8 @@ void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const mbedtls_ecdh_context *ecdh,
mbedtls_debug_ecdh_attr attr);
#endif
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED &&
MBEDTLS_ECDH_C */
#ifdef __cplusplus
}

View file

@ -325,7 +325,7 @@ size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx);
* initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p field is invalid.
* \return #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p param is invalid.
* \return An \c MBEDTLS_ERR_MPI_XXX error code if the copy fails.
*/
int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,

View file

@ -207,8 +207,9 @@ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
* \param md_alg The hash algorithm used to hash the original data.
* \param f_rng_blind The RNG function used for blinding. This must not be
* \c NULL.
* \param p_rng_blind The RNG context to be passed to \p f_rng. This may be
* \c NULL if \p f_rng doesn't need a context parameter.
* \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This
* may be \c NULL if \p f_rng_blind doesn't need a context
* parameter.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
@ -326,8 +327,8 @@ int mbedtls_ecdsa_sign_restartable(
* \param md_alg The hash algorithm used to hash the original data.
* \param f_rng_blind The RNG function used for blinding. This must not be
* \c NULL.
* \param p_rng_blind The RNG context to be passed to \p f_rng. This may be
* \c NULL if \p f_rng doesn't need a context parameter.
* \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This may be
* \c NULL if \p f_rng_blind doesn't need a context parameter.
* \param rs_ctx The restart context to use. This may be \c NULL
* to disable restarting. If it is not \c NULL, it
* must point to an initialized restart context.
@ -459,7 +460,7 @@ int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
* via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
* \param md_alg The message digest that was used to hash the message.
* \param hash The message hash to be signed. This must be a readable
* buffer of length \p blen Bytes.
* buffer of length \p hlen Bytes.
* \param hlen The length of the hash \p hash in Bytes.
* \param sig The buffer to which to write the signature. This must be a
* writable buffer of length at least twice as large as the
@ -502,7 +503,7 @@ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
* via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
* \param md_alg The message digest that was used to hash the message.
* \param hash The message hash to be signed. This must be a readable
* buffer of length \p blen Bytes.
* buffer of length \p hlen Bytes.
* \param hlen The length of the hash \p hash in Bytes.
* \param sig The buffer to which to write the signature. This must be a
* writable buffer of length at least twice as large as the
@ -549,7 +550,7 @@ int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
* \param ctx The ECDSA context to use. This must be initialized
* and have a group and public key bound to it.
* \param hash The message hash that was signed. This must be a readable
* buffer of length \p size Bytes.
* buffer of length \p hlen Bytes.
* \param hlen The size of the hash \p hash.
* \param sig The signature to read and verify. This must be a readable
* buffer of length \p slen Bytes.
@ -579,7 +580,7 @@ int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,
* \param ctx The ECDSA context to use. This must be initialized
* and have a group and public key bound to it.
* \param hash The message hash that was signed. This must be a readable
* buffer of length \p size Bytes.
* buffer of length \p hlen Bytes.
* \param hlen The size of the hash \p hash.
* \param sig The signature to read and verify. This must be a readable
* buffer of length \p slen Bytes.

View file

@ -197,6 +197,27 @@ mbedtls_ecp_point;
* odd prime as mbedtls_ecp_mul() requires an odd number, and
* mbedtls_ecdsa_sign() requires that it is prime for blinding purposes.
*
* The default implementation only initializes \p A without setting it to the
* authentic value for curves with <code>A = -3</code>(SECP256R1, etc), in which
* case you need to load \p A by yourself when using domain parameters directly,
* for example:
* \code
* mbedtls_mpi_init(&A);
* mbedtls_ecp_group_init(&grp);
* CHECK_RETURN(mbedtls_ecp_group_load(&grp, grp_id));
* if (mbedtls_ecp_group_a_is_minus_3(&grp)) {
* CHECK_RETURN(mbedtls_mpi_sub_int(&A, &grp.P, 3));
* } else {
* CHECK_RETURN(mbedtls_mpi_copy(&A, &grp.A));
* }
*
* do_something_with_a(&A);
*
* cleanup:
* mbedtls_mpi_free(&A);
* mbedtls_ecp_group_free(&grp);
* \endcode
*
* For Montgomery curves, we do not store \p A, but <code>(A + 2) / 4</code>,
* which is the quantity used in the formulas. Additionally, \p nbits is
* not the size of \p N but the required size for private keys.
@ -223,8 +244,11 @@ mbedtls_ecp_point;
typedef struct mbedtls_ecp_group {
mbedtls_ecp_group_id id; /*!< An internal group identifier. */
mbedtls_mpi P; /*!< The prime modulus of the base field. */
mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For
Montgomery curves: <code>(A + 2) / 4</code>. */
mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. Note that
\p A is not set to the authentic value in some cases.
Refer to detailed description of ::mbedtls_ecp_group if
using domain parameters in the structure.
For Montgomery curves: <code>(A + 2) / 4</code>. */
mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation.
For Montgomery curves: unused. */
mbedtls_ecp_point G; /*!< The generator of the subgroup used. */
@ -991,6 +1015,26 @@ int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
mbedtls_ecp_restart_ctx *rs_ctx);
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
/**
* \brief This function checks if domain parameter A of the curve is
* \c -3.
*
* \note This function is only defined for short Weierstrass curves.
* It may not be included in builds without any short
* Weierstrass curve.
*
* \param grp The ECP group to use.
* This must be initialized and have group parameters
* set, for example through mbedtls_ecp_group_load().
*
* \return \c 1 if <code>A = -3</code>.
* \return \c 0 Otherwise.
*/
static inline int mbedtls_ecp_group_a_is_minus_3(const mbedtls_ecp_group *grp)
{
return grp->A.MBEDTLS_PRIVATE(p) == NULL;
}
/**
* \brief This function performs multiplication and addition of two
* points by integers: \p R = \p m * \p P + \p n * \p Q
@ -1083,7 +1127,7 @@ int mbedtls_ecp_muladd_restartable(
*
* It only checks that the point is non-zero, has
* valid coordinates and lies on the curve. It does not verify
* that it is indeed a multiple of \p G. This additional
* that it is indeed a multiple of \c G. This additional
* check is computationally more expensive, is not required
* by standards, and should not be necessary if the group
* used has a small cofactor. In particular, it is useless for
@ -1108,7 +1152,7 @@ int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp,
const mbedtls_ecp_point *pt);
/**
* \brief This function checks that an \p mbedtls_mpi is a
* \brief This function checks that an \c mbedtls_mpi is a
* valid private key for this curve.
*
* \note This function uses bare components rather than an

View file

@ -183,8 +183,8 @@ void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx);
* \param len The length of the personalization string.
* This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
* and also at most
* #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2
* where \p entropy_len is the entropy length
* #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \c entropy_len * 3 / 2
* where \c entropy_len is the entropy length
* described above.
*
* \return \c 0 if successful.
@ -313,8 +313,8 @@ int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
* \param len The length of the additional data.
* This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
* and also at most
* #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len
* where \p entropy_len is the entropy length
* #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \c entropy_len
* where \c entropy_len is the entropy length
* (see mbedtls_hmac_drbg_set_entropy_len()).
*
* \return \c 0 if successful.

View file

@ -172,15 +172,47 @@
* This allows different allocators (self-implemented or provided) to be
* provided to the platform abstraction layer.
*
* Enabling MBEDTLS_PLATFORM_MEMORY without the
* Enabling #MBEDTLS_PLATFORM_MEMORY without the
* MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
* "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
* free() function pointer at runtime.
*
* Enabling MBEDTLS_PLATFORM_MEMORY and specifying
* Enabling #MBEDTLS_PLATFORM_MEMORY and specifying
* MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
* alternate function at compile time.
*
* An overview of how the value of mbedtls_calloc is determined:
*
* - if !MBEDTLS_PLATFORM_MEMORY
* - mbedtls_calloc = calloc
* - if MBEDTLS_PLATFORM_MEMORY
* - if (MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO):
* - mbedtls_calloc = MBEDTLS_PLATFORM_CALLOC_MACRO
* - if !(MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO):
* - Dynamic setup via mbedtls_platform_set_calloc_free is now possible with a default value MBEDTLS_PLATFORM_STD_CALLOC.
* - How is MBEDTLS_PLATFORM_STD_CALLOC handled?
* - if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS:
* - MBEDTLS_PLATFORM_STD_CALLOC is not set to anything;
* - MBEDTLS_PLATFORM_STD_MEM_HDR can be included if present;
* - if !MBEDTLS_PLATFORM_NO_STD_FUNCTIONS:
* - if MBEDTLS_PLATFORM_STD_CALLOC is present:
* - User-defined MBEDTLS_PLATFORM_STD_CALLOC is respected;
* - if !MBEDTLS_PLATFORM_STD_CALLOC:
* - MBEDTLS_PLATFORM_STD_CALLOC = calloc
*
* - At this point the presence of MBEDTLS_PLATFORM_STD_CALLOC is checked.
* - if !MBEDTLS_PLATFORM_STD_CALLOC
* - MBEDTLS_PLATFORM_STD_CALLOC = uninitialized_calloc
*
* - mbedtls_calloc = MBEDTLS_PLATFORM_STD_CALLOC.
*
* Defining MBEDTLS_PLATFORM_CALLOC_MACRO and #MBEDTLS_PLATFORM_STD_CALLOC at the same time is not possible.
* MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO must both be defined or undefined at the same time.
* #MBEDTLS_PLATFORM_STD_CALLOC and #MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used,
* dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases.
* An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer.
* An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything.
*
* Requires: MBEDTLS_PLATFORM_C
*
* Enable this layer to allow use of alternative memory allocators.
@ -1283,8 +1315,8 @@
* );
* ```
* The \c context value is initialized to 0 before the first call.
* The function must fill the \c output buffer with \p output_size bytes
* of random data and set \c *output_length to \p output_size.
* The function must fill the \c output buffer with \c output_size bytes
* of random data and set \c *output_length to \c output_size.
*
* Requires: MBEDTLS_PSA_CRYPTO_C
*
@ -1671,7 +1703,7 @@
*
* Enable TLS 1.3 ephemeral key exchange mode.
*
* Requires: PSA_WANT_ALG_ECDH
* Requires: PSA_WANT_ALG_ECDH or PSA_WANT_ALG_FFDH
* MBEDTLS_X509_CRT_PARSE_C
* and at least one of:
* MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA)
@ -1689,7 +1721,7 @@
*
* Enable TLS 1.3 PSK ephemeral key exchange mode.
*
* Requires: PSA_WANT_ALG_ECDH
* Requires: PSA_WANT_ALG_ECDH or PSA_WANT_ALG_FFDH
*
* Comment to disable support for the PSK ephemeral key exchange mode in
* TLS 1.3. If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not
@ -1998,8 +2030,15 @@
* If the symbol #MBEDTLS_PSA_CRYPTO_CONFIG_FILE is defined, it specifies
* an alternative header to include instead of include/psa/crypto_config.h.
*
* This feature is still experimental and is not ready for production since
* it is not completed.
* \warning This option is experimental, in that the set of `PSA_WANT_XXX`
* symbols is not completely finalized yet, and the configuration
* tooling is not ideally adapted to having two separate configuration
* files.
* Future minor releases of Mbed TLS may make minor changes to those
* symbols, but we will endeavor to provide a transition path.
* Nonetheless, this option is considered mature enough to use in
* production, as long as you accept that you may need to make
* minor changes to psa/crypto_config.h when upgrading Mbed TLS.
*/
//#define MBEDTLS_PSA_CRYPTO_CONFIG
@ -2113,7 +2152,10 @@
* the CPU when this option is enabled.
*
* \note Minimum compiler versions for this feature are Clang 4.0,
* GCC 6.0 or MSVC 2019 version 16.11.2.
* armclang 6.6, GCC 6.0 or MSVC 2019 version 16.11.2.
*
* \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for
* armclang <= 6.9
*
* This module adds support for the AES Armv8-A Cryptographic Extensions on Aarch64 systems.
*/
@ -3130,6 +3172,12 @@
* \note If MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT is defined when building
* for a non-Aarch64 build it will be silently ignored.
*
* \note Minimum compiler versions for this feature are Clang 4.0,
* armclang 6.6 or GCC 6.0.
*
* \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for
* armclang <= 6.9
*
* \warning MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT cannot be defined at the
* same time as MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY.
*
@ -3152,6 +3200,12 @@
* \note This allows builds with a smaller code size than with
* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
*
* \note Minimum compiler versions for this feature are Clang 4.0,
* armclang 6.6 or GCC 6.0.
*
* \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for
* armclang <= 6.9
*
* \warning MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY cannot be defined at the same
* time as MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT.
*
@ -3216,8 +3270,11 @@
* \note If MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT is defined when building
* for a non-Aarch64 build it will be silently ignored.
*
* \note The code uses the SHA-512 Neon intrinsics, so requires GCC >= 8 or
* Clang >= 7.
* \note Minimum compiler versions for this feature are Clang 7.0,
* armclang 6.9 or GCC 8.0.
*
* \note \c CFLAGS must be set to a minimum of \c -march=armv8.2-a+sha3 for
* armclang 6.9
*
* \warning MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT cannot be defined at the
* same time as MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY.
@ -3241,8 +3298,11 @@
* \note This allows builds with a smaller code size than with
* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
*
* \note The code uses the SHA-512 Neon intrinsics, so requires GCC >= 8 or
* Clang >= 7.
* \note Minimum compiler versions for this feature are Clang 7.0,
* armclang 6.9 or GCC 8.0.
*
* \note \c CFLAGS must be set to a minimum of \c -march=armv8.2-a+sha3 for
* armclang 6.9
*
* \warning MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY cannot be defined at the same
* time as MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT.
@ -3680,8 +3740,29 @@
/* Platform options */
//#define MBEDTLS_PLATFORM_STD_MEM_HDR <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */
//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */
/** \def MBEDTLS_PLATFORM_STD_CALLOC
*
* Default allocator to use, can be undefined.
* It must initialize the allocated buffer memory to zeroes.
* The size of the buffer is the product of the two parameters.
* The calloc function returns either a null pointer or a pointer to the allocated space.
* If the product is 0, the function may either return NULL or a valid pointer to an array of size 0 which is a valid input to the deallocation function.
* An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer.
* See the description of #MBEDTLS_PLATFORM_MEMORY for more details.
* The corresponding deallocation function is #MBEDTLS_PLATFORM_STD_FREE.
*/
//#define MBEDTLS_PLATFORM_STD_CALLOC calloc
/** \def MBEDTLS_PLATFORM_STD_FREE
*
* Default free to use, can be undefined.
* NULL is a valid parameter, and the function must do nothing.
* A non-null parameter will always be a pointer previously returned by #MBEDTLS_PLATFORM_STD_CALLOC and not yet freed.
* An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything.
* See the description of #MBEDTLS_PLATFORM_MEMORY for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply).
*/
//#define MBEDTLS_PLATFORM_STD_FREE free
//#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< Default setbuf to use, can be undefined */
//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */
//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
@ -3695,10 +3776,10 @@
//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */
/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
/* To use the following function macros, MBEDTLS_PLATFORM_C must be enabled. */
/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */
//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */
//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_CALLOC for requirements. */
//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_FREE for requirements. */
//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */
//#define MBEDTLS_PLATFORM_SETBUF_MACRO setbuf /**< Default setbuf macro to use, can be undefined */
//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
@ -3760,6 +3841,9 @@
*/
//#define MBEDTLS_PSA_KEY_SLOT_COUNT 32
/* RSA OPTIONS */
#define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024 /**< Minimum RSA key size that can be generated in bits (Minimum possible value is 128 bits) */
/* SSL Cache options */
//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */
//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */
@ -3976,4 +4060,27 @@
*/
//#define MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED
/**
* Uncomment to enable using new bignum code in the ECC modules.
*
* \warning This is currently experimental, incomplete and therefore should not
* be used in production.
*/
//#define MBEDTLS_ECP_WITH_MPI_UINT
/*
* Disable plain C implementation for AES.
*
* When the plain C implementation is enabled, and an implementation using a
* special CPU feature (such as MBEDTLS_AESCE_C) is also enabled, runtime
* detection will be used to select between them.
*
* If only one implementation is present, runtime detection will not be used.
* This configuration will crash at runtime if running on a CPU without the
* necessary features. It will not build unless at least one of MBEDTLS_AESCE_C
* and/or MBEDTLS_AESNI_C is enabled & present in the build.
*/
//#define MBEDTLS_AES_USE_HARDWARE_ONLY
/** \} name SECTION: Module configuration options */

View file

@ -146,19 +146,22 @@ extern "C" {
* stronger message digests instead.
*
*/
/* Note: these are aligned with the definitions of PSA_ALG_ macros for hashes,
* in order to enable an efficient implementation of conversion functions.
* This is tested by md_to_from_psa() in test_suite_md. */
typedef enum {
MBEDTLS_MD_NONE=0, /**< None. */
MBEDTLS_MD_MD5, /**< The MD5 message digest. */
MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */
MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */
MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */
MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */
MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */
MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */
MBEDTLS_MD_SHA3_224, /**< The SHA3-224 message digest. */
MBEDTLS_MD_SHA3_256, /**< The SHA3-256 message digest. */
MBEDTLS_MD_SHA3_384, /**< The SHA3-384 message digest. */
MBEDTLS_MD_SHA3_512, /**< The SHA3-512 message digest. */
MBEDTLS_MD_MD5=0x03, /**< The MD5 message digest. */
MBEDTLS_MD_RIPEMD160=0x04, /**< The RIPEMD-160 message digest. */
MBEDTLS_MD_SHA1=0x05, /**< The SHA-1 message digest. */
MBEDTLS_MD_SHA224=0x08, /**< The SHA-224 message digest. */
MBEDTLS_MD_SHA256=0x09, /**< The SHA-256 message digest. */
MBEDTLS_MD_SHA384=0x0a, /**< The SHA-384 message digest. */
MBEDTLS_MD_SHA512=0x0b, /**< The SHA-512 message digest. */
MBEDTLS_MD_SHA3_224=0x10, /**< The SHA3-224 message digest. */
MBEDTLS_MD_SHA3_256=0x11, /**< The SHA3-256 message digest. */
MBEDTLS_MD_SHA3_384=0x12, /**< The SHA3-384 message digest. */
MBEDTLS_MD_SHA3_512=0x13, /**< The SHA3-512 message digest. */
} mbedtls_md_type_t;
/* Note: this should always be >= PSA_HASH_MAX_SIZE
@ -464,8 +467,8 @@ const int *mbedtls_md_list(void);
const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name);
/**
* \brief This function extracts the message-digest name from the
* message-digest information structure.
* \brief This function returns the name of the message digest for
* the message-digest information structure given.
*
* \param md_info The information structure of the message-digest algorithm
* to use.

View file

@ -286,6 +286,10 @@ int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len,
* \brief Closes down the connection and free associated data
*
* \param ctx The context to close
*
* \note This function frees and clears data associated with the
* context but does not free the memory pointed to by \p ctx.
* This memory is the responsibility of the caller.
*/
void mbedtls_net_close(mbedtls_net_context *ctx);
@ -293,6 +297,10 @@ void mbedtls_net_close(mbedtls_net_context *ctx);
* \brief Gracefully shutdown the connection and free associated data
*
* \param ctx The context to free
*
* \note This function frees and clears data associated with the
* context but does not free the memory pointed to by \p ctx.
* This memory is the responsibility of the caller.
*/
void mbedtls_net_free(mbedtls_net_context *ctx);

View file

@ -171,40 +171,9 @@ typedef struct mbedtls_pk_rsassa_pss_options {
#endif
#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */
/**
* \brief The following defines are meant to list ECDSA capabilities of the
* PK module in a general way (without any reference to how this
* is achieved, which can be either through PSA driver or
* MBEDTLS_ECDSA_C)
*/
#if !defined(MBEDTLS_USE_PSA_CRYPTO)
#if defined(MBEDTLS_ECDSA_C)
#define MBEDTLS_PK_CAN_ECDSA_SIGN
#define MBEDTLS_PK_CAN_ECDSA_VERIFY
#endif
#else /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(PSA_WANT_ALG_ECDSA)
#if defined(MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_LEGACY)
#define MBEDTLS_PK_CAN_ECDSA_SIGN
#endif
#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
#define MBEDTLS_PK_CAN_ECDSA_VERIFY
#endif
#endif /* PSA_WANT_ALG_ECDSA */
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
#define MBEDTLS_PK_CAN_ECDSA_SOME
#endif
#if (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_ECDH)) || \
(!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C))
#define MBEDTLS_PK_CAN_ECDH
#endif
/* Internal helper to define which fields in the pk_context structure below
* should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly)
* format. It should be noticed that this only affect how data is stored, not
* format. It should be noticed that this only affects how data is stored, not
* which functions are used for various operations. The overall picture looks
* like this:
* - if USE_PSA is not defined and ECP_C is then use ecp_keypair data structure
@ -231,6 +200,28 @@ typedef struct mbedtls_pk_rsassa_pss_options {
#define MBEDTLS_PK_HAVE_ECC_KEYS
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */
/* Internal helper to define which fields in the pk_context structure below
* should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly)
* format. It should be noted that this only affect how data is stored, not
* which functions are used for various operations. The overall picture looks
* like this:
* - if USE_PSA is not defined and ECP_C is then use ecp_keypair data structure
* and legacy functions
* - if USE_PSA is defined and
* - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly
* format and use PSA functions
* - if !ECP_C then use new raw data and PSA functions directly.
*
* The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long
* as ECP_C is defined mbedtls_pk_ec() gives the user read/write access to the
* ecp_keypair structure inside the pk_context so they can modify it using
* ECP functions which are not under the PK module's control.
*/
#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
!defined(MBEDTLS_ECP_C)
#define MBEDTLS_PK_USE_PSA_EC_DATA
#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_ECP_C */
/**
* \brief Types for interfacing with the debug module
*/
@ -552,7 +543,7 @@ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
*
* \return 0 on success (signature is valid),
* #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid
* signature in sig but its length is less than \p siglen,
* signature in \p sig but its length is less than \p sig_len,
* or a specific error code.
*
* \note For RSA keys, the default padding type is PKCS#1 v1.5.
@ -606,7 +597,7 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
* #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be
* used for this type of signatures,
* #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid
* signature in sig but its length is less than \p siglen,
* signature in \p sig but its length is less than \p sig_len,
* or a specific error code.
*
* \note If hash_len is 0, then the length associated with md_alg

View file

@ -130,11 +130,22 @@ extern "C" {
#endif
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
/* Enable certain documented defines only when generating doxygen to avoid
* an "unrecognized define" error. */
#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_CALLOC)
#define MBEDTLS_PLATFORM_STD_CALLOC
#endif
#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_FREE)
#define MBEDTLS_PLATFORM_STD_FREE
#endif
/** \} name SECTION: Module settings */
/*
* The function pointers for calloc and free.
* Please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE
* in mbedtls_config.h for more information about behaviour and requirements.
*/
#if defined(MBEDTLS_PLATFORM_MEMORY)
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \

View file

@ -2,9 +2,6 @@
* \file psa_util.h
*
* \brief Utility functions for the use of the PSA Crypto library.
*
* \warning This function is not part of the public API and may
* change at any time.
*/
/*
* Copyright The Mbed TLS Contributors
@ -29,212 +26,8 @@
#include "mbedtls/build_info.h"
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include "psa/crypto.h"
#include "mbedtls/ecp.h"
#include "mbedtls/md.h"
#include "mbedtls/pk.h"
#include "mbedtls/oid.h"
#include "mbedtls/error.h"
#include <string.h>
/* Translations for symmetric crypto. */
static inline psa_key_type_t mbedtls_psa_translate_cipher_type(
mbedtls_cipher_type_t cipher)
{
switch (cipher) {
case MBEDTLS_CIPHER_AES_128_CCM:
case MBEDTLS_CIPHER_AES_192_CCM:
case MBEDTLS_CIPHER_AES_256_CCM:
case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG:
case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG:
case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG:
case MBEDTLS_CIPHER_AES_128_GCM:
case MBEDTLS_CIPHER_AES_192_GCM:
case MBEDTLS_CIPHER_AES_256_GCM:
case MBEDTLS_CIPHER_AES_128_CBC:
case MBEDTLS_CIPHER_AES_192_CBC:
case MBEDTLS_CIPHER_AES_256_CBC:
case MBEDTLS_CIPHER_AES_128_ECB:
case MBEDTLS_CIPHER_AES_192_ECB:
case MBEDTLS_CIPHER_AES_256_ECB:
return PSA_KEY_TYPE_AES;
/* ARIA not yet supported in PSA. */
/* case MBEDTLS_CIPHER_ARIA_128_CCM:
case MBEDTLS_CIPHER_ARIA_192_CCM:
case MBEDTLS_CIPHER_ARIA_256_CCM:
case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG:
case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG:
case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG:
case MBEDTLS_CIPHER_ARIA_128_GCM:
case MBEDTLS_CIPHER_ARIA_192_GCM:
case MBEDTLS_CIPHER_ARIA_256_GCM:
case MBEDTLS_CIPHER_ARIA_128_CBC:
case MBEDTLS_CIPHER_ARIA_192_CBC:
case MBEDTLS_CIPHER_ARIA_256_CBC:
return( PSA_KEY_TYPE_ARIA ); */
default:
return 0;
}
}
static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode(
mbedtls_cipher_mode_t mode, size_t taglen)
{
switch (mode) {
case MBEDTLS_MODE_ECB:
return PSA_ALG_ECB_NO_PADDING;
case MBEDTLS_MODE_GCM:
return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen);
case MBEDTLS_MODE_CCM:
return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen);
case MBEDTLS_MODE_CCM_STAR_NO_TAG:
return PSA_ALG_CCM_STAR_NO_TAG;
case MBEDTLS_MODE_CBC:
if (taglen == 0) {
return PSA_ALG_CBC_NO_PADDING;
} else {
return 0;
}
default:
return 0;
}
}
static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation(
mbedtls_operation_t op)
{
switch (op) {
case MBEDTLS_ENCRYPT:
return PSA_KEY_USAGE_ENCRYPT;
case MBEDTLS_DECRYPT:
return PSA_KEY_USAGE_DECRYPT;
default:
return 0;
}
}
/* Translations for ECC. */
static inline int mbedtls_psa_get_ecc_oid_from_id(
psa_ecc_family_t curve, size_t bits,
char const **oid, size_t *oid_len)
{
switch (curve) {
case PSA_ECC_FAMILY_SECP_R1:
switch (bits) {
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
case 192:
*oid = MBEDTLS_OID_EC_GRP_SECP192R1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP192R1);
return 0;
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
case 224:
*oid = MBEDTLS_OID_EC_GRP_SECP224R1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP224R1);
return 0;
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
case 256:
*oid = MBEDTLS_OID_EC_GRP_SECP256R1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP256R1);
return 0;
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
case 384:
*oid = MBEDTLS_OID_EC_GRP_SECP384R1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP384R1);
return 0;
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
case 521:
*oid = MBEDTLS_OID_EC_GRP_SECP521R1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP521R1);
return 0;
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
}
break;
case PSA_ECC_FAMILY_SECP_K1:
switch (bits) {
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
case 192:
*oid = MBEDTLS_OID_EC_GRP_SECP192K1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP192K1);
return 0;
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
case 224:
*oid = MBEDTLS_OID_EC_GRP_SECP224K1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP224K1);
return 0;
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
case 256:
*oid = MBEDTLS_OID_EC_GRP_SECP256K1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP256K1);
return 0;
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
}
break;
case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
switch (bits) {
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
case 256:
*oid = MBEDTLS_OID_EC_GRP_BP256R1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP256R1);
return 0;
#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
case 384:
*oid = MBEDTLS_OID_EC_GRP_BP384R1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP384R1);
return 0;
#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
case 512:
*oid = MBEDTLS_OID_EC_GRP_BP512R1;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP512R1);
return 0;
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
}
break;
case PSA_ECC_FAMILY_MONTGOMERY:
switch (bits) {
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
case 255:
*oid = MBEDTLS_OID_X25519;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_X25519);
return 0;
#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
case 448:
*oid = MBEDTLS_OID_X448;
*oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_X448);
return 0;
#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
}
break;
}
(void) oid;
(void) oid_len;
return -1;
}
#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \
PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
#define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \
PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
/* Expose whatever RNG the PSA subsystem uses to applications using the
* mbedtls_xxx API. The declarations and definitions here need to be
* consistent with the implementation in library/psa_crypto_random_impl.h.
@ -319,58 +112,5 @@ extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
typedef struct {
/* Error codes used by PSA crypto are in -255..-128, fitting in 16 bits. */
int16_t psa_status;
/* Error codes used by Mbed TLS are in one of the ranges
* -127..-1 (low-level) or -32767..-4096 (high-level with a low-level
* code optionally added), fitting in 16 bits. */
int16_t mbedtls_error;
} mbedtls_error_pair_t;
#if defined(MBEDTLS_MD_LIGHT)
extern const mbedtls_error_pair_t psa_to_md_errors[4];
#endif
#if defined(MBEDTLS_LMS_C)
extern const mbedtls_error_pair_t psa_to_lms_errors[3];
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
extern const mbedtls_error_pair_t psa_to_ssl_errors[7];
#endif
#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \
defined(MBEDTLS_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_LEGACY)
extern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8];
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
extern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7];
#endif
/* Generic fallback function for error translation,
* when the received state was not module-specific. */
int psa_generic_status_to_mbedtls(psa_status_t status);
/* This function iterates over provided local error translations,
* and if no match was found - calls the fallback error translation function. */
int psa_status_to_mbedtls(psa_status_t status,
const mbedtls_error_pair_t *local_translations,
size_t local_errors_num,
int (*fallback_f)(psa_status_t));
/* The second out of three-stage error handling functions of the pk module,
* acts as a fallback after RSA / ECDSA error translation, and if no match
* is found, it itself calls psa_generic_status_to_mbedtls. */
int psa_pk_status_to_mbedtls(psa_status_t status);
/* Utility macro to shorten the defines of error translator in modules. */
#define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f) \
psa_status_to_mbedtls(status, error_list, \
sizeof(error_list)/sizeof(error_list[0]), \
fallback_f)
#endif /* MBEDTLS_PSA_CRYPTO_C */
#endif /* MBEDTLS_PSA_UTIL_H */

View file

@ -85,6 +85,12 @@ extern "C" {
// Regular implementation
//
#if !defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS)
#define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024
#elif MBEDTLS_RSA_GEN_KEY_MIN_BITS < 128
#error "MBEDTLS_RSA_GEN_KEY_MIN_BITS must be at least 128 bits"
#endif
/**
* \brief The RSA context structure.
*/
@ -282,15 +288,15 @@ int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx,
* \brief This function completes an RSA context from
* a set of imported core parameters.
*
* To setup an RSA public key, precisely \p N and \p E
* To setup an RSA public key, precisely \c N and \c E
* must have been imported.
*
* To setup an RSA private key, sufficient information must
* be present for the other parameters to be derivable.
*
* The default implementation supports the following:
* <ul><li>Derive \p P, \p Q from \p N, \p D, \p E.</li>
* <li>Derive \p N, \p D from \p P, \p Q, \p E.</li></ul>
* <ul><li>Derive \c P, \c Q from \c N, \c D, \c E.</li>
* <li>Derive \c N, \c D from \c P, \c Q, \c E.</li></ul>
* Alternative implementations need not support these.
*
* If this function runs successfully, it guarantees that
@ -547,7 +553,7 @@ int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub,
* \note This function does not handle message padding.
*
* \note Make sure to set \p input[0] = 0 or ensure that
* input is smaller than \p N.
* input is smaller than \c N.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@ -984,8 +990,8 @@ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
* verification.
*
* \note For PKCS#1 v2.1 encoding, see comments on
* mbedtls_rsa_rsassa_pss_verify() about \p md_alg and
* \p hash_id.
* mbedtls_rsa_rsassa_pss_verify() about \c md_alg and
* \c hash_id.
*
* \param ctx The initialized RSA public key context to use.
* \param md_alg The message-digest algorithm used to hash the original data.

View file

@ -42,7 +42,7 @@
#include "mbedtls/md.h"
#if defined(MBEDTLS_ECDH_C)
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED)
#include "mbedtls/ecdh.h"
#endif
@ -619,6 +619,7 @@
/* Dummy type used only for its size */
union mbedtls_ssl_premaster_secret {
unsigned char dummy; /* Make the union non-empty even with SSL disabled */
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */
#endif
@ -1486,7 +1487,7 @@ struct mbedtls_ssl_config {
const uint16_t *MBEDTLS_PRIVATE(sig_algs); /*!< allowed signature algorithms */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_ECP_LIGHT) && !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_DEPRECATED_REMOVED)
const mbedtls_ecp_group_id *MBEDTLS_PRIVATE(curve_list); /*!< allowed curves */
#endif
@ -1918,6 +1919,19 @@ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl);
*/
void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint);
/**
* \brief Get the current endpoint type
*
* \param conf SSL configuration
*
* \return Endpoint type, either MBEDTLS_SSL_IS_CLIENT
* or MBEDTLS_SSL_IS_SERVER
*/
static inline int mbedtls_ssl_conf_get_endpoint(const mbedtls_ssl_config *conf)
{
return conf->MBEDTLS_PRIVATE(endpoint);
}
/**
* \brief Set the transport type (TLS or DTLS).
* Default: TLS
@ -2157,10 +2171,10 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,
* \param own_cid The address of the readable buffer holding the CID we want
* the peer to use when sending encrypted messages to us.
* This may be \c NULL if \p own_cid_len is \c 0.
* This parameter is unused if \p enabled is set to
* This parameter is unused if \p enable is set to
* MBEDTLS_SSL_CID_DISABLED.
* \param own_cid_len The length of \p own_cid.
* This parameter is unused if \p enabled is set to
* This parameter is unused if \p enable is set to
* MBEDTLS_SSL_CID_DISABLED.
*
* \note The value of \p own_cid_len must match the value of the
@ -3111,8 +3125,8 @@ int mbedtls_ssl_session_load(mbedtls_ssl_session *session,
*
* \param session The session structure to be saved.
* \param buf The buffer to write the serialized data to. It must be a
* writeable buffer of at least \p len bytes, or may be \c
* NULL if \p len is \c 0.
* writeable buffer of at least \p buf_len bytes, or may be \c
* NULL if \p buf_len is \c 0.
* \param buf_len The number of bytes available for writing in \p buf.
* \param olen The size in bytes of the data that has been or would have
* been written. It must point to a valid \c size_t.
@ -3253,7 +3267,7 @@ void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf,
* record headers.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p own_cid_len
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p len
* is too large.
*/
int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len,
@ -3621,7 +3635,7 @@ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf,
unsigned int bitlen);
#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_ECP_LIGHT)
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
/**
* \brief Set the allowed curves in order of preference.
@ -3667,7 +3681,7 @@ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf,
void MBEDTLS_DEPRECATED mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf,
const mbedtls_ecp_group_id *curves);
#endif /* MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_ECP_LIGHT */
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
/**
* \brief Set the allowed groups in order of preference.
@ -3777,13 +3791,28 @@ void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf,
* On too long input failure, old hostname is unchanged.
*/
int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname);
/**
* \brief Get the hostname that checked against the received
* server certificate. It is used to set the ServerName
* TLS extension, too, if that extension is enabled.
* (client-side only)
*
* \param ssl SSL context
*
* \return const pointer to the hostname value
*/
static inline const char *mbedtls_ssl_get_hostname(mbedtls_ssl_context *ssl)
{
return ssl->MBEDTLS_PRIVATE(hostname);
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
/**
* \brief Retrieve SNI extension value for the current handshake.
* Available in \p f_cert_cb of \c mbedtls_ssl_conf_cert_cb(),
* this is the same value passed to \p f_sni callback of
* Available in \c f_cert_cb of \c mbedtls_ssl_conf_cert_cb(),
* this is the same value passed to \c f_sni callback of
* \c mbedtls_ssl_conf_sni() and may be used instead of
* \c mbedtls_ssl_conf_sni().
*
@ -3792,10 +3821,10 @@ int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname);
* 0 if SNI extension is not present or not yet processed.
*
* \return const pointer to SNI extension value.
* - value is valid only when called in \p f_cert_cb
* - value is valid only when called in \c f_cert_cb
* registered with \c mbedtls_ssl_conf_cert_cb().
* - value is NULL if SNI extension is not present.
* - value is not '\0'-terminated. Use \c name_len for len.
* - value is not '\0'-terminated. Use \c name_len for len.
* - value must not be freed.
*/
const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl,
@ -4088,7 +4117,7 @@ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, i
* negotiated.
*
* \param conf SSL configuration
* \param tls_version TLS protocol version number (\p mbedtls_ssl_protocol_version)
* \param tls_version TLS protocol version number (\c mbedtls_ssl_protocol_version)
* (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid)
*/
static inline void mbedtls_ssl_conf_max_tls_version(mbedtls_ssl_config *conf,
@ -4145,7 +4174,7 @@ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, i
* negotiated.
*
* \param conf SSL configuration
* \param tls_version TLS protocol version number (\p mbedtls_ssl_protocol_version)
* \param tls_version TLS protocol version number (\c mbedtls_ssl_protocol_version)
* (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid)
*/
static inline void mbedtls_ssl_conf_min_tls_version(mbedtls_ssl_config *conf,

View file

@ -137,7 +137,7 @@ int mbedtls_ssl_cache_set(void *data,
*
* \param data The SSL cache context to use.
* \param session_id The pointer to the buffer holding the session ID
* associated to \p session.
* associated to session.
* \param session_id_len The length of \p session_id in bytes.
*
* \return \c 0 on success. This indicates the cache entry for
@ -160,6 +160,20 @@ int mbedtls_ssl_cache_remove(void *data,
* \param timeout cache entry timeout in seconds
*/
void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout);
/**
* \brief Get the cache timeout
*
* A timeout of 0 indicates no timeout.
*
* \param cache SSL cache context
*
* \return cache entry timeout in seconds
*/
static inline int mbedtls_ssl_cache_get_timeout(mbedtls_ssl_cache_context *cache)
{
return cache->MBEDTLS_PRIVATE(timeout);
}
#endif /* MBEDTLS_HAVE_TIME */
/**

View file

@ -346,11 +346,6 @@ typedef enum {
#define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
#define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED
#endif
/* Key exchanges using DHE */
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
@ -364,6 +359,62 @@ typedef enum {
#define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED
#endif
/* TLS 1.2 key exchanges using ECDH or ECDHE*/
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED
#endif
/* TLS 1.3 PSK key exchanges */
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED
#endif
/* TLS 1.2 or 1.3 key exchanges with PSK */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
#define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED
#endif
/* TLS 1.3 ephemeral key exchanges */
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED
#endif
/* TLS 1.3 key exchanges using ECDHE */
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) && \
defined(PSA_WANT_ALG_ECDH)
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED
#endif
/* TLS 1.2 or 1.3 key exchanges using ECDH or ECDHE */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED)
#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED
#endif
/* TLS 1.2 XXDH key exchanges: ECDH or ECDHE or FFDH */
#if (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED))
#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_1_2_ENABLED
#endif
/* The handshake params structure has a set of fields called xxdh_psa which are used:
* - by TLS 1.2 with `USE_PSA` to do ECDH or ECDHE;
* - by TLS 1.3 to do ECDHE or FFDHE.
* The following macros can be used to guard their declaration and use.
*/
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) && \
defined(MBEDTLS_USE_PSA_CRYPTO)
#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED
#endif
typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t;
#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */

View file

@ -366,6 +366,31 @@ static inline mbedtls_x509_name *mbedtls_x509_dn_get_next(
*/
int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial);
/**
* \brief Compare pair of mbedtls_x509_time.
*
* \param t1 mbedtls_x509_time to compare
* \param t2 mbedtls_x509_time to compare
*
* \return < 0 if t1 is before t2
* 0 if t1 equals t2
* > 0 if t1 is after t2
*/
int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2);
#if defined(MBEDTLS_HAVE_TIME_DATE)
/**
* \brief Fill mbedtls_x509_time with provided mbedtls_time_t.
*
* \param tt mbedtls_time_t to convert
* \param now mbedtls_x509_time to fill with converted mbedtls_time_t
*
* \return \c 0 on success
* \return A non-zero return value on failure.
*/
int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now);
#endif /* MBEDTLS_HAVE_TIME_DATE */
/**
* \brief Check a given mbedtls_x509_time against the system time
* and tell if it's in the past.
@ -404,7 +429,7 @@ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
* \param san_buf The buffer holding the raw data item of the subject
* alternative name.
* \param san The target structure to populate with the parsed presentation
* of the subject alternative name encoded in \p san_raw.
* of the subject alternative name encoded in \p san_buf.
*
* \note Supported GeneralName types, as defined in RFC 5280:
* "rfc822Name", "dnsName", "directoryName",
@ -414,7 +439,7 @@ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
* \note This function should be called on a single raw data of
* subject alternative name. For example, after successful
* certificate parsing, one must iterate on every item in the
* \p crt->subject_alt_names sequence, and pass it to
* \c crt->subject_alt_names sequence, and pass it to
* this function.
*
* \warning The target structure contains pointers to the raw data of the
@ -478,7 +503,8 @@ int mbedtls_x509_write_names(unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first);
int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len,
unsigned char *sig, size_t size);
unsigned char *sig, size_t size,
mbedtls_pk_type_t pk_alg);
int mbedtls_x509_get_ns_cert_type(unsigned char **p,
const unsigned char *end,
unsigned char *ns_cert_type);
@ -500,6 +526,9 @@ int mbedtls_x509_info_cert_type(char **buf, size_t *size,
int mbedtls_x509_info_key_usage(char **buf, size_t *size,
unsigned int key_usage);
int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions,
const mbedtls_x509_san_list *san_list);
/**
* \brief This function parses a CN string as an IP address.
*

View file

@ -4407,9 +4407,9 @@ psa_status_t psa_sign_hash_start(
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p signature buffer is too small. You can
* determine a sufficient buffer size by calling
* #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
* #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \c alg)
* where \c key_type and \c key_bits are the type and bit-size
* respectively of \p key.
* respectively of \c key.
*
* \retval #PSA_ERROR_BAD_STATE
* An operation was not previously started on this context via

View file

@ -105,7 +105,7 @@ typedef struct psa_tls12_prf_key_derivation_s {
} psa_tls12_prf_key_derivation_t;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
#if defined(PSA_HAVE_SOFT_PBKDF2)
typedef enum {
PSA_PBKDF2_STATE_INIT, /* no input provided */
PSA_PBKDF2_STATE_INPUT_COST_SET, /* input cost has been set */
@ -125,6 +125,6 @@ typedef struct {
uint8_t MBEDTLS_PRIVATE(bytes_used);
uint32_t MBEDTLS_PRIVATE(block_number);
} psa_pbkdf2_key_derivation_t;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
#endif /* PSA_HAVE_SOFT_PBKDF2 */
#endif /* PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H */

View file

@ -94,7 +94,8 @@ typedef struct {
defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
#define MBEDTLS_PSA_BUILTIN_CIPHER 1
#endif

View file

@ -76,6 +76,7 @@
#define PSA_WANT_ALG_MD5 1
#define PSA_WANT_ALG_OFB 1
#define PSA_WANT_ALG_PBKDF2_HMAC 1
#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 1
#define PSA_WANT_ALG_RIPEMD160 1
#define PSA_WANT_ALG_RSA_OAEP 1
#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1
@ -91,7 +92,8 @@
#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1
/* Note: when adding support, also adjust include/mbedtls/config_psa.h */
/* XTS is not yet supported via the PSA API in Mbed TLS.
* Note: when adding support, also adjust include/mbedtls/config_psa.h */
//#define PSA_WANT_ALG_XTS 1
#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1

View file

@ -55,7 +55,7 @@ typedef union {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms);
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
#if defined(PSA_HAVE_SOFT_PBKDF2)
psa_pbkdf2_key_derivation_t MBEDTLS_PRIVATE(pbkdf2);
#endif
} psa_driver_key_derivation_context_t;

View file

@ -1036,12 +1036,12 @@ typedef uint32_t psa_pake_primitive_t;
* (value of type ::psa_pake_primitive_type_t).
* \param pake_family The family of the primitive
* (the type and interpretation of this parameter depends
* on \p type, for more information consult the
* on \p pake_type, for more information consult the
* documentation of individual ::psa_pake_primitive_type_t
* constants).
* \param pake_bits The bit-size of the primitive
* (Value of type \c size_t. The interpretation
* of this parameter depends on \p family, for more
* of this parameter depends on \p pake_family, for more
* information consult the documentation of individual
* ::psa_pake_primitive_type_t constants).
*
@ -1545,7 +1545,7 @@ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation,
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p user_id is not valid for the \p operation's algorithm and cipher
* \p peer_id is not valid for the \p operation's algorithm and cipher
* suite.
* \retval #PSA_ERROR_NOT_SUPPORTED
* The algorithm doesn't associate a second identity with the session.
@ -1627,8 +1627,8 @@ psa_status_t psa_pake_set_role(psa_pake_operation_t *operation,
* \c PSA_PAKE_STEP_XXX constants for more
* information.
* \param output_size Size of the \p output buffer in bytes. This must
* be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \p
* primitive, \p step) where \p alg and
* be at least #PSA_PAKE_OUTPUT_SIZE(\c alg, \c
* primitive, \p output_step) where \c alg and
* \p primitive are the PAKE algorithm and primitive
* in the operation's cipher suite, and \p step is
* the output step.
@ -1693,9 +1693,9 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation,
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The verification fails for a #PSA_PAKE_STEP_ZK_PROOF input step.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p is not compatible with the \p operations algorithm, or the
* \p input is not valid for the \p operation's algorithm, cipher suite
* or \p step.
* \p input_length is not compatible with the \p operations algorithm,
* or the \p input is not valid for the \p operation's algorithm,
* cipher suite or \p step.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p step p is not supported with the \p operation's algorithm, or the
* \p input is not supported for the \p operation's algorithm, cipher
@ -1744,7 +1744,7 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation,
*
* When this function returns successfully, \p operation becomes inactive.
* If this function returns an error status, both \p operation
* and \p key_derivation operations enter an error state and must be aborted by
* and \c key_derivation operations enter an error state and must be aborted by
* calling psa_pake_abort() and psa_key_derivation_abort() respectively.
*
* \param[in,out] operation Active PAKE operation.
@ -1877,7 +1877,7 @@ psa_status_t psa_pake_abort(psa_pake_operation_t *operation);
* The value of this macro must be at least as large as the largest value
* returned by PSA_PAKE_OUTPUT_SIZE()
*
* See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p step).
* See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p output_step).
*/
#define PSA_PAKE_OUTPUT_MAX_SIZE 65
@ -1889,7 +1889,7 @@ psa_status_t psa_pake_abort(psa_pake_operation_t *operation);
* The value of this macro must be at least as large as the largest value
* returned by PSA_PAKE_INPUT_SIZE()
*
* See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p step).
* See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p output_step).
*/
#define PSA_PAKE_INPUT_MAX_SIZE 65
@ -1984,34 +1984,6 @@ struct psa_crypto_driver_pake_inputs_s {
psa_pake_cipher_suite_t MBEDTLS_PRIVATE(cipher_suite);
};
typedef enum psa_jpake_step {
PSA_PAKE_STEP_INVALID = 0,
PSA_PAKE_STEP_X1_X2 = 1,
PSA_PAKE_STEP_X2S = 2,
PSA_PAKE_STEP_DERIVE = 3,
} psa_jpake_step_t;
typedef enum psa_jpake_state {
PSA_PAKE_STATE_INVALID = 0,
PSA_PAKE_STATE_SETUP = 1,
PSA_PAKE_STATE_READY = 2,
PSA_PAKE_OUTPUT_X1_X2 = 3,
PSA_PAKE_OUTPUT_X2S = 4,
PSA_PAKE_INPUT_X1_X2 = 5,
PSA_PAKE_INPUT_X4S = 6,
} psa_jpake_state_t;
typedef enum psa_jpake_sequence {
PSA_PAKE_SEQ_INVALID = 0,
PSA_PAKE_X1_STEP_KEY_SHARE = 1, /* also X2S & X4S KEY_SHARE */
PSA_PAKE_X1_STEP_ZK_PUBLIC = 2, /* also X2S & X4S ZK_PUBLIC */
PSA_PAKE_X1_STEP_ZK_PROOF = 3, /* also X2S & X4S ZK_PROOF */
PSA_PAKE_X2_STEP_KEY_SHARE = 4,
PSA_PAKE_X2_STEP_ZK_PUBLIC = 5,
PSA_PAKE_X2_STEP_ZK_PROOF = 6,
PSA_PAKE_SEQ_END = 7,
} psa_jpake_sequence_t;
typedef enum psa_crypto_driver_pake_step {
PSA_JPAKE_STEP_INVALID = 0, /* Invalid step */
PSA_JPAKE_X1_STEP_KEY_SHARE = 1, /* Round 1: input/output key share (for ephemeral private key X1).*/
@ -2028,14 +2000,35 @@ typedef enum psa_crypto_driver_pake_step {
PSA_JPAKE_X4S_STEP_ZK_PROOF = 12 /* Round 2: input Schnorr NIZKP proof for the X4S key (from peer) */
} psa_crypto_driver_pake_step_t;
typedef enum psa_jpake_round {
PSA_JPAKE_FIRST = 0,
PSA_JPAKE_SECOND = 1,
PSA_JPAKE_FINISHED = 2
} psa_jpake_round_t;
typedef enum psa_jpake_io_mode {
PSA_JPAKE_INPUT = 0,
PSA_JPAKE_OUTPUT = 1
} psa_jpake_io_mode_t;
struct psa_jpake_computation_stage_s {
psa_jpake_state_t MBEDTLS_PRIVATE(state);
psa_jpake_sequence_t MBEDTLS_PRIVATE(sequence);
psa_jpake_step_t MBEDTLS_PRIVATE(input_step);
psa_jpake_step_t MBEDTLS_PRIVATE(output_step);
/* The J-PAKE round we are currently on */
psa_jpake_round_t MBEDTLS_PRIVATE(round);
/* The 'mode' we are currently in (inputting or outputting) */
psa_jpake_io_mode_t MBEDTLS_PRIVATE(io_mode);
/* The number of completed inputs so far this round */
uint8_t MBEDTLS_PRIVATE(inputs);
/* The number of completed outputs so far this round */
uint8_t MBEDTLS_PRIVATE(outputs);
/* The next expected step (KEY_SHARE, ZK_PUBLIC or ZK_PROOF) */
psa_pake_step_t MBEDTLS_PRIVATE(step);
};
#define PSA_JPAKE_EXPECTED_INPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \
((round) == PSA_JPAKE_FIRST ? 2 : 1))
#define PSA_JPAKE_EXPECTED_OUTPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \
((round) == PSA_JPAKE_FIRST ? 2 : 1))
struct psa_pake_operation_s {
/** Unique ID indicating which driver got assigned to do the
* operation. Since driver contexts are driver-specific, swapping

View file

@ -4,8 +4,8 @@
* \brief Add temporary suppport for deprecated symbols before they are
* removed from the library.
*
* PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_LEGACY and
* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_LEGACY symbols are deprecated.
* PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR
* symbols are deprecated.
* New symols add a suffix to that base name in order to clearly state what is
* the expected use for the key (use, import, export, generate, derive).
* Here we define some backward compatibility support for uses stil using

View file

@ -208,6 +208,18 @@
* operations, and does not need to accept all key sizes up to the limit. */
#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096
/* The minimum size of an RSA key on this implementation, in bits.
* This is a vendor-specific macro.
*
* Limits RSA key generation to a minimum due to avoid accidental misuse.
* This value cannot be less than 128 bits.
*/
#if defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS)
#define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS MBEDTLS_RSA_GEN_KEY_MIN_BITS
#else
#define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS 1024
#endif
/* The maximum size of an DH key on this implementation, in bits.
*
* Note that an implementation may set different size limits for different
@ -633,10 +645,18 @@
* This macro expands to a compile-time constant integer. This value
* is the maximum size of a signature in bytes.
*/
#define PSA_SIGNATURE_MAX_SIZE \
(PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \
PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \
PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE)
#define PSA_SIGNATURE_MAX_SIZE 1
#if (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)) && \
(PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE > PSA_SIGNATURE_MAX_SIZE)
#undef PSA_SIGNATURE_MAX_SIZE
#define PSA_SIGNATURE_MAX_SIZE PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE
#endif
#if (defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) || defined(PSA_WANT_ALG_RSA_PSS)) && \
(PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_SIGNATURE_MAX_SIZE)
#undef PSA_SIGNATURE_MAX_SIZE
#define PSA_SIGNATURE_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)
#endif
/** Sufficient output buffer size for psa_asymmetric_encrypt().
*
@ -948,10 +968,29 @@
*
* See also #PSA_EXPORT_KEY_OUTPUT_SIZE(\p key_type, \p key_bits).
*/
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \
PSA_MAX_OF_THREE(PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS), \
PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS), \
PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS))
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE 1
#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \
(PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \
PSA_EXPORT_KEY_PAIR_MAX_SIZE)
#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \
PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
#endif
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) && \
(PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \
PSA_EXPORT_KEY_PAIR_MAX_SIZE)
#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \
PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)
#endif
#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \
(PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \
PSA_EXPORT_KEY_PAIR_MAX_SIZE)
#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \
PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS)
#endif
/** Sufficient buffer size for exporting any asymmetric public key.
*
@ -962,11 +1001,29 @@
*
* See also #PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(\p key_type, \p key_bits).
*/
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
PSA_MAX_OF_THREE(PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS), \
PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS), \
PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS))
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE 1
#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
(PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \
PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)
#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
#endif
#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) && \
(PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \
PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)
#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)
#endif
#if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \
(PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \
PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)
#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS)
#endif
/** Sufficient output buffer size for psa_raw_key_agreement().
*
@ -1002,11 +1059,18 @@
*
* See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\p key_type, \p key_bits).
*/
#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE \
(PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \
PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) ? \
PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) : \
PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS))
#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE 1
#if defined(PSA_WANT_ALG_ECDH) && \
(PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE)
#undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE
#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)
#endif
#if defined(PSA_WANT_ALG_FFDH) && \
(PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE)
#undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE
#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS)
#endif
/** The default IV size for a cipher algorithm, in bytes.
*

View file

@ -2115,6 +2115,10 @@
*/
#define PSA_ALG_PBKDF2_AES_CMAC_PRF_128 ((psa_algorithm_t) 0x08800200)
#define PSA_ALG_IS_PBKDF2(kdf_alg) \
(PSA_ALG_IS_PBKDF2_HMAC(kdf_alg) || \
((kdf_alg) == PSA_ALG_PBKDF2_AES_CMAC_PRF_128))
#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t) 0xfe00ffff)
#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t) 0xffff0000)

3
library/.gitignore vendored
View file

@ -2,8 +2,9 @@ libmbed*
*.sln
*.vcxproj
# Automatically generated files
###START_GENERATED_FILES###
/error.c
/version_features.c
/ssl_debug_helpers_generated.c
/psa_crypto_driver_wrappers.c
###END_GENERATED_FILES###

View file

@ -38,6 +38,7 @@ set(src_crypto
ecjpake.c
ecp.c
ecp_curves.c
ecp_curves_new.c
entropy.c
entropy_poll.c
error.c
@ -98,6 +99,7 @@ set(src_x509
x509_crl.c
x509_crt.c
x509_csr.c
x509write.c
x509write_crt.c
x509write_csr.c
)
@ -289,7 +291,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.4.0 SOVERSION 14)
set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.4.1 SOVERSION 14)
target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
if(TARGET everest)
@ -301,11 +303,11 @@ if(USE_SHARED_MBEDTLS_LIBRARY)
endif()
add_library(${mbedx509_target} SHARED ${src_x509})
set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.4.0 SOVERSION 5)
set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.4.1 SOVERSION 5)
target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
add_library(${mbedtls_target} SHARED ${src_tls})
set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.4.0 SOVERSION 19)
set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.4.1 SOVERSION 19)
target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
endif(USE_SHARED_MBEDTLS_LIBRARY)
@ -320,6 +322,15 @@ foreach(target IN LISTS target_libraries)
PUBLIC $<BUILD_INTERFACE:${MBEDTLS_DIR}/include/>
$<INSTALL_INTERFACE:include/>
PRIVATE ${MBEDTLS_DIR}/library/)
# Pass-through MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE
if(MBEDTLS_CONFIG_FILE)
target_compile_definitions(${target}
PUBLIC MBEDTLS_CONFIG_FILE="${MBEDTLS_CONFIG_FILE}")
endif()
if(MBEDTLS_USER_CONFIG_FILE)
target_compile_definitions(${target}
PUBLIC MBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}")
endif()
install(
TARGETS ${target}
EXPORT MbedTLSTargets

View file

@ -103,6 +103,7 @@ OBJS_CRYPTO= \
ecjpake.o \
ecp.o \
ecp_curves.o \
ecp_curves_new.o \
entropy.o \
entropy_poll.o \
error.o \
@ -166,6 +167,7 @@ OBJS_X509= \
x509_crl.o \
x509_crt.o \
x509_csr.o \
x509write.o \
x509write_crt.o \
x509write_csr.o \
pkcs7.o \

View file

@ -19,7 +19,7 @@
/*
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
*
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
* https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
@ -33,6 +33,36 @@
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#if defined(__aarch64__)
#if !defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
#endif
#endif
#if defined(__amd64__) || defined(__x86_64__) || \
((defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC))
#if !defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
#endif
#endif
#if defined(__i386__) || defined(_M_IX86)
#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && !defined(MBEDTLS_AESNI_C)
#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PADLOCK_C)
#if !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
#error "MBEDTLS_AES_USE_HARDWARE_ONLY cannot be defined when " \
"MBEDTLS_PADLOCK_C is set"
#endif
#endif
#endif
#if defined(MBEDTLS_PADLOCK_C)
#include "padlock.h"
#endif
@ -47,7 +77,7 @@
#if !defined(MBEDTLS_AES_ALT)
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
static int aes_padlock_ace = -1;
#endif
@ -55,6 +85,8 @@ static int aes_padlock_ace = -1;
/*
* Forward S-box
*/
#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
!defined(MBEDTLS_AES_SETKEY_DEC_ALT)
static const unsigned char FSb[256] =
{
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
@ -90,6 +122,8 @@ static const unsigned char FSb[256] =
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};
#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
!defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
/*
* Forward tables
@ -161,6 +195,7 @@ static const unsigned char FSb[256] =
V(C3, 41, 41, 82), V(B0, 99, 99, 29), V(77, 2D, 2D, 5A), V(11, 0F, 0F, 1E), \
V(CB, B0, B0, 7B), V(FC, 54, 54, A8), V(D6, BB, BB, 6D), V(3A, 16, 16, 2C)
#if !defined(MBEDTLS_AES_ENCRYPT_ALT)
#define V(a, b, c, d) 0x##a##b##c##d
static const uint32_t FT0[256] = { FT };
#undef V
@ -181,8 +216,11 @@ static const uint32_t FT3[256] = { FT };
#endif /* !MBEDTLS_AES_FEWER_TABLES */
#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) */
#undef FT
#if !defined(MBEDTLS_AES_DECRYPT_ALT)
/*
* Reverse S-box
*/
@ -221,6 +259,7 @@ static const unsigned char RSb[256] =
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
};
#endif /* defined(MBEDTLS_AES_DECRYPT_ALT)) */
/*
* Reverse tables
@ -292,6 +331,8 @@ static const unsigned char RSb[256] =
V(71, 01, A8, 39), V(DE, B3, 0C, 08), V(9C, E4, B4, D8), V(90, C1, 56, 64), \
V(61, 84, CB, 7B), V(70, B6, 32, D5), V(74, 5C, 6C, 48), V(42, 57, B8, D0)
#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
#define V(a, b, c, d) 0x##a##b##c##d
static const uint32_t RT0[256] = { RT };
#undef V
@ -312,8 +353,11 @@ static const uint32_t RT3[256] = { RT };
#endif /* !MBEDTLS_AES_FEWER_TABLES */
#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
#undef RT
#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
/*
* Round constants
*/
@ -323,31 +367,44 @@ static const uint32_t RCON[10] =
0x00000010, 0x00000020, 0x00000040, 0x00000080,
0x0000001B, 0x00000036
};
#endif /* !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */
#else /* MBEDTLS_AES_ROM_TABLES */
/*
* Forward S-box & tables
*/
#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
!defined(MBEDTLS_AES_SETKEY_DEC_ALT)
static unsigned char FSb[256];
#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
!defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
static uint32_t FT0[256];
#if !defined(MBEDTLS_AES_FEWER_TABLES)
static uint32_t FT1[256];
static uint32_t FT2[256];
static uint32_t FT3[256];
#endif /* !MBEDTLS_AES_FEWER_TABLES */
#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */
/*
* Reverse S-box & tables
*/
#if !(defined(MBEDTLS_AES_SETKEY_ENC_ALT) && defined(MBEDTLS_AES_DECRYPT_ALT))
static unsigned char RSb[256];
#endif /* !(defined(MBEDTLS_AES_SETKEY_ENC_ALT) && defined(MBEDTLS_AES_DECRYPT_ALT)) */
#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
static uint32_t RT0[256];
#if !defined(MBEDTLS_AES_FEWER_TABLES)
static uint32_t RT1[256];
static uint32_t RT2[256];
static uint32_t RT3[256];
#endif /* !MBEDTLS_AES_FEWER_TABLES */
#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
/*
* Round constants
*/
@ -364,25 +421,26 @@ static int aes_init_done = 0;
static void aes_gen_tables(void)
{
int i, x, y, z;
int pow[256];
int log[256];
int i;
uint8_t x, y, z;
uint8_t pow[256];
uint8_t log[256];
/*
* compute pow and log tables over GF(2^8)
*/
for (i = 0, x = 1; i < 256; i++) {
pow[i] = x;
log[x] = i;
x = MBEDTLS_BYTE_0(x ^ XTIME(x));
log[x] = (uint8_t) i;
x ^= XTIME(x);
}
/*
* calculate the round constants
*/
for (i = 0, x = 1; i < 10; i++) {
RCON[i] = (uint32_t) x;
x = MBEDTLS_BYTE_0(XTIME(x));
RCON[i] = x;
x = XTIME(x);
}
/*
@ -394,13 +452,13 @@ static void aes_gen_tables(void)
for (i = 1; i < 256; i++) {
x = pow[255 - log[i]];
y = x; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
y = x; y = (y << 1) | (y >> 7);
x ^= y; y = (y << 1) | (y >> 7);
x ^= y; y = (y << 1) | (y >> 7);
x ^= y; y = (y << 1) | (y >> 7);
x ^= y ^ 0x63;
FSb[i] = (unsigned char) x;
FSb[i] = x;
RSb[x] = (unsigned char) i;
}
@ -409,8 +467,8 @@ static void aes_gen_tables(void)
*/
for (i = 0; i < 256; i++) {
x = FSb[i];
y = MBEDTLS_BYTE_0(XTIME(x));
z = MBEDTLS_BYTE_0(y ^ x);
y = XTIME(x);
z = y ^ x;
FT0[i] = ((uint32_t) y) ^
((uint32_t) x << 8) ^
@ -425,6 +483,7 @@ static void aes_gen_tables(void)
x = RSb[i];
#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
RT0[i] = ((uint32_t) MUL(0x0E, x)) ^
((uint32_t) MUL(0x09, x) << 8) ^
((uint32_t) MUL(0x0D, x) << 16) ^
@ -435,9 +494,12 @@ static void aes_gen_tables(void)
RT2[i] = ROTL8(RT1[i]);
RT3[i] = ROTL8(RT2[i]);
#endif /* !MBEDTLS_AES_FEWER_TABLES */
#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
}
}
#endif /* !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */
#undef ROTL8
#endif /* MBEDTLS_AES_ROM_TABLES */
@ -510,16 +572,19 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx)
* Note that the offset is in units of elements of buf, i.e. 32-bit words,
* i.e. an offset of 1 means 4 bytes and so on.
*/
#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) || \
#if (defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)) || \
(defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)
#define MAY_NEED_TO_ALIGN
#endif
#if defined(MAY_NEED_TO_ALIGN) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) || \
!defined(MBEDTLS_AES_SETKEY_ENC_ALT)
static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
{
#if defined(MAY_NEED_TO_ALIGN)
int align_16_bytes = 0;
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
if (aes_padlock_ace == -1) {
aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
}
@ -550,6 +615,8 @@ static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
return 0;
}
#endif /* defined(MAY_NEED_TO_ALIGN) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) || \
!defined(MBEDTLS_AES_SETKEY_ENC_ALT) */
/*
* AES key schedule (encryption)
@ -558,7 +625,6 @@ static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits)
{
unsigned int i;
uint32_t *RK;
switch (keybits) {
@ -587,19 +653,20 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
#endif
#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
if (mbedtls_aesce_has_support()) {
if (MBEDTLS_AESCE_HAS_SUPPORT()) {
return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits);
}
#endif
for (i = 0; i < (keybits >> 5); i++) {
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
for (unsigned int i = 0; i < (keybits >> 5); i++) {
RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2);
}
switch (ctx->nr) {
case 10:
for (i = 0; i < 10; i++, RK += 4) {
for (unsigned int i = 0; i < 10; i++, RK += 4) {
RK[4] = RK[0] ^ RCON[i] ^
((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^
((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] << 8) ^
@ -615,7 +682,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
case 12:
for (i = 0; i < 8; i++, RK += 6) {
for (unsigned int i = 0; i < 8; i++, RK += 6) {
RK[6] = RK[0] ^ RCON[i] ^
((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^
((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] << 8) ^
@ -632,7 +699,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
case 14:
for (i = 0; i < 7; i++, RK += 8) {
for (unsigned int i = 0; i < 7; i++, RK += 8) {
RK[8] = RK[0] ^ RCON[i] ^
((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^
((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] << 8) ^
@ -658,6 +725,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
}
return 0;
#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
}
#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */
@ -668,10 +736,13 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits)
{
int i, j, ret;
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
uint32_t *SK;
#endif
int ret;
mbedtls_aes_context cty;
uint32_t *RK;
uint32_t *SK;
mbedtls_aes_init(&cty);
@ -694,7 +765,7 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
#endif
#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
if (mbedtls_aesce_has_support()) {
if (MBEDTLS_AESCE_HAS_SUPPORT()) {
mbedtls_aesce_inverse_key(
(unsigned char *) RK,
(const unsigned char *) (cty.buf + cty.rk_offset),
@ -703,15 +774,16 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
}
#endif
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
SK = cty.buf + cty.rk_offset + cty.nr * 4;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) {
for (j = 0; j < 4; j++, SK++) {
SK -= 8;
for (int i = ctx->nr - 1; i > 0; i--, SK -= 8) {
for (int j = 0; j < 4; j++, SK++) {
*RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^
AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^
AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^
@ -723,7 +795,7 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
exit:
mbedtls_aes_free(&cty);
@ -1020,43 +1092,29 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,
#endif
#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
if (mbedtls_aesce_has_support()) {
if (MBEDTLS_AESCE_HAS_SUPPORT()) {
return mbedtls_aesce_crypt_ecb(ctx, mode, input, output);
}
#endif
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
if (aes_padlock_ace > 0) {
return mbedtls_padlock_xcryptecb(ctx, mode, input, output);
}
#endif
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
if (mode == MBEDTLS_AES_ENCRYPT) {
return mbedtls_internal_aes_encrypt(ctx, input, output);
} else {
return mbedtls_internal_aes_decrypt(ctx, input, output);
}
#endif
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
#if defined(__ARM_NEON) && defined(__aarch64__)
/* Avoid using the NEON implementation of mbedtls_xor. Because of the dependency on
* the result for the next block in CBC, and the cost of transferring that data from
* NEON registers, it is faster to use the following on aarch64.
* For 32-bit arm, NEON should be faster. */
#define CBC_XOR_16(r, a, b) do { \
mbedtls_put_unaligned_uint64(r, \
mbedtls_get_unaligned_uint64(a) ^ \
mbedtls_get_unaligned_uint64(b)); \
mbedtls_put_unaligned_uint64(r + 8, \
mbedtls_get_unaligned_uint64(a + 8) ^ \
mbedtls_get_unaligned_uint64(b + 8)); \
} while (0)
#else
#define CBC_XOR_16(r, a, b) mbedtls_xor(r, a, b, 16)
#endif
/*
* AES-CBC buffer encryption/decryption
*/
@ -1074,11 +1132,16 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
/* Nothing to do if length is zero. */
if (length == 0) {
return 0;
}
if (length % 16) {
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
if (aes_padlock_ace > 0) {
if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) {
return 0;
@ -1099,7 +1162,10 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
if (ret != 0) {
goto exit;
}
CBC_XOR_16(output, output, iv);
/* Avoid using the NEON implementation of mbedtls_xor. Because of the dependency on
* the result for the next block in CBC, and the cost of transferring that data from
* NEON registers, NEON is slower on aarch64. */
mbedtls_xor_no_simd(output, output, iv, 16);
memcpy(iv, temp, 16);
@ -1109,7 +1175,7 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
}
} else {
while (length > 0) {
CBC_XOR_16(output, input, ivp);
mbedtls_xor_no_simd(output, input, ivp, 16);
ret = mbedtls_aes_crypt_ecb(ctx, mode, output, output);
if (ret != 0) {
@ -1142,8 +1208,11 @@ typedef unsigned char mbedtls_be128[16];
* for machine endianness and hence works correctly on both big and little
* endian machines.
*/
static void mbedtls_gf128mul_x_ble(unsigned char r[16],
const unsigned char x[16])
#if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C)
MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
#endif
static inline void mbedtls_gf128mul_x_ble(unsigned char r[16],
const unsigned char x[16])
{
uint64_t a, b, ra, rb;
@ -1159,7 +1228,13 @@ static void mbedtls_gf128mul_x_ble(unsigned char r[16],
/*
* AES-XTS buffer encryption/decryption
*
* Use of MBEDTLS_OPTIMIZE_FOR_PERFORMANCE here and for mbedtls_gf128mul_x_ble()
* is a 3x performance improvement for gcc -Os, if we have hardware AES support.
*/
#if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C)
MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
#endif
int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx,
int mode,
size_t length,
@ -1818,22 +1893,33 @@ int mbedtls_aes_self_test(int verbose)
#if defined(MBEDTLS_AES_ALT)
mbedtls_printf(" AES note: alternative implementation.\n");
#else /* MBEDTLS_AES_ALT */
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
mbedtls_printf(" AES note: using VIA Padlock.\n");
} else
#endif
#if defined(MBEDTLS_AESNI_HAVE_CODE)
#if MBEDTLS_AESNI_HAVE_CODE == 1
mbedtls_printf(" AES note: AESNI code present (assembly implementation).\n");
#elif MBEDTLS_AESNI_HAVE_CODE == 2
mbedtls_printf(" AES note: AESNI code present (intrinsics implementation).\n");
#else
#error "Unrecognised value for MBEDTLS_AESNI_HAVE_CODE"
#endif
if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
mbedtls_printf(" AES note: using AESNI.\n");
} else
#endif
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
mbedtls_printf(" AES note: using VIA Padlock.\n");
} else
#endif
#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
if (mbedtls_aesce_has_support()) {
if (MBEDTLS_AESCE_HAS_SUPPORT()) {
mbedtls_printf(" AES note: using AESCE.\n");
} else
#endif
mbedtls_printf(" AES note: built-in implementation.\n");
{
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
mbedtls_printf(" AES note: built-in implementation.\n");
#endif
}
#endif /* MBEDTLS_AES_ALT */
}

View file

@ -66,94 +66,167 @@
# endif
#endif
#if !defined(__ARM_FEATURE_AES) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
# if defined(__clang__)
# pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
#ifdef __ARM_NEON
#include <arm_neon.h>
#else
#error "Target does not support NEON instructions"
#endif
#if !(defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)) || \
defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
# if defined(__ARMCOMPILER_VERSION)
# if __ARMCOMPILER_VERSION <= 6090000
# error "Must use minimum -march=armv8-a+crypto for MBEDTLS_AESCE_C"
# else
# pragma clang attribute push (__attribute__((target("aes"))), apply_to=function)
# define MBEDTLS_POP_TARGET_PRAGMA
# endif
# elif defined(__clang__)
# pragma clang attribute push (__attribute__((target("aes"))), apply_to=function)
# define MBEDTLS_POP_TARGET_PRAGMA
# elif defined(__GNUC__)
# pragma GCC push_options
# pragma GCC target ("arch=armv8-a+crypto")
# pragma GCC target ("+crypto")
# define MBEDTLS_POP_TARGET_PRAGMA
# elif defined(_MSC_VER)
# error "Required feature(__ARM_FEATURE_AES) is not enabled."
# endif
#endif /* !__ARM_FEATURE_AES || MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */
#endif /* !(__ARM_FEATURE_CRYPTO || __ARM_FEATURE_AES) ||
MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */
#include <arm_neon.h>
#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
#if defined(__linux__)
#include <asm/hwcap.h>
#include <sys/auxv.h>
#endif
signed char mbedtls_aesce_has_support_result = -1;
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
/*
* AES instruction support detection routine
*/
int mbedtls_aesce_has_support(void)
int mbedtls_aesce_has_support_impl(void)
{
#if defined(__linux__)
unsigned long auxval = getauxval(AT_HWCAP);
return (auxval & (HWCAP_ASIMD | HWCAP_AES)) ==
(HWCAP_ASIMD | HWCAP_AES);
#else
/* Assume AES instructions are supported. */
return 1;
#endif
/* To avoid many calls to getauxval, cache the result. This is
* thread-safe, because we store the result in a char so cannot
* be vulnerable to non-atomic updates.
* It is possible that we could end up setting result more than
* once, but that is harmless.
*/
if (mbedtls_aesce_has_support_result == -1) {
unsigned long auxval = getauxval(AT_HWCAP);
if ((auxval & (HWCAP_ASIMD | HWCAP_AES)) ==
(HWCAP_ASIMD | HWCAP_AES)) {
mbedtls_aesce_has_support_result = 1;
} else {
mbedtls_aesce_has_support_result = 0;
}
}
return mbedtls_aesce_has_support_result;
}
#endif
#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
/* Single round of AESCE encryption */
#define AESCE_ENCRYPT_ROUND \
block = vaeseq_u8(block, vld1q_u8(keys)); \
block = vaesmcq_u8(block); \
keys += 16
/* Two rounds of AESCE encryption */
#define AESCE_ENCRYPT_ROUND_X2 AESCE_ENCRYPT_ROUND; AESCE_ENCRYPT_ROUND
MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
static uint8x16_t aesce_encrypt_block(uint8x16_t block,
unsigned char *keys,
int rounds)
{
for (int i = 0; i < rounds - 1; i++) {
/* AES AddRoundKey, SubBytes, ShiftRows (in this order).
* AddRoundKey adds the round key for the previous round. */
block = vaeseq_u8(block, vld1q_u8(keys + i * 16));
/* AES mix columns */
block = vaesmcq_u8(block);
/* 10, 12 or 14 rounds. Unroll loop. */
if (rounds == 10) {
goto rounds_10;
}
if (rounds == 12) {
goto rounds_12;
}
AESCE_ENCRYPT_ROUND_X2;
rounds_12:
AESCE_ENCRYPT_ROUND_X2;
rounds_10:
AESCE_ENCRYPT_ROUND_X2;
AESCE_ENCRYPT_ROUND_X2;
AESCE_ENCRYPT_ROUND_X2;
AESCE_ENCRYPT_ROUND_X2;
AESCE_ENCRYPT_ROUND;
/* AES AddRoundKey for the previous round.
* SubBytes, ShiftRows for the final round. */
block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16));
block = vaeseq_u8(block, vld1q_u8(keys));
keys += 16;
/* Final round: no MixColumns */
/* Final AddRoundKey */
block = veorq_u8(block, vld1q_u8(keys + rounds * 16));
block = veorq_u8(block, vld1q_u8(keys));
return block;
}
/* Single round of AESCE decryption
*
* AES AddRoundKey, SubBytes, ShiftRows
*
* block = vaesdq_u8(block, vld1q_u8(keys));
*
* AES inverse MixColumns for the next round.
*
* This means that we switch the order of the inverse AddRoundKey and
* inverse MixColumns operations. We have to do this as AddRoundKey is
* done in an atomic instruction together with the inverses of SubBytes
* and ShiftRows.
*
* It works because MixColumns is a linear operation over GF(2^8) and
* AddRoundKey is an exclusive or, which is equivalent to addition over
* GF(2^8). (The inverse of MixColumns needs to be applied to the
* affected round keys separately which has been done when the
* decryption round keys were calculated.)
*
* block = vaesimcq_u8(block);
*/
#define AESCE_DECRYPT_ROUND \
block = vaesdq_u8(block, vld1q_u8(keys)); \
block = vaesimcq_u8(block); \
keys += 16
/* Two rounds of AESCE decryption */
#define AESCE_DECRYPT_ROUND_X2 AESCE_DECRYPT_ROUND; AESCE_DECRYPT_ROUND
static uint8x16_t aesce_decrypt_block(uint8x16_t block,
unsigned char *keys,
int rounds)
{
for (int i = 0; i < rounds - 1; i++) {
/* AES AddRoundKey, SubBytes, ShiftRows */
block = vaesdq_u8(block, vld1q_u8(keys + i * 16));
/* AES inverse MixColumns for the next round.
*
* This means that we switch the order of the inverse AddRoundKey and
* inverse MixColumns operations. We have to do this as AddRoundKey is
* done in an atomic instruction together with the inverses of SubBytes
* and ShiftRows.
*
* It works because MixColumns is a linear operation over GF(2^8) and
* AddRoundKey is an exclusive or, which is equivalent to addition over
* GF(2^8). (The inverse of MixColumns needs to be applied to the
* affected round keys separately which has been done when the
* decryption round keys were calculated.) */
block = vaesimcq_u8(block);
/* 10, 12 or 14 rounds. Unroll loop. */
if (rounds == 10) {
goto rounds_10;
}
if (rounds == 12) {
goto rounds_12;
}
AESCE_DECRYPT_ROUND_X2;
rounds_12:
AESCE_DECRYPT_ROUND_X2;
rounds_10:
AESCE_DECRYPT_ROUND_X2;
AESCE_DECRYPT_ROUND_X2;
AESCE_DECRYPT_ROUND_X2;
AESCE_DECRYPT_ROUND_X2;
AESCE_DECRYPT_ROUND;
/* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the
* last full round. */
block = vaesdq_u8(block, vld1q_u8(keys + (rounds - 1) * 16));
block = vaesdq_u8(block, vld1q_u8(keys));
keys += 16;
/* Inverse AddRoundKey for inverting the initial round key addition. */
block = veorq_u8(block, vld1q_u8(keys + rounds * 16));
block = veorq_u8(block, vld1q_u8(keys));
return block;
}

View file

@ -42,16 +42,36 @@
extern "C" {
#endif
#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
extern signed char mbedtls_aesce_has_support_result;
/**
* \brief Internal function to detect the crypto extension in CPUs.
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
int mbedtls_aesce_has_support(void);
int mbedtls_aesce_has_support_impl(void);
#define MBEDTLS_AESCE_HAS_SUPPORT() (mbedtls_aesce_has_support_result == -1 ? \
mbedtls_aesce_has_support_impl() : \
mbedtls_aesce_has_support_result)
#else /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
/* If we are not on Linux, we can't detect support so assume that it's supported.
* Similarly, assume support if MBEDTLS_AES_USE_HARDWARE_ONLY is set.
*/
#define MBEDTLS_AESCE_HAS_SUPPORT() 1
#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
/**
* \brief Internal AES-ECB block encryption and decryption
*
* \warning This assumes that the context specifies either 10, 12 or 14
* rounds and will behave incorrectly if this is not the case.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block

View file

@ -35,10 +35,13 @@
#if MBEDTLS_AESNI_HAVE_CODE == 2
#if !defined(_WIN32)
#include <cpuid.h>
#else
#include <intrin.h>
#endif
#include <immintrin.h>
#endif
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
/*
* AES-NI support detection routine
*/
@ -68,6 +71,7 @@ int mbedtls_aesni_has_support(unsigned int what)
return (c & what) != 0;
}
#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
#if MBEDTLS_AESNI_HAVE_CODE == 2

View file

@ -35,13 +35,20 @@
/* Can we do AESNI with inline assembly?
* (Only implemented with gas syntax, only for 64-bit.)
*/
#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
(defined(__amd64__) || defined(__x86_64__)) && \
!defined(MBEDTLS_HAVE_X86_64)
#if !defined(MBEDTLS_HAVE_X86_64) && \
(defined(__amd64__) || defined(__x86_64__) || \
defined(_M_X64) || defined(_M_AMD64)) && \
!defined(_M_ARM64EC)
#define MBEDTLS_HAVE_X86_64
#endif
#if defined(MBEDTLS_AESNI_C)
#if !defined(MBEDTLS_HAVE_X86) && \
(defined(__i386__) || defined(_M_IX86))
#define MBEDTLS_HAVE_X86
#endif
#if defined(MBEDTLS_AESNI_C) && \
(defined(MBEDTLS_HAVE_X86_64) || defined(MBEDTLS_HAVE_X86))
/* Can we do AESNI with intrinsics?
* (Only implemented with certain compilers, only for certain targets.)
@ -59,16 +66,21 @@
#define MBEDTLS_AESNI_HAVE_INTRINSICS
#endif
/* Choose the implementation of AESNI, if one is available. */
#undef MBEDTLS_AESNI_HAVE_CODE
/* To minimize disruption when releasing the intrinsics-based implementation,
* favor the assembly-based implementation if it's available. We intend to
* revise this in a later release of Mbed TLS 3.x. In the long run, we will
* likely remove the assembly implementation. */
#if defined(MBEDTLS_HAVE_X86_64)
#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
/* Choose the implementation of AESNI, if one is available.
*
* Favor the intrinsics-based implementation if it's available, for better
* maintainability.
* Performance is about the same (see #7380).
* In the long run, we will likely remove the assembly implementation. */
#if defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics
#elif defined(MBEDTLS_HAVE_ASM) && \
defined(__GNUC__) && defined(MBEDTLS_HAVE_X86_64)
#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
#elif defined(__GNUC__)
# error "Must use `-mpclmul -msse2 -maes` for MBEDTLS_AESNI_C"
#else
#error "MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available"
#endif
#if defined(MBEDTLS_AESNI_HAVE_CODE)
@ -88,7 +100,11 @@ extern "C" {
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
int mbedtls_aesni_has_support(unsigned int what);
#else
#define mbedtls_aesni_has_support(what) 1
#endif
/**
* \brief Internal AES-NI AES-ECB block encryption and decryption

View file

@ -181,6 +181,9 @@ inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
/* Detect armcc built-in byteswap routine */
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)
#if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */
#include <arm_acle.h>
#endif
#define MBEDTLS_BSWAP32 __rev
#endif

View file

@ -24,6 +24,7 @@
#if defined(MBEDTLS_BASE64_C)
#include "mbedtls/base64.h"
#include "base64_internal.h"
#include "constant_time_internal.h"
#include <stdint.h>
@ -33,6 +34,39 @@
#include "mbedtls/platform.h"
#endif /* MBEDTLS_SELF_TEST */
MBEDTLS_STATIC_TESTABLE
unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
{
unsigned char digit = 0;
/* For each range of values, if value is in that range, mask digit with
* the corresponding value. Since value can only be in a single range,
* only at most one masking will change digit. */
digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value);
digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26);
digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52);
digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+');
digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/');
return digit;
}
MBEDTLS_STATIC_TESTABLE
signed char mbedtls_ct_base64_dec_value(unsigned char c)
{
unsigned char val = 0;
/* For each range of digits, if c is in that range, mask val with
* the corresponding value. Since c can only be in a single range,
* only at most one masking will change val. Set val to one plus
* the desired value so that it stays 0 if c is in none of the ranges. */
val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' + 0 + 1);
val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1);
val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1);
val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1);
val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1);
/* At this point, val is 0 if c is an invalid digit and v+1 if c is
* a digit with the value v. */
return val - 1;
}
/*
* Encode a buffer into base64 format
*/

57
library/base64_internal.h Normal file
View file

@ -0,0 +1,57 @@
/**
* \file base64_internal.h
*
* \brief RFC 1521 base64 encoding/decoding: interfaces for invasive 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 MBEDTLS_BASE64_INTERNAL
#define MBEDTLS_BASE64_INTERNAL
#include "common.h"
#if defined(MBEDTLS_TEST_HOOKS)
/** Given a value in the range 0..63, return the corresponding Base64 digit.
*
* The implementation assumes that letters are consecutive (e.g. ASCII
* but not EBCDIC).
*
* \param value A value in the range 0..63.
*
* \return A base64 digit converted from \p value.
*/
unsigned char mbedtls_ct_base64_enc_char(unsigned char value);
/** Given a Base64 digit, return its value.
*
* If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
* return -1.
*
* The implementation assumes that letters are consecutive (e.g. ASCII
* but not EBCDIC).
*
* \param c A base64 digit.
*
* \return The value of the base64 digit \p c.
*/
signed char mbedtls_ct_base64_dec_value(unsigned char c);
#endif /* MBEDTLS_TEST_HOOKS */
#endif /* MBEDTLS_BASE64_INTERNAL */

View file

@ -54,12 +54,135 @@
#define MPI_VALIDATE(cond) \
MBEDTLS_INTERNAL_VALIDATE(cond)
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
/*
* Compare signed values in constant time
*/
int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
const mbedtls_mpi *Y,
unsigned *ret)
{
mbedtls_platform_zeroize(v, ciL * n);
mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
MPI_VALIDATE_RET(X != NULL);
MPI_VALIDATE_RET(Y != NULL);
MPI_VALIDATE_RET(ret != NULL);
if (X->n != Y->n) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
/*
* Set sign_N to 1 if N >= 0, 0 if N < 0.
* We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
*/
X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
/*
* If the signs are different, then the positive operand is the bigger.
* That is if X is negative (X_is_negative == 1), then X < Y is true and it
* is false if X is positive (X_is_negative == 0).
*/
different_sign = mbedtls_ct_bool_xor(X_is_negative, Y_is_negative); // non-zero if different sign
result = mbedtls_ct_bool_and(different_sign, X_is_negative);
/*
* Assuming signs are the same, compare X and Y. We switch the comparison
* order if they are negative so that we get the right result, regardles of
* sign.
*/
/* This array is used to conditionally swap the pointers in const time */
void * const p[2] = { X->p, Y->p };
size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
/*
* Store in result iff the signs are the same (i.e., iff different_sign == false). If
* the signs differ, result has already been set, so we don't change it.
*/
result = mbedtls_ct_bool_or(result,
mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
*ret = mbedtls_ct_uint_if_else_0(result, 1);
return 0;
}
/*
* Conditionally assign X = Y, without leaking information
* about whether the assignment was made or not.
* (Leaking information about the respective sizes of X and Y is ok however.)
*/
#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
/*
* MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
* https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
*/
__declspec(noinline)
#endif
int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
const mbedtls_mpi *Y,
unsigned char assign)
{
int ret = 0;
MPI_VALIDATE_RET(X != NULL);
MPI_VALIDATE_RET(Y != NULL);
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
X->s = (int) mbedtls_ct_uint_if(do_assign, Y->s, X->s);
mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
for (size_t i = Y->n; i < X->n; i++) {
X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
}
cleanup:
return ret;
}
/*
* Conditionally swap X and Y, without leaking information
* about whether the swap was made or not.
* Here it is not ok to simply swap the pointers, which would lead to
* different memory access patterns when X and Y are used afterwards.
*/
int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
mbedtls_mpi *Y,
unsigned char swap)
{
int ret = 0;
int s;
MPI_VALIDATE_RET(X != NULL);
MPI_VALIDATE_RET(Y != NULL);
if (X == Y) {
return 0;
}
mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
s = X->s;
X->s = (int) mbedtls_ct_uint_if(do_swap, Y->s, X->s);
Y->s = (int) mbedtls_ct_uint_if(do_swap, s, Y->s);
mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
cleanup:
return ret;
}
/* Implementation that should never be optimized out by the compiler */
#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
/*
* Initialize one MPI
*/
@ -82,8 +205,7 @@ void mbedtls_mpi_free(mbedtls_mpi *X)
}
if (X->p != NULL) {
mbedtls_mpi_zeroize(X->p, X->n);
mbedtls_free(X->p);
mbedtls_mpi_zeroize_and_free(X->p, X->n);
}
X->s = 1;
@ -110,11 +232,12 @@ int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
if (X->p != NULL) {
memcpy(p, X->p, X->n * ciL);
mbedtls_mpi_zeroize(X->p, X->n);
mbedtls_free(X->p);
mbedtls_mpi_zeroize_and_free(X->p, X->n);
}
X->n = nblimbs;
/* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
* fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
X->n = (unsigned short) nblimbs;
X->p = p;
}
@ -158,11 +281,12 @@ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
if (X->p != NULL) {
memcpy(p, X->p, i * ciL);
mbedtls_mpi_zeroize(X->p, X->n);
mbedtls_free(X->p);
mbedtls_mpi_zeroize_and_free(X->p, X->n);
}
X->n = i;
/* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
* fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
X->n = (unsigned short) i;
X->p = p;
return 0;
@ -260,6 +384,10 @@ static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
}
/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
* This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
#define TO_SIGN(x) ((((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
/*
* Set value from integer
*/
@ -272,7 +400,7 @@ int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
memset(X->p, 0, X->n * ciL);
X->p[0] = mpi_sint_abs(z);
X->s = (z < 0) ? -1 : 1;
X->s = TO_SIGN(z);
cleanup:
@ -328,16 +456,35 @@ cleanup:
*/
size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
{
size_t i, j, count = 0;
size_t i;
MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
#if defined(__has_builtin)
#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
#define mbedtls_mpi_uint_ctz __builtin_ctz
#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
#define mbedtls_mpi_uint_ctz __builtin_ctzl
#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
#define mbedtls_mpi_uint_ctz __builtin_ctzll
#endif
#endif
#if defined(mbedtls_mpi_uint_ctz)
for (i = 0; i < X->n; i++) {
for (j = 0; j < biL; j++, count++) {
if (X->p[i] != 0) {
return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
}
}
#else
size_t count = 0;
for (i = 0; i < X->n; i++) {
for (size_t j = 0; j < biL; j++, count++) {
if (((X->p[i] >> j) & 1) != 0) {
return count;
}
}
}
#endif
return 0;
}
@ -798,9 +945,8 @@ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
}
}
if (i == 0 && j == 0) {
return 0;
}
/* If i == j == 0, i.e. abs(X) == abs(Y),
* we end up returning 0 at the end of the function. */
if (i > j) {
return 1;
@ -882,7 +1028,7 @@ int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
MPI_VALIDATE_RET(X != NULL);
*p = mpi_sint_abs(z);
Y.s = (z < 0) ? -1 : 1;
Y.s = TO_SIGN(z);
Y.n = 1;
Y.p = p;
@ -896,6 +1042,8 @@ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t j;
mbedtls_mpi_uint *p;
mbedtls_mpi_uint c;
MPI_VALIDATE_RET(X != NULL);
MPI_VALIDATE_RET(A != NULL);
MPI_VALIDATE_RET(B != NULL);
@ -929,9 +1077,9 @@ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
/* j is the number of non-zero limbs of B. Add those to X. */
mbedtls_mpi_uint *p = X->p;
p = X->p;
mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
c = mbedtls_mpi_core_add(p, p, B->p, j);
p += j;
@ -1068,7 +1216,7 @@ int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b
MPI_VALIDATE_RET(A != NULL);
p[0] = mpi_sint_abs(b);
B.s = (b < 0) ? -1 : 1;
B.s = TO_SIGN(b);
B.n = 1;
B.p = p;
@ -1086,7 +1234,7 @@ int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b
MPI_VALIDATE_RET(A != NULL);
p[0] = mpi_sint_abs(b);
B.s = (b < 0) ? -1 : 1;
B.s = TO_SIGN(b);
B.n = 1;
B.p = p;
@ -1436,7 +1584,7 @@ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
MPI_VALIDATE_RET(A != NULL);
p[0] = mpi_sint_abs(b);
B.s = (b < 0) ? -1 : 1;
B.s = TO_SIGN(b);
B.n = 1;
B.p = p;
@ -1574,8 +1722,8 @@ static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
{
mbedtls_mpi_uint z = 1;
mbedtls_mpi U;
U.n = U.s = (int) z;
U.n = 1;
U.s = 1;
U.p = &z;
mpi_montmul(A, &U, N, mm, T);
@ -1602,10 +1750,8 @@ static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_
for (size_t i = 0; i < T_size; i++) {
MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
(unsigned char) mbedtls_ct_size_bool_eq(i,
idx)));
(unsigned char) mbedtls_ct_uint_eq(i, idx)));
}
cleanup:
return ret;
}
@ -1680,8 +1826,9 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
* and squarings. Firstly, when multiplying by an element of the window
* W[i], we do a constant-trace table lookup to obfuscate i. This leaves
* squarings as having a different memory access patterns from other
* multiplications. So secondly, we put the accumulator X in the table as
* well, and also do a constant-trace table lookup to multiply by X.
* multiplications. So secondly, we put the accumulator in the table as
* well, and also do a constant-trace table lookup to multiply by the
* accumulator which is W[x_index].
*
* This way, all multiplications take the form of a lookup-and-multiply.
* The number of lookup-and-multiply operations inside each iteration of
@ -1694,19 +1841,16 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
* observe both memory accesses and branches. However, branch prediction
* exploitation typically requires many traces of execution over the same
* data, which is defeated by randomized blinding.
*
* To achieve this, we make a copy of X and we use the table entry in each
* calculation from this point on.
*/
const size_t x_index = 0;
mbedtls_mpi_init(&W[x_index]);
mbedtls_mpi_copy(&W[x_index], X);
j = N->n + 1;
/* All W[i] and X must have at least N->n limbs for the mpi_montmul()
* and mpi_montred() calls later. Here we ensure that W[1] and X are
* large enough, and later we'll grow other W[i] to the same length.
* They must not be shrunk midway through this function!
/* All W[i] including the accumulator must have at least N->n limbs for
* the mpi_montmul() and mpi_montred() calls later. Here we ensure that
* W[1] and the accumulator W[x_index] are large enough. later we'll grow
* other W[i] to the same length. They must not be shrunk midway through
* this function!
*/
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
@ -1887,7 +2031,7 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
/*
* Load the result in the output variable.
*/
mbedtls_mpi_copy(X, &W[x_index]);
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
cleanup:
@ -2165,29 +2309,30 @@ cleanup:
#if defined(MBEDTLS_GENPRIME)
static const int small_prime[] =
{
3, 5, 7, 11, 13, 17, 19, 23,
29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97,
101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251, 257, 263, 269,
271, 277, 281, 283, 293, 307, 311, 313,
317, 331, 337, 347, 349, 353, 359, 367,
373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461,
463, 467, 479, 487, 491, 499, 503, 509,
521, 523, 541, 547, 557, 563, 569, 571,
577, 587, 593, 599, 601, 607, 613, 617,
619, 631, 641, 643, 647, 653, 659, 661,
673, 677, 683, 691, 701, 709, 719, 727,
733, 739, 743, 751, 757, 761, 769, 773,
787, 797, 809, 811, 821, 823, 827, 829,
839, 853, 857, 859, 863, 877, 881, 883,
887, 907, 911, 919, 929, 937, 941, 947,
953, 967, 971, 977, 983, 991, 997, -103
/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
static const unsigned char small_prime_gaps[] = {
2, 2, 4, 2, 4, 2, 4, 6,
2, 6, 4, 2, 4, 6, 6, 2,
6, 4, 2, 6, 4, 6, 8, 4,
2, 4, 2, 4, 14, 4, 6, 2,
10, 2, 6, 6, 4, 6, 6, 2,
10, 2, 4, 2, 12, 12, 4, 2,
4, 6, 2, 10, 6, 6, 6, 2,
6, 4, 2, 10, 14, 4, 2, 4,
14, 6, 10, 2, 4, 6, 8, 6,
6, 4, 6, 8, 4, 8, 10, 2,
10, 2, 6, 4, 6, 8, 4, 2,
4, 12, 8, 4, 8, 4, 6, 12,
2, 18, 6, 10, 6, 6, 2, 6,
10, 6, 6, 2, 6, 6, 4, 2,
12, 10, 2, 4, 6, 6, 2, 12,
4, 6, 8, 10, 8, 10, 8, 6,
6, 4, 8, 6, 4, 8, 4, 14,
10, 12, 2, 10, 2, 4, 2, 10,
14, 4, 2, 4, 14, 4, 2, 4,
20, 4, 8, 10, 8, 4, 6, 6,
14, 4, 6, 6, 8, 6, /*reaches 997*/
0 /* the last entry is effectively unused */
};
/*
@ -2204,20 +2349,20 @@ static int mpi_check_small_factors(const mbedtls_mpi *X)
int ret = 0;
size_t i;
mbedtls_mpi_uint r;
unsigned p = 3; /* The first odd prime */
if ((X->p[0] & 1) == 0) {
return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
}
for (i = 0; small_prime[i] > 0; i++) {
if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
return 1;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
if (r == 0) {
return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
if (mbedtls_mpi_cmp_int(X, p) == 0) {
return 1;
} else {
return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
}
}
}

View file

@ -36,22 +36,17 @@
size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a)
{
#if defined(__has_builtin)
#if __has_builtin(__builtin_clz)
if (sizeof(mbedtls_mpi_uint) == sizeof(unsigned int)) {
return (size_t) __builtin_clz(a);
}
#endif
#if __has_builtin(__builtin_clzl)
if (sizeof(mbedtls_mpi_uint) == sizeof(unsigned long)) {
return (size_t) __builtin_clzl(a);
}
#endif
#if __has_builtin(__builtin_clzll)
if (sizeof(mbedtls_mpi_uint) == sizeof(unsigned long long)) {
return (size_t) __builtin_clzll(a);
}
#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_clz)
#define core_clz __builtin_clz
#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_clzl)
#define core_clz __builtin_clzl
#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_clzll)
#define core_clz __builtin_clzll
#endif
#endif
#if defined(core_clz)
return (size_t) core_clz(a);
#else
size_t j;
mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
@ -64,6 +59,7 @@ size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a)
}
return j;
#endif
}
size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs)
@ -148,54 +144,92 @@ 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)
mbedtls_ct_condition_t 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);
mbedtls_ct_condition_t min_le_lsl = mbedtls_ct_uint_ge(A[0], min);
/* limbs other than the least significant one are all zero? */
mbedtls_mpi_uint msll_mask = 0;
mbedtls_ct_condition_t msll_mask = MBEDTLS_CT_FALSE;
for (size_t i = 1; i < A_limbs; i++) {
msll_mask |= A[i];
msll_mask = mbedtls_ct_bool_or(msll_mask, mbedtls_ct_bool(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;
return mbedtls_ct_bool_or(msll_mask, min_le_lsl);
}
mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs)
{
mbedtls_ct_condition_t ret = MBEDTLS_CT_FALSE, cond = MBEDTLS_CT_FALSE, done = MBEDTLS_CT_FALSE;
for (size_t i = limbs; i > 0; i--) {
/*
* If B[i - 1] < A[i - 1] then A < B is false and the result must
* remain 0.
*
* Again even if we can make a decision, we just mark the result and
* the fact that we are done and continue looping.
*/
cond = mbedtls_ct_uint_lt(B[i - 1], A[i - 1]);
done = mbedtls_ct_bool_or(done, cond);
/*
* If A[i - 1] < B[i - 1] then A < B is true.
*
* Again even if we can make a decision, we just mark the result and
* the fact that we are done and continue looping.
*/
cond = mbedtls_ct_uint_lt(A[i - 1], B[i - 1]);
ret = mbedtls_ct_bool_or(ret, mbedtls_ct_bool_and(cond, mbedtls_ct_bool_not(done)));
done = mbedtls_ct_bool_or(done, cond);
}
/*
* If all the limbs were equal, then the numbers are equal, A < B is false
* and leaving the result 0 is correct.
*/
return ret;
}
void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned char assign)
mbedtls_ct_condition_t assign)
{
if (X == A) {
return;
}
mbedtls_ct_mpi_uint_cond_assign(limbs, X, A, assign);
/* This function is very performance-sensitive for RSA. For this reason
* we have the loop below, instead of calling mbedtls_ct_memcpy_if
* (this is more optimal since here we don't have to handle the case where
* we copy awkwardly sized data).
*/
for (size_t i = 0; i < limbs; i++) {
X[i] = mbedtls_ct_mpi_uint_if(assign, A[i], X[i]);
}
}
void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
size_t limbs,
unsigned char swap)
mbedtls_ct_condition_t swap)
{
if (X == Y) {
return;
}
/* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(swap);
for (size_t i = 0; i < limbs; i++) {
mbedtls_mpi_uint tmp = X[i];
X[i] = (X[i] & ~limb_mask) | (Y[i] & limb_mask);
Y[i] = (Y[i] & ~limb_mask) | (tmp & limb_mask);
X[i] = mbedtls_ct_mpi_uint_if(swap, Y[i], X[i]);
Y[i] = mbedtls_ct_mpi_uint_if(swap, tmp, Y[i]);
}
}
@ -426,11 +460,10 @@ mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X,
{
mbedtls_mpi_uint c = 0;
/* all-bits 0 if cond is 0, all-bits 1 if cond is non-0 */
const mbedtls_mpi_uint mask = mbedtls_ct_mpi_uint_mask(cond);
mbedtls_ct_condition_t do_add = mbedtls_ct_bool(cond);
for (size_t i = 0; i < limbs; i++) {
mbedtls_mpi_uint add = mask & A[i];
mbedtls_mpi_uint add = mbedtls_ct_mpi_uint_if_else_0(do_add, A[i]);
mbedtls_mpi_uint t = c + X[i];
c = (t < X[i]);
t += add;
@ -572,7 +605,11 @@ void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X,
* So the correct return value is already in X if (carry ^ borrow) = 0,
* but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1.
*/
mbedtls_ct_mpi_uint_cond_assign(AN_limbs, X, T, (unsigned char) (carry ^ borrow));
mbedtls_ct_memcpy_if(mbedtls_ct_bool(carry ^ borrow),
(unsigned char *) X,
(unsigned char *) T,
NULL,
AN_limbs * sizeof(mbedtls_mpi_uint));
}
int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X,
@ -597,7 +634,7 @@ void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest,
size_t index)
{
for (size_t i = 0; i < count; i++, table += limbs) {
unsigned char assign = mbedtls_ct_size_bool_eq(i, index);
mbedtls_ct_condition_t assign = mbedtls_ct_uint_eq(i, index);
mbedtls_mpi_core_cond_assign(dest, table, limbs, assign);
}
}
@ -637,7 +674,7 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
unsigned ge_lower = 1, lt_upper = 0;
mbedtls_ct_condition_t ge_lower = MBEDTLS_CT_TRUE, lt_upper = MBEDTLS_CT_FALSE;
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;
@ -682,7 +719,7 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
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);
} while (mbedtls_ct_bool_and(ge_lower, lt_upper) == MBEDTLS_CT_FALSE);
cleanup:
return ret;
@ -690,16 +727,16 @@ cleanup:
static size_t exp_mod_get_window_size(size_t Ebits)
{
size_t wsize = (Ebits > 671) ? 6 : (Ebits > 239) ? 5 :
(Ebits > 79) ? 4 : 1;
#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
if (wsize > MBEDTLS_MPI_WINDOW_SIZE) {
wsize = MBEDTLS_MPI_WINDOW_SIZE;
}
#if MBEDTLS_MPI_WINDOW_SIZE >= 6
return (Ebits > 671) ? 6 : (Ebits > 239) ? 5 : (Ebits > 79) ? 4 : 1;
#elif MBEDTLS_MPI_WINDOW_SIZE == 5
return (Ebits > 239) ? 5 : (Ebits > 79) ? 4 : 1;
#elif MBEDTLS_MPI_WINDOW_SIZE > 1
return (Ebits > 79) ? MBEDTLS_MPI_WINDOW_SIZE : 1;
#else
(void) Ebits;
return 1;
#endif
return wsize;
}
size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs)

View file

@ -86,6 +86,8 @@
#include "mbedtls/bignum.h"
#endif
#include "constant_time_internal.h"
#define ciL (sizeof(mbedtls_mpi_uint)) /** chars in limb */
#define biL (ciL << 3) /** bits in limb */
#define biH (ciL << 2) /** half limb size */
@ -142,11 +144,29 @@ void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,
* \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.
* \return MBEDTLS_CT_TRUE if \p min is less than or equal to \p A, otherwise MBEDTLS_CT_FALSE.
*/
unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
const mbedtls_mpi_uint *A,
size_t A_limbs);
mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
const mbedtls_mpi_uint *A,
size_t A_limbs);
/**
* \brief Check if one unsigned MPI is less than another in constant
* time.
*
* \param A The left-hand MPI. This must point to an array of limbs
* with the same allocated length as \p B.
* \param B The right-hand MPI. This must point to an array of limbs
* with the same allocated length as \p A.
* \param limbs The number of limbs in \p A and \p B.
* This must not be 0.
*
* \return MBEDTLS_CT_TRUE if \p A is less than \p B.
* MBEDTLS_CT_FALSE if \p A is greater than or equal to \p B.
*/
mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs);
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
@ -158,21 +178,17 @@ unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
* \param[in] A The address of the source MPI. This must be initialized.
* \param limbs The number of limbs of \p A.
* \param assign The condition deciding whether to perform the
* assignment or not. Must be either 0 or 1:
* * \c 1: Perform the assignment `X = A`.
* * \c 0: Keep the original value of \p X.
* assignment or not. Callers will need to use
* the constant time interface (e.g. `mbedtls_ct_bool()`)
* to construct this argument.
*
* \note This function avoids leaking any information about whether
* the assignment was done or not.
*
* \warning If \p assign is neither 0 nor 1, the result of this function
* is indeterminate, and the resulting value in \p X might be
* neither its original value nor the value in \p A.
*/
void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned char assign);
mbedtls_ct_condition_t assign);
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
@ -184,21 +200,15 @@ void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
* This must be initialized.
* \param limbs The number of limbs of \p X and \p Y.
* \param swap The condition deciding whether to perform
* the swap or not. Must be either 0 or 1:
* * \c 1: Swap the values of \p X and \p Y.
* * \c 0: Keep the original values of \p X and \p Y.
* the swap or not.
*
* \note This function avoids leaking any information about whether
* the swap was done or not.
*
* \warning If \p swap is neither 0 nor 1, the result of this function
* is indeterminate, and both \p X and \p Y might end up with
* values different to either of the original ones.
*/
void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
size_t limbs,
unsigned char swap);
mbedtls_ct_condition_t swap);
/** Import X from unsigned binary data, little-endian.
*

View file

@ -19,7 +19,7 @@
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C)
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
#include <string.h>
@ -80,9 +80,8 @@ void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)
switch (N->int_rep) {
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
if (N->rep.mont.rr != NULL) {
mbedtls_platform_zeroize((mbedtls_mpi_uint *) N->rep.mont.rr,
mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr,
N->limbs * sizeof(mbedtls_mpi_uint));
mbedtls_free((mbedtls_mpi_uint *) N->rep.mont.rr);
N->rep.mont.rr = NULL;
}
N->rep.mont.mm = 0;
@ -295,9 +294,8 @@ int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
break;
}
mbedtls_platform_zeroize(working_memory,
mbedtls_zeroize_and_free(working_memory,
working_limbs * sizeof(mbedtls_mpi_uint));
mbedtls_free(working_memory);
return ret;
}
@ -399,11 +397,10 @@ cleanup:
if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY &&
working_memory != NULL) {
mbedtls_platform_zeroize(working_memory, working_memory_len);
mbedtls_free(working_memory);
mbedtls_zeroize_and_free(working_memory, working_memory_len);
}
return ret;
}
#endif /* MBEDTLS_BIGNUM_C */
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */

View file

@ -19,7 +19,7 @@
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C)
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
#include <string.h>
@ -40,7 +40,7 @@ void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign)
{
mbedtls_mpi_core_cond_assign(X, A, N->limbs, assign);
mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));
}
void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
@ -48,7 +48,7 @@ void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap)
{
mbedtls_mpi_core_cond_swap(X, Y, N->limbs, swap);
mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));
}
int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
@ -114,8 +114,6 @@ void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
(void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
}
#if defined(MBEDTLS_TEST_HOOKS)
MBEDTLS_STATIC_TESTABLE
void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N)
@ -125,7 +123,6 @@ void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
(void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
}
#endif /* MBEDTLS_TEST_HOOKS */
void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
@ -133,8 +130,31 @@ void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
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);
/* Standard (A * B) multiplication stored into pre-allocated T
* buffer of fixed limb size of (2N + 1).
*
* The space may not not fully filled by when
* MBEDTLS_MPI_MOD_REP_OPT_RED is used. */
const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2;
switch (N->int_rep) {
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
N->rep.mont.mm, T);
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs);
/* Optimised Reduction */
(*N->rep.ored.modp)(T, T_limbs);
/* Convert back to canonical representation */
mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N);
memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint));
break;
default:
break;
}
}
size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)
@ -233,8 +253,7 @@ int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,
N->rep.mont.mm, N->rep.mont.rr, T);
mbedtls_platform_zeroize(T, t_limbs * ciL);
mbedtls_free(T);
mbedtls_zeroize_and_free(T, t_limbs * ciL);
return 0;
}
@ -250,8 +269,7 @@ int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);
mbedtls_platform_zeroize(T, t_limbs * ciL);
mbedtls_free(T);
mbedtls_zeroize_and_free(T, t_limbs * ciL);
return 0;
}
@ -267,4 +285,4 @@ void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
(void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);
}
#endif /* MBEDTLS_BIGNUM_C */
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */

Some files were not shown because too many files have changed in this diff Show more