feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -59,18 +59,6 @@
// Disable deprecated
#define MBEDTLS_DEPRECATED_REMOVED
// mbedTLS 3.6 finally enabled TLSv1.3 by default, but it requires some mobule
// changes, and to enable PSA crypto (new "standard" API specification).
// Disable it for now.
#undef MBEDTLS_SSL_PROTO_TLS1_3
// Disable PSA Crypto.
#undef MBEDTLS_PSA_CRYPTO_CONFIG
#undef MBEDTLS_PSA_CRYPTO_C
#undef MBEDTLS_PSA_CRYPTO_STORAGE_C
#undef MBEDTLS_PSA_ITS_FILE_C
#undef MBEDTLS_LMS_C
#endif // GODOT_MBEDTLS_INCLUDE_H
#endif // GODOT_MODULE_MBEDTLS_CONFIG_H

View file

@ -880,7 +880,7 @@ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A,
mbedtls_mpi_sint b);
/**
* \brief Perform a sliding-window exponentiation: X = A^E mod N
* \brief Perform a modular exponentiation: X = A^E mod N
*
* \param X The destination MPI. This must point to an initialized MPI.
* This must not alias E or N.

View file

@ -26,16 +26,16 @@
*/
#define MBEDTLS_VERSION_MAJOR 3
#define MBEDTLS_VERSION_MINOR 6
#define MBEDTLS_VERSION_PATCH 0
#define MBEDTLS_VERSION_PATCH 2
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
#define MBEDTLS_VERSION_NUMBER 0x03060000
#define MBEDTLS_VERSION_STRING "3.6.0"
#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.6.0"
#define MBEDTLS_VERSION_NUMBER 0x03060200
#define MBEDTLS_VERSION_STRING "3.6.2"
#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.6.2"
/* Macros for build-time platform detection */
@ -101,6 +101,13 @@
#define inline __inline
#endif
#if defined(MBEDTLS_CONFIG_FILES_READ)
#error "Something went wrong: MBEDTLS_CONFIG_FILES_READ defined before reading the config files!"
#endif
#if defined(MBEDTLS_CONFIG_IS_FINALIZED)
#error "Something went wrong: MBEDTLS_CONFIG_IS_FINALIZED defined before reading the config files!"
#endif
/* X.509, TLS and non-PSA crypto configuration */
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/mbedtls_config.h"
@ -135,6 +142,12 @@
#endif
#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */
/* Indicate that all configuration files have been read.
* It is now time to adjust the configuration (follow through on dependencies,
* make PSA and legacy crypto consistent, etc.).
*/
#define MBEDTLS_CONFIG_FILES_READ
/* 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.
@ -169,8 +182,13 @@
#include "mbedtls/config_adjust_ssl.h"
/* Make sure all configuration symbols are set before including check_config.h,
* even the ones that are calculated programmatically. */
/* Indicate that all configuration symbols are set,
* even the ones that are calculated programmatically.
* It is now safe to query the configuration (to check it, to size buffers,
* etc.).
*/
#define MBEDTLS_CONFIG_IS_FINALIZED
#include "mbedtls/check_config.h"
#endif /* MBEDTLS_BUILD_INFO_H */

View file

@ -2,6 +2,13 @@
* \file check_config.h
*
* \brief Consistency checks for configuration options
*
* This is an internal header. Do not include it directly.
*
* This header is included automatically by all public Mbed TLS headers
* (via mbedtls/build_info.h). Do not include it directly in a configuration
* file such as mbedtls/mbedtls_config.h or #MBEDTLS_USER_CONFIG_FILE!
* It would run at the wrong time due to missing derived symbols.
*/
/*
* Copyright The Mbed TLS Contributors
@ -12,6 +19,13 @@
#define MBEDTLS_CHECK_CONFIG_H
/* *INDENT-OFF* */
#if !defined(MBEDTLS_CONFIG_IS_FINALIZED)
#warning "Do not include mbedtls/check_config.h manually! " \
"This may cause spurious errors. " \
"It is included automatically at the right point since Mbed TLS 3.0."
#endif /* !MBEDTLS_CONFIG_IS_FINALIZED */
/*
* We assume CHAR_BIT is 8 in many places. In practice, this is true on our
* target platforms, so not an issue, but let's just be extra sure.

View file

@ -2,7 +2,9 @@
* \file mbedtls/config_adjust_legacy_crypto.h
* \brief Adjust legacy configuration configuration
*
* Automatically enable certain dependencies. Generally, MBEDLTS_xxx
* This is an internal header. Do not include it directly.
*
* Automatically enable certain dependencies. Generally, MBEDTLS_xxx
* configurations need to be explicitly enabled by the user: enabling
* MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
* compilation error. However, we do automatically enable certain options
@ -22,6 +24,14 @@
#ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H
#define MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
/* Ideally, we'd set those as defaults in mbedtls_config.h, but
* putting an #ifdef _WIN32 in mbedtls_config.h would confuse config.py.
*
@ -48,7 +58,8 @@
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_CCM_STAR_NO_TAG))
defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC))
#define MBEDTLS_CIPHER_C
#endif
@ -293,6 +304,14 @@
#define MBEDTLS_ECP_LIGHT
#endif
/* Backward compatibility: after #8740 the RSA module offers functions to parse
* and write RSA private/public keys without relying on the PK one. Of course
* this needs ASN1 support to do so, so we enable it here. */
#if defined(MBEDTLS_RSA_C)
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C
#endif
/* MBEDTLS_PK_PARSE_EC_COMPRESSED is introduced in Mbed TLS version 3.5, while
* in previous version compressed points were automatically supported as long
* as PK_PARSE_C and ECP_C were enabled. As a consequence, for backward
@ -409,12 +428,12 @@
/* psa_util file features some ECDSA conversion functions, to convert between
* legacy's ASN.1 DER format and PSA's raw one. */
#if defined(MBEDTLS_ECDSA_C) || (defined(MBEDTLS_PSA_CRYPTO_C) && \
#if (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \
(defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)))
#define MBEDTLS_PSA_UTIL_HAVE_ECDSA
#endif
/* Some internal helpers to determine which keys are availble. */
/* Some internal helpers to determine which keys are available. */
#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_AES_C)) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_AES))
#define MBEDTLS_SSL_HAVE_AES
@ -428,7 +447,7 @@
#define MBEDTLS_SSL_HAVE_CAMELLIA
#endif
/* Some internal helpers to determine which operation modes are availble. */
/* Some internal helpers to determine which operation modes are available. */
#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CIPHER_MODE_CBC)) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CBC_NO_PADDING))
#define MBEDTLS_SSL_HAVE_CBC

View file

@ -2,6 +2,8 @@
* \file mbedtls/config_adjust_legacy_from_psa.h
* \brief Adjust PSA configuration: activate legacy implementations
*
* This is an internal header. Do not include it directly.
*
* When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, activate legacy implementations
* of cryptographic mechanisms as needed to fulfill the needs of the PSA
* configuration. Generally speaking, we activate a legacy mechanism if
@ -16,6 +18,14 @@
#ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H
#define MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
/* Define appropriate ACCEL macros for the p256-m driver.
* In the future, those should be generated from the drivers JSON description.
*/
@ -498,7 +508,6 @@
* The PSA implementation has its own implementation of HKDF, separate from
* hkdf.c. No need to enable MBEDTLS_HKDF_C here.
*/
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */
#endif /* PSA_WANT_ALG_HKDF */
@ -509,7 +518,6 @@
* The PSA implementation has its own implementation of HKDF, separate from
* hkdf.c. No need to enable MBEDTLS_HKDF_C here.
*/
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */
#endif /* PSA_WANT_ALG_HKDF_EXTRACT */
@ -520,7 +528,6 @@
* The PSA implementation has its own implementation of HKDF, separate from
* hkdf.c. No need to enable MBEDTLS_HKDF_C here.
*/
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */
#endif /* PSA_WANT_ALG_HKDF_EXPAND */
@ -630,9 +637,6 @@
#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC)
#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1
#define PSA_HAVE_SOFT_PBKDF2_HMAC 1
#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */
#endif /* !MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
#endif /* PSA_WANT_ALG_PBKDF2_HMAC */

View file

@ -2,6 +2,8 @@
* \file mbedtls/config_adjust_psa_from_legacy.h
* \brief Adjust PSA configuration: construct PSA configuration from legacy
*
* This is an internal header. Do not include it directly.
*
* When MBEDTLS_PSA_CRYPTO_CONFIG is disabled, we automatically enable
* cryptographic mechanisms through the PSA interface when the corresponding
* legacy mechanism is enabled. In many cases, this just enables the PSA
@ -18,6 +20,14 @@
#ifndef MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H
#define MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
/*
* Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG
* is not defined

View file

@ -2,6 +2,8 @@
* \file mbedtls/config_adjust_psa_superset_legacy.h
* \brief Adjust PSA configuration: automatic enablement from legacy
*
* This is an internal header. Do not include it directly.
*
* To simplify some edge cases, we automatically enable certain cryptographic
* mechanisms in the PSA API if they are enabled in the legacy API. The general
* idea is that if legacy module M uses mechanism A internally, and A has
@ -17,6 +19,14 @@
#ifndef MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H
#define MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
/****************************************************************/
/* Hashes that are built in are also enabled in PSA.
* This simplifies dependency declarations especially

View file

@ -2,7 +2,9 @@
* \file mbedtls/config_adjust_ssl.h
* \brief Adjust TLS configuration
*
* Automatically enable certain dependencies. Generally, MBEDLTS_xxx
* This is an internal header. Do not include it directly.
*
* Automatically enable certain dependencies. Generally, MBEDTLS_xxx
* configurations need to be explicitly enabled by the user: enabling
* MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
* compilation error. However, we do automatically enable certain options
@ -22,6 +24,14 @@
#ifndef MBEDTLS_CONFIG_ADJUST_SSL_H
#define MBEDTLS_CONFIG_ADJUST_SSL_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
/* 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. */

View file

@ -2,7 +2,9 @@
* \file mbedtls/config_adjust_x509.h
* \brief Adjust X.509 configuration
*
* Automatically enable certain dependencies. Generally, MBEDLTS_xxx
* This is an internal header. Do not include it directly.
*
* Automatically enable certain dependencies. Generally, MBEDTLS_xxx
* configurations need to be explicitly enabled by the user: enabling
* MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
* compilation error. However, we do automatically enable certain options
@ -22,4 +24,12 @@
#ifndef MBEDTLS_CONFIG_ADJUST_X509_H
#define MBEDTLS_CONFIG_ADJUST_X509_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
#endif /* MBEDTLS_CONFIG_ADJUST_X509_H */

View file

@ -22,6 +22,8 @@
#include "psa/crypto_adjust_config_synonyms.h"
#include "psa/crypto_adjust_config_dependencies.h"
#include "mbedtls/config_adjust_psa_superset_legacy.h"
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
@ -32,7 +34,11 @@
* before we deduce what built-ins are required. */
#include "psa/crypto_adjust_config_key_pair_types.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
/* If we are implementing PSA crypto ourselves, then we want to enable the
* required built-ins. Otherwise, PSA features will be provided by the server. */
#include "mbedtls/config_adjust_legacy_from_psa.h"
#endif
#else /* MBEDTLS_PSA_CRYPTO_CONFIG */

View file

@ -32,12 +32,27 @@
#include "mbedtls/build_info.h"
/* In case AES_C is defined then it is the primary option for backward
* compatibility purposes. If that's not available, PSA is used instead */
#if defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#else
/* The CTR_DRBG implementation can either directly call the low-level AES
* module (gated by MBEDTLS_AES_C) or call the PSA API to perform AES
* operations. Calling the AES module directly is the default, both for
* maximum backward compatibility and because it's a bit more efficient
* (less glue code).
*
* When MBEDTLS_AES_C is disabled, the CTR_DRBG module calls PSA crypto and
* thus benefits from the PSA AES accelerator driver.
* It is technically possible to enable MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO
* to use PSA even when MBEDTLS_AES_C is enabled, but there is very little
* reason to do so other than testing purposes and this is not officially
* supported.
*/
#if !defined(MBEDTLS_AES_C)
#define MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO
#endif
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#else
#include "mbedtls/aes.h"
#endif
#include "entropy.h"
@ -157,7 +172,7 @@ extern "C" {
#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN (MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1) / 2
#endif
#if !defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
typedef struct mbedtls_ctr_drbg_psa_context {
mbedtls_svc_key_id_t key_id;
psa_cipher_operation_t operation;
@ -189,10 +204,10 @@ typedef struct mbedtls_ctr_drbg_context {
* This is the maximum number of requests
* that can be made between reseedings. */
#if defined(MBEDTLS_AES_C)
mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx); /*!< The AES context. */
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
mbedtls_ctr_drbg_psa_context MBEDTLS_PRIVATE(psa_ctx); /*!< The PSA context. */
#else
mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx); /*!< The AES context. */
#endif
/*

View file

@ -325,7 +325,7 @@ int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
* \brief This function sets up an ECDH context from an EC key.
*
* It is used by clients and servers in place of the
* ServerKeyEchange for static ECDH, and imports ECDH
* ServerKeyExchange for static ECDH, and imports ECDH
* parameters from the EC key information of a certificate.
*
* \see ecp.h

View file

@ -216,7 +216,7 @@ mbedtls_ecp_point;
* range of <code>0..2^(2*pbits)-1</code>, and transforms it in-place to an integer
* which is congruent mod \p P to the given MPI, and is close enough to \p pbits
* in size, so that it may be efficiently brought in the 0..P-1 range by a few
* additions or subtractions. Therefore, it is only an approximative modular
* additions or subtractions. Therefore, it is only an approximate modular
* reduction. It must return 0 on success and non-zero on failure.
*
* \note Alternative implementations of the ECP module must obey the

View file

@ -1118,7 +1118,7 @@
* MBEDTLS_ECP_DP_SECP256R1_ENABLED
*
* \warning If SHA-256 is provided only by a PSA driver, you must call
* psa_crypto_init() before the first hanshake (even if
* psa_crypto_init() before the first handshake (even if
* MBEDTLS_USE_PSA_CRYPTO is disabled).
*
* This enables the following ciphersuites (if other requisites are
@ -1414,6 +1414,23 @@
*/
//#define MBEDTLS_PSA_CRYPTO_SPM
/**
* \def MBEDTLS_PSA_KEY_STORE_DYNAMIC
*
* Dynamically resize the PSA key store to accommodate any number of
* volatile keys (until the heap memory is exhausted).
*
* If this option is disabled, the key store has a fixed size
* #MBEDTLS_PSA_KEY_SLOT_COUNT for volatile keys and loaded persistent keys
* together.
*
* This option has no effect when #MBEDTLS_PSA_CRYPTO_C is disabled.
*
* Module: library/psa_crypto.c
* Requires: MBEDTLS_PSA_CRYPTO_C
*/
#define MBEDTLS_PSA_KEY_STORE_DYNAMIC
/**
* Uncomment to enable p256-m. This is an alternative implementation of
* key generation, ECDH and (randomized) ECDSA on the curve SECP256R1.
@ -1781,8 +1798,9 @@
* Requires: MBEDTLS_PSA_CRYPTO_C
*
* \note TLS 1.3 uses PSA crypto for cryptographic operations that are
* directly performed by TLS 1.3 code. As a consequence, you must
* call psa_crypto_init() before the first TLS 1.3 handshake.
* directly performed by TLS 1.3 code. As a consequence, when TLS 1.3
* is enabled, a TLS handshake may call psa_crypto_init(), even
* if it ends up negotiating a different TLS version.
*
* \note Cryptographic operations performed indirectly via another module
* (X.509, PK) or by code shared with TLS 1.2 (record protection,
@ -2625,7 +2643,7 @@
* The CTR_DRBG generator uses AES-256 by default.
* To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above.
*
* AES support can either be achived through builtin (MBEDTLS_AES_C) or PSA.
* AES support can either be achieved through builtin (MBEDTLS_AES_C) or PSA.
* Builtin is the default option when MBEDTLS_AES_C is defined otherwise PSA
* is used.
*
@ -4016,22 +4034,38 @@
* Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the
* PSA crypto subsystem.
*
* If this option is unset:
* - If CTR_DRBG is available, the PSA subsystem uses it rather than HMAC_DRBG.
* - Otherwise, the PSA subsystem uses HMAC_DRBG with either
* #MBEDTLS_MD_SHA512 or #MBEDTLS_MD_SHA256 based on availability and
* on unspecified heuristics.
* If this option is unset, the library chooses a hash (currently between
* #MBEDTLS_MD_SHA512 and #MBEDTLS_MD_SHA256) based on availability and
* unspecified heuristics.
*
* \note The PSA crypto subsystem uses the first available mechanism amongst
* the following:
* - #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG if enabled;
* - Entropy from #MBEDTLS_ENTROPY_C plus CTR_DRBG with AES
* if #MBEDTLS_CTR_DRBG_C is enabled;
* - Entropy from #MBEDTLS_ENTROPY_C plus HMAC_DRBG.
*
* A future version may reevaluate the prioritization of DRBG mechanisms.
*/
//#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
/** \def MBEDTLS_PSA_KEY_SLOT_COUNT
* Restrict the PSA library to supporting a maximum amount of simultaneously
* loaded keys. A loaded key is a key stored by the PSA Crypto core as a
* volatile key, or a persistent key which is loaded temporarily by the
* library as part of a crypto operation in flight.
*
* If this option is unset, the library will fall back to a default value of
* 32 keys.
* When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled,
* the maximum amount of PSA keys simultaneously in memory. This counts all
* volatile keys, plus loaded persistent keys.
*
* When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled,
* the maximum number of loaded persistent keys.
*
* Currently, persistent keys do not need to be loaded all the time while
* a multipart operation is in progress, only while the operation is being
* set up. This may change in future versions of the library.
*
* Currently, the library traverses of the whole table on each access to a
* persistent key. Therefore large values may cause poor performance.
*
* This option has no effect when #MBEDTLS_PSA_CRYPTO_C is disabled.
*/
//#define MBEDTLS_PSA_KEY_SLOT_COUNT 32

View file

@ -359,32 +359,40 @@ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info);
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief Initialize a PK context to wrap a PSA key.
* \brief Initialize a PK context to wrap a PSA key.
*
* \note This function replaces mbedtls_pk_setup() for contexts
* that wrap a (possibly opaque) PSA key instead of
* storing and manipulating the key material directly.
* This function creates a PK context which wraps a PSA key. The PSA wrapped
* key must be an EC or RSA key pair (DH is not suported in the PK module).
*
* \param ctx The context to initialize. It must be empty (type NONE).
* \param key The PSA key to wrap, which must hold an ECC or RSA key
* pair (see notes below).
* Under the hood PSA functions will be used to perform the required
* operations and, based on the key type, used algorithms will be:
* * EC:
* * verify, verify_ext, sign, sign_ext: ECDSA.
* * RSA:
* * sign, decrypt: use the primary algorithm in the wrapped PSA key;
* * sign_ext: RSA PSS if the pk_type is #MBEDTLS_PK_RSASSA_PSS, otherwise
* it falls back to the sign() case;
* * verify, verify_ext, encrypt: not supported.
*
* \note The wrapped key must remain valid as long as the
* wrapping PK context is in use, that is at least between
* the point this function is called and the point
* mbedtls_pk_free() is called on this context. The wrapped
* key might then be independently used or destroyed.
* In order for the above operations to succeed, the policy of the wrapped PSA
* key must allow the specified algorithm.
*
* \note This function is currently only available for ECC or RSA
* key pairs (that is, keys containing private key material).
* Support for other key types may be added later.
* Opaque PK contexts wrapping an EC keys also support \c mbedtls_pk_check_pair(),
* whereas RSA ones do not.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input
* (context already used, invalid key identifier).
* \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an
* ECC key pair.
* \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
* \warning The PSA wrapped key must remain valid as long as the wrapping PK
* context is in use, that is at least between the point this function
* is called and the point mbedtls_pk_free() is called on this context.
*
* \param ctx The context to initialize. It must be empty (type NONE).
* \param key The PSA key to wrap, which must hold an ECC or RSA key pair.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input (context already
* used, invalid key identifier).
* \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an ECC or
* RSA key pair.
* \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
*/
int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
const mbedtls_svc_key_id_t key);

View file

@ -83,10 +83,7 @@
/** Processing of the Certificate handshake message failed. */
#define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00
/* Error space gap */
/**
* Received NewSessionTicket Post Handshake Message.
* This error code is experimental and may be changed or removed without notice.
*/
/** A TLS 1.3 NewSessionTicket message has been received. */
#define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00
/** Not possible to read early data */
#define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA -0x7B80
@ -324,6 +321,9 @@
#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0
#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1
#define MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED 0
#define MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED 1
#define MBEDTLS_SSL_PRESET_DEFAULT 0
#define MBEDTLS_SSL_PRESET_SUITEB 2
@ -1446,6 +1446,12 @@ struct mbedtls_ssl_config {
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
defined(MBEDTLS_SSL_CLI_C)
/** Encodes two booleans, one stating whether TLS 1.2 session tickets are
* enabled or not, the other one whether the handling of TLS 1.3
* NewSessionTicket messages is enabled or not. They are respectively set
* by mbedtls_ssl_conf_session_tickets() and
* mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets().
*/
uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */
#endif
@ -2364,7 +2370,7 @@ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl,
*/
int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl,
int *enabled,
unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX],
unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX],
size_t *own_cid_len);
/**
@ -3216,16 +3222,16 @@ void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf,
* a full handshake.
*
* \note This function can handle a variety of mechanisms for session
* resumption: For TLS 1.2, both session ID-based resumption and
* ticket-based resumption will be considered. For TLS 1.3,
* once implemented, sessions equate to tickets, and loading
* one or more sessions via this call will lead to their
* corresponding tickets being advertised as resumption PSKs
* by the client.
*
* \note Calling this function multiple times will only be useful
* once TLS 1.3 is supported. For TLS 1.2 connections, this
* function should be called at most once.
* resumption: For TLS 1.2, both session ID-based resumption
* and ticket-based resumption will be considered. For TLS 1.3,
* sessions equate to tickets, and loading one session by
* calling this function will lead to its corresponding ticket
* being advertised as resumption PSK by the client. This
* depends on session tickets being enabled (see
* #MBEDTLS_SSL_SESSION_TICKETS configuration option) though.
* If session tickets are disabled, a call to this function
* with a TLS 1.3 session, will not have any effect on the next
* handshake for the SSL context \p ssl.
*
* \param ssl The SSL context representing the connection which should
* be attempted to be setup using session resumption. This
@ -3240,9 +3246,10 @@ void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf,
*
* \return \c 0 if successful.
* \return \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session
* could not be loaded because of an implementation limitation.
* This error is non-fatal, and has no observable effect on
* the SSL context or the session that was attempted to be loaded.
* could not be loaded because one session has already been
* loaded. This error is non-fatal, and has no observable
* effect on the SSL context or the session that was attempted
* to be loaded.
* \return Another negative error code on other kinds of failure.
*
* \sa mbedtls_ssl_get_session()
@ -3309,8 +3316,16 @@ int mbedtls_ssl_session_load(mbedtls_ssl_session *session,
* to determine the necessary size by calling this function
* with \p buf set to \c NULL and \p buf_len to \c 0.
*
* \note For TLS 1.3 sessions, this feature is supported only if the
* MBEDTLS_SSL_SESSION_TICKETS configuration option is enabled,
* as in TLS 1.3 session resumption is possible only with
* tickets.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small.
* \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the
* MBEDTLS_SSL_SESSION_TICKETS configuration option is disabled
* and the session is a TLS 1.3 session.
*/
int mbedtls_ssl_session_save(const mbedtls_ssl_session *session,
unsigned char *buf,
@ -4456,21 +4471,50 @@ int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_co
void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order);
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
defined(MBEDTLS_SSL_CLI_C)
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
/**
* \brief Enable / Disable session tickets (client only).
* (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.)
* \brief Enable / Disable TLS 1.2 session tickets (client only,
* TLS 1.2 only). Enabled by default.
*
* \note On server, use \c mbedtls_ssl_conf_session_tickets_cb().
*
* \param conf SSL configuration
* \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or
* MBEDTLS_SSL_SESSION_TICKETS_DISABLED)
* \param use_tickets Enable or disable (#MBEDTLS_SSL_SESSION_TICKETS_ENABLED or
* #MBEDTLS_SSL_SESSION_TICKETS_DISABLED)
*/
void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets);
#endif /* MBEDTLS_SSL_SESSION_TICKETS &&
MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/**
* \brief Enable / Disable handling of TLS 1.3 NewSessionTicket messages
* (client only, TLS 1.3 only).
*
* The handling of TLS 1.3 NewSessionTicket messages is disabled by
* default.
*
* In TLS 1.3, servers may send a NewSessionTicket message at any time,
* and may send multiple NewSessionTicket messages. By default, TLS 1.3
* clients ignore NewSessionTicket messages.
*
* To support session tickets in TLS 1.3 clients, call this function
* with #MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED. When
* this is enabled, when a client receives a NewSessionTicket message,
* the next call to a message processing functions (notably
* mbedtls_ssl_handshake() and mbedtls_ssl_read()) will return
* #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET. The client should then
* call mbedtls_ssl_get_session() to retrieve the session ticket before
* calling the same message processing function again.
*
* \param conf SSL configuration
* \param signal_new_session_tickets Enable or disable
* (#MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED or
* #MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED)
*/
void mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(
mbedtls_ssl_config *conf, int signal_new_session_tickets);
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
defined(MBEDTLS_SSL_SRV_C) && \
@ -4837,23 +4881,16 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl
* \note This function can handle a variety of mechanisms for session
* resumption: For TLS 1.2, both session ID-based resumption and
* ticket-based resumption will be considered. For TLS 1.3,
* once implemented, sessions equate to tickets, and calling
* this function multiple times will export the available
* tickets one a time until no further tickets are available,
* in which case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE will
* be returned.
*
* \note Calling this function multiple times will only be useful
* once TLS 1.3 is supported. For TLS 1.2 connections, this
* function should be called at most once.
* sessions equate to tickets, and if session tickets are
* enabled (see #MBEDTLS_SSL_SESSION_TICKETS configuration
* option), this function exports the last received ticket and
* the exported session may be used to resume the TLS 1.3
* session. If session tickets are disabled, exported sessions
* cannot be used to resume a TLS 1.3 session.
*
* \return \c 0 if successful. In this case, \p session can be used for
* session resumption by passing it to mbedtls_ssl_set_session(),
* and serialized for storage via mbedtls_ssl_session_save().
* \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no further session
* is available for export.
* This error is a non-fatal, and has no observable effect on
* the SSL context or the destination session.
* \return Another negative error code on other kinds of failure.
*
* \sa mbedtls_ssl_set_session()
@ -4885,6 +4922,10 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,
* \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use
* and the client did not demonstrate reachability yet - in
* this case you must stop using the context (see below).
* \return #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3
* NewSessionTicket message has been received. See the
* documentation of mbedtls_ssl_read() for more information
* about this error code.
* \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as
* defined in RFC 8446 (TLS 1.3 specification), has been
* received as part of the handshake. This is server specific
@ -4901,6 +4942,7 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,
* #MBEDTLS_ERR_SSL_WANT_WRITE,
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
* #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or
* #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,
* you must stop using the SSL context for reading or writing,
* and either free it or call \c mbedtls_ssl_session_reset()
@ -4921,10 +4963,13 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,
* currently being processed might or might not contain further
* DTLS records.
*
* \note If the context is configured to allow TLS 1.3, or if
* #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
* \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
* subsystem must have been initialized by calling
* psa_crypto_init() before calling this function.
* Otherwise, the handshake may call psa_crypto_init()
* if a negotiation involving TLS 1.3 takes place (this may
* be the case even if TLS 1.3 is offered but eventually
* not selected).
*/
int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl);
@ -4972,6 +5017,7 @@ static inline int mbedtls_ssl_is_handshake_over(mbedtls_ssl_context *ssl)
* #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
* #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or
* #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, you must stop using
* the SSL context for reading or writing, and either free it
* or call \c mbedtls_ssl_session_reset() on it before
@ -5040,6 +5086,17 @@ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl);
* \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server
* side of a DTLS connection and the client is initiating a
* new connection using the same source port. See below.
* \return #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3
* NewSessionTicket message has been received.
* This error code is only returned on the client side. It is
* only returned if handling of TLS 1.3 NewSessionTicket
* messages has been enabled through
* mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets().
* This error code indicates that a TLS 1.3 NewSessionTicket
* message has been received and parsed successfully by the
* client. The ticket data can be retrieved from the SSL
* context by calling mbedtls_ssl_get_session(). It remains
* available until the next call to mbedtls_ssl_read().
* \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as
* defined in RFC 8446 (TLS 1.3 specification), has been
* received as part of the handshake. This is server specific
@ -5057,6 +5114,7 @@ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl);
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
* #MBEDTLS_ERR_SSL_CLIENT_RECONNECT or
* #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or
* #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,
* you must stop using the SSL context for reading or writing,
* and either free it or call \c mbedtls_ssl_session_reset()
@ -5122,6 +5180,10 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len);
* operation is in progress (see mbedtls_ecp_set_max_ops()) -
* in this case you must call this function again to complete
* the handshake when you're done attending other tasks.
* \return #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3
* NewSessionTicket message has been received. See the
* documentation of mbedtls_ssl_read() for more information
* about this error code.
* \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as
* defined in RFC 8446 (TLS 1.3 specification), has been
* received as part of the handshake. This is server specific
@ -5138,6 +5200,7 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len);
* #MBEDTLS_ERR_SSL_WANT_WRITE,
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
* #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or
* #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,
* you must stop using the SSL context for reading or writing,
* and either free it or call \c mbedtls_ssl_session_reset()

View file

@ -121,8 +121,8 @@ static psa_key_attributes_t psa_key_attributes_init(void);
* value in the structure.
* The persistent key will be written to storage when the attribute
* structure is passed to a key creation function such as
* psa_import_key(), psa_generate_key(), psa_generate_key_ext(),
* psa_key_derivation_output_key(), psa_key_derivation_output_key_ext()
* psa_import_key(), psa_generate_key(), psa_generate_key_custom(),
* psa_key_derivation_output_key(), psa_key_derivation_output_key_custom()
* or psa_copy_key().
*
* This function may be declared as `static` (i.e. without external
@ -131,6 +131,9 @@ static psa_key_attributes_t psa_key_attributes_init(void);
*
* \param[out] attributes The attribute structure to write to.
* \param key The persistent identifier for the key.
* This can be any value in the range from
* #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX
* inclusive.
*/
static void psa_set_key_id(psa_key_attributes_t *attributes,
mbedtls_svc_key_id_t key);
@ -166,8 +169,8 @@ static void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes,
* value in the structure.
* The persistent key will be written to storage when the attribute
* structure is passed to a key creation function such as
* psa_import_key(), psa_generate_key(), psa_generate_key_ext(),
* psa_key_derivation_output_key(), psa_key_derivation_output_key_ext()
* psa_import_key(), psa_generate_key(), psa_generate_key_custom(),
* psa_key_derivation_output_key(), psa_key_derivation_output_key_custom()
* or psa_copy_key().
*
* This function may be declared as `static` (i.e. without external
@ -875,7 +878,7 @@ psa_status_t psa_hash_compute(psa_algorithm_t alg,
* such that #PSA_ALG_IS_HASH(\p alg) is true).
* \param[in] input Buffer containing the message to hash.
* \param input_length Size of the \p input buffer in bytes.
* \param[out] hash Buffer containing the expected hash value.
* \param[in] hash Buffer containing the expected hash value.
* \param hash_length Size of the \p hash buffer in bytes.
*
* \retval #PSA_SUCCESS
@ -1230,7 +1233,7 @@ psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key,
* such that #PSA_ALG_IS_MAC(\p alg) is true).
* \param[in] input Buffer containing the input message.
* \param input_length Size of the \p input buffer in bytes.
* \param[out] mac Buffer containing the expected MAC value.
* \param[in] mac Buffer containing the expected MAC value.
* \param mac_length Size of the \p mac buffer in bytes.
*
* \retval #PSA_SUCCESS
@ -2922,7 +2925,7 @@ psa_status_t psa_sign_message(mbedtls_svc_key_id_t key,
* \p key.
* \param[in] input The message whose signature is to be verified.
* \param[in] input_length Size of the \p input buffer in bytes.
* \param[out] signature Buffer containing the signature to verify.
* \param[in] signature Buffer containing the signature to verify.
* \param[in] signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS \emptydescription
@ -3248,7 +3251,7 @@ static psa_key_derivation_operation_t psa_key_derivation_operation_init(void);
* of or after providing inputs. For some algorithms, this step is mandatory
* because the output depends on the maximum capacity.
* -# To derive a key, call psa_key_derivation_output_key() or
* psa_key_derivation_output_key_ext().
* psa_key_derivation_output_key_custom().
* To derive a byte string for a different purpose, call
* psa_key_derivation_output_bytes().
* Successive calls to these functions use successive output bytes
@ -3471,7 +3474,7 @@ psa_status_t psa_key_derivation_input_integer(
* \note Once all inputs steps are completed, the operations will allow:
* - psa_key_derivation_output_bytes() if each input was either a direct input
* or a key with #PSA_KEY_USAGE_DERIVE set;
* - psa_key_derivation_output_key() or psa_key_derivation_output_key_ext()
* - psa_key_derivation_output_key() or psa_key_derivation_output_key_custom()
* if the input for step
* #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD
* was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was
@ -3721,9 +3724,9 @@ psa_status_t psa_key_derivation_output_bytes(
* on the derived key based on the attributes and strength of the secret key.
*
* \note This function is equivalent to calling
* psa_key_derivation_output_key_ext()
* with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT
* and `params_data_length == 0` (i.e. `params->data` is empty).
* psa_key_derivation_output_key_custom()
* with the custom production parameters #PSA_CUSTOM_KEY_PARAMETERS_INIT
* and `custom_data_length == 0` (i.e. `custom_data` is empty).
*
* \param[in] attributes The attributes for the new key.
* If the key type to be created is
@ -3795,6 +3798,85 @@ psa_status_t psa_key_derivation_output_key(
* the policy must be the same as in the current
* operation.
* \param[in,out] operation The key derivation operation object to read from.
* \param[in] custom Customization parameters for the key generation.
* When this is #PSA_CUSTOM_KEY_PARAMETERS_INIT
* with \p custom_data_length = 0,
* this function is equivalent to
* psa_key_derivation_output_key().
* \param[in] custom_data Variable-length data associated with \c custom.
* \param custom_data_length
* Length of `custom_data` in bytes.
* \param[out] key On success, an identifier for the newly created
* key. For persistent keys, this is the key
* identifier defined in \p attributes.
* \c 0 on failure.
*
* \retval #PSA_SUCCESS
* Success.
* If the key is persistent, the key material and the key's metadata
* have been saved to persistent storage.
* \retval #PSA_ERROR_ALREADY_EXISTS
* This is an attempt to create a persistent key, and there is
* already a persistent key with the given identifier.
* \retval #PSA_ERROR_INSUFFICIENT_DATA
* There was not enough data to create the desired key.
* Note that in this case, no output is written to the output buffer.
* The operation's capacity is set to 0, thus subsequent calls to
* this function will not succeed, even with a smaller output buffer.
* \retval #PSA_ERROR_NOT_SUPPORTED
* The key type or key size is not supported, either by the
* implementation in general or in this particular location.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The provided key attributes are not valid for the operation.
* \retval #PSA_ERROR_NOT_PERMITTED
* The #PSA_KEY_DERIVATION_INPUT_SECRET or
* #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
* key; or one of the inputs was a key whose policy didn't allow
* #PSA_KEY_USAGE_DERIVE.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
* \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
* \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_DATA_INVALID \emptydescription
* \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
* \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
* \retval #PSA_ERROR_BAD_STATE
* The operation state is not valid (it must be active and completed
* all required input steps), or the library has not been previously
* initialized by psa_crypto_init().
* It is implementation-dependent whether a failure to initialize
* results in this error code.
*/
psa_status_t psa_key_derivation_output_key_custom(
const psa_key_attributes_t *attributes,
psa_key_derivation_operation_t *operation,
const psa_custom_key_parameters_t *custom,
const uint8_t *custom_data,
size_t custom_data_length,
mbedtls_svc_key_id_t *key);
#ifndef __cplusplus
/* Omitted when compiling in C++, because one of the parameters is a
* pointer to a struct with a flexible array member, and that is not
* standard C++.
* https://github.com/Mbed-TLS/mbedtls/issues/9020
*/
/** Derive a key from an ongoing key derivation operation with custom
* production parameters.
*
* \note
* This is a deprecated variant of psa_key_derivation_output_key_custom().
* It is equivalent except that the associated variable-length data
* is passed in `params->data` instead of a separate parameter.
* This function will be removed in a future version of Mbed TLS.
*
* \param[in] attributes The attributes for the new key.
* If the key type to be created is
* #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
* the policy must be the same as in the current
* operation.
* \param[in,out] operation The key derivation operation object to read from.
* \param[in] params Customization parameters for the key derivation.
* When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
* with \p params_data_length = 0,
@ -3848,14 +3930,13 @@ psa_status_t psa_key_derivation_output_key(
* It is implementation-dependent whether a failure to initialize
* results in this error code.
*/
#ifndef __cplusplus
psa_status_t psa_key_derivation_output_key_ext(
const psa_key_attributes_t *attributes,
psa_key_derivation_operation_t *operation,
const psa_key_production_parameters_t *params,
size_t params_data_length,
mbedtls_svc_key_id_t *key);
#endif
#endif /* !__cplusplus */
/** Compare output data from a key derivation operation to an expected value.
*
@ -3881,8 +3962,8 @@ psa_status_t psa_key_derivation_output_key_ext(
* psa_key_derivation_abort().
*
* \param[in,out] operation The key derivation operation object to read from.
* \param[in] expected_output Buffer containing the expected derivation output.
* \param output_length Length of the expected output; this is also the
* \param[in] expected Buffer containing the expected derivation output.
* \param expected_length Length of the expected output; this is also the
* number of bytes that will be read.
*
* \retval #PSA_SUCCESS \emptydescription
@ -3912,8 +3993,8 @@ psa_status_t psa_key_derivation_output_key_ext(
*/
psa_status_t psa_key_derivation_verify_bytes(
psa_key_derivation_operation_t *operation,
const uint8_t *expected_output,
size_t output_length);
const uint8_t *expected,
size_t expected_length);
/** Compare output data from a key derivation operation to an expected value
* stored in a key object.
@ -3943,7 +4024,7 @@ psa_status_t psa_key_derivation_verify_bytes(
* operation. The value of this key was likely
* computed by a previous call to
* psa_key_derivation_output_key() or
* psa_key_derivation_output_key_ext().
* psa_key_derivation_output_key_custom().
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_INVALID_SIGNATURE
@ -4111,9 +4192,9 @@ psa_status_t psa_generate_random(uint8_t *output,
* between 2^{n-1} and 2^n where n is the bit size specified in the
* attributes.
*
* \note This function is equivalent to calling psa_generate_key_ext()
* with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT
* and `params_data_length == 0` (i.e. `params->data` is empty).
* \note This function is equivalent to calling psa_generate_key_custom()
* with the custom production parameters #PSA_CUSTOM_KEY_PARAMETERS_INIT
* and `custom_data_length == 0` (i.e. `custom_data` is empty).
*
* \param[in] attributes The attributes for the new key.
* \param[out] key On success, an identifier for the newly created
@ -4153,7 +4234,7 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
* See the description of psa_generate_key() for the operation of this
* function with the default production parameters. In addition, this function
* supports the following production customizations, described in more detail
* in the documentation of ::psa_key_production_parameters_t:
* in the documentation of ::psa_custom_key_parameters_t:
*
* - RSA keys: generation with a custom public exponent.
*
@ -4161,6 +4242,64 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
* versions of Mbed TLS.
*
* \param[in] attributes The attributes for the new key.
* \param[in] custom Customization parameters for the key generation.
* When this is #PSA_CUSTOM_KEY_PARAMETERS_INIT
* with \p custom_data_length = 0,
* this function is equivalent to
* psa_generate_key().
* \param[in] custom_data Variable-length data associated with \c custom.
* \param custom_data_length
* Length of `custom_data` in bytes.
* \param[out] key On success, an identifier for the newly created
* key. For persistent keys, this is the key
* identifier defined in \p attributes.
* \c 0 on failure.
*
* \retval #PSA_SUCCESS
* Success.
* If the key is persistent, the key material and the key's metadata
* have been saved to persistent storage.
* \retval #PSA_ERROR_ALREADY_EXISTS
* This is an attempt to create a persistent key, and there is
* already a persistent key with the given identifier.
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
* \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
* \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
* \retval #PSA_ERROR_DATA_INVALID \emptydescription
* \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
* \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
* \retval #PSA_ERROR_BAD_STATE
* The library has not been previously initialized by psa_crypto_init().
* It is implementation-dependent whether a failure to initialize
* results in this error code.
*/
psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes,
const psa_custom_key_parameters_t *custom,
const uint8_t *custom_data,
size_t custom_data_length,
mbedtls_svc_key_id_t *key);
#ifndef __cplusplus
/* Omitted when compiling in C++, because one of the parameters is a
* pointer to a struct with a flexible array member, and that is not
* standard C++.
* https://github.com/Mbed-TLS/mbedtls/issues/9020
*/
/**
* \brief Generate a key or key pair using custom production parameters.
*
* \note
* This is a deprecated variant of psa_key_derivation_output_key_custom().
* It is equivalent except that the associated variable-length data
* is passed in `params->data` instead of a separate parameter.
* This function will be removed in a future version of Mbed TLS.
*
* \param[in] attributes The attributes for the new key.
* \param[in] params Customization parameters for the key generation.
* When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
* with \p params_data_length = 0,
@ -4196,12 +4335,11 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
* It is implementation-dependent whether a failure to initialize
* results in this error code.
*/
#ifndef __cplusplus
psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
const psa_key_production_parameters_t *params,
size_t params_data_length,
mbedtls_svc_key_id_t *key);
#endif
#endif /* !__cplusplus */
/**@}*/

View file

@ -2,6 +2,8 @@
* \file psa/crypto_adjust_auto_enabled.h
* \brief Adjust PSA configuration: enable always-on features
*
* This is an internal header. Do not include it directly.
*
* Always enable certain features which require a negligible amount of code
* to implement, to avoid some edge cases in the configuration combinatorics.
*/
@ -13,6 +15,14 @@
#ifndef PSA_CRYPTO_ADJUST_AUTO_ENABLED_H
#define PSA_CRYPTO_ADJUST_AUTO_ENABLED_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
#define PSA_WANT_KEY_TYPE_DERIVE 1
#define PSA_WANT_KEY_TYPE_PASSWORD 1
#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1

View file

@ -0,0 +1,51 @@
/**
* \file psa/crypto_adjust_config_dependencies.h
* \brief Adjust PSA configuration by resolving some dependencies.
*
* This is an internal header. Do not include it directly.
*
* See docs/proposed/psa-conditional-inclusion-c.md.
* If the Mbed TLS implementation of a cryptographic mechanism A depends on a
* cryptographic mechanism B then if the cryptographic mechanism A is enabled
* and not accelerated enable B. Note that if A is enabled and accelerated, it
* is not necessary to enable B for A support.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H
#define PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
#if (defined(PSA_WANT_ALG_TLS12_PRF) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)) || \
(defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)) || \
(defined(PSA_WANT_ALG_HKDF) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)) || \
(defined(PSA_WANT_ALG_HKDF_EXTRACT) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT)) || \
(defined(PSA_WANT_ALG_HKDF_EXPAND) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND)) || \
(defined(PSA_WANT_ALG_PBKDF2_HMAC) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC))
#define PSA_WANT_ALG_HMAC 1
#define PSA_WANT_KEY_TYPE_HMAC 1
#endif
#if (defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128))
#define PSA_WANT_KEY_TYPE_AES 1
#define PSA_WANT_ALG_CMAC 1
#endif
#endif /* PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H */

View file

@ -2,6 +2,8 @@
* \file psa/crypto_adjust_config_key_pair_types.h
* \brief Adjust PSA configuration for key pair types.
*
* This is an internal header. Do not include it directly.
*
* See docs/proposed/psa-conditional-inclusion-c.md.
* - Support non-basic operations in a keypair type implicitly enables basic
* support for that keypair type.
@ -19,6 +21,14 @@
#ifndef PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H
#define PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
/*****************************************************************
* ANYTHING -> BASIC
****************************************************************/

View file

@ -2,6 +2,8 @@
* \file psa/crypto_adjust_config_synonyms.h
* \brief Adjust PSA configuration: enable quasi-synonyms
*
* This is an internal header. Do not include it directly.
*
* When two features require almost the same code, we automatically enable
* both when either one is requested, to reduce the combinatorics of
* possible configurations.
@ -14,6 +16,14 @@
#ifndef PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H
#define PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H
#if !defined(MBEDTLS_CONFIG_FILES_READ)
#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
"up to and including runtime errors such as buffer overflows. " \
"If you're trying to fix a complaint from check_config.h, just remove " \
"it from your configuration file: since Mbed TLS 3.0, it is included " \
"automatically at the right point."
#endif /* */
/****************************************************************/
/* De facto synonyms */
/****************************************************************/

View file

@ -154,6 +154,14 @@ static inline void psa_clear_key_slot_number(
* specified in \p attributes.
*
* \param[in] attributes The attributes of the existing key.
* - The lifetime must be a persistent lifetime
* in a secure element. Volatile lifetimes are
* not currently supported.
* - The key identifier must be in the valid
* range for persistent keys.
* - The key type and size must be specified and
* must be consistent with the key material
* in the secure element.
*
* \retval #PSA_SUCCESS
* The key was successfully registered.
@ -479,7 +487,7 @@ psa_status_t mbedtls_psa_external_get_random(
* #PSA_KEY_ID_VENDOR_MIN and #PSA_KEY_ID_VENDOR_MAX and must not intersect
* with any other set of implementation-chosen key identifiers.
*
* This value is part of the library's ABI since changing it would invalidate
* This value is part of the library's API since changing it would invalidate
* the values of built-in key identifiers in applications.
*/
#define MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ((psa_key_id_t) 0x7fff0000)

View file

@ -223,13 +223,36 @@ static inline struct psa_key_derivation_s psa_key_derivation_operation_init(
return v;
}
#ifndef __cplusplus
struct psa_key_production_parameters_s {
struct psa_custom_key_parameters_s {
/* Future versions may add other fields in this structure. */
uint32_t flags;
};
/** The default production parameters for key generation or key derivation.
*
* Calling psa_generate_key_custom() or psa_key_derivation_output_key_custom()
* with `custom=PSA_CUSTOM_KEY_PARAMETERS_INIT` and `custom_data_length=0` is
* equivalent to calling psa_generate_key() or psa_key_derivation_output_key()
* respectively.
*/
#define PSA_CUSTOM_KEY_PARAMETERS_INIT { 0 }
#ifndef __cplusplus
/* Omitted when compiling in C++, because one of the parameters is a
* pointer to a struct with a flexible array member, and that is not
* standard C++.
* https://github.com/Mbed-TLS/mbedtls/issues/9020
*/
/* This is a deprecated variant of `struct psa_custom_key_parameters_s`.
* It has exactly the same layout, plus an extra field which is a flexible
* array member. Thus a `const struct psa_key_production_parameters_s *`
* can be passed to any function that reads a
* `const struct psa_custom_key_parameters_s *`.
*/
struct psa_key_production_parameters_s {
uint32_t flags;
uint8_t data[];
};
#endif
/** The default production parameters for key generation or key derivation.
*
@ -240,6 +263,7 @@ struct psa_key_production_parameters_s {
* respectively.
*/
#define PSA_KEY_PRODUCTION_PARAMETERS_INIT { 0 }
#endif /* !__cplusplus */
struct psa_key_policy_s {
psa_key_usage_t MBEDTLS_PRIVATE(usage);

View file

@ -455,6 +455,30 @@ typedef uint64_t psa_key_slot_number_t;
*/
typedef uint16_t psa_key_derivation_step_t;
/** \brief Custom parameters for key generation or key derivation.
*
* This is a structure type with at least the following field:
*
* - \c flags: an unsigned integer type. 0 for the default production parameters.
*
* Functions that take such a structure as input also take an associated
* input buffer \c custom_data of length \c custom_data_length.
*
* The interpretation of this structure and the associated \c custom_data
* parameter depend on the type of the created key.
*
* - #PSA_KEY_TYPE_RSA_KEY_PAIR:
* - \c flags: must be 0.
* - \c custom_data: the public exponent, in little-endian order.
* This must be an odd integer and must not be 1.
* Implementations must support 65537, should support 3 and may
* support other values.
* When not using a driver, Mbed TLS supports values up to \c INT_MAX.
* If this is empty, the default value 65537 is used.
* - Other key types: reserved for future use. \c flags must be 0.
*/
typedef struct psa_custom_key_parameters_s psa_custom_key_parameters_t;
/** \brief Custom parameters for key generation or key derivation.
*
* This is a structure type with at least the following fields:
@ -477,9 +501,7 @@ typedef uint16_t psa_key_derivation_step_t;
* - Other key types: reserved for future use. \c flags must be 0.
*
*/
#ifndef __cplusplus
typedef struct psa_key_production_parameters_s psa_key_production_parameters_t;
#endif
/**@}*/

View file

@ -27,6 +27,7 @@
#include "mbedtls/bignum.h"
#include "bignum_core.h"
#include "bignum_internal.h"
#include "bn_mul.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
@ -1610,9 +1611,13 @@ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_s
return 0;
}
int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *E, const mbedtls_mpi *N,
mbedtls_mpi *prec_RR)
/*
* Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
* this function is not constant time with respect to the exponent (parameter E).
*/
static int mbedtls_mpi_exp_mod_optionally_safe(mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *E, int E_public,
const mbedtls_mpi *N, mbedtls_mpi *prec_RR)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@ -1695,7 +1700,11 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
{
mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
if (E_public == MBEDTLS_MPI_IS_PUBLIC) {
mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
} else {
mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
}
mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
}
@ -1720,6 +1729,20 @@ cleanup:
return ret;
}
int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *E, const mbedtls_mpi *N,
mbedtls_mpi *prec_RR)
{
return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR);
}
int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *E, const mbedtls_mpi *N,
mbedtls_mpi *prec_RR)
{
return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR);
}
/*
* Greatest common divisor: G = gcd(A, B) (HAC 14.54)
*/

View file

@ -746,7 +746,93 @@ static void exp_mod_precompute_window(const mbedtls_mpi_uint *A,
}
}
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
// Set to a default that is neither MBEDTLS_MPI_IS_PUBLIC nor MBEDTLS_MPI_IS_SECRET
int mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC + MBEDTLS_MPI_IS_SECRET + 1;
#endif
/*
* This function calculates the indices of the exponent where the exponentiation algorithm should
* start processing.
*
* Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
* this function is not constant time with respect to the exponent (parameter E).
*/
static inline void exp_mod_calc_first_bit_optionally_safe(const mbedtls_mpi_uint *E,
size_t E_limbs,
int E_public,
size_t *E_limb_index,
size_t *E_bit_index)
{
if (E_public == MBEDTLS_MPI_IS_PUBLIC) {
/*
* Skip leading zero bits.
*/
size_t E_bits = mbedtls_mpi_core_bitlen(E, E_limbs);
if (E_bits == 0) {
/*
* If E is 0 mbedtls_mpi_core_bitlen() returns 0. Even if that is the case, we will want
* to represent it as a single 0 bit and as such the bitlength will be 1.
*/
E_bits = 1;
}
*E_limb_index = E_bits / biL;
*E_bit_index = E_bits % biL;
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC;
#endif
} else {
/*
* Here we need to be constant time with respect to E and can't do anything better than
* start at the first allocated bit.
*/
*E_limb_index = E_limbs;
*E_bit_index = 0;
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
// Only mark the codepath safe if there wasn't an unsafe codepath before
if (mbedtls_mpi_optionally_safe_codepath != MBEDTLS_MPI_IS_PUBLIC) {
mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_SECRET;
}
#endif
}
}
/*
* Warning! If the parameter window_public has MBEDTLS_MPI_IS_PUBLIC as its value, this function is
* not constant time with respect to the window parameter and consequently the exponent of the
* exponentiation (parameter E of mbedtls_mpi_core_exp_mod_optionally_safe).
*/
static inline void exp_mod_table_lookup_optionally_safe(mbedtls_mpi_uint *Wselect,
mbedtls_mpi_uint *Wtable,
size_t AN_limbs, size_t welem,
mbedtls_mpi_uint window,
int window_public)
{
if (window_public == MBEDTLS_MPI_IS_PUBLIC) {
memcpy(Wselect, Wtable + window * AN_limbs, AN_limbs * ciL);
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC;
#endif
} else {
/* Select Wtable[window] without leaking window through
* memory access patterns. */
mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable,
AN_limbs, welem, window);
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
// Only mark the codepath safe if there wasn't an unsafe codepath before
if (mbedtls_mpi_optionally_safe_codepath != MBEDTLS_MPI_IS_PUBLIC) {
mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_SECRET;
}
#endif
}
}
/* Exponentiation: X := A^E mod N.
*
* Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
* this function is not constant time with respect to the exponent (parameter E).
*
* A must already be in Montgomery form.
*
@ -758,16 +844,25 @@ static void exp_mod_precompute_window(const mbedtls_mpi_uint *A,
* (The difference is that the body in our loop processes a single bit instead
* of a full window.)
*/
void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N,
size_t AN_limbs,
const mbedtls_mpi_uint *E,
size_t E_limbs,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T)
static void mbedtls_mpi_core_exp_mod_optionally_safe(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N,
size_t AN_limbs,
const mbedtls_mpi_uint *E,
size_t E_limbs,
int E_public,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T)
{
const size_t wsize = exp_mod_get_window_size(E_limbs * biL);
/* We'll process the bits of E from most significant
* (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant
* (limb_index=0, E_bit_index=0). */
size_t E_limb_index;
size_t E_bit_index;
exp_mod_calc_first_bit_optionally_safe(E, E_limbs, E_public,
&E_limb_index, &E_bit_index);
const size_t wsize = exp_mod_get_window_size(E_limb_index * biL);
const size_t welem = ((size_t) 1) << wsize;
/* This is how we will use the temporary storage T, which must have space
@ -786,7 +881,7 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N);
/* Set Wtable[i] = A^(2^i) (in Montgomery representation) */
/* Set Wtable[i] = A^i (in Montgomery representation) */
exp_mod_precompute_window(A, N, AN_limbs,
mm, RR,
welem, Wtable, temp);
@ -798,11 +893,6 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
/* X = 1 (in Montgomery presentation) initially */
memcpy(X, Wtable, AN_limbs * ciL);
/* We'll process the bits of E from most significant
* (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant
* (limb_index=0, E_bit_index=0). */
size_t E_limb_index = E_limbs;
size_t E_bit_index = 0;
/* At any given time, window contains window_bits bits from E.
* window_bits can go up to wsize. */
size_t window_bits = 0;
@ -828,10 +918,9 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
* when we've finished processing the exponent. */
if (window_bits == wsize ||
(E_bit_index == 0 && E_limb_index == 0)) {
/* Select Wtable[window] without leaking window through
* memory access patterns. */
mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable,
AN_limbs, welem, window);
exp_mod_table_lookup_optionally_safe(Wselect, Wtable, AN_limbs, welem,
window, E_public);
/* Multiply X by the selected element. */
mbedtls_mpi_core_montmul(X, X, Wselect, AN_limbs, N, AN_limbs, mm,
temp);
@ -841,6 +930,42 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
} while (!(E_bit_index == 0 && E_limb_index == 0));
}
void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N, size_t AN_limbs,
const mbedtls_mpi_uint *E, size_t E_limbs,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T)
{
mbedtls_mpi_core_exp_mod_optionally_safe(X,
A,
N,
AN_limbs,
E,
E_limbs,
MBEDTLS_MPI_IS_SECRET,
RR,
T);
}
void mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N, size_t AN_limbs,
const mbedtls_mpi_uint *E, size_t E_limbs,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T)
{
mbedtls_mpi_core_exp_mod_optionally_safe(X,
A,
N,
AN_limbs,
E,
E_limbs,
MBEDTLS_MPI_IS_PUBLIC,
RR,
T);
}
mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
mbedtls_mpi_uint c, /* doubles as carry */

View file

@ -90,6 +90,27 @@
#define GET_BYTE(X, i) \
(((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
/* Constants to identify whether a value is public or secret. If a parameter is marked as secret by
* this constant, the function must be constant time with respect to the parameter.
*
* This is only needed for functions with the _optionally_safe postfix. All other functions have
* fixed behavior that can't be changed at runtime and are constant time with respect to their
* parameters as prescribed by their documentation or by conventions in their module's documentation.
*
* Parameters should be named X_public where X is the name of the
* corresponding input parameter.
*
* Implementation should always check using
* if (X_public == MBEDTLS_MPI_IS_PUBLIC) {
* // unsafe path
* } else {
* // safe path
* }
* not the other way round, in order to prevent misuse. (This is, if a value
* other than the two below is passed, default to the safe path.) */
#define MBEDTLS_MPI_IS_PUBLIC 0x2a2a2a2a
#define MBEDTLS_MPI_IS_SECRET 0
/** Count leading zero bits in a given integer.
*
* \warning The result is undefined if \p a == 0
@ -604,6 +625,42 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
*/
size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs);
/**
* \brief Perform a modular exponentiation with public or secret exponent:
* X = A^E mod N, where \p A is already in Montgomery form.
*
* \warning This function is not constant time with respect to \p E (the exponent).
*
* \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs ==
* \p AN_limbs.
*
* \param[out] X The destination MPI, as a little endian array of length
* \p AN_limbs.
* \param[in] A The base MPI, as a little endian array of length \p AN_limbs.
* Must be in Montgomery form.
* \param[in] N The modulus, as a little endian array of length \p AN_limbs.
* \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR.
* \param[in] E The exponent, as a little endian array of length \p E_limbs.
* \param E_limbs The number of limbs in \p E.
* \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little
* endian array of length \p AN_limbs.
* \param[in,out] T Temporary storage of at least the number of limbs returned
* by `mbedtls_mpi_core_exp_mod_working_limbs()`.
* Its initial content is unused and its final content is
* indeterminate.
* It must not alias or otherwise overlap any of the other
* parameters.
* It is up to the caller to zeroize \p T when it is no
* longer needed, and before freeing it if it was dynamically
* allocated.
*/
void mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N, size_t AN_limbs,
const mbedtls_mpi_uint *E, size_t E_limbs,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T);
/**
* \brief Perform a modular exponentiation with secret exponent:
* X = A^E mod N, where \p A is already in Montgomery form.
@ -760,4 +817,17 @@ void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X,
mbedtls_mpi_uint mm,
mbedtls_mpi_uint *T);
/*
* Can't define thread local variables with our abstraction layer: do nothing if threading is on.
*/
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
extern int mbedtls_mpi_optionally_safe_codepath;
static inline void mbedtls_mpi_optionally_safe_codepath_reset(void)
{
// Set to a default that is neither MBEDTLS_MPI_IS_PUBLIC nor MBEDTLS_MPI_IS_SECRET
mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC + MBEDTLS_MPI_IS_SECRET + 1;
}
#endif
#endif /* MBEDTLS_BIGNUM_CORE_H */

View file

@ -0,0 +1,50 @@
/**
* \file bignum_internal.h
*
* \brief Internal-only bignum public-key cryptosystem API.
*
* This file declares bignum-related functions that are to be used
* only from within the Mbed TLS library itself.
*
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_BIGNUM_INTERNAL_H
#define MBEDTLS_BIGNUM_INTERNAL_H
/**
* \brief Perform a modular exponentiation: X = A^E mod N
*
* \warning This function is not constant time with respect to \p E (the exponent).
*
* \param X The destination MPI. This must point to an initialized MPI.
* This must not alias E or N.
* \param A The base of the exponentiation.
* This must point to an initialized MPI.
* \param E The exponent MPI. This must point to an initialized MPI.
* \param N The base for the modular reduction. This must point to an
* initialized MPI.
* \param prec_RR A helper MPI depending solely on \p N which can be used to
* speed-up multiple modular exponentiations for the same value
* of \p N. This may be \c NULL. If it is not \c NULL, it must
* point to an initialized MPI. If it hasn't been used after
* the call to mbedtls_mpi_init(), this function will compute
* the helper value and store it in \p prec_RR for reuse on
* subsequent calls to this function. Otherwise, the function
* will assume that \p prec_RR holds the helper value set by a
* previous call to mbedtls_mpi_exp_mod(), and reuse it.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or
* even, or if \c E is negative.
* \return Another negative error code on different kinds of failures.
*
*/
int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *E, const mbedtls_mpi *N,
mbedtls_mpi *prec_RR);
#endif /* bignum_internal.h */

View file

@ -1,394 +0,0 @@
/**
* Modular bignum functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
#include <string.h>
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "mbedtls/bignum.h"
#include "mbedtls/platform.h"
#include "bignum_core.h"
#include "bignum_mod.h"
#include "bignum_mod_raw.h"
#include "constant_time_internal.h"
int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
const mbedtls_mpi_mod_modulus *N,
mbedtls_mpi_uint *p,
size_t p_limbs)
{
if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
r->limbs = N->limbs;
r->p = p;
return 0;
}
void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r)
{
if (r == NULL) {
return;
}
r->limbs = 0;
r->p = NULL;
}
void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N)
{
if (N == NULL) {
return;
}
N->p = NULL;
N->limbs = 0;
N->bits = 0;
N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
}
void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)
{
if (N == NULL) {
return;
}
switch (N->int_rep) {
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
if (N->rep.mont.rr != NULL) {
mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr,
N->limbs * sizeof(mbedtls_mpi_uint));
N->rep.mont.rr = NULL;
}
N->rep.mont.mm = 0;
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
N->rep.ored.modp = NULL;
break;
case MBEDTLS_MPI_MOD_REP_INVALID:
break;
}
N->p = NULL;
N->limbs = 0;
N->bits = 0;
N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
}
static int set_mont_const_square(const mbedtls_mpi_uint **X,
const mbedtls_mpi_uint *A,
size_t limbs)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi N;
mbedtls_mpi RR;
*X = NULL;
mbedtls_mpi_init(&N);
mbedtls_mpi_init(&RR);
if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) {
goto cleanup;
}
if (mbedtls_mpi_grow(&N, limbs)) {
goto cleanup;
}
memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs);
ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
if (ret == 0) {
*X = RR.p;
RR.p = NULL;
}
cleanup:
mbedtls_mpi_free(&N);
mbedtls_mpi_free(&RR);
ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
return ret;
}
static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N,
const mbedtls_mpi_uint *p,
size_t p_limbs,
mbedtls_mpi_mod_rep_selector int_rep)
{
N->p = p;
N->limbs = p_limbs;
N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);
N->int_rep = int_rep;
}
int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
const mbedtls_mpi_uint *p,
size_t p_limbs)
{
int ret = 0;
standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY);
N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
if (ret != 0) {
mbedtls_mpi_mod_modulus_free(N);
}
return ret;
}
int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
const mbedtls_mpi_uint *p,
size_t p_limbs,
mbedtls_mpi_modp_fn modp)
{
standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED);
N->rep.ored.modp = modp;
return 0;
}
int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_residue *B,
const mbedtls_mpi_mod_modulus *N)
{
if (N->limbs == 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL);
if (T == NULL) {
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
}
mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T);
mbedtls_free(T);
return 0;
}
int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_residue *B,
const mbedtls_mpi_mod_modulus *N)
{
if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N);
return 0;
}
static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_modulus *N,
mbedtls_mpi_uint *working_memory)
{
/* Input already in Montgomery form, so there's little to do */
mbedtls_mpi_mod_raw_inv_prime(X->p, A->p,
N->p, N->limbs,
N->rep.mont.rr,
working_memory);
return 0;
}
static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_modulus *N,
mbedtls_mpi_uint *working_memory)
{
/* Need to convert input into Montgomery form */
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_mod_modulus Nmont;
mbedtls_mpi_mod_modulus_init(&Nmont);
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs));
/* We'll use X->p to hold the Montgomery form of the input A->p */
mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,
Nmont.rep.mont.mm, Nmont.rep.mont.rr,
working_memory);
mbedtls_mpi_mod_raw_inv_prime(X->p, X->p,
Nmont.p, Nmont.limbs,
Nmont.rep.mont.rr,
working_memory);
/* And convert back from Montgomery form */
mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs,
Nmont.rep.mont.mm, working_memory);
cleanup:
mbedtls_mpi_mod_modulus_free(&Nmont);
return ret;
}
int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_modulus *N)
{
if (X->limbs != N->limbs || A->limbs != N->limbs) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
/* Zero has the same value regardless of Montgomery form or not */
if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
size_t working_limbs =
mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs);
mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs,
sizeof(mbedtls_mpi_uint));
if (working_memory == NULL) {
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
}
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
switch (N->int_rep) {
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory);
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory);
break;
default:
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
break;
}
mbedtls_zeroize_and_free(working_memory,
working_limbs * sizeof(mbedtls_mpi_uint));
return ret;
}
int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_residue *B,
const mbedtls_mpi_mod_modulus *N)
{
if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);
return 0;
}
int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
mbedtls_mpi_uint min,
const mbedtls_mpi_mod_modulus *N,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
if (X->limbs != N->limbs) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng);
}
int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
const mbedtls_mpi_mod_modulus *N,
const unsigned char *buf,
size_t buflen,
mbedtls_mpi_mod_ext_rep ext_rep)
{
int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
/* Do our best to check if r and m have been set up */
if (r->limbs == 0 || N->limbs == 0) {
goto cleanup;
}
if (r->limbs != N->limbs) {
goto cleanup;
}
ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep);
if (ret != 0) {
goto cleanup;
}
r->limbs = N->limbs;
ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N);
cleanup:
return ret;
}
int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
const mbedtls_mpi_mod_modulus *N,
unsigned char *buf,
size_t buflen,
mbedtls_mpi_mod_ext_rep ext_rep)
{
/* Do our best to check if r and m have been set up */
if (r->limbs == 0 || N->limbs == 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
if (r->limbs != N->limbs) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_uint *working_memory = r->p;
size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs;
if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint));
if (working_memory == NULL) {
ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
goto cleanup;
}
memcpy(working_memory, r->p, working_memory_len);
ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N);
if (ret != 0) {
goto cleanup;
}
}
ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep);
cleanup:
if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY &&
working_memory != NULL) {
mbedtls_zeroize_and_free(working_memory, working_memory_len);
}
return ret;
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */

View file

@ -1,203 +0,0 @@
/**
* \file block_cipher.c
*
* \brief Lightweight abstraction layer for block ciphers with 128 bit blocks,
* for use by the GCM and CCM modules.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
#include "psa/crypto.h"
#include "psa_crypto_core.h"
#include "psa_util_internal.h"
#endif
#include "block_cipher_internal.h"
#if defined(MBEDTLS_BLOCK_CIPHER_C)
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id)
{
switch (cipher_id) {
#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA)
case MBEDTLS_BLOCK_CIPHER_ID_AES:
return PSA_KEY_TYPE_AES;
#endif
#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA)
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
return PSA_KEY_TYPE_ARIA;
#endif
#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA)
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
return PSA_KEY_TYPE_CAMELLIA;
#endif
default:
return PSA_KEY_TYPE_NONE;
}
}
static int mbedtls_cipher_error_from_psa(psa_status_t status)
{
return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors,
psa_generic_status_to_mbedtls);
}
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx)
{
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
psa_destroy_key(ctx->psa_key_id);
return;
}
#endif
switch (ctx->id) {
#if defined(MBEDTLS_AES_C)
case MBEDTLS_BLOCK_CIPHER_ID_AES:
mbedtls_aes_free(&ctx->ctx.aes);
break;
#endif
#if defined(MBEDTLS_ARIA_C)
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
mbedtls_aria_free(&ctx->ctx.aria);
break;
#endif
#if defined(MBEDTLS_CAMELLIA_C)
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
mbedtls_camellia_free(&ctx->ctx.camellia);
break;
#endif
default:
break;
}
ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;
}
int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx,
mbedtls_cipher_id_t cipher_id)
{
ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES :
(cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA :
(cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA :
MBEDTLS_BLOCK_CIPHER_ID_NONE;
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id);
if (psa_key_type != PSA_KEY_TYPE_NONE &&
psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) {
ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA;
return 0;
}
ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY;
#endif
switch (ctx->id) {
#if defined(MBEDTLS_AES_C)
case MBEDTLS_BLOCK_CIPHER_ID_AES:
mbedtls_aes_init(&ctx->ctx.aes);
return 0;
#endif
#if defined(MBEDTLS_ARIA_C)
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
mbedtls_aria_init(&ctx->ctx.aria);
return 0;
#endif
#if defined(MBEDTLS_CAMELLIA_C)
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
mbedtls_camellia_init(&ctx->ctx.camellia);
return 0;
#endif
default:
ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
}
int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx,
const unsigned char *key,
unsigned key_bitlen)
{
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id));
psa_set_key_bits(&key_attr, key_bitlen);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);
status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id);
if (status != PSA_SUCCESS) {
return mbedtls_cipher_error_from_psa(status);
}
psa_reset_key_attributes(&key_attr);
return 0;
}
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
switch (ctx->id) {
#if defined(MBEDTLS_AES_C)
case MBEDTLS_BLOCK_CIPHER_ID_AES:
return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen);
#endif
#if defined(MBEDTLS_ARIA_C)
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen);
#endif
#if defined(MBEDTLS_CAMELLIA_C)
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen);
#endif
default:
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
}
}
int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx,
const unsigned char input[16],
unsigned char output[16])
{
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
psa_status_t status;
size_t olen;
status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING,
input, 16, output, 16, &olen);
if (status != PSA_SUCCESS) {
return mbedtls_cipher_error_from_psa(status);
}
return 0;
}
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
switch (ctx->id) {
#if defined(MBEDTLS_AES_C)
case MBEDTLS_BLOCK_CIPHER_ID_AES:
return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT,
input, output);
#endif
#if defined(MBEDTLS_ARIA_C)
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output);
#endif
#if defined(MBEDTLS_CAMELLIA_C)
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia,
MBEDTLS_CAMELLIA_ENCRYPT,
input, output);
#endif
default:
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
}
}
#endif /* MBEDTLS_BLOCK_CIPHER_C */

View file

@ -849,6 +849,9 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len,
}
padding_len = input[input_len - 1];
if (padding_len == 0 || padding_len > input_len) {
return MBEDTLS_ERR_CIPHER_INVALID_PADDING;
}
*data_len = input_len - padding_len;
mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len);

View file

@ -352,17 +352,19 @@ static inline void mbedtls_xor_no_simd(unsigned char *r,
#endif
/* Always provide a static assert macro, so it can be used unconditionally.
* It will expand to nothing on some systems.
* Can be used outside functions (but don't add a trailing ';' in that case:
* the semicolon is included here to avoid triggering -Wextra-semi when
* MBEDTLS_STATIC_ASSERT() expands to nothing).
* Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
* It does nothing on systems where we don't know how to define a static assert.
*/
/* Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
* defines static_assert even with -std=c99, but then complains about it.
*/
#if defined(static_assert) && !defined(__FreeBSD__)
#define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg);
#define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg)
#else
#define MBEDTLS_STATIC_ASSERT(expr, msg)
/* Make sure `MBEDTLS_STATIC_ASSERT(expr, msg);` is valid both inside and
* outside a function. We choose a struct declaration, which can be repeated
* any number of times and does not need a matching definition. */
#define MBEDTLS_STATIC_ASSERT(expr, msg) \
struct ISO_C_does_not_allow_extra_semicolon_outside_of_a_function
#endif
#if defined(__has_builtin)

View file

@ -26,13 +26,13 @@
#endif
/* Using error translation functions from PSA to MbedTLS */
#if !defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
#include "psa_util_internal.h"
#endif
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx,
unsigned char *key, size_t key_len)
{
@ -73,11 +73,11 @@ static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx)
void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
#if defined(MBEDTLS_AES_C)
mbedtls_aes_init(&ctx->aes_ctx);
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
ctx->psa_ctx.operation = psa_cipher_operation_init();
#else
mbedtls_aes_init(&ctx->aes_ctx);
#endif
/* Indicate that the entropy nonce length is not set explicitly.
* See mbedtls_ctr_drbg_set_nonce_len(). */
@ -102,10 +102,10 @@ void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
mbedtls_mutex_free(&ctx->mutex);
}
#endif
#if defined(MBEDTLS_AES_C)
mbedtls_aes_free(&ctx->aes_ctx);
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
#else
mbedtls_aes_free(&ctx->aes_ctx);
#endif
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
@ -168,15 +168,15 @@ static int block_cipher_df(unsigned char *output,
unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
unsigned char *p, *iv;
int ret = 0;
#if defined(MBEDTLS_AES_C)
mbedtls_aes_context aes_ctx;
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
psa_status_t status;
size_t tmp_len;
mbedtls_ctr_drbg_psa_context psa_ctx;
psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_ctx.operation = psa_cipher_operation_init();
#else
mbedtls_aes_context aes_ctx;
#endif
int i, j;
@ -209,19 +209,19 @@ static int block_cipher_df(unsigned char *output,
key[i] = i;
}
#if defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));
if (status != PSA_SUCCESS) {
ret = psa_generic_status_to_mbedtls(status);
goto exit;
}
#else
mbedtls_aes_init(&aes_ctx);
if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
goto exit;
}
#else
status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));
if (status != PSA_SUCCESS) {
ret = psa_generic_status_to_mbedtls(status);
goto exit;
}
#endif
/*
@ -238,18 +238,18 @@ static int block_cipher_df(unsigned char *output,
use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
#if defined(MBEDTLS_AES_C)
if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
chain, chain)) != 0) {
goto exit;
}
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,
chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
if (status != PSA_SUCCESS) {
ret = psa_generic_status_to_mbedtls(status);
goto exit;
}
#else
if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
chain, chain)) != 0) {
goto exit;
}
#endif
}
@ -264,12 +264,7 @@ static int block_cipher_df(unsigned char *output,
/*
* Do final encryption with reduced data
*/
#if defined(MBEDTLS_AES_C)
if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
goto exit;
}
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
ctr_drbg_destroy_psa_contex(&psa_ctx);
status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
@ -277,32 +272,37 @@ static int block_cipher_df(unsigned char *output,
ret = psa_generic_status_to_mbedtls(status);
goto exit;
}
#else
if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
goto exit;
}
#endif
iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
p = output;
for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
#if defined(MBEDTLS_AES_C)
if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
iv, iv)) != 0) {
goto exit;
}
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,
iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
if (status != PSA_SUCCESS) {
ret = psa_generic_status_to_mbedtls(status);
goto exit;
}
#else
if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
iv, iv)) != 0) {
goto exit;
}
#endif
memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
}
exit:
#if defined(MBEDTLS_AES_C)
mbedtls_aes_free(&aes_ctx);
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
ctr_drbg_destroy_psa_contex(&psa_ctx);
#else
mbedtls_aes_free(&aes_ctx);
#endif
/*
* tidy up the stack
@ -336,7 +336,7 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
unsigned char *p = tmp;
int j;
int ret = 0;
#if !defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
psa_status_t status;
size_t tmp_len;
#endif
@ -352,18 +352,18 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
/*
* Crypt counter block
*/
#if defined(MBEDTLS_AES_C)
if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
ctx->counter, p)) != 0) {
goto exit;
}
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
if (status != PSA_SUCCESS) {
ret = psa_generic_status_to_mbedtls(status);
goto exit;
}
#else
if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
ctx->counter, p)) != 0) {
goto exit;
}
#endif
p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
@ -374,12 +374,7 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
/*
* Update key and counter
*/
#if defined(MBEDTLS_AES_C)
if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
goto exit;
}
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
@ -387,6 +382,11 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
ret = psa_generic_status_to_mbedtls(status);
goto exit;
}
#else
if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
goto exit;
}
#endif
memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
MBEDTLS_CTR_DRBG_BLOCKSIZE);
@ -564,12 +564,7 @@ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
good_nonce_len(ctx->entropy_len));
/* Initialize with an empty key. */
#if defined(MBEDTLS_AES_C)
if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
return ret;
}
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
psa_status_t status;
status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);
@ -577,6 +572,11 @@ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
ret = psa_generic_status_to_mbedtls(status);
return status;
}
#else
if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
return ret;
}
#endif
/* Do the initial seeding. */
@ -655,12 +655,7 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng,
/*
* Crypt counter block
*/
#if defined(MBEDTLS_AES_C)
if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
ctx->counter, locals.tmp)) != 0) {
goto exit;
}
#else
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
psa_status_t status;
size_t tmp_len;
@ -670,6 +665,11 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng,
ret = psa_generic_status_to_mbedtls(status);
goto exit;
}
#else
if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
ctx->counter, locals.tmp)) != 0) {
goto exit;
}
#endif
use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)

File diff suppressed because it is too large Load diff

View file

@ -61,6 +61,10 @@ void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
{
if (ctx == NULL) {
return;
}
/* If the context was already free, don't call free() again.
* This is important for mutexes which don't allow double-free. */
if (ctx->accumulator_started == -1) {

View file

@ -5,10 +5,12 @@
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#if defined(__linux__) || defined(__midipix__) && !defined(_GNU_SOURCE)
#if defined(__linux__) || defined(__midipix__)
/* Ensure that syscall() is available even when compiling with -std=c99 */
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#endif
#include "common.h"

View file

@ -418,7 +418,7 @@ const char *mbedtls_high_level_strerr(int error_code)
case -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE):
return( "SSL - Processing of the Certificate handshake message failed" );
case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET):
return( "SSL - * Received NewSessionTicket Post Handshake Message. This error code is experimental and may be changed or removed without notice" );
return( "SSL - A TLS 1.3 NewSessionTicket message has been received" );
case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA):
return( "SSL - Not possible to read early data" );
case -(MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA):

View file

@ -1,778 +0,0 @@
/*
* The LM-OTS one-time public-key signature scheme
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* The following sources were referenced in the design of this implementation
* of the LM-OTS algorithm:
*
* [1] IETF RFC8554
* D. McGrew, M. Curcio, S.Fluhrer
* https://datatracker.ietf.org/doc/html/rfc8554
*
* [2] NIST Special Publication 800-208
* David A. Cooper et. al.
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
*/
#include "common.h"
#if defined(MBEDTLS_LMS_C)
#include <string.h>
#include "lmots.h"
#include "mbedtls/lms.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "psa_util_internal.h"
#include "psa/crypto.h"
/* Define a local translating function to save code size by not using too many
* arguments in each translating place. */
static int local_err_translation(psa_status_t status)
{
return psa_status_to_mbedtls(status, psa_to_lms_errors,
ARRAY_LENGTH(psa_to_lms_errors),
psa_generic_status_to_mbedtls);
}
#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
#define PUBLIC_KEY_TYPE_OFFSET (0)
#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
MBEDTLS_LMOTS_TYPE_LEN)
#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
MBEDTLS_LMOTS_I_KEY_ID_LEN)
#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \
MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
/* We only support parameter sets that use 8-bit digits, as it does not require
* translation logic between digits and bytes */
#define W_WINTERNITZ_PARAMETER (8u)
#define CHECKSUM_LEN (2)
#define I_DIGIT_IDX_LEN (2)
#define J_HASH_IDX_LEN (1)
#define D_CONST_LEN (2)
#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u)
#define D_CONST_LEN (2)
static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 };
static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 };
#if defined(MBEDTLS_TEST_HOOKS)
int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL;
#endif /* defined(MBEDTLS_TEST_HOOKS) */
/* Calculate the checksum digits that are appended to the end of the LMOTS digit
* string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of
* the checksum algorithm.
*
* params The LMOTS parameter set, I and q values which
* describe the key being used.
*
* digest The digit string to create the digest from. As
* this does not contain a checksum, it is the same
* size as a hash output.
*/
static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params,
const unsigned char *digest)
{
size_t idx;
unsigned sum = 0;
for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) {
sum += DIGIT_MAX_VALUE - digest[idx];
}
return sum;
}
/* Create the string of digest digits (in the base determined by the Winternitz
* parameter with the checksum appended to the end (Q || cksm(Q)). See NIST
* SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm
* 4b step 3) for details.
*
* params The LMOTS parameter set, I and q values which
* describe the key being used.
*
* msg The message that will be hashed to create the
* digest.
*
* msg_size The size of the message.
*
* C_random_value The random value that will be combined with the
* message digest. This is always the same size as a
* hash output for whichever hash algorithm is
* determined by the parameter set.
*
* output An output containing the digit string (+
* checksum) of length P digits (in the case of
* MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of
* size P bytes).
*/
static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params,
const unsigned char *msg,
size_t msg_len,
const unsigned char *C_random_value,
unsigned char *out)
{
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned short checksum;
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, params->q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, C_random_value,
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type));
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, msg, msg_len);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_finish(&op, out,
MBEDTLS_LMOTS_N_HASH_LEN(params->type),
&output_hash_len);
if (status != PSA_SUCCESS) {
goto exit;
}
checksum = lmots_checksum_calculate(params, out);
MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type));
exit:
psa_hash_abort(&op);
return PSA_TO_MBEDTLS_ERR(status);
}
/* Hash each element of the string of digits (+ checksum), producing a hash
* output for each element. This is used in several places (by varying the
* hash_idx_min/max_values) in order to calculate a public key from a private
* key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554
* Algorithm 3 step 5), and to calculate a public key candidate from a
* signature and message (RFC8554 Algorithm 4b step 3).
*
* params The LMOTS parameter set, I and q values which
* describe the key being used.
*
* x_digit_array The array of digits (of size P, 34 in the case of
* MBEDTLS_LMOTS_SHA256_N32_W8).
*
* hash_idx_min_values An array of the starting values of the j iterator
* for each of the members of the digit array. If
* this value in NULL, then all iterators will start
* at 0.
*
* hash_idx_max_values An array of the upper bound values of the j
* iterator for each of the members of the digit
* array. If this value in NULL, then iterator is
* bounded to be less than 2^w - 1 (255 in the case
* of MBEDTLS_LMOTS_SHA256_N32_W8)
*
* output An array containing a hash output for each member
* of the digit string P. In the case of
* MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 *
* 34.
*/
static int hash_digit_array(const mbedtls_lmots_parameters_t *params,
const unsigned char *x_digit_array,
const unsigned char *hash_idx_min_values,
const unsigned char *hash_idx_max_values,
unsigned char *output)
{
unsigned int i_digit_idx;
unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN];
unsigned int j_hash_idx;
unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN];
unsigned int j_hash_idx_min;
unsigned int j_hash_idx_max;
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
for (i_digit_idx = 0;
i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type);
i_digit_idx++) {
memcpy(tmp_hash,
&x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
MBEDTLS_LMOTS_N_HASH_LEN(params->type));
j_hash_idx_min = hash_idx_min_values != NULL ?
hash_idx_min_values[i_digit_idx] : 0;
j_hash_idx_max = hash_idx_max_values != NULL ?
hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE;
for (j_hash_idx = j_hash_idx_min;
j_hash_idx < j_hash_idx_max;
j_hash_idx++) {
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op,
params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op,
params->q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);
status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
j_hash_idx_bytes[0] = (uint8_t) j_hash_idx;
status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, tmp_hash,
MBEDTLS_LMOTS_N_HASH_LEN(params->type));
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash),
&output_hash_len);
if (status != PSA_SUCCESS) {
goto exit;
}
psa_hash_abort(&op);
}
memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type));
}
exit:
psa_hash_abort(&op);
mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash));
return PSA_TO_MBEDTLS_ERR(status);
}
/* Combine the hashes of the digit array into a public key. This is used in
* in order to calculate a public key from a private key (RFC8554 Algorithm 1
* step 4), and to calculate a public key candidate from a signature and message
* (RFC8554 Algorithm 4b step 3).
*
* params The LMOTS parameter set, I and q values which describe
* the key being used.
* y_hashed_digits The array of hashes, one hash for each digit of the
* symbol array (which is of size P, 34 in the case of
* MBEDTLS_LMOTS_SHA256_N32_W8)
*
* pub_key The output public key (or candidate public key in
* case this is being run as part of signature
* verification), in the form of a hash output.
*/
static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params,
const unsigned char *y_hashed_digits,
unsigned char *pub_key)
{
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op,
params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, params->q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, y_hashed_digits,
MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) *
MBEDTLS_LMOTS_N_HASH_LEN(params->type));
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_finish(&op, pub_key,
MBEDTLS_LMOTS_N_HASH_LEN(params->type),
&output_hash_len);
if (status != PSA_SUCCESS) {
exit:
psa_hash_abort(&op);
}
return PSA_TO_MBEDTLS_ERR(status);
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
int mbedtls_lms_error_from_psa(psa_status_t status)
{
switch (status) {
case PSA_SUCCESS:
return 0;
case PSA_ERROR_HARDWARE_FAILURE:
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
case PSA_ERROR_NOT_SUPPORTED:
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
case PSA_ERROR_BUFFER_TOO_SMALL:
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
case PSA_ERROR_INVALID_ARGUMENT:
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
default:
return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
}
}
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx)
{
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
}
int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,
const unsigned char *key, size_t key_len)
{
if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ctx->params.type = (mbedtls_lmots_algorithm_type_t)
MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
memcpy(ctx->params.I_key_identifier,
key + PUBLIC_KEY_I_KEY_ID_OFFSET,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
memcpy(ctx->params.q_leaf_identifier,
key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
memcpy(ctx->public_key,
key + PUBLIC_KEY_KEY_HASH_OFFSET,
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
ctx->have_public_key = 1;
return 0;
}
int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,
unsigned char *key, size_t key_size,
size_t *key_len)
{
if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
}
if (!ctx->have_public_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
ctx->params.I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
ctx->params.q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key,
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
if (key_len != NULL) {
*key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type);
}
return 0;
}
int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,
const unsigned char *msg,
size_t msg_size,
const unsigned char *sig,
size_t sig_size,
unsigned char *out,
size_t out_size,
size_t *out_len)
{
unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (msg == NULL && msg_size != 0) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) ||
out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ret = create_digit_array_with_checksum(params, msg, msg_size,
sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET,
tmp_digit_array);
if (ret) {
return ret;
}
ret = hash_digit_array(params,
sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type),
tmp_digit_array, NULL, (unsigned char *) y_hashed_digits);
if (ret) {
return ret;
}
ret = public_key_from_hashed_digit_array(params,
(unsigned char *) y_hashed_digits,
out);
if (ret) {
return ret;
}
if (out_len != NULL) {
*out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type);
}
return 0;
}
int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,
const unsigned char *msg, size_t msg_size,
const unsigned char *sig, size_t sig_size)
{
unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (msg == NULL && msg_size != 0) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (!ctx->have_public_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params,
msg, msg_size, sig, sig_size,
Kc_public_key_candidate,
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
NULL);
if (ret) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
if (memcmp(&Kc_public_key_candidate, ctx->public_key,
sizeof(ctx->public_key))) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
return 0;
}
#if defined(MBEDTLS_LMS_PRIVATE)
void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx)
{
mbedtls_platform_zeroize(ctx,
sizeof(*ctx));
}
int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
mbedtls_lmots_algorithm_type_t type,
const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
uint32_t q_leaf_identifier,
const unsigned char *seed,
size_t seed_size)
{
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned int i_digit_idx;
unsigned char i_digit_idx_bytes[2];
unsigned char const_bytes[1] = { 0xFF };
if (ctx->have_private_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (type != MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ctx->params.type = type;
memcpy(ctx->params.I_key_identifier,
I_key_identifier,
sizeof(ctx->params.I_key_identifier));
MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0);
for (i_digit_idx = 0;
i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type);
i_digit_idx++) {
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op,
ctx->params.I_key_identifier,
sizeof(ctx->params.I_key_identifier));
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op,
ctx->params.q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);
status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, const_bytes, sizeof(const_bytes));
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, seed, seed_size);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_finish(&op,
ctx->private_key[i_digit_idx],
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
&output_hash_len);
if (status != PSA_SUCCESS) {
goto exit;
}
psa_hash_abort(&op);
}
ctx->have_private_key = 1;
exit:
psa_hash_abort(&op);
return PSA_TO_MBEDTLS_ERR(status);
}
int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,
const mbedtls_lmots_private_t *priv_ctx)
{
unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Check that a private key is loaded */
if (!priv_ctx->have_private_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ret = hash_digit_array(&priv_ctx->params,
(unsigned char *) priv_ctx->private_key, NULL,
NULL, (unsigned char *) y_hashed_digits);
if (ret) {
goto exit;
}
ret = public_key_from_hashed_digit_array(&priv_ctx->params,
(unsigned char *) y_hashed_digits,
ctx->public_key);
if (ret) {
goto exit;
}
memcpy(&ctx->params, &priv_ctx->params,
sizeof(ctx->params));
ctx->have_public_key = 1;
exit:
mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits));
return ret;
}
int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, const unsigned char *msg, size_t msg_size,
unsigned char *sig, size_t sig_size, size_t *sig_len)
{
unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
/* Create a temporary buffer to prepare the signature in. This allows us to
* finish creating a signature (ensuring the process doesn't fail), and then
* erase the private key **before** writing any data into the sig parameter
* buffer. If data were directly written into the sig buffer, it might leak
* a partial signature on failure, which effectively compromises the private
* key.
*/
unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (msg == NULL && msg_size != 0) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) {
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
}
/* Check that a private key is loaded */
if (!ctx->have_private_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ret = f_rng(p_rng, tmp_c_random,
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
if (ret) {
return ret;
}
ret = create_digit_array_with_checksum(&ctx->params,
msg, msg_size,
tmp_c_random,
tmp_digit_array);
if (ret) {
goto exit;
}
ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key,
NULL, tmp_digit_array, (unsigned char *) tmp_sig);
if (ret) {
goto exit;
}
MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
/* Test hook to check if sig is being written to before we invalidate the
* private key.
*/
#if defined(MBEDTLS_TEST_HOOKS)
if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) {
ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig);
if (ret != 0) {
return ret;
}
}
#endif /* defined(MBEDTLS_TEST_HOOKS) */
/* We've got a valid signature now, so it's time to make sure the private
* key can't be reused.
*/
ctx->have_private_key = 0;
mbedtls_platform_zeroize(ctx->private_key,
sizeof(ctx->private_key));
memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random,
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type));
memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig,
MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type)
* MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
if (sig_len != NULL) {
*sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type);
}
ret = 0;
exit:
mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array));
mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig));
return ret;
}
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
#endif /* defined(MBEDTLS_LMS_C) */

View file

@ -1,761 +0,0 @@
/*
* The LMS stateful-hash public-key signature scheme
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* The following sources were referenced in the design of this implementation
* of the LMS algorithm:
*
* [1] IETF RFC8554
* D. McGrew, M. Curcio, S.Fluhrer
* https://datatracker.ietf.org/doc/html/rfc8554
*
* [2] NIST Special Publication 800-208
* David A. Cooper et. al.
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
*/
#include "common.h"
#if defined(MBEDTLS_LMS_C)
#include <string.h>
#include "lmots.h"
#include "psa/crypto.h"
#include "psa_util_internal.h"
#include "mbedtls/lms.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/platform.h"
/* Define a local translating function to save code size by not using too many
* arguments in each translating place. */
static int local_err_translation(psa_status_t status)
{
return psa_status_to_mbedtls(status, psa_to_lms_errors,
ARRAY_LENGTH(psa_to_lms_errors),
psa_generic_status_to_mbedtls);
}
#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
#define SIG_Q_LEAF_ID_OFFSET (0)
#define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \
MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \
MBEDTLS_LMOTS_SIG_LEN(otstype))
#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \
MBEDTLS_LMS_TYPE_LEN)
#define PUBLIC_KEY_TYPE_OFFSET (0)
#define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
MBEDTLS_LMS_TYPE_LEN)
#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \
MBEDTLS_LMOTS_TYPE_LEN)
#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
MBEDTLS_LMOTS_I_KEY_ID_LEN)
/* Currently only support H=10 */
#define H_TREE_HEIGHT_MAX 10
#define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
#define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \
(1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)))
#define D_CONST_LEN (2)
static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };
static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 };
/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a
* public key and some other parameters like the leaf index). This function
* implements RFC8554 section 5.3, in the case where r >= 2^h.
*
* params The LMS parameter set, the underlying LMOTS
* parameter set, and I value which describe the key
* being used.
*
* pub_key The public key of the private whose index
* corresponds to the index of this leaf node. This
* is a hash output.
*
* r_node_idx The index of this node in the Merkle tree. Note
* that the root node of the Merkle tree is
* 1-indexed.
*
* out The output node value, which is a hash output.
*/
static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params,
unsigned char *pub_key,
unsigned int r_node_idx,
unsigned char *out)
{
psa_hash_operation_t op;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned char r_node_idx_bytes[4];
op = psa_hash_operation_init();
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
status = psa_hash_update(&op, r_node_idx_bytes, 4);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, pub_key,
MBEDTLS_LMOTS_N_HASH_LEN(params->otstype));
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
&output_hash_len);
if (status != PSA_SUCCESS) {
goto exit;
}
exit:
psa_hash_abort(&op);
return PSA_TO_MBEDTLS_ERR(status);
}
/* Calculate the value of an internal node of the Merkle tree (which is a hash
* of a public key and some other parameters like the node index). This function
* implements RFC8554 section 5.3, in the case where r < 2^h.
*
* params The LMS parameter set, the underlying LMOTS
* parameter set, and I value which describe the key
* being used.
*
* left_node The value of the child of this node which is on
* the left-hand side. As with all nodes on the
* Merkle tree, this is a hash output.
*
* right_node The value of the child of this node which is on
* the right-hand side. As with all nodes on the
* Merkle tree, this is a hash output.
*
* r_node_idx The index of this node in the Merkle tree. Note
* that the root node of the Merkle tree is
* 1-indexed.
*
* out The output node value, which is a hash output.
*/
static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params,
const unsigned char *left_node,
const unsigned char *right_node,
unsigned int r_node_idx,
unsigned char *out)
{
psa_hash_operation_t op;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned char r_node_idx_bytes[4];
op = psa_hash_operation_init();
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
status = psa_hash_update(&op, r_node_idx_bytes, 4);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, left_node,
MBEDTLS_LMS_M_NODE_BYTES(params->type));
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&op, right_node,
MBEDTLS_LMS_M_NODE_BYTES(params->type));
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
&output_hash_len);
if (status != PSA_SUCCESS) {
goto exit;
}
exit:
psa_hash_abort(&op);
return PSA_TO_MBEDTLS_ERR(status);
}
void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx)
{
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
}
int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,
const unsigned char *key, size_t key_size)
{
mbedtls_lms_algorithm_type_t type;
mbedtls_lmots_algorithm_type_t otstype;
type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET);
if (type != MBEDTLS_LMS_SHA256_M32_H10) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ctx->params.type = type;
if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
otstype = (mbedtls_lmots_algorithm_type_t)
MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET);
if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ctx->params.otstype = otstype;
memcpy(ctx->params.I_key_identifier,
key + PUBLIC_KEY_I_KEY_ID_OFFSET,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET,
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
ctx->have_public_key = 1;
return 0;
}
int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,
unsigned char *key,
size_t key_size, size_t *key_len)
{
if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
}
if (!ctx->have_public_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET);
MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET);
memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
ctx->params.I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET,
ctx->T_1_pub_key,
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
if (key_len != NULL) {
*key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type);
}
return 0;
}
int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
const unsigned char *msg, size_t msg_size,
const unsigned char *sig, size_t sig_size)
{
unsigned int q_leaf_identifier;
unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX];
unsigned int height;
unsigned int curr_node_id;
unsigned int parent_node_id;
const unsigned char *left_node;
const unsigned char *right_node;
mbedtls_lmots_parameters_t ots_params;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (!ctx->have_public_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (ctx->params.type
!= MBEDTLS_LMS_SHA256_M32_H10) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (ctx->params.otstype
!= MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET)
!= MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype))
!= MBEDTLS_LMS_SHA256_M32_H10) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET);
if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
memcpy(ots_params.I_key_identifier,
ctx->params.I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0);
ots_params.type = ctx->params.otstype;
ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params,
msg,
msg_size,
sig + SIG_OTS_SIG_OFFSET,
MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype),
Kc_candidate_ots_pub_key,
sizeof(Kc_candidate_ots_pub_key),
NULL);
if (ret != 0) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
create_merkle_leaf_value(
&ctx->params,
Kc_candidate_ots_pub_key,
MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
Tc_candidate_root_node);
curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) +
q_leaf_identifier;
for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
height++) {
parent_node_id = curr_node_id / 2;
/* Left/right node ordering matters for the hash */
if (curr_node_id & 1) {
left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
right_node = Tc_candidate_root_node;
} else {
left_node = Tc_candidate_root_node;
right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
}
create_merkle_internal_value(&ctx->params, left_node, right_node,
parent_node_id, Tc_candidate_root_node);
curr_node_id /= 2;
}
if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key,
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) {
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
}
return 0;
}
#if defined(MBEDTLS_LMS_PRIVATE)
/* Calculate a full Merkle tree based on a private key. This function
* implements RFC8554 section 5.3, and is used to generate a public key (as the
* public key is the root node of the Merkle tree).
*
* ctx The LMS private context, containing a parameter
* set and private key material consisting of both
* public and private OTS.
*
* tree The output tree, which is 2^(H + 1) hash outputs.
* In the case of H=10 we have 2048 tree nodes (of
* which 1024 of them are leaf nodes). Note that
* because the Merkle tree root is 1-indexed, the 0
* index tree node is never used.
*/
static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx,
unsigned char *tree)
{
unsigned int priv_key_idx;
unsigned int r_node_idx;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* First create the leaf nodes, in ascending order */
for (priv_key_idx = 0;
priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type);
priv_key_idx++) {
r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx;
ret = create_merkle_leaf_value(&ctx->params,
ctx->ots_public_keys[priv_key_idx].public_key,
r_node_idx,
&tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(
ctx->params.type)]);
if (ret != 0) {
return ret;
}
}
/* Then the internal nodes, in reverse order so that we can guarantee the
* parent has been created */
for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1;
r_node_idx > 0;
r_node_idx--) {
ret = create_merkle_internal_value(&ctx->params,
&tree[(r_node_idx * 2) *
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
&tree[(r_node_idx * 2 + 1) *
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
r_node_idx,
&tree[r_node_idx *
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]);
if (ret != 0) {
return ret;
}
}
return 0;
}
/* Calculate a path from a leaf node of the Merkle tree to the root of the tree,
* and return the full path. This function implements RFC8554 section 5.4.1, as
* the Merkle path is the main component of an LMS signature.
*
* ctx The LMS private context, containing a parameter
* set and private key material consisting of both
* public and private OTS.
*
* leaf_node_id Which leaf node to calculate the path from.
*
* path The output path, which is H hash outputs.
*/
static int get_merkle_path(mbedtls_lms_private_t *ctx,
unsigned int leaf_node_id,
unsigned char *path)
{
const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
unsigned int curr_node_id = leaf_node_id;
unsigned int adjacent_node_id;
unsigned char *tree = NULL;
unsigned int height;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type),
node_bytes);
if (tree == NULL) {
return MBEDTLS_ERR_LMS_ALLOC_FAILED;
}
ret = calculate_merkle_tree(ctx, tree);
if (ret != 0) {
goto exit;
}
for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
height++) {
adjacent_node_id = curr_node_id ^ 1;
memcpy(&path[height * node_bytes],
&tree[adjacent_node_id * node_bytes], node_bytes);
curr_node_id >>= 1;
}
ret = 0;
exit:
mbedtls_zeroize_and_free(tree, node_bytes *
(size_t) MERKLE_TREE_NODE_AM(ctx->params.type));
return ret;
}
void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx)
{
unsigned int idx;
if (ctx->have_private_key) {
if (ctx->ots_private_keys != NULL) {
for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]);
}
}
if (ctx->ots_public_keys != NULL) {
for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]);
}
}
mbedtls_free(ctx->ots_private_keys);
mbedtls_free(ctx->ots_public_keys);
}
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
}
int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx,
mbedtls_lms_algorithm_type_t type,
mbedtls_lmots_algorithm_type_t otstype,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, const unsigned char *seed,
size_t seed_size)
{
unsigned int idx = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (type != MBEDTLS_LMS_SHA256_M32_H10) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (ctx->have_private_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ctx->params.type = type;
ctx->params.otstype = otstype;
ctx->have_private_key = 1;
ret = f_rng(p_rng,
ctx->params.I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN);
if (ret != 0) {
goto exit;
}
/* Requires a cast to size_t to avoid an implicit cast warning on certain
* platforms (particularly Windows) */
ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
sizeof(*ctx->ots_private_keys));
if (ctx->ots_private_keys == NULL) {
ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
goto exit;
}
/* Requires a cast to size_t to avoid an implicit cast warning on certain
* platforms (particularly Windows) */
ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
sizeof(*ctx->ots_public_keys));
if (ctx->ots_public_keys == NULL) {
ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
goto exit;
}
for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]);
mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]);
}
for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx],
otstype,
ctx->params.I_key_identifier,
idx, seed, seed_size);
if (ret != 0) {
goto exit;
}
ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx],
&ctx->ots_private_keys[idx]);
if (ret != 0) {
goto exit;
}
}
ctx->q_next_usable_key = 0;
exit:
if (ret != 0) {
mbedtls_lms_private_free(ctx);
}
return ret;
}
int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,
const mbedtls_lms_private_t *priv_ctx)
{
const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type);
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *tree = NULL;
if (!priv_ctx->have_private_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (priv_ctx->params.type
!= MBEDTLS_LMS_SHA256_M32_H10) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (priv_ctx->params.otstype
!= MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type),
node_bytes);
if (tree == NULL) {
return MBEDTLS_ERR_LMS_ALLOC_FAILED;
}
memcpy(&ctx->params, &priv_ctx->params,
sizeof(mbedtls_lmots_parameters_t));
ret = calculate_merkle_tree(priv_ctx, tree);
if (ret != 0) {
goto exit;
}
/* Root node is always at position 1, due to 1-based indexing */
memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes);
ctx->have_public_key = 1;
ret = 0;
exit:
mbedtls_zeroize_and_free(tree, node_bytes *
(size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type));
return ret;
}
int mbedtls_lms_sign(mbedtls_lms_private_t *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, const unsigned char *msg,
unsigned int msg_size, unsigned char *sig, size_t sig_size,
size_t *sig_len)
{
uint32_t q_leaf_identifier;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (!ctx->have_private_key) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
}
if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (ctx->params.otstype
!= MBEDTLS_LMOTS_SHA256_N32_W8) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS;
}
q_leaf_identifier = ctx->q_next_usable_key;
/* This new value must _always_ be written back to the disk before the
* signature is returned.
*/
ctx->q_next_usable_key += 1;
if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)
< SIG_OTS_SIG_OFFSET) {
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
}
ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier],
f_rng,
p_rng,
msg,
msg_size,
sig + SIG_OTS_SIG_OFFSET,
MBEDTLS_LMS_SIG_LEN(ctx->params.type,
ctx->params.otstype) - SIG_OTS_SIG_OFFSET,
NULL);
if (ret != 0) {
return ret;
}
MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype));
MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET);
ret = get_merkle_path(ctx,
MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
sig + SIG_PATH_OFFSET(ctx->params.otstype));
if (ret != 0) {
return ret;
}
if (sig_len != NULL) {
*sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype);
}
return 0;
}
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
#endif /* defined(MBEDTLS_LMS_C) */

View file

@ -41,7 +41,7 @@
#include "mbedtls/sha512.h"
#include "mbedtls/sha3.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include <psa/crypto.h>
#include "md_psa.h"
#include "psa_util_internal.h"
@ -761,13 +761,13 @@ mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info)
return md_info->type;
}
#if defined(MBEDTLS_PSA_CRYPTO_C)
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
int mbedtls_md_error_from_psa(psa_status_t status)
{
return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_md_errors,
psa_generic_status_to_mbedtls);
}
#endif /* MBEDTLS_PSA_CRYPTO_C */
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
/************************************************************************

View file

@ -683,7 +683,7 @@ void mbedtls_net_close(mbedtls_net_context *ctx)
*/
void mbedtls_net_free(mbedtls_net_context *ctx)
{
if (ctx->fd == -1) {
if (ctx == NULL || ctx->fd == -1) {
return;
}

View file

@ -102,6 +102,10 @@ int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
*/
void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_cipher_free(&ctx->cipher_ctx);
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
}

View file

@ -481,6 +481,10 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
void mbedtls_pem_free(mbedtls_pem_context *ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->buf != NULL) {
mbedtls_zeroize_and_free(ctx->buf, ctx->buflen);
}

View file

@ -868,7 +868,6 @@ static int copy_from_psa(mbedtls_svc_key_id_t key_id,
psa_status_t status;
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type;
psa_algorithm_t alg_type;
size_t key_bits;
/* Use a buffer size large enough to contain either a key pair or public key. */
unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE];
@ -899,7 +898,6 @@ static int copy_from_psa(mbedtls_svc_key_id_t key_id,
key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);
}
key_bits = psa_get_key_bits(&key_attr);
alg_type = psa_get_key_algorithm(&key_attr);
#if defined(MBEDTLS_RSA_C)
if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) ||
@ -919,6 +917,7 @@ static int copy_from_psa(mbedtls_svc_key_id_t key_id,
goto exit;
}
psa_algorithm_t alg_type = psa_get_key_algorithm(&key_attr);
mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) {
md_type = mbedtls_md_type_from_psa_alg(alg_type);
@ -968,6 +967,7 @@ static int copy_from_psa(mbedtls_svc_key_id_t key_id,
} else
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
{
(void) key_bits;
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
@ -1327,43 +1327,19 @@ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
}
if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t psa_alg, sign_alg;
#if defined(MBEDTLS_PSA_CRYPTO_C)
psa_algorithm_t psa_enrollment_alg;
#endif /* MBEDTLS_PSA_CRYPTO_C */
psa_status_t status;
status = psa_get_key_attributes(ctx->priv_id, &key_attr);
if (status != PSA_SUCCESS) {
return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
}
psa_alg = psa_get_key_algorithm(&key_attr);
#if defined(MBEDTLS_PSA_CRYPTO_C)
psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr);
#endif /* MBEDTLS_PSA_CRYPTO_C */
psa_reset_key_attributes(&key_attr);
/* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between
* alg and enrollment alg should be of type RSA_PSS. */
if (PSA_ALG_IS_RSA_PSS(psa_alg)) {
sign_alg = psa_alg;
}
#if defined(MBEDTLS_PSA_CRYPTO_C)
else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) {
sign_alg = psa_enrollment_alg;
}
#endif /* MBEDTLS_PSA_CRYPTO_C */
else {
/* The opaque key has no RSA PSS algorithm associated. */
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
/* Adjust the hashing algorithm. */
sign_alg = (sign_alg & ~PSA_ALG_HASH_MASK) | PSA_ALG_GET_HASH(psa_md_alg);
status = psa_sign_hash(ctx->priv_id, sign_alg,
/* PSA_ALG_RSA_PSS() behaves the same as PSA_ALG_RSA_PSS_ANY_SALT() when
* performing a signature, but they are encoded differently. Instead of
* extracting the proper one from the wrapped key policy, just try both. */
status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg),
hash, hash_len,
sig, sig_size, sig_len);
if (status == PSA_ERROR_NOT_PERMITTED) {
status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg),
hash, hash_len,
sig, sig_size, sig_len);
}
return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
}

View file

@ -65,17 +65,21 @@ static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
size_t len = 0, tmp_len = 0;
size_t tmp_len = 0;
if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
/* Ensure there's enough space in the provided buffer before copying data into it. */
if (tmp_len > (size_t) (*p - buf)) {
mbedtls_platform_zeroize(tmp, sizeof(tmp));
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*p -= tmp_len;
memcpy(*p, tmp, tmp_len);
len += tmp_len;
mbedtls_platform_zeroize(tmp, sizeof(tmp));
return (int) len;
return (int) tmp_len;
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
@ -125,6 +129,10 @@ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
/* Ensure there's enough space in the provided buffer before copying data into it. */
if (len > (size_t) (*p - start)) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*p -= len;
memcpy(*p, buf, len);
return (int) len;

View file

@ -149,7 +149,7 @@ void mbedtls_zeroize_and_free(void *buf, size_t len)
#include <time.h>
#if !defined(_WIN32) && (defined(unix) || \
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
defined(__MACH__)) || defined__midipix__)
defined(__MACH__)) || defined(__midipix__))
#include <unistd.h>
#endif /* !_WIN32 && (unix || __unix || __unix__ ||
* (__APPLE__ && __MACH__) || __midipix__) */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,649 @@
/*
* PSA AEAD entry points
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include "psa_crypto_aead.h"
#include "psa_crypto_core.h"
#include "psa_crypto_cipher.h"
#include <string.h>
#include "mbedtls/platform.h"
#include "mbedtls/ccm.h"
#include "mbedtls/chachapoly.h"
#include "mbedtls/cipher.h"
#include "mbedtls/gcm.h"
#include "mbedtls/error.h"
static psa_status_t psa_aead_setup(
mbedtls_psa_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_cipher_id_t cipher_id;
mbedtls_cipher_mode_t mode;
size_t key_bits = attributes->bits;
(void) key_buffer_size;
status = mbedtls_cipher_values_from_psa(alg, attributes->type,
&key_bits, &mode, &cipher_id);
if (status != PSA_SUCCESS) {
return status;
}
switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
operation->alg = PSA_ALG_CCM;
/* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
* The call to mbedtls_ccm_encrypt_and_tag or
* mbedtls_ccm_auth_decrypt will validate the tag length. */
if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mbedtls_ccm_init(&operation->ctx.ccm);
status = mbedtls_to_psa_error(
mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id,
key_buffer, (unsigned int) key_bits));
if (status != PSA_SUCCESS) {
return status;
}
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
operation->alg = PSA_ALG_GCM;
/* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
* The call to mbedtls_gcm_crypt_and_tag or
* mbedtls_gcm_auth_decrypt will validate the tag length. */
if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mbedtls_gcm_init(&operation->ctx.gcm);
status = mbedtls_to_psa_error(
mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id,
key_buffer, (unsigned int) key_bits));
if (status != PSA_SUCCESS) {
return status;
}
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
operation->alg = PSA_ALG_CHACHA20_POLY1305;
/* We only support the default tag length. */
if (alg != PSA_ALG_CHACHA20_POLY1305) {
return PSA_ERROR_NOT_SUPPORTED;
}
mbedtls_chachapoly_init(&operation->ctx.chachapoly);
status = mbedtls_to_psa_error(
mbedtls_chachapoly_setkey(&operation->ctx.chachapoly,
key_buffer));
if (status != PSA_SUCCESS) {
return status;
}
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
default:
(void) status;
(void) key_buffer;
return PSA_ERROR_NOT_SUPPORTED;
}
operation->key_type = psa_get_key_type(attributes);
operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_aead_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *plaintext, size_t plaintext_length,
uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
uint8_t *tag;
status = psa_aead_setup(&operation, attributes, key_buffer,
key_buffer_size, alg);
if (status != PSA_SUCCESS) {
goto exit;
}
/* For all currently supported modes, the tag is at the end of the
* ciphertext. */
if (ciphertext_size < (plaintext_length + operation.tag_length)) {
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
tag = ciphertext + plaintext_length;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation.alg == PSA_ALG_CCM) {
status = mbedtls_to_psa_error(
mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm,
plaintext_length,
nonce, nonce_length,
additional_data,
additional_data_length,
plaintext, ciphertext,
tag, operation.tag_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation.alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm,
MBEDTLS_GCM_ENCRYPT,
plaintext_length,
nonce, nonce_length,
additional_data, additional_data_length,
plaintext, ciphertext,
operation.tag_length, tag));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
if (operation.tag_length != 16) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly,
plaintext_length,
nonce,
additional_data,
additional_data_length,
plaintext,
ciphertext,
tag));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) tag;
(void) nonce;
(void) nonce_length;
(void) additional_data;
(void) additional_data_length;
(void) plaintext;
return PSA_ERROR_NOT_SUPPORTED;
}
if (status == PSA_SUCCESS) {
*ciphertext_length = plaintext_length + operation.tag_length;
}
exit:
mbedtls_psa_aead_abort(&operation);
return status;
}
/* Locate the tag in a ciphertext buffer containing the encrypted data
* followed by the tag. Return the length of the part preceding the tag in
* *plaintext_length. This is the size of the plaintext in modes where
* the encrypted data has the same size as the plaintext, such as
* CCM and GCM. */
static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length,
const uint8_t *ciphertext,
size_t ciphertext_length,
size_t plaintext_size,
const uint8_t **p_tag)
{
size_t payload_length;
if (tag_length > ciphertext_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}
payload_length = ciphertext_length - tag_length;
if (payload_length > plaintext_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
*p_tag = ciphertext + payload_length;
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_aead_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
const uint8_t *tag = NULL;
status = psa_aead_setup(&operation, attributes, key_buffer,
key_buffer_size, alg);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_aead_unpadded_locate_tag(operation.tag_length,
ciphertext, ciphertext_length,
plaintext_size, &tag);
if (status != PSA_SUCCESS) {
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation.alg == PSA_ALG_CCM) {
status = mbedtls_to_psa_error(
mbedtls_ccm_auth_decrypt(&operation.ctx.ccm,
ciphertext_length - operation.tag_length,
nonce, nonce_length,
additional_data,
additional_data_length,
ciphertext, plaintext,
tag, operation.tag_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation.alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_auth_decrypt(&operation.ctx.gcm,
ciphertext_length - operation.tag_length,
nonce, nonce_length,
additional_data,
additional_data_length,
tag, operation.tag_length,
ciphertext, plaintext));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
if (operation.tag_length != 16) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly,
ciphertext_length - operation.tag_length,
nonce,
additional_data,
additional_data_length,
tag,
ciphertext,
plaintext));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) nonce;
(void) nonce_length;
(void) additional_data;
(void) additional_data_length;
(void) plaintext;
return PSA_ERROR_NOT_SUPPORTED;
}
if (status == PSA_SUCCESS) {
*plaintext_length = ciphertext_length - operation.tag_length;
}
exit:
mbedtls_psa_aead_abort(&operation);
if (status == PSA_SUCCESS) {
*plaintext_length = ciphertext_length - operation.tag_length;
}
return status;
}
/* Set the key and algorithm for a multipart authenticated encryption
* operation. */
psa_status_t mbedtls_psa_aead_encrypt_setup(
mbedtls_psa_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
status = psa_aead_setup(operation, attributes, key_buffer,
key_buffer_size, alg);
if (status == PSA_SUCCESS) {
operation->is_encrypt = 1;
}
return status;
}
/* Set the key and algorithm for a multipart authenticated decryption
* operation. */
psa_status_t mbedtls_psa_aead_decrypt_setup(
mbedtls_psa_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
status = psa_aead_setup(operation, attributes, key_buffer,
key_buffer_size, alg);
if (status == PSA_SUCCESS) {
operation->is_encrypt = 0;
}
return status;
}
/* Set a nonce for the multipart AEAD operation*/
psa_status_t mbedtls_psa_aead_set_nonce(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation->alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_starts(&operation->ctx.gcm,
operation->is_encrypt ?
MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
nonce,
nonce_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
status = mbedtls_to_psa_error(
mbedtls_ccm_starts(&operation->ctx.ccm,
operation->is_encrypt ?
MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT,
nonce,
nonce_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
/* Note - ChaChaPoly allows an 8 byte nonce, but we would have to
* allocate a buffer in the operation, copy the nonce to it and pad
* it, so for now check the nonce is 12 bytes, as
* mbedtls_chachapoly_starts() assumes it can read 12 bytes from the
* passed in buffer. */
if (nonce_length != 12) {
return PSA_ERROR_INVALID_ARGUMENT;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_starts(&operation->ctx.chachapoly,
nonce,
operation->is_encrypt ?
MBEDTLS_CHACHAPOLY_ENCRYPT :
MBEDTLS_CHACHAPOLY_DECRYPT));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) operation;
(void) nonce;
(void) nonce_length;
return PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
/* Declare the lengths of the message and additional data for AEAD. */
psa_status_t mbedtls_psa_aead_set_lengths(
mbedtls_psa_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length)
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
return mbedtls_to_psa_error(
mbedtls_ccm_set_lengths(&operation->ctx.ccm,
ad_length,
plaintext_length,
operation->tag_length));
}
#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
(void) operation;
(void) ad_length;
(void) plaintext_length;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
return PSA_SUCCESS;
}
/* Pass additional data to an active multipart AEAD operation. */
psa_status_t mbedtls_psa_aead_update_ad(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation->alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
status = mbedtls_to_psa_error(
mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
status = mbedtls_to_psa_error(
mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly,
input,
input_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) operation;
(void) input;
(void) input_length;
return PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
/* Encrypt or decrypt a message fragment in an active multipart AEAD
* operation.*/
psa_status_t mbedtls_psa_aead_update(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
size_t update_output_length;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
update_output_length = input_length;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation->alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_update(&operation->ctx.gcm,
input, input_length,
output, output_size,
&update_output_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
if (output_size < input_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = mbedtls_to_psa_error(
mbedtls_ccm_update(&operation->ctx.ccm,
input, input_length,
output, output_size,
&update_output_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
if (output_size < input_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_update(&operation->ctx.chachapoly,
input_length,
input,
output));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) operation;
(void) input;
(void) output;
(void) output_size;
return PSA_ERROR_NOT_SUPPORTED;
}
if (status == PSA_SUCCESS) {
*output_length = update_output_length;
}
return status;
}
/* Finish encrypting a message in a multipart AEAD operation. */
psa_status_t mbedtls_psa_aead_finish(
mbedtls_psa_aead_operation_t *operation,
uint8_t *ciphertext,
size_t ciphertext_size,
size_t *ciphertext_length,
uint8_t *tag,
size_t tag_size,
size_t *tag_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t finish_output_size = 0;
if (tag_size < operation->tag_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation->alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_finish(&operation->ctx.gcm,
ciphertext, ciphertext_size, ciphertext_length,
tag, operation->tag_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
/* tag must be big enough to store a tag of size passed into set
* lengths. */
if (tag_size < operation->tag_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = mbedtls_to_psa_error(
mbedtls_ccm_finish(&operation->ctx.ccm,
tag, operation->tag_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
/* Belt and braces. Although the above tag_size check should have
* already done this, if we later start supporting smaller tag sizes
* for chachapoly, then passing a tag buffer smaller than 16 into here
* could cause a buffer overflow, so better safe than sorry. */
if (tag_size < 16) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_finish(&operation->ctx.chachapoly,
tag));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) ciphertext;
(void) ciphertext_size;
(void) ciphertext_length;
(void) tag;
(void) tag_size;
(void) tag_length;
return PSA_ERROR_NOT_SUPPORTED;
}
if (status == PSA_SUCCESS) {
/* This will be zero for all supported algorithms currently, but left
* here for future support. */
*ciphertext_length = finish_output_size;
*tag_length = operation->tag_length;
}
return status;
}
/* Abort an AEAD operation */
psa_status_t mbedtls_psa_aead_abort(
mbedtls_psa_aead_operation_t *operation)
{
switch (operation->alg) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
case PSA_ALG_CCM:
mbedtls_ccm_free(&operation->ctx.ccm);
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
case PSA_ALG_GCM:
mbedtls_gcm_free(&operation->ctx.gcm);
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
case PSA_ALG_CHACHA20_POLY1305:
mbedtls_chachapoly_free(&operation->ctx.chachapoly);
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
}
operation->is_encrypt = 0;
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -0,0 +1,724 @@
/*
* PSA cipher driver entry points
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include "psa_crypto_cipher.h"
#include "psa_crypto_core.h"
#include "psa_crypto_random_impl.h"
#include "mbedtls/cipher.h"
#include "mbedtls/error.h"
#include <string.h>
/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols
* are enabled, but it does not provide any compatibility check between them
* (i.e. if the specified key works with the specified algorithm). This helper
* function is meant to provide this support.
* mbedtls_cipher_info_from_psa() might be used for the same purpose, but it
* requires CIPHER_C to be enabled.
*/
static psa_status_t mbedtls_cipher_validate_values(
psa_algorithm_t alg,
psa_key_type_t key_type)
{
/* Reduce code size - hinting to the compiler about what it can assume allows the compiler to
eliminate bits of the logic below. */
#if !defined(PSA_WANT_KEY_TYPE_AES)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES);
#endif
#if !defined(PSA_WANT_KEY_TYPE_ARIA)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA);
#endif
#if !defined(PSA_WANT_KEY_TYPE_CAMELLIA)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA);
#endif
#if !defined(PSA_WANT_KEY_TYPE_CHACHA20)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20);
#endif
#if !defined(PSA_WANT_KEY_TYPE_DES)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES);
#endif
#if !defined(PSA_WANT_ALG_CCM)
MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0));
#endif
#if !defined(PSA_WANT_ALG_GCM)
MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0));
#endif
#if !defined(PSA_WANT_ALG_STREAM_CIPHER)
MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER);
#endif
#if !defined(PSA_WANT_ALG_CHACHA20_POLY1305)
MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0));
#endif
#if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)
MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG);
#endif
#if !defined(PSA_WANT_ALG_CTR)
MBEDTLS_ASSUME(alg != PSA_ALG_CTR);
#endif
#if !defined(PSA_WANT_ALG_CFB)
MBEDTLS_ASSUME(alg != PSA_ALG_CFB);
#endif
#if !defined(PSA_WANT_ALG_OFB)
MBEDTLS_ASSUME(alg != PSA_ALG_OFB);
#endif
#if !defined(PSA_WANT_ALG_XTS)
MBEDTLS_ASSUME(alg != PSA_ALG_XTS);
#endif
#if !defined(PSA_WANT_ALG_ECB_NO_PADDING)
MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING);
#endif
#if !defined(PSA_WANT_ALG_CBC_NO_PADDING)
MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING);
#endif
#if !defined(PSA_WANT_ALG_CBC_PKCS7)
MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7);
#endif
#if !defined(PSA_WANT_ALG_CMAC)
MBEDTLS_ASSUME(alg != PSA_ALG_CMAC);
#endif
if (alg == PSA_ALG_STREAM_CIPHER ||
alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) {
if (key_type == PSA_KEY_TYPE_CHACHA20) {
return PSA_SUCCESS;
}
}
if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) ||
alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) ||
alg == PSA_ALG_CCM_STAR_NO_TAG) {
if (key_type == PSA_KEY_TYPE_AES ||
key_type == PSA_KEY_TYPE_ARIA ||
key_type == PSA_KEY_TYPE_CAMELLIA) {
return PSA_SUCCESS;
}
}
if (alg == PSA_ALG_CTR ||
alg == PSA_ALG_CFB ||
alg == PSA_ALG_OFB ||
alg == PSA_ALG_XTS ||
alg == PSA_ALG_ECB_NO_PADDING ||
alg == PSA_ALG_CBC_NO_PADDING ||
alg == PSA_ALG_CBC_PKCS7 ||
alg == PSA_ALG_CMAC) {
if (key_type == PSA_KEY_TYPE_AES ||
key_type == PSA_KEY_TYPE_ARIA ||
key_type == PSA_KEY_TYPE_DES ||
key_type == PSA_KEY_TYPE_CAMELLIA) {
return PSA_SUCCESS;
}
}
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_cipher_values_from_psa(
psa_algorithm_t alg,
psa_key_type_t key_type,
size_t *key_bits,
mbedtls_cipher_mode_t *mode,
mbedtls_cipher_id_t *cipher_id)
{
mbedtls_cipher_id_t cipher_id_tmp;
/* Only DES modifies key_bits */
#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
(void) key_bits;
#endif
if (PSA_ALG_IS_AEAD(alg)) {
alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
}
if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
switch (alg) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
case PSA_ALG_STREAM_CIPHER:
*mode = MBEDTLS_MODE_STREAM;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
case PSA_ALG_CTR:
*mode = MBEDTLS_MODE_CTR;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
case PSA_ALG_CFB:
*mode = MBEDTLS_MODE_CFB;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
case PSA_ALG_OFB:
*mode = MBEDTLS_MODE_OFB;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
case PSA_ALG_ECB_NO_PADDING:
*mode = MBEDTLS_MODE_ECB;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
case PSA_ALG_CBC_NO_PADDING:
*mode = MBEDTLS_MODE_CBC;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
case PSA_ALG_CBC_PKCS7:
*mode = MBEDTLS_MODE_CBC;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
case PSA_ALG_CCM_STAR_NO_TAG:
*mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
*mode = MBEDTLS_MODE_CCM;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
*mode = MBEDTLS_MODE_GCM;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
*mode = MBEDTLS_MODE_CHACHAPOLY;
break;
#endif
default:
return PSA_ERROR_NOT_SUPPORTED;
}
} else if (alg == PSA_ALG_CMAC) {
*mode = MBEDTLS_MODE_ECB;
} else {
return PSA_ERROR_NOT_SUPPORTED;
}
switch (key_type) {
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
case PSA_KEY_TYPE_AES:
cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
case PSA_KEY_TYPE_ARIA:
cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
case PSA_KEY_TYPE_DES:
/* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
* and 192 for three-key Triple-DES. */
if (*key_bits == 64) {
cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
} else {
cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
}
/* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
* but two-key Triple-DES is functionally three-key Triple-DES
* with K1=K3, so that's how we present it to mbedtls. */
if (*key_bits == 128) {
*key_bits = 192;
}
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
case PSA_KEY_TYPE_CAMELLIA:
cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
case PSA_KEY_TYPE_CHACHA20:
cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
break;
#endif
default:
return PSA_ERROR_NOT_SUPPORTED;
}
if (cipher_id != NULL) {
*cipher_id = cipher_id_tmp;
}
return mbedtls_cipher_validate_values(alg, key_type);
}
#if defined(MBEDTLS_CIPHER_C)
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
psa_algorithm_t alg,
psa_key_type_t key_type,
size_t key_bits,
mbedtls_cipher_id_t *cipher_id)
{
mbedtls_cipher_mode_t mode;
psa_status_t status;
mbedtls_cipher_id_t cipher_id_tmp = MBEDTLS_CIPHER_ID_NONE;
status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
if (status != PSA_SUCCESS) {
return NULL;
}
if (cipher_id != NULL) {
*cipher_id = cipher_id_tmp;
}
return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
}
#endif /* MBEDTLS_CIPHER_C */
#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
static psa_status_t psa_cipher_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
mbedtls_operation_t cipher_operation)
{
int ret = 0;
size_t key_bits;
const mbedtls_cipher_info_t *cipher_info = NULL;
psa_key_type_t key_type = attributes->type;
(void) key_buffer_size;
mbedtls_cipher_init(&operation->ctx.cipher);
operation->alg = alg;
key_bits = attributes->bits;
cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
key_bits, NULL);
if (cipher_info == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
if (ret != 0) {
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
/* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
uint8_t keys[24];
memcpy(keys, key_buffer, 16);
memcpy(keys + 16, key_buffer, 8);
ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
keys,
192, cipher_operation);
} else
#endif
{
ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
(int) key_bits, cipher_operation);
}
if (ret != 0) {
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
switch (alg) {
case PSA_ALG_CBC_NO_PADDING:
ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
MBEDTLS_PADDING_NONE);
break;
case PSA_ALG_CBC_PKCS7:
ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
MBEDTLS_PADDING_PKCS7);
break;
default:
/* The algorithm doesn't involve padding. */
ret = 0;
break;
}
if (ret != 0) {
goto exit;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
exit:
return mbedtls_to_psa_error(ret);
}
psa_status_t mbedtls_psa_cipher_encrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
return psa_cipher_setup(operation, attributes,
key_buffer, key_buffer_size,
alg, MBEDTLS_ENCRYPT);
}
psa_status_t mbedtls_psa_cipher_decrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
return psa_cipher_setup(operation, attributes,
key_buffer, key_buffer_size,
alg, MBEDTLS_DECRYPT);
}
psa_status_t mbedtls_psa_cipher_set_iv(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length)
{
if (iv_length != operation->iv_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}
return mbedtls_to_psa_error(
mbedtls_cipher_set_iv(&operation->ctx.cipher,
iv, iv_length));
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
/** Process input for which the algorithm is set to ECB mode.
*
* This requires manual processing, since the PSA API is defined as being
* able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
* but the underlying mbedtls_cipher_update only takes full blocks.
*
* \param ctx The mbedtls cipher context to use. It must have been
* set up for ECB.
* \param[in] input The input plaintext or ciphertext to process.
* \param input_length The number of bytes to process from \p input.
* This does not need to be aligned to a block boundary.
* If there is a partial block at the end of the input,
* it is stored in \p ctx for future processing.
* \param output The buffer where the output is written. It must be
* at least `BS * floor((p + input_length) / BS)` bytes
* long, where `p` is the number of bytes in the
* unprocessed partial block in \p ctx (with
* `0 <= p <= BS - 1`) and `BS` is the block size.
* \param output_length On success, the number of bytes written to \p output.
* \c 0 on error.
*
* \return #PSA_SUCCESS or an error from a hardware accelerator
*/
static psa_status_t psa_cipher_update_ecb(
mbedtls_cipher_context_t *ctx,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
size_t internal_output_length = 0;
*output_length = 0;
if (input_length == 0) {
status = PSA_SUCCESS;
goto exit;
}
if (ctx->unprocessed_len > 0) {
/* Fill up to block size, and run the block if there's a full one. */
size_t bytes_to_copy = block_size - ctx->unprocessed_len;
if (input_length < bytes_to_copy) {
bytes_to_copy = input_length;
}
memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
input, bytes_to_copy);
input_length -= bytes_to_copy;
input += bytes_to_copy;
ctx->unprocessed_len += bytes_to_copy;
if (ctx->unprocessed_len == block_size) {
status = mbedtls_to_psa_error(
mbedtls_cipher_update(ctx,
ctx->unprocessed_data,
block_size,
output, &internal_output_length));
if (status != PSA_SUCCESS) {
goto exit;
}
output += internal_output_length;
*output_length += internal_output_length;
ctx->unprocessed_len = 0;
}
}
while (input_length >= block_size) {
/* Run all full blocks we have, one by one */
status = mbedtls_to_psa_error(
mbedtls_cipher_update(ctx, input,
block_size,
output, &internal_output_length));
if (status != PSA_SUCCESS) {
goto exit;
}
input_length -= block_size;
input += block_size;
output += internal_output_length;
*output_length += internal_output_length;
}
if (input_length > 0) {
/* Save unprocessed bytes for later processing */
memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
input, input_length);
ctx->unprocessed_len += input_length;
}
status = PSA_SUCCESS;
exit:
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
psa_status_t mbedtls_psa_cipher_update(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t expected_output_size;
if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
/* Take the unprocessed partial block left over from previous
* update calls, if any, plus the input to this call. Remove
* the last partial block, if any. You get the data that will be
* output in this call. */
expected_output_size =
(operation->ctx.cipher.unprocessed_len + input_length)
/ operation->block_length * operation->block_length;
} else {
expected_output_size = input_length;
}
if (output_size < expected_output_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
/* mbedtls_cipher_update has an API inconsistency: it will only
* process a single block at a time in ECB mode. Abstract away that
* inconsistency here to match the PSA API behaviour. */
status = psa_cipher_update_ecb(&operation->ctx.cipher,
input,
input_length,
output,
output_length);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
if (input_length == 0) {
/* There is no input, nothing to be done */
*output_length = 0;
status = PSA_SUCCESS;
} else {
status = mbedtls_to_psa_error(
mbedtls_cipher_update(&operation->ctx.cipher, input,
input_length, output, output_length));
if (*output_length > output_size) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
}
return status;
}
psa_status_t mbedtls_psa_cipher_finish(
mbedtls_psa_cipher_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length)
{
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
if (operation->ctx.cipher.unprocessed_len != 0) {
if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
operation->alg == PSA_ALG_CBC_NO_PADDING) {
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
}
status = mbedtls_to_psa_error(
mbedtls_cipher_finish(&operation->ctx.cipher,
temp_output_buffer,
output_length));
if (status != PSA_SUCCESS) {
goto exit;
}
if (*output_length == 0) {
; /* Nothing to copy. Note that output may be NULL in this case. */
} else if (output_size >= *output_length) {
memcpy(output, temp_output_buffer, *output_length);
} else {
status = PSA_ERROR_BUFFER_TOO_SMALL;
}
exit:
mbedtls_platform_zeroize(temp_output_buffer,
sizeof(temp_output_buffer));
return status;
}
psa_status_t mbedtls_psa_cipher_abort(
mbedtls_psa_cipher_operation_t *operation)
{
/* Sanity check (shouldn't happen: operation->alg should
* always have been initialized to a valid value). */
if (!PSA_ALG_IS_CIPHER(operation->alg)) {
return PSA_ERROR_BAD_STATE;
}
mbedtls_cipher_free(&operation->ctx.cipher);
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_cipher_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *iv,
size_t iv_length,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
size_t update_output_length, finish_output_length;
status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (iv_length > 0) {
status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
status = mbedtls_psa_cipher_update(&operation, input, input_length,
output, output_size,
&update_output_length);
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_psa_cipher_finish(
&operation,
mbedtls_buffer_offset(output, update_output_length),
output_size - update_output_length, &finish_output_length);
if (status != PSA_SUCCESS) {
goto exit;
}
*output_length = update_output_length + finish_output_length;
exit:
if (status == PSA_SUCCESS) {
status = mbedtls_psa_cipher_abort(&operation);
} else {
mbedtls_psa_cipher_abort(&operation);
}
return status;
}
psa_status_t mbedtls_psa_cipher_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
size_t olength, accumulated_length;
status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (operation.iv_length > 0) {
status = mbedtls_psa_cipher_set_iv(&operation,
input, operation.iv_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
status = mbedtls_psa_cipher_update(
&operation,
mbedtls_buffer_offset_const(input, operation.iv_length),
input_length - operation.iv_length,
output, output_size, &olength);
if (status != PSA_SUCCESS) {
goto exit;
}
accumulated_length = olength;
status = mbedtls_psa_cipher_finish(
&operation,
mbedtls_buffer_offset(output, accumulated_length),
output_size - accumulated_length, &olength);
if (status != PSA_SUCCESS) {
goto exit;
}
*output_length = accumulated_length + olength;
exit:
if (status == PSA_SUCCESS) {
status = mbedtls_psa_cipher_abort(&operation);
} else {
mbedtls_psa_cipher_abort(&operation);
}
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -0,0 +1,22 @@
/*
* PSA crypto client code
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#include "psa/crypto.h"
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include <string.h>
#include "mbedtls/platform.h"
void psa_reset_key_attributes(psa_key_attributes_t *attributes)
{
memset(attributes, 0, sizeof(*attributes));
}
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */

View file

@ -59,6 +59,8 @@ typedef enum {
* and metadata for one key.
*/
typedef struct {
/* This field is accessed in a lot of places. Putting it first
* reduces the code size. */
psa_key_attributes_t attr;
/*
@ -78,35 +80,77 @@ typedef struct {
* slots that are in a suitable state for the function.
* For example, psa_get_and_lock_key_slot_in_memory, which finds a slot
* containing a given key ID, will only check slots whose state variable is
* PSA_SLOT_FULL. */
* PSA_SLOT_FULL.
*/
psa_key_slot_state_t state;
/*
* Number of functions registered as reading the material in the key slot.
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
/* The index of the slice containing this slot.
* This field must be filled if the slot contains a key
* (including keys being created or destroyed), and can be either
* filled or 0 when the slot is free.
*
* Library functions must not write directly to registered_readers
*
* A function must call psa_register_read(slot) before reading the current
* contents of the slot for an operation.
* They then must call psa_unregister_read(slot) once they have finished
* reading the current contents of the slot. If the key slot mutex is not
* held (when mutexes are enabled), this call must be done via a call to
* psa_unregister_read_under_mutex(slot).
* A function must call psa_key_slot_has_readers(slot) to check if
* the slot is in use for reading.
*
* This counter is used to prevent resetting the key slot while the library
* may access it. For example, such control is needed in the following
* scenarios:
* . In case of key slot starvation, all key slots contain the description
* of a key, and the library asks for the description of a persistent
* key not present in the key slots, the key slots currently accessed by
* the library cannot be reclaimed to free a key slot to load the
* persistent key.
* . In case of a multi-threaded application where one thread asks to close
* or purge or destroy a key while it is in use by the library through
* another thread. */
size_t registered_readers;
* In most cases, the slice index can be deduced from the key identifer.
* We keep it in a separate field for robustness (it reduces the chance
* that a coding mistake in the key store will result in accessing the
* wrong slice), and also so that it's available even on code paths
* during creation or destruction where the key identifier might not be
* filled in.
* */
uint8_t slice_index;
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
union {
struct {
/* The index of the next slot in the free list for this
* slice, relative * to the next array element.
*
* That is, 0 means the next slot, 1 means the next slot
* but one, etc. -1 would mean the slot itself. -2 means
* the previous slot, etc.
*
* If this is beyond the array length, the free list ends with the
* current element.
*
* The reason for this strange encoding is that 0 means the next
* element. This way, when we allocate a slice and initialize it
* to all-zero, the slice is ready for use, with a free list that
* consists of all the slots in order.
*/
int32_t next_free_relative_to_next;
} free;
struct {
/*
* Number of functions registered as reading the material in the key slot.
*
* Library functions must not write directly to registered_readers
*
* A function must call psa_register_read(slot) before reading
* the current contents of the slot for an operation.
* They then must call psa_unregister_read(slot) once they have
* finished reading the current contents of the slot. If the key
* slot mutex is not held (when mutexes are enabled), this call
* must be done via a call to
* psa_unregister_read_under_mutex(slot).
* A function must call psa_key_slot_has_readers(slot) to check if
* the slot is in use for reading.
*
* This counter is used to prevent resetting the key slot while
* the library may access it. For example, such control is needed
* in the following scenarios:
* . In case of key slot starvation, all key slots contain the
* description of a key, and the library asks for the
* description of a persistent key not present in the
* key slots, the key slots currently accessed by the
* library cannot be reclaimed to free a key slot to load
* the persistent key.
* . In case of a multi-threaded application where one thread
* asks to close or purge or destroy a key while it is in use
* by the library through another thread. */
size_t registered_readers;
} occupied;
} var;
/* Dynamically allocated key data buffer.
* Format as specified in psa_export_key(). */
@ -169,7 +213,7 @@ typedef struct {
*/
static inline int psa_key_slot_has_readers(const psa_key_slot_t *slot)
{
return slot->registered_readers > 0;
return slot->var.occupied.registered_readers > 0;
}
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@ -343,19 +387,18 @@ psa_status_t psa_export_public_key_internal(
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length);
/** Whether a key production parameters structure is the default.
/** Whether a key custom production parameters structure is the default.
*
* Calls to a key generation driver with non-default production parameters
* Calls to a key generation driver with non-default custom production parameters
* require a driver supporting custom production parameters.
*
* \param[in] params The key production parameters to check.
* \param params_data_length Size of `params->data` in bytes.
* \param[in] custom The key custom production parameters to check.
* \param custom_data_length Size of the associated variable-length data
* in bytes.
*/
#ifndef __cplusplus
int psa_key_production_parameters_are_default(
const psa_key_production_parameters_t *params,
size_t params_data_length);
#endif
int psa_custom_key_parameters_are_default(
const psa_custom_key_parameters_t *custom,
size_t custom_data_length);
/**
* \brief Generate a key.
@ -364,9 +407,9 @@ int psa_key_production_parameters_are_default(
* entry point.
*
* \param[in] attributes The attributes for the key to generate.
* \param[in] params The production parameters from
* psa_generate_key_ext().
* \param params_data_length The size of `params->data` in bytes.
* \param[in] custom Custom parameters for the key generation.
* \param[in] custom_data Variable-length data associated with \c custom.
* \param custom_data_length Length of `custom_data` in bytes.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
@ -380,14 +423,13 @@ int psa_key_production_parameters_are_default(
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
*/
#ifndef __cplusplus
psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes,
const psa_key_production_parameters_t *params,
size_t params_data_length,
const psa_custom_key_parameters_t *custom,
const uint8_t *custom_data,
size_t custom_data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length);
#endif
/** Sign a message with a private key. For hash-and-sign algorithms,
* this includes the hashing step.

View file

@ -728,10 +728,10 @@ static inline psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data(
}
}
#ifndef __cplusplus
static inline psa_status_t psa_driver_wrapper_generate_key(
const psa_key_attributes_t *attributes,
const psa_key_production_parameters_t *params, size_t params_data_length,
const psa_custom_key_parameters_t *custom,
const uint8_t *custom_data, size_t custom_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
@ -740,7 +740,7 @@ static inline psa_status_t psa_driver_wrapper_generate_key(
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
int is_default_production =
psa_key_production_parameters_are_default(params, params_data_length);
psa_custom_key_parameters_are_default(custom, custom_data_length);
if( location != PSA_KEY_LOCATION_LOCAL_STORAGE && !is_default_production )
{
/* We don't support passing custom production parameters
@ -811,7 +811,7 @@ static inline psa_status_t psa_driver_wrapper_generate_key(
/* Software fallback */
status = psa_generate_key_internal(
attributes, params, params_data_length,
attributes, custom, custom_data, custom_data_length,
key_buffer, key_buffer_size, key_buffer_length );
break;
@ -833,7 +833,6 @@ static inline psa_status_t psa_driver_wrapper_generate_key(
return( status );
}
#endif
static inline psa_status_t psa_driver_wrapper_import_key(
const psa_key_attributes_t *attributes,

View file

@ -0,0 +1,256 @@
/*
* Functions to delegate cryptographic operations to an available
* and appropriate accelerator.
* Warning: This file is now auto-generated.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/* BEGIN-common headers */
#include "common.h"
#include "psa_crypto_aead.h"
#include "psa_crypto_cipher.h"
#include "psa_crypto_core.h"
#include "psa_crypto_driver_wrappers_no_static.h"
#include "psa_crypto_hash.h"
#include "psa_crypto_mac.h"
#include "psa_crypto_pake.h"
#include "psa_crypto_rsa.h"
#include "mbedtls/platform.h"
/* END-common headers */
#if defined(MBEDTLS_PSA_CRYPTO_C)
/* BEGIN-driver headers */
/* Headers for mbedtls_test opaque driver */
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test/drivers/test_driver.h"
#endif
/* Headers for mbedtls_test transparent driver */
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test/drivers/test_driver.h"
#endif
/* Headers for p256 transparent driver */
#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
#include "../3rdparty/p256-m/p256-m_driver_entrypoints.h"
#endif
/* END-driver headers */
/* Auto-generated values depending on which drivers are registered.
* ID 0 is reserved for unallocated operations.
* ID 1 is reserved for the Mbed TLS software driver. */
/* BEGIN-driver id definition */
#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1)
#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2)
#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3)
#define P256_TRANSPARENT_DRIVER_ID (4)
/* END-driver id */
/* BEGIN-Common Macro definitions */
/* END-Common Macro definitions */
/* Support the 'old' SE interface when asked to */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style
* SE driver is present, to avoid unused argument errors at compile time. */
#ifndef PSA_CRYPTO_DRIVER_PRESENT
#define PSA_CRYPTO_DRIVER_PRESENT
#endif
#include "psa_crypto_se.h"
#endif
/** Get the key buffer size required to store the key material of a key
* associated with an opaque driver.
*
* \param[in] attributes The key attributes.
* \param[out] key_buffer_size Minimum buffer size to contain the key material
*
* \retval #PSA_SUCCESS
* The minimum size for a buffer to contain the key material has been
* returned successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED
* The type and/or the size in bits of the key or the combination of
* the two is not supported.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key is declared with a lifetime not known to us.
*/
psa_status_t psa_driver_wrapper_get_key_buffer_size(
const psa_key_attributes_t *attributes,
size_t *key_buffer_size )
{
psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
psa_key_type_t key_type = psa_get_key_type(attributes);
size_t key_bits = psa_get_key_bits(attributes);
*key_buffer_size = 0;
switch( location )
{
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TEST_DRIVER_LOCATION:
#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
/* Emulate property 'builtin_key_size' */
if( psa_key_id_is_builtin(
MBEDTLS_SVC_KEY_ID_GET_KEY_ID(
psa_get_key_id( attributes ) ) ) )
{
*key_buffer_size = sizeof( psa_drv_slot_number_t );
return( PSA_SUCCESS );
}
#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
*key_buffer_size = mbedtls_test_opaque_size_function( key_type,
key_bits );
return( ( *key_buffer_size != 0 ) ?
PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED );
#endif /* PSA_CRYPTO_DRIVER_TEST */
default:
(void)key_type;
(void)key_bits;
return( PSA_ERROR_INVALID_ARGUMENT );
}
}
psa_status_t psa_driver_wrapper_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length )
{
psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
psa_get_key_lifetime( attributes ) );
/* Try dynamically-registered SE interface first */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
const psa_drv_se_t *drv;
psa_drv_se_context_t *drv_context;
if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
{
if( ( drv->key_management == NULL ) ||
( drv->key_management->p_export_public == NULL ) )
{
return( PSA_ERROR_NOT_SUPPORTED );
}
return( drv->key_management->p_export_public(
drv_context,
*( (psa_key_slot_number_t *)key_buffer ),
data, data_size, data_length ) );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
switch( location )
{
case PSA_KEY_LOCATION_LOCAL_STORAGE:
/* Key is stored in the slot in export representation, so
* cycle through all known transparent accelerators */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if (defined(PSA_CRYPTO_DRIVER_TEST) )
status = mbedtls_test_transparent_export_public_key
(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length
);
if( status != PSA_ERROR_NOT_SUPPORTED )
return( status );
#endif
#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) )
status = p256_transparent_export_public_key
(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length
);
if( status != PSA_ERROR_NOT_SUPPORTED )
return( status );
#endif
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
/* Fell through, meaning no accelerator supports this operation */
return( psa_export_public_key_internal( attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length ) );
/* Add cases for opaque driver here */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if (defined(PSA_CRYPTO_DRIVER_TEST) )
case 0x7fffff:
return( mbedtls_test_opaque_export_public_key
(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length
));
#endif
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
default:
/* Key is declared with a lifetime not known to us */
return( status );
}
}
psa_status_t psa_driver_wrapper_get_builtin_key(
psa_drv_slot_number_t slot_number,
psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
switch( location )
{
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if (defined(PSA_CRYPTO_DRIVER_TEST) )
case 0x7fffff:
return( mbedtls_test_opaque_get_builtin_key
(slot_number,
attributes,
key_buffer,
key_buffer_size,
key_buffer_length
));
#endif
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
default:
(void) slot_number;
(void) key_buffer;
(void) key_buffer_size;
(void) key_buffer_length;
return( PSA_ERROR_DOES_NOT_EXIST );
}
}
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -0,0 +1,596 @@
/*
* PSA ECP layer on top of Mbed TLS crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_ecp.h"
#include "psa_crypto_random_impl.h"
#include "mbedtls/psa_util.h"
#include <stdlib.h>
#include <string.h>
#include "mbedtls/platform.h"
#include <mbedtls/ecdsa.h>
#include <mbedtls/ecdh.h>
#include <mbedtls/ecp.h>
#include <mbedtls/error.h>
#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_PUBLIC_KEY) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
/* Helper function to verify if the provided EC's family and key bit size are valid.
*
* Note: "bits" parameter is used both as input and output and it might be updated
* in case provided input value is not multiple of 8 ("sloppy" bits).
*/
static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits)
{
switch (family) {
case PSA_ECC_FAMILY_SECP_R1:
switch (*bits) {
case 192:
case 224:
case 256:
case 384:
case 521:
return PSA_SUCCESS;
case 528:
*bits = 521;
return PSA_SUCCESS;
}
break;
case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
switch (*bits) {
case 256:
case 384:
case 512:
return PSA_SUCCESS;
}
break;
case PSA_ECC_FAMILY_MONTGOMERY:
switch (*bits) {
case 448:
case 255:
return PSA_SUCCESS;
case 256:
*bits = 255;
return PSA_SUCCESS;
}
break;
case PSA_ECC_FAMILY_SECP_K1:
switch (*bits) {
case 192:
/* secp224k1 is not and will not be supported in PSA (#3541). */
case 256:
return PSA_SUCCESS;
}
break;
}
return PSA_ERROR_INVALID_ARGUMENT;
}
psa_status_t mbedtls_psa_ecp_load_representation(
psa_key_type_t type, size_t curve_bits,
const uint8_t *data, size_t data_length,
mbedtls_ecp_keypair **p_ecp)
{
mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
psa_status_t status;
mbedtls_ecp_keypair *ecp = NULL;
size_t curve_bytes = data_length;
int explicit_bits = (curve_bits != 0);
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {
/* A Weierstrass public key is represented as:
* - The byte 0x04;
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
* So its data length is 2m+1 where m is the curve size in bits.
*/
if ((data_length & 1) == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
curve_bytes = data_length / 2;
/* Montgomery public keys are represented in compressed format, meaning
* their curve_bytes is equal to the amount of input. */
/* Private keys are represented in uncompressed private random integer
* format, meaning their curve_bytes is equal to the amount of input. */
}
if (explicit_bits) {
/* With an explicit bit-size, the data must have the matching length. */
if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
} else {
/* We need to infer the bit-size from the data. Since the only
* information we have is the length in bytes, the value of curve_bits
* at this stage is rounded up to the nearest multiple of 8. */
curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
}
/* Allocate and initialize a key representation. */
ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
if (ecp == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
mbedtls_ecp_keypair_init(ecp);
status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits);
if (status != PSA_SUCCESS) {
goto exit;
}
/* Load the group. */
grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),
curve_bits);
if (grp_id == MBEDTLS_ECP_DP_NONE) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecp_group_load(&ecp->grp, grp_id));
if (status != PSA_SUCCESS) {
goto exit;
}
/* Load the key material. */
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
/* Load the public value. */
status = mbedtls_to_psa_error(
mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
data,
data_length));
if (status != PSA_SUCCESS) {
goto exit;
}
/* Check that the point is on the curve. */
status = mbedtls_to_psa_error(
mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
if (status != PSA_SUCCESS) {
goto exit;
}
} else {
/* Load and validate the secret value. */
status = mbedtls_to_psa_error(
mbedtls_ecp_read_key(ecp->grp.id,
ecp,
data,
data_length));
if (status != PSA_SUCCESS) {
goto exit;
}
}
*p_ecp = ecp;
exit:
if (status != PSA_SUCCESS) {
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
}
return status;
}
#endif /* 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_PUBLIC_KEY) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
#if 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_PUBLIC_KEY)
psa_status_t mbedtls_psa_ecp_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits)
{
psa_status_t status;
mbedtls_ecp_keypair *ecp = NULL;
/* Parse input */
status = mbedtls_psa_ecp_load_representation(attributes->type,
attributes->bits,
data,
data_length,
&ecp);
if (status != PSA_SUCCESS) {
goto exit;
}
if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) ==
PSA_ECC_FAMILY_MONTGOMERY) {
*bits = ecp->grp.nbits + 1;
} else {
*bits = ecp->grp.nbits;
}
/* Re-export the data to PSA export format. There is currently no support
* for other input formats then the export format, so this is a 1-1
* copy operation. */
status = mbedtls_psa_ecp_export_key(attributes->type,
ecp,
key_buffer,
key_buffer_size,
key_buffer_length);
exit:
/* Always free the PK object (will also free contained ECP context) */
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return status;
}
psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,
mbedtls_ecp_keypair *ecp,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
psa_status_t status;
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
/* Check whether the public part is loaded */
if (mbedtls_ecp_is_zero(&ecp->Q)) {
/* Calculate the public key */
status = mbedtls_to_psa_error(
mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
if (status != PSA_SUCCESS) {
return status;
}
}
status = mbedtls_to_psa_error(
mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
data_length,
data,
data_size));
if (status != PSA_SUCCESS) {
memset(data, 0, data_size);
}
return status;
} else {
status = mbedtls_to_psa_error(
mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size));
return status;
}
}
psa_status_t mbedtls_psa_ecp_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
status = mbedtls_psa_ecp_load_representation(
attributes->type, attributes->bits,
key_buffer, key_buffer_size, &ecp);
if (status != PSA_SUCCESS) {
return status;
}
status = mbedtls_psa_ecp_export_key(
PSA_KEY_TYPE_ECC_PUBLIC_KEY(
PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)),
ecp, data, data_size, data_length);
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return status;
}
#endif /* 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_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
psa_status_t mbedtls_psa_ecp_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
attributes->type);
mbedtls_ecp_group_id grp_id =
mbedtls_ecc_group_from_psa(curve, attributes->bits);
const mbedtls_ecp_curve_info *curve_info =
mbedtls_ecp_curve_info_from_grp_id(grp_id);
mbedtls_ecp_keypair ecp;
if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
mbedtls_ecp_keypair_init(&ecp);
ret = mbedtls_ecp_gen_key(grp_id, &ecp,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE);
if (ret != 0) {
mbedtls_ecp_keypair_free(&ecp);
return mbedtls_to_psa_error(ret);
}
status = mbedtls_to_psa_error(
mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,
key_buffer, key_buffer_size));
mbedtls_ecp_keypair_free(&ecp);
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
/****************************************************************/
/* ECDSA sign/verify */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
psa_status_t mbedtls_psa_ecdsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t curve_bytes;
mbedtls_mpi r, s;
status = mbedtls_psa_ecp_load_representation(attributes->type,
attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
if (status != PSA_SUCCESS) {
return status;
}
curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
if (signature_size < 2 * curve_bytes) {
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
goto cleanup;
}
if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(
&ecp->grp, &r, &s,
&ecp->d, hash,
hash_length, md_alg,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
#else
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
goto cleanup;
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
} else {
(void) alg;
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,
hash, hash_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
}
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,
signature,
curve_bytes));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,
signature + curve_bytes,
curve_bytes));
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
if (ret == 0) {
*signature_length = 2 * curve_bytes;
}
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return mbedtls_to_psa_error(ret);
}
psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)
{
int ret = 0;
/* Check whether the public part is loaded. If not, load it. */
if (mbedtls_ecp_is_zero(&ecp->Q)) {
ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q,
&ecp->d, &ecp->grp.G,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE);
}
return mbedtls_to_psa_error(ret);
}
psa_status_t mbedtls_psa_ecdsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
size_t curve_bytes;
mbedtls_mpi r, s;
(void) alg;
status = mbedtls_psa_ecp_load_representation(attributes->type,
attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
if (status != PSA_SUCCESS) {
return status;
}
curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
if (signature_length != 2 * curve_bytes) {
status = PSA_ERROR_INVALID_SIGNATURE;
goto cleanup;
}
status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,
signature,
curve_bytes));
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,
signature + curve_bytes,
curve_bytes));
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = mbedtls_psa_ecp_load_public_part(ecp);
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,
hash_length, &ecp->Q,
&r, &s));
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
/****************************************************************/
/* ECDH Key Agreement */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
psa_status_t mbedtls_psa_key_agreement_ecdh(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
uint8_t *shared_secret, size_t shared_secret_size,
size_t *shared_secret_length)
{
psa_status_t status;
if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) ||
!PSA_ALG_IS_ECDH(alg)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mbedtls_ecp_keypair *ecp = NULL;
status = mbedtls_psa_ecp_load_representation(
attributes->type,
attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
if (status != PSA_SUCCESS) {
return status;
}
mbedtls_ecp_keypair *their_key = NULL;
mbedtls_ecdh_context ecdh;
size_t bits = 0;
psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits);
mbedtls_ecdh_init(&ecdh);
status = mbedtls_psa_ecp_load_representation(
PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
bits,
peer_key,
peer_key_length,
&their_key);
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS));
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS));
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecdh_calc_secret(&ecdh,
shared_secret_length,
shared_secret, shared_secret_size,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
if (status != PSA_SUCCESS) {
goto exit;
}
if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) {
status = PSA_ERROR_CORRUPTION_DETECTED;
}
exit:
if (status != PSA_SUCCESS) {
mbedtls_platform_zeroize(shared_secret, shared_secret_size);
}
mbedtls_ecdh_free(&ecdh);
mbedtls_ecp_keypair_free(their_key);
mbedtls_free(their_key);
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -0,0 +1,321 @@
/*
* PSA FFDH layer on top of Mbed TLS crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
/* This header is only needed because it defines
* MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in
* mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module
* only uses bignum functions for arithmetic. */
#include <mbedtls/dhm.h>
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_ffdh.h"
#include "psa_crypto_random_impl.h"
#include "mbedtls/platform.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size,
mbedtls_mpi *P,
mbedtls_mpi *G)
{
const unsigned char *dhm_P = NULL;
const unsigned char *dhm_G = NULL;
size_t dhm_size_P = 0;
size_t dhm_size_G = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (P == NULL && G == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
static const unsigned char dhm_P_2048[] =
MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN;
static const unsigned char dhm_G_2048[] =
MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
static const unsigned char dhm_P_3072[] =
MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;
static const unsigned char dhm_G_3072[] =
MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
static const unsigned char dhm_P_4096[] =
MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;
static const unsigned char dhm_G_4096[] =
MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
static const unsigned char dhm_P_6144[] =
MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN;
static const unsigned char dhm_G_6144[] =
MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
static const unsigned char dhm_P_8192[] =
MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN;
static const unsigned char dhm_G_8192[] =
MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
switch (key_size) {
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
case sizeof(dhm_P_2048):
dhm_P = dhm_P_2048;
dhm_G = dhm_G_2048;
dhm_size_P = sizeof(dhm_P_2048);
dhm_size_G = sizeof(dhm_G_2048);
break;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
case sizeof(dhm_P_3072):
dhm_P = dhm_P_3072;
dhm_G = dhm_G_3072;
dhm_size_P = sizeof(dhm_P_3072);
dhm_size_G = sizeof(dhm_G_3072);
break;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
case sizeof(dhm_P_4096):
dhm_P = dhm_P_4096;
dhm_G = dhm_G_4096;
dhm_size_P = sizeof(dhm_P_4096);
dhm_size_G = sizeof(dhm_G_4096);
break;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
case sizeof(dhm_P_6144):
dhm_P = dhm_P_6144;
dhm_G = dhm_G_6144;
dhm_size_P = sizeof(dhm_P_6144);
dhm_size_G = sizeof(dhm_G_6144);
break;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
case sizeof(dhm_P_8192):
dhm_P = dhm_P_8192;
dhm_G = dhm_G_8192;
dhm_size_P = sizeof(dhm_P_8192);
dhm_size_G = sizeof(dhm_G_8192);
break;
#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
default:
return PSA_ERROR_INVALID_ARGUMENT;
}
if (P != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P,
dhm_size_P));
}
if (G != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G,
dhm_size_G));
}
cleanup:
if (ret != 0) {
return mbedtls_to_psa_error(ret);
}
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||
MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE ||
MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||
MBEDTLS_PSA_BUILTIN_ALG_FFDH */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
psa_status_t mbedtls_psa_ffdh_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi GX, G, X, P;
psa_key_type_t type = attributes->type;
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
if (key_buffer_size > data_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(data, key_buffer, key_buffer_size);
memset(data + key_buffer_size, 0,
data_size - key_buffer_size);
*data_length = key_buffer_size;
return PSA_SUCCESS;
}
mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G);
mbedtls_mpi_init(&X); mbedtls_mpi_init(&P);
size_t key_len = PSA_BITS_TO_BYTES(attributes->bits);
status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G);
if (status != PSA_SUCCESS) {
goto cleanup;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,
key_buffer_size));
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len));
*data_length = key_len;
ret = 0;
cleanup:
mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);
mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX);
if (status == PSA_SUCCESS && ret != 0) {
status = mbedtls_to_psa_error(ret);
}
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||
MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)
psa_status_t mbedtls_psa_ffdh_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
mbedtls_mpi X, P;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_init(&P); mbedtls_mpi_init(&X);
(void) attributes;
status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL);
if (status != PSA_SUCCESS) {
goto cleanup;
}
/* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their
secret exponent from the range [2, P-2].
Select random value in range [3, P-1] and decrease it by 1. */
MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size));
*key_buffer_length = key_buffer_size;
cleanup:
mbedtls_mpi_free(&P); mbedtls_mpi_free(&X);
if (status == PSA_SUCCESS && ret != 0) {
return mbedtls_to_psa_error(ret);
}
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT)
psa_status_t mbedtls_psa_ffdh_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits)
{
(void) attributes;
if (key_buffer_size < data_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(key_buffer, data, data_length);
*key_buffer_length = data_length;
*bits = PSA_BYTES_TO_BITS(data_length);
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
psa_status_t mbedtls_psa_ffdh_key_agreement(
const psa_key_attributes_t *attributes,
const uint8_t *peer_key,
size_t peer_key_length,
const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi P, G, X, GY, K;
const size_t calculated_shared_secret_size = peer_key_length;
if (peer_key_length != key_buffer_size ||
calculated_shared_secret_size > shared_secret_size) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mbedtls_mpi_init(&P); mbedtls_mpi_init(&G);
mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY);
mbedtls_mpi_init(&K);
status = mbedtls_psa_ffdh_set_prime_generator(
PSA_BITS_TO_BYTES(attributes->bits), &P, &G);
if (status != PSA_SUCCESS) {
goto cleanup;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,
key_buffer_size));
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key,
peer_key_length));
/* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret,
calculated_shared_secret_size));
*shared_secret_length = calculated_shared_secret_size;
ret = 0;
cleanup:
mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);
mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY);
mbedtls_mpi_free(&K);
if (status == PSA_SUCCESS && ret != 0) {
status = mbedtls_to_psa_error(ret);
}
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -0,0 +1,470 @@
/*
* PSA hashing layer on top of Mbed TLS software crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_hash.h"
#include <mbedtls/error.h>
#include <string.h>
#if defined(MBEDTLS_PSA_BUILTIN_HASH)
psa_status_t mbedtls_psa_hash_abort(
mbedtls_psa_hash_operation_t *operation)
{
switch (operation->alg) {
case 0:
/* The object has (apparently) been initialized but it is not
* in use. It's ok to call abort on such an object, and there's
* nothing to do. */
break;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
mbedtls_md5_free(&operation->ctx.md5);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
mbedtls_ripemd160_free(&operation->ctx.ripemd160);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
mbedtls_sha1_free(&operation->ctx.sha1);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
mbedtls_sha256_free(&operation->ctx.sha256);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
mbedtls_sha256_free(&operation->ctx.sha256);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
mbedtls_sha512_free(&operation->ctx.sha512);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
mbedtls_sha512_free(&operation->ctx.sha512);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
case PSA_ALG_SHA3_224:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
case PSA_ALG_SHA3_256:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
case PSA_ALG_SHA3_384:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
case PSA_ALG_SHA3_512:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
mbedtls_sha3_free(&operation->ctx.sha3);
break;
#endif
default:
return PSA_ERROR_BAD_STATE;
}
operation->alg = 0;
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_hash_setup(
mbedtls_psa_hash_operation_t *operation,
psa_algorithm_t alg)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* A context must be freshly initialized before it can be set up. */
if (operation->alg != 0) {
return PSA_ERROR_BAD_STATE;
}
switch (alg) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
mbedtls_md5_init(&operation->ctx.md5);
ret = mbedtls_md5_starts(&operation->ctx.md5);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
mbedtls_ripemd160_init(&operation->ctx.ripemd160);
ret = mbedtls_ripemd160_starts(&operation->ctx.ripemd160);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
mbedtls_sha1_init(&operation->ctx.sha1);
ret = mbedtls_sha1_starts(&operation->ctx.sha1);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
mbedtls_sha256_init(&operation->ctx.sha256);
ret = mbedtls_sha256_starts(&operation->ctx.sha256, 1);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
mbedtls_sha256_init(&operation->ctx.sha256);
ret = mbedtls_sha256_starts(&operation->ctx.sha256, 0);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
mbedtls_sha512_init(&operation->ctx.sha512);
ret = mbedtls_sha512_starts(&operation->ctx.sha512, 1);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
mbedtls_sha512_init(&operation->ctx.sha512);
ret = mbedtls_sha512_starts(&operation->ctx.sha512, 0);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
case PSA_ALG_SHA3_224:
mbedtls_sha3_init(&operation->ctx.sha3);
ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_224);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
case PSA_ALG_SHA3_256:
mbedtls_sha3_init(&operation->ctx.sha3);
ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_256);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
case PSA_ALG_SHA3_384:
mbedtls_sha3_init(&operation->ctx.sha3);
ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_384);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
case PSA_ALG_SHA3_512:
mbedtls_sha3_init(&operation->ctx.sha3);
ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_512);
break;
#endif
default:
return PSA_ALG_IS_HASH(alg) ?
PSA_ERROR_NOT_SUPPORTED :
PSA_ERROR_INVALID_ARGUMENT;
}
if (ret == 0) {
operation->alg = alg;
} else {
mbedtls_psa_hash_abort(operation);
}
return mbedtls_to_psa_error(ret);
}
psa_status_t mbedtls_psa_hash_clone(
const mbedtls_psa_hash_operation_t *source_operation,
mbedtls_psa_hash_operation_t *target_operation)
{
switch (source_operation->alg) {
case 0:
return PSA_ERROR_BAD_STATE;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
mbedtls_md5_clone(&target_operation->ctx.md5,
&source_operation->ctx.md5);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
mbedtls_ripemd160_clone(&target_operation->ctx.ripemd160,
&source_operation->ctx.ripemd160);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
mbedtls_sha1_clone(&target_operation->ctx.sha1,
&source_operation->ctx.sha1);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
mbedtls_sha256_clone(&target_operation->ctx.sha256,
&source_operation->ctx.sha256);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
mbedtls_sha256_clone(&target_operation->ctx.sha256,
&source_operation->ctx.sha256);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
mbedtls_sha512_clone(&target_operation->ctx.sha512,
&source_operation->ctx.sha512);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
mbedtls_sha512_clone(&target_operation->ctx.sha512,
&source_operation->ctx.sha512);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
case PSA_ALG_SHA3_224:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
case PSA_ALG_SHA3_256:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
case PSA_ALG_SHA3_384:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
case PSA_ALG_SHA3_512:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
mbedtls_sha3_clone(&target_operation->ctx.sha3,
&source_operation->ctx.sha3);
break;
#endif
default:
(void) source_operation;
(void) target_operation;
return PSA_ERROR_NOT_SUPPORTED;
}
target_operation->alg = source_operation->alg;
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_hash_update(
mbedtls_psa_hash_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
switch (operation->alg) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
ret = mbedtls_md5_update(&operation->ctx.md5,
input, input_length);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
ret = mbedtls_ripemd160_update(&operation->ctx.ripemd160,
input, input_length);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
ret = mbedtls_sha1_update(&operation->ctx.sha1,
input, input_length);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
ret = mbedtls_sha256_update(&operation->ctx.sha256,
input, input_length);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
ret = mbedtls_sha256_update(&operation->ctx.sha256,
input, input_length);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
ret = mbedtls_sha512_update(&operation->ctx.sha512,
input, input_length);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
ret = mbedtls_sha512_update(&operation->ctx.sha512,
input, input_length);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
case PSA_ALG_SHA3_224:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
case PSA_ALG_SHA3_256:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
case PSA_ALG_SHA3_384:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
case PSA_ALG_SHA3_512:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
ret = mbedtls_sha3_update(&operation->ctx.sha3,
input, input_length);
break;
#endif
default:
(void) input;
(void) input_length;
return PSA_ERROR_BAD_STATE;
}
return mbedtls_to_psa_error(ret);
}
psa_status_t mbedtls_psa_hash_finish(
mbedtls_psa_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length)
{
psa_status_t status;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t actual_hash_length = PSA_HASH_LENGTH(operation->alg);
/* Fill the output buffer with something that isn't a valid hash
* (barring an attack on the hash and deliberately-crafted input),
* in case the caller doesn't check the return status properly. */
*hash_length = hash_size;
/* If hash_size is 0 then hash may be NULL and then the
* call to memset would have undefined behavior. */
if (hash_size != 0) {
memset(hash, '!', hash_size);
}
if (hash_size < actual_hash_length) {
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
switch (operation->alg) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
ret = mbedtls_md5_finish(&operation->ctx.md5, hash);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
ret = mbedtls_ripemd160_finish(&operation->ctx.ripemd160, hash);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
ret = mbedtls_sha1_finish(&operation->ctx.sha1, hash);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash);
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
case PSA_ALG_SHA3_224:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
case PSA_ALG_SHA3_256:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
case PSA_ALG_SHA3_384:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
case PSA_ALG_SHA3_512:
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
ret = mbedtls_sha3_finish(&operation->ctx.sha3, hash, hash_size);
break;
#endif
default:
(void) hash;
return PSA_ERROR_BAD_STATE;
}
status = mbedtls_to_psa_error(ret);
exit:
if (status == PSA_SUCCESS) {
*hash_length = actual_hash_length;
}
return status;
}
psa_status_t mbedtls_psa_hash_compute(
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *hash,
size_t hash_size,
size_t *hash_length)
{
mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
*hash_length = hash_size;
status = mbedtls_psa_hash_setup(&operation, alg);
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_psa_hash_update(&operation, input, input_length);
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_psa_hash_finish(&operation, hash, hash_size, hash_length);
if (status != PSA_SUCCESS) {
goto exit;
}
exit:
abort_status = mbedtls_psa_hash_abort(&operation);
if (status == PSA_SUCCESS) {
return abort_status;
} else {
return status;
}
}
#endif /* MBEDTLS_PSA_BUILTIN_HASH */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -0,0 +1,496 @@
/*
* PSA MAC layer on top of Mbed TLS software crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_cipher.h"
#include "psa_crypto_mac.h"
#include <mbedtls/md.h>
#include <mbedtls/error.h>
#include "mbedtls/constant_time.h"
#include <string.h>
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
static psa_status_t psa_hmac_abort_internal(
mbedtls_psa_hmac_operation_t *hmac)
{
mbedtls_platform_zeroize(hmac->opad, sizeof(hmac->opad));
return psa_hash_abort(&hmac->hash_ctx);
}
static psa_status_t psa_hmac_setup_internal(
mbedtls_psa_hmac_operation_t *hmac,
const uint8_t *key,
size_t key_length,
psa_algorithm_t hash_alg)
{
uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
size_t i;
size_t hash_size = PSA_HASH_LENGTH(hash_alg);
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
psa_status_t status;
hmac->alg = hash_alg;
/* Sanity checks on block_size, to guarantee that there won't be a buffer
* overflow below. This should never trigger if the hash algorithm
* is implemented correctly. */
/* The size checks against the ipad and opad buffers cannot be written
* `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
* because that triggers -Wlogical-op on GCC 7.3. */
if (block_size > sizeof(ipad)) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (block_size > sizeof(hmac->opad)) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (block_size < hash_size) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (key_length > block_size) {
status = psa_hash_compute(hash_alg, key, key_length,
ipad, sizeof(ipad), &key_length);
if (status != PSA_SUCCESS) {
goto cleanup;
}
}
/* A 0-length key is not commonly used in HMAC when used as a MAC,
* but it is permitted. It is common when HMAC is used in HKDF, for
* example. Don't call `memcpy` in the 0-length because `key` could be
* an invalid pointer which would make the behavior undefined. */
else if (key_length != 0) {
memcpy(ipad, key, key_length);
}
/* ipad contains the key followed by garbage. Xor and fill with 0x36
* to create the ipad value. */
for (i = 0; i < key_length; i++) {
ipad[i] ^= 0x36;
}
memset(ipad + key_length, 0x36, block_size - key_length);
/* Copy the key material from ipad to opad, flipping the requisite bits,
* and filling the rest of opad with the requisite constant. */
for (i = 0; i < key_length; i++) {
hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
}
memset(hmac->opad + key_length, 0x5C, block_size - key_length);
status = psa_hash_setup(&hmac->hash_ctx, hash_alg);
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = psa_hash_update(&hmac->hash_ctx, ipad, block_size);
cleanup:
mbedtls_platform_zeroize(ipad, sizeof(ipad));
return status;
}
static psa_status_t psa_hmac_update_internal(
mbedtls_psa_hmac_operation_t *hmac,
const uint8_t *data,
size_t data_length)
{
return psa_hash_update(&hmac->hash_ctx, data, data_length);
}
static psa_status_t psa_hmac_finish_internal(
mbedtls_psa_hmac_operation_t *hmac,
uint8_t *mac,
size_t mac_size)
{
uint8_t tmp[PSA_HASH_MAX_SIZE];
psa_algorithm_t hash_alg = hmac->alg;
size_t hash_size = 0;
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
psa_status_t status;
status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);
if (status != PSA_SUCCESS) {
return status;
}
/* From here on, tmp needs to be wiped. */
status = psa_hash_setup(&hmac->hash_ctx, hash_alg);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&hmac->hash_ctx, hmac->opad, block_size);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_update(&hmac->hash_ctx, tmp, hash_size);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);
if (status != PSA_SUCCESS) {
goto exit;
}
memcpy(mac, tmp, mac_size);
exit:
mbedtls_platform_zeroize(tmp, hash_size);
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(PSA_WANT_KEY_TYPE_DES)
/* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept
* to do CMAC with pure DES, so return NOT_SUPPORTED here. */
if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES &&
(psa_get_key_bits(attributes) == 64 ||
psa_get_key_bits(attributes) == 128)) {
return PSA_ERROR_NOT_SUPPORTED;
}
#endif
const mbedtls_cipher_info_t *cipher_info =
mbedtls_cipher_info_from_psa(
PSA_ALG_CMAC,
psa_get_key_type(attributes),
psa_get_key_bits(attributes),
NULL);
if (cipher_info == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info);
if (ret != 0) {
goto exit;
}
ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac,
key_buffer,
psa_get_key_bits(attributes));
exit:
return mbedtls_to_psa_error(ret);
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
/* Initialize this driver's MAC operation structure. Once this function has been
* called, mbedtls_psa_mac_abort can run and will do the right thing. */
static psa_status_t mac_init(
mbedtls_psa_mac_operation_t *operation,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
operation->alg = alg;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
mbedtls_cipher_init(&operation->ctx.cmac);
status = PSA_SUCCESS;
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
if (PSA_ALG_IS_HMAC(operation->alg)) {
/* We'll set up the hash operation later in psa_hmac_setup_internal. */
operation->ctx.hmac.alg = 0;
status = PSA_SUCCESS;
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
{
(void) operation;
status = PSA_ERROR_NOT_SUPPORTED;
}
if (status != PSA_SUCCESS) {
memset(operation, 0, sizeof(*operation));
}
return status;
}
psa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation)
{
if (operation->alg == 0) {
/* The object has (apparently) been initialized but it is not
* in use. It's ok to call abort on such an object, and there's
* nothing to do. */
return PSA_SUCCESS;
} else
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
mbedtls_cipher_free(&operation->ctx.cmac);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
if (PSA_ALG_IS_HMAC(operation->alg)) {
psa_hmac_abort_internal(&operation->ctx.hmac);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
{
/* Sanity check (shouldn't happen: operation->alg should
* always have been initialized to a valid value). */
goto bad_state;
}
operation->alg = 0;
return PSA_SUCCESS;
bad_state:
/* If abort is called on an uninitialized object, we can't trust
* anything. Wipe the object in case it contains confidential data.
* This may result in a memory leak if a pointer gets overwritten,
* but it's too late to do anything about this. */
memset(operation, 0, sizeof(*operation));
return PSA_ERROR_BAD_STATE;
}
static psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
/* A context must be freshly initialized before it can be set up. */
if (operation->alg != 0) {
return PSA_ERROR_BAD_STATE;
}
status = mac_init(operation, alg);
if (status != PSA_SUCCESS) {
return status;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {
/* Key buffer size for CMAC is dictated by the key bits set on the
* attributes, and previously validated by the core on key import. */
(void) key_buffer_size;
status = cmac_setup(operation, attributes, key_buffer);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
if (PSA_ALG_IS_HMAC(alg)) {
status = psa_hmac_setup_internal(&operation->ctx.hmac,
key_buffer,
key_buffer_size,
PSA_ALG_HMAC_GET_HASH(alg));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
{
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
status = PSA_ERROR_NOT_SUPPORTED;
}
if (status != PSA_SUCCESS) {
mbedtls_psa_mac_abort(operation);
}
return status;
}
psa_status_t mbedtls_psa_mac_sign_setup(
mbedtls_psa_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
return psa_mac_setup(operation, attributes,
key_buffer, key_buffer_size, alg);
}
psa_status_t mbedtls_psa_mac_verify_setup(
mbedtls_psa_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
return psa_mac_setup(operation, attributes,
key_buffer, key_buffer_size, alg);
}
psa_status_t mbedtls_psa_mac_update(
mbedtls_psa_mac_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
if (operation->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
return mbedtls_to_psa_error(
mbedtls_cipher_cmac_update(&operation->ctx.cmac,
input, input_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
if (PSA_ALG_IS_HMAC(operation->alg)) {
return psa_hmac_update_internal(&operation->ctx.hmac,
input, input_length);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
{
/* This shouldn't happen if `operation` was initialized by
* a setup function. */
(void) input;
(void) input_length;
return PSA_ERROR_BAD_STATE;
}
}
static psa_status_t psa_mac_finish_internal(
mbedtls_psa_mac_operation_t *operation,
uint8_t *mac, size_t mac_size)
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE];
int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp);
if (ret == 0) {
memcpy(mac, tmp, mac_size);
}
mbedtls_platform_zeroize(tmp, sizeof(tmp));
return mbedtls_to_psa_error(ret);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
if (PSA_ALG_IS_HMAC(operation->alg)) {
return psa_hmac_finish_internal(&operation->ctx.hmac,
mac, mac_size);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
{
/* This shouldn't happen if `operation` was initialized by
* a setup function. */
(void) operation;
(void) mac;
(void) mac_size;
return PSA_ERROR_BAD_STATE;
}
}
psa_status_t mbedtls_psa_mac_sign_finish(
mbedtls_psa_mac_operation_t *operation,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if (operation->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
status = psa_mac_finish_internal(operation, mac, mac_size);
if (status == PSA_SUCCESS) {
*mac_length = mac_size;
}
return status;
}
psa_status_t mbedtls_psa_mac_verify_finish(
mbedtls_psa_mac_operation_t *operation,
const uint8_t *mac,
size_t mac_length)
{
uint8_t actual_mac[PSA_MAC_MAX_SIZE];
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if (operation->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
/* Consistency check: requested MAC length fits our local buffer */
if (mac_length > sizeof(actual_mac)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
status = psa_mac_finish_internal(operation, actual_mac, mac_length);
if (status != PSA_SUCCESS) {
goto cleanup;
}
if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) {
status = PSA_ERROR_INVALID_SIGNATURE;
}
cleanup:
mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));
return status;
}
psa_status_t mbedtls_psa_mac_compute(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT;
status = psa_mac_setup(&operation,
attributes, key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (input_length > 0) {
status = mbedtls_psa_mac_update(&operation, input, input_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
status = psa_mac_finish_internal(&operation, mac, mac_size);
if (status == PSA_SUCCESS) {
*mac_length = mac_size;
}
exit:
mbedtls_psa_mac_abort(&operation);
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -0,0 +1,571 @@
/*
* PSA PAKE layer on top of Mbed TLS software crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_pake.h"
#include "psa_crypto_slot_management.h"
#include <mbedtls/ecjpake.h>
#include "psa_util_internal.h"
#include <mbedtls/platform.h>
#include <mbedtls/error.h>
#include <string.h>
/*
* State sequence:
*
* psa_pake_setup()
* |
* |-- In any order:
* | | psa_pake_set_password_key()
* | | psa_pake_set_user()
* | | psa_pake_set_peer()
* | | psa_pake_set_role()
* |
* |--- In any order: (First round input before or after first round output)
* | |
* | |------ In Order
* | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
* | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
* | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
* | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
* | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
* | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
* | |
* | |------ In Order:
* | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
* | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
* | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
* | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
* | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
* | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
* |
* |--- In any order: (Second round input before or after second round output)
* | |
* | |------ In Order
* | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
* | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
* | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
* | |
* | |------ In Order:
* | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
* | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
* | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
* |
* psa_pake_get_implicit_key()
* psa_pake_abort()
*/
/*
* Possible sequence of calls to implementation:
*
* |--- In any order:
* | |
* | |------ In Order
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF)
* | |
* | |------ In Order:
* | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF)
* |
* |--- In any order:
* | |
* | |------ In Order
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF)
* | |
* | |------ In Order:
* | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF)
*/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
static psa_status_t mbedtls_ecjpake_to_psa_error(int ret)
{
switch (ret) {
case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
case MBEDTLS_ERR_ECP_INVALID_KEY:
case MBEDTLS_ERR_ECP_VERIFY_FAILED:
return PSA_ERROR_DATA_INVALID;
case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
return PSA_ERROR_BUFFER_TOO_SMALL;
case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:
return PSA_ERROR_NOT_SUPPORTED;
case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
return PSA_ERROR_CORRUPTION_DETECTED;
default:
return PSA_ERROR_GENERIC_ERROR;
}
}
#endif
#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
static psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecjpake_init(&operation->ctx.jpake);
ret = mbedtls_ecjpake_setup(&operation->ctx.jpake,
operation->role,
MBEDTLS_MD_SHA256,
MBEDTLS_ECP_DP_SECP256R1,
operation->password,
operation->password_len);
mbedtls_platform_zeroize(operation->password, operation->password_len);
if (ret != 0) {
return mbedtls_ecjpake_to_psa_error(ret);
}
return PSA_SUCCESS;
}
#endif
/* The only two JPAKE user/peer identifiers supported in built-in implementation. */
static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' };
static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' };
psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation,
const psa_crypto_driver_pake_inputs_t *inputs)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t user_len = 0, peer_len = 0, password_len = 0;
uint8_t *peer = NULL, *user = NULL;
size_t actual_user_len = 0, actual_peer_len = 0, actual_password_len = 0;
psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
status = psa_crypto_driver_pake_get_password_len(inputs, &password_len);
if (status != PSA_SUCCESS) {
return status;
}
status = psa_crypto_driver_pake_get_user_len(inputs, &user_len);
if (status != PSA_SUCCESS) {
return status;
}
status = psa_crypto_driver_pake_get_peer_len(inputs, &peer_len);
if (status != PSA_SUCCESS) {
return status;
}
status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite);
if (status != PSA_SUCCESS) {
return status;
}
operation->password = mbedtls_calloc(1, password_len);
if (operation->password == NULL) {
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto error;
}
user = mbedtls_calloc(1, user_len);
if (user == NULL) {
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto error;
}
peer = mbedtls_calloc(1, peer_len);
if (peer == NULL) {
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto error;
}
status = psa_crypto_driver_pake_get_password(inputs, operation->password,
password_len, &actual_password_len);
if (status != PSA_SUCCESS) {
goto error;
}
status = psa_crypto_driver_pake_get_user(inputs, user,
user_len, &actual_user_len);
if (status != PSA_SUCCESS) {
goto error;
}
status = psa_crypto_driver_pake_get_peer(inputs, peer,
peer_len, &actual_peer_len);
if (status != PSA_SUCCESS) {
goto error;
}
operation->password_len = actual_password_len;
operation->alg = cipher_suite.algorithm;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
if (cipher_suite.algorithm == PSA_ALG_JPAKE) {
if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC ||
cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 ||
cipher_suite.bits != 256 ||
cipher_suite.hash != PSA_ALG_SHA_256) {
status = PSA_ERROR_NOT_SUPPORTED;
goto error;
}
const size_t user_peer_len = sizeof(jpake_client_id); // client and server have the same length
if (actual_user_len != user_peer_len ||
actual_peer_len != user_peer_len) {
status = PSA_ERROR_NOT_SUPPORTED;
goto error;
}
if (memcmp(user, jpake_client_id, actual_user_len) == 0 &&
memcmp(peer, jpake_server_id, actual_peer_len) == 0) {
operation->role = MBEDTLS_ECJPAKE_CLIENT;
} else
if (memcmp(user, jpake_server_id, actual_user_len) == 0 &&
memcmp(peer, jpake_client_id, actual_peer_len) == 0) {
operation->role = MBEDTLS_ECJPAKE_SERVER;
} else {
status = PSA_ERROR_NOT_SUPPORTED;
goto error;
}
operation->buffer_length = 0;
operation->buffer_offset = 0;
status = psa_pake_ecjpake_setup(operation);
if (status != PSA_SUCCESS) {
goto error;
}
/* Role has been set, release user/peer buffers. */
mbedtls_free(user); mbedtls_free(peer);
return PSA_SUCCESS;
} else
#else
(void) operation;
(void) inputs;
#endif
{ status = PSA_ERROR_NOT_SUPPORTED; }
error:
mbedtls_free(user); mbedtls_free(peer);
/* In case of failure of the setup of a multipart operation, the PSA driver interface
* specifies that the core does not call any other driver entry point thus does not
* call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean
* up like freeing the memory that may have been allocated to store the password.
*/
mbedtls_psa_pake_abort(operation);
return status;
}
static psa_status_t mbedtls_psa_pake_output_internal(
mbedtls_psa_pake_operation_t *operation,
psa_crypto_driver_pake_step_t step,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t length;
(void) step; // Unused parameter
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
/*
* The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different
* handling of output sequencing.
*
* The Mbed TLS JPAKE API outputs the whole X1+X2 and X2S steps data
* at once, on the other side the PSA CRYPTO PAKE api requires
* the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be
* retrieved in sequence.
*
* In order to achieve API compatibility, the whole X1+X2 or X2S steps
* data is stored in an intermediate buffer at first step output call,
* and data is sliced down by parsing the ECPoint records in order
* to return the right parts on each step.
*/
if (operation->alg == PSA_ALG_JPAKE) {
/* Initialize & write round on KEY_SHARE sequences */
if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) {
ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake,
operation->buffer,
sizeof(operation->buffer),
&operation->buffer_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE);
if (ret != 0) {
return mbedtls_ecjpake_to_psa_error(ret);
}
operation->buffer_offset = 0;
} else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) {
ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake,
operation->buffer,
sizeof(operation->buffer),
&operation->buffer_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE);
if (ret != 0) {
return mbedtls_ecjpake_to_psa_error(ret);
}
operation->buffer_offset = 0;
}
/*
* mbedtls_ecjpake_write_round_xxx() outputs thing in the format
* defined by draft-cragie-tls-ecjpake-01 section 7. The summary is
* that the data for each step is prepended with a length byte, and
* then they're concatenated. Additionally, the server's second round
* output is prepended with a 3-bytes ECParameters structure.
*
* In PSA, we output each step separately, and don't prepend the
* output with a length byte, even less a curve identifier, as that
* information is already available.
*/
if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE &&
operation->role == MBEDTLS_ECJPAKE_SERVER) {
/* Skip ECParameters, with is 3 bytes (RFC 8422) */
operation->buffer_offset += 3;
}
/* Read the length byte then move past it to the data */
length = operation->buffer[operation->buffer_offset];
operation->buffer_offset += 1;
if (operation->buffer_offset + length > operation->buffer_length) {
return PSA_ERROR_DATA_CORRUPT;
}
if (output_size < length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(output,
operation->buffer + operation->buffer_offset,
length);
*output_length = length;
operation->buffer_offset += length;
/* Reset buffer after ZK_PROOF sequence */
if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) ||
(step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) {
mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
operation->buffer_length = 0;
operation->buffer_offset = 0;
}
return PSA_SUCCESS;
} else
#else
(void) step;
(void) output;
(void) output_size;
(void) output_length;
#endif
{ return PSA_ERROR_NOT_SUPPORTED; }
}
psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation,
psa_crypto_driver_pake_step_t step,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
psa_status_t status = mbedtls_psa_pake_output_internal(
operation, step, output, output_size, output_length);
return status;
}
static psa_status_t mbedtls_psa_pake_input_internal(
mbedtls_psa_pake_operation_t *operation,
psa_crypto_driver_pake_step_t step,
const uint8_t *input,
size_t input_length)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
(void) step; // Unused parameter
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
/*
* The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different
* handling of input sequencing.
*
* The Mbed TLS JPAKE API takes the whole X1+X2 or X4S steps data
* at once as input, on the other side the PSA CRYPTO PAKE api requires
* the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be
* given in sequence.
*
* In order to achieve API compatibility, each X1+X2 or X4S step data
* is stored sequentially in an intermediate buffer and given to the
* Mbed TLS JPAKE API on the last step.
*
* This causes any input error to be only detected on the last step.
*/
if (operation->alg == PSA_ALG_JPAKE) {
/*
* Copy input to local buffer and format it as the Mbed TLS API
* expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7.
* The summary is that the data for each step is prepended with a
* length byte, and then they're concatenated. Additionally, the
* server's second round output is prepended with a 3-bytes
* ECParameters structure - which means we have to prepend that when
* we're a client.
*/
if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE &&
operation->role == MBEDTLS_ECJPAKE_CLIENT) {
/* We only support secp256r1. */
/* This is the ECParameters structure defined by RFC 8422. */
unsigned char ecparameters[3] = {
3, /* named_curve */
0, 23 /* secp256r1 */
};
if (operation->buffer_length + sizeof(ecparameters) >
sizeof(operation->buffer)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(operation->buffer + operation->buffer_length,
ecparameters, sizeof(ecparameters));
operation->buffer_length += sizeof(ecparameters);
}
/*
* The core checks that input_length is smaller than
* PSA_PAKE_INPUT_MAX_SIZE.
* Thus no risk of integer overflow here.
*/
if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
/* Write the length byte */
operation->buffer[operation->buffer_length] = (uint8_t) input_length;
operation->buffer_length += 1;
/* Finally copy the data */
memcpy(operation->buffer + operation->buffer_length,
input, input_length);
operation->buffer_length += input_length;
/* Load buffer at each last round ZK_PROOF */
if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) {
ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake,
operation->buffer,
operation->buffer_length);
mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
operation->buffer_length = 0;
if (ret != 0) {
return mbedtls_ecjpake_to_psa_error(ret);
}
} else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) {
ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake,
operation->buffer,
operation->buffer_length);
mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
operation->buffer_length = 0;
if (ret != 0) {
return mbedtls_ecjpake_to_psa_error(ret);
}
}
return PSA_SUCCESS;
} else
#else
(void) step;
(void) input;
(void) input_length;
#endif
{ return PSA_ERROR_NOT_SUPPORTED; }
}
psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation,
psa_crypto_driver_pake_step_t step,
const uint8_t *input,
size_t input_length)
{
psa_status_t status = mbedtls_psa_pake_input_internal(
operation, step, input, input_length);
return status;
}
psa_status_t mbedtls_psa_pake_get_implicit_key(
mbedtls_psa_pake_operation_t *operation,
uint8_t *output, size_t output_size,
size_t *output_length)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
if (operation->alg == PSA_ALG_JPAKE) {
ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake,
output,
output_size,
output_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE);
if (ret != 0) {
return mbedtls_ecjpake_to_psa_error(ret);
}
return PSA_SUCCESS;
} else
#else
(void) output;
#endif
{ return PSA_ERROR_NOT_SUPPORTED; }
}
psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation)
{
mbedtls_zeroize_and_free(operation->password, operation->password_len);
operation->password = NULL;
operation->password_len = 0;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
if (operation->alg == PSA_ALG_JPAKE) {
operation->role = MBEDTLS_ECJPAKE_NONE;
mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
operation->buffer_length = 0;
operation->buffer_offset = 0;
mbedtls_ecjpake_free(&operation->ctx.jpake);
}
#endif
operation->alg = PSA_ALG_NONE;
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_BUILTIN_PAKE */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -21,13 +21,10 @@ typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t;
#include "mbedtls/entropy.h"
/* Choose a DRBG based on configuration and availability */
#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
#include "mbedtls/hmac_drbg.h"
#elif defined(MBEDTLS_CTR_DRBG_C)
#if defined(MBEDTLS_CTR_DRBG_C)
#include "mbedtls/ctr_drbg.h"
#undef MBEDTLS_PSA_HMAC_DRBG_MD_TYPE
#elif defined(MBEDTLS_HMAC_DRBG_C)
@ -49,17 +46,11 @@ typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t;
#error "No hash algorithm available for HMAC_DBRG."
#endif
#else /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
#else /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
#error "No DRBG module available for the psa_crypto module."
#endif /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
#if defined(MBEDTLS_CTR_DRBG_C)
#include "mbedtls/ctr_drbg.h"
#elif defined(MBEDTLS_HMAC_DRBG_C)
#include "mbedtls/hmac_drbg.h"
#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
/* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */
#if defined(MBEDTLS_CTR_DRBG_C)

View file

@ -0,0 +1,705 @@
/*
* PSA RSA layer on top of Mbed TLS crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa/crypto_values.h"
#include "psa_crypto_core.h"
#include "psa_crypto_random_impl.h"
#include "psa_crypto_rsa.h"
#include "psa_crypto_hash.h"
#include "mbedtls/psa_util.h"
#include <stdlib.h>
#include <string.h>
#include "mbedtls/platform.h"
#include <mbedtls/rsa.h>
#include <mbedtls/error.h>
#include "rsa_internal.h"
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
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_PUBLIC_KEY)
/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes
* that are not a multiple of 8) well. For example, there is only
* mbedtls_rsa_get_len(), which returns a number of bytes, and no
* way to return the exact bit size of a key.
* To keep things simple, reject non-byte-aligned key sizes. */
static psa_status_t psa_check_rsa_key_byte_aligned(
const mbedtls_rsa_context *rsa)
{
mbedtls_mpi n;
psa_status_t status;
mbedtls_mpi_init(&n);
status = mbedtls_to_psa_error(
mbedtls_rsa_export(rsa, &n, NULL, NULL, NULL, NULL));
if (status == PSA_SUCCESS) {
if (mbedtls_mpi_bitlen(&n) % 8 != 0) {
status = PSA_ERROR_NOT_SUPPORTED;
}
}
mbedtls_mpi_free(&n);
return status;
}
psa_status_t mbedtls_psa_rsa_load_representation(
psa_key_type_t type, const uint8_t *data, size_t data_length,
mbedtls_rsa_context **p_rsa)
{
psa_status_t status;
size_t bits;
*p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));
if (*p_rsa == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
mbedtls_rsa_init(*p_rsa);
/* Parse the data. */
if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length));
} else {
status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length));
}
if (status != PSA_SUCCESS) {
goto exit;
}
/* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS
* supports non-byte-aligned key sizes, but not well. For example,
* mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */
bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa));
if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = psa_check_rsa_key_byte_aligned(*p_rsa);
if (status != PSA_SUCCESS) {
goto exit;
}
exit:
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
* 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_PUBLIC_KEY) */
#if (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_PUBLIC_KEY)
psa_status_t mbedtls_psa_rsa_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits)
{
psa_status_t status;
mbedtls_rsa_context *rsa = NULL;
/* Parse input */
status = mbedtls_psa_rsa_load_representation(attributes->type,
data,
data_length,
&rsa);
if (status != PSA_SUCCESS) {
goto exit;
}
*bits = (psa_key_bits_t) PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(rsa));
/* Re-export the data to PSA export format, such that we can store export
* representation in the key slot. Export representation in case of RSA is
* the smallest representation that's allowed as input, so a straight-up
* allocation of the same size as the input buffer will be large enough. */
status = mbedtls_psa_rsa_export_key(attributes->type,
rsa,
key_buffer,
key_buffer_size,
key_buffer_length);
exit:
/* Always free the RSA object */
mbedtls_rsa_free(rsa);
mbedtls_free(rsa);
return status;
}
#endif /* (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_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type,
mbedtls_rsa_context *rsa,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
int ret;
uint8_t *end = data + data_size;
/* PSA Crypto API defines the format of an RSA key as a DER-encoded
* representation of the non-encrypted PKCS#1 RSAPrivateKey for a
* private key and of the RFC3279 RSAPublicKey for a public key. */
if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
ret = mbedtls_rsa_write_key(rsa, data, &end);
} else {
ret = mbedtls_rsa_write_pubkey(rsa, data, &end);
}
if (ret < 0) {
/* Clean up in case pk_write failed halfway through. */
memset(data, 0, data_size);
return mbedtls_to_psa_error(ret);
}
/* The mbedtls_pk_xxx functions write to the end of the buffer.
* Move the data to the beginning and erase remaining data
* at the original location. */
if (2 * (size_t) ret <= data_size) {
memcpy(data, data + data_size - ret, ret);
memset(data + data_size - ret, 0, ret);
} else if ((size_t) ret < data_size) {
memmove(data, data + data_size - ret, ret);
memset(data + ret, 0, data_size - ret);
}
*data_length = ret;
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_rsa_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
status = mbedtls_psa_rsa_load_representation(
attributes->type, key_buffer, key_buffer_size, &rsa);
if (status == PSA_SUCCESS) {
status = mbedtls_psa_rsa_export_key(PSA_KEY_TYPE_RSA_PUBLIC_KEY,
rsa,
data,
data_size,
data_length);
}
mbedtls_rsa_free(rsa);
mbedtls_free(rsa);
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes,
size_t e_length,
int *exponent)
{
size_t i;
uint32_t acc = 0;
/* Mbed TLS encodes the public exponent as an int. For simplicity, only
* support values that fit in a 32-bit integer, which is larger than
* int on just about every platform anyway. */
if (e_length > sizeof(acc)) {
return PSA_ERROR_NOT_SUPPORTED;
}
for (i = 0; i < e_length; i++) {
acc = (acc << 8) | e_bytes[i];
}
if (acc > INT_MAX) {
return PSA_ERROR_NOT_SUPPORTED;
}
*exponent = acc;
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
const uint8_t *custom_data, size_t custom_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
psa_status_t status;
mbedtls_rsa_context rsa;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int exponent = 65537;
if (custom_data_length != 0) {
status = psa_rsa_read_exponent(custom_data, custom_data_length,
&exponent);
if (status != PSA_SUCCESS) {
return status;
}
}
mbedtls_rsa_init(&rsa);
ret = mbedtls_rsa_gen_key(&rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
(unsigned int) attributes->bits,
exponent);
if (ret != 0) {
mbedtls_rsa_free(&rsa);
return mbedtls_to_psa_error(ret);
}
status = mbedtls_psa_rsa_export_key(attributes->type,
&rsa, key_buffer, key_buffer_size,
key_buffer_length);
mbedtls_rsa_free(&rsa);
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */
/****************************************************************/
/* Sign/verify hashes */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
/* Decode the hash algorithm from alg and store the mbedtls encoding in
* md_alg. Verify that the hash length is acceptable. */
static psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg,
size_t hash_length,
mbedtls_md_type_t *md_alg)
{
psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
*md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
/* The Mbed TLS RSA module uses an unsigned int for hash length
* parameters. Validate that it fits so that we don't risk an
* overflow later. */
#if SIZE_MAX > UINT_MAX
if (hash_length > UINT_MAX) {
return PSA_ERROR_INVALID_ARGUMENT;
}
#endif
/* For signatures using a hash, the hash length must be correct. */
if (alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) {
if (*md_alg == MBEDTLS_MD_NONE) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (mbedtls_md_get_size_from_type(*md_alg) != hash_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}
}
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_rsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = mbedtls_psa_rsa_load_representation(attributes->type,
key_buffer,
key_buffer_size,
&rsa);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_rsa_decode_md_type(alg, hash_length, &md_alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (signature_size < mbedtls_rsa_get_len(rsa)) {
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE);
if (ret == 0) {
ret = mbedtls_rsa_pkcs1_sign(rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
md_alg,
(unsigned int) hash_length,
hash,
signature);
}
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
if (PSA_ALG_IS_RSA_PSS(alg)) {
ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
if (ret == 0) {
ret = mbedtls_rsa_rsassa_pss_sign(rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
hash,
signature);
}
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
if (ret == 0) {
*signature_length = mbedtls_rsa_get_len(rsa);
}
status = mbedtls_to_psa_error(ret);
exit:
mbedtls_rsa_free(rsa);
mbedtls_free(rsa);
return status;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
static int rsa_pss_expected_salt_len(psa_algorithm_t alg,
const mbedtls_rsa_context *rsa,
size_t hash_length)
{
if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) {
return MBEDTLS_RSA_SALT_LEN_ANY;
}
/* Otherwise: standard salt length, i.e. largest possible salt length
* up to the hash length. */
int klen = (int) mbedtls_rsa_get_len(rsa); // known to fit
int hlen = (int) hash_length; // known to fit
int room = klen - 2 - hlen;
if (room < 0) {
return 0; // there is no valid signature in this case anyway
} else if (room > hlen) {
return hlen;
} else {
return room;
}
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
psa_status_t mbedtls_psa_rsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = mbedtls_psa_rsa_load_representation(attributes->type,
key_buffer,
key_buffer_size,
&rsa);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_rsa_decode_md_type(alg, hash_length, &md_alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (signature_length != mbedtls_rsa_get_len(rsa)) {
status = PSA_ERROR_INVALID_SIGNATURE;
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE);
if (ret == 0) {
ret = mbedtls_rsa_pkcs1_verify(rsa,
md_alg,
(unsigned int) hash_length,
hash,
signature);
}
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
if (PSA_ALG_IS_RSA_PSS(alg)) {
ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
if (ret == 0) {
int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length);
ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa,
md_alg,
(unsigned) hash_length,
hash,
md_alg,
slen,
signature);
}
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
/* Mbed TLS distinguishes "invalid padding" from "valid padding but
* the rest of the signature is invalid". This has little use in
* practice and PSA doesn't report this distinction. */
status = (ret == MBEDTLS_ERR_RSA_INVALID_PADDING) ?
PSA_ERROR_INVALID_SIGNATURE :
mbedtls_to_psa_error(ret);
exit:
mbedtls_rsa_free(rsa);
mbedtls_free(rsa);
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
/****************************************************************/
/* Asymmetric cryptography */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
static int psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg,
mbedtls_rsa_context *rsa)
{
psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg);
mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
/* Just to get the error status right, as rsa_set_padding() doesn't
* distinguish between "bad RSA algorithm" and "unknown hash". */
if (mbedtls_md_info_from_type(md_alg) == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
const uint8_t *salt,
size_t salt_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
(void) key_buffer;
(void) key_buffer_size;
(void) input;
(void) input_length;
(void) salt;
(void) salt_length;
(void) output;
(void) output_size;
(void) output_length;
if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
mbedtls_rsa_context *rsa = NULL;
status = mbedtls_psa_rsa_load_representation(attributes->type,
key_buffer,
key_buffer_size,
&rsa);
if (status != PSA_SUCCESS) {
goto rsa_exit;
}
if (output_size < mbedtls_rsa_get_len(rsa)) {
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto rsa_exit;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
status = mbedtls_to_psa_error(
mbedtls_rsa_pkcs1_encrypt(rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
input_length,
input,
output));
#else
status = PSA_ERROR_NOT_SUPPORTED;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
} else
if (PSA_ALG_IS_RSA_OAEP(alg)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
status = mbedtls_to_psa_error(
psa_rsa_oaep_set_padding_mode(alg, rsa));
if (status != PSA_SUCCESS) {
goto rsa_exit;
}
status = mbedtls_to_psa_error(
mbedtls_rsa_rsaes_oaep_encrypt(rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
salt, salt_length,
input_length,
input,
output));
#else
status = PSA_ERROR_NOT_SUPPORTED;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
} else {
status = PSA_ERROR_INVALID_ARGUMENT;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
rsa_exit:
if (status == PSA_SUCCESS) {
*output_length = mbedtls_rsa_get_len(rsa);
}
mbedtls_rsa_free(rsa);
mbedtls_free(rsa);
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
} else {
status = PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
const uint8_t *salt,
size_t salt_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
(void) key_buffer;
(void) key_buffer_size;
(void) input;
(void) input_length;
(void) salt;
(void) salt_length;
(void) output;
(void) output_size;
(void) output_length;
*output_length = 0;
if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
mbedtls_rsa_context *rsa = NULL;
status = mbedtls_psa_rsa_load_representation(attributes->type,
key_buffer,
key_buffer_size,
&rsa);
if (status != PSA_SUCCESS) {
goto rsa_exit;
}
if (input_length != mbedtls_rsa_get_len(rsa)) {
status = PSA_ERROR_INVALID_ARGUMENT;
goto rsa_exit;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
status = mbedtls_to_psa_error(
mbedtls_rsa_pkcs1_decrypt(rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
output_length,
input,
output,
output_size));
#else
status = PSA_ERROR_NOT_SUPPORTED;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
} else
if (PSA_ALG_IS_RSA_OAEP(alg)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
status = mbedtls_to_psa_error(
psa_rsa_oaep_set_padding_mode(alg, rsa));
if (status != PSA_SUCCESS) {
goto rsa_exit;
}
status = mbedtls_to_psa_error(
mbedtls_rsa_rsaes_oaep_decrypt(rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
salt, salt_length,
output_length,
input,
output,
output_size));
#else
status = PSA_ERROR_NOT_SUPPORTED;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
} else {
status = PSA_ERROR_INVALID_ARGUMENT;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
rsa_exit:
mbedtls_rsa_free(rsa);
mbedtls_free(rsa);
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
} else {
status = PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
#endif /* MBEDTLS_PSA_CRYPTO_C */

View file

@ -105,17 +105,11 @@ psa_status_t mbedtls_psa_rsa_export_public_key(
/**
* \brief Generate an RSA key.
*
* \note The signature of the function is that of a PSA driver generate_key
* entry point.
*
* \param[in] attributes The attributes for the RSA key to generate.
* \param[in] params Production parameters for the key
* generation. This function only uses
* `params->data`,
* which contains the public exponent.
* \param[in] custom_data The public exponent to use.
* This can be a null pointer if
* \c params_data_length is 0.
* \param params_data_length Length of `params->data` in bytes.
* \param custom_data_length Length of \p custom_data in bytes.
* This can be 0, in which case the
* public exponent will be 65537.
* \param[out] key_buffer Buffer where the key data is to be written.
@ -130,12 +124,10 @@ psa_status_t mbedtls_psa_rsa_export_public_key(
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
*/
#ifndef __cplusplus
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
const psa_key_production_parameters_t *params, size_t params_data_length,
const uint8_t *custom_data, size_t custom_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
#endif
/** Sign an already-calculated hash with an RSA private key.
*

View file

@ -0,0 +1,373 @@
/*
* PSA crypto support for secure element drivers
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
#include <stdint.h>
#include <string.h>
#include "psa/crypto_se_driver.h"
#include "psa_crypto_se.h"
#if defined(MBEDTLS_PSA_ITS_FILE_C)
#include "psa_crypto_its.h"
#else /* Native ITS implementation */
#include "psa/error.h"
#include "psa/internal_trusted_storage.h"
#endif
#include "mbedtls/platform.h"
/****************************************************************/
/* Driver lookup */
/****************************************************************/
/* This structure is identical to psa_drv_se_context_t declared in
* `crypto_se_driver.h`, except that some parts are writable here
* (non-const, or pointer to non-const). */
typedef struct {
void *persistent_data;
size_t persistent_data_size;
uintptr_t transient_data;
} psa_drv_se_internal_context_t;
struct psa_se_drv_table_entry_s {
psa_key_location_t location;
const psa_drv_se_t *methods;
union {
psa_drv_se_internal_context_t internal;
psa_drv_se_context_t context;
} u;
};
static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];
psa_se_drv_table_entry_t *psa_get_se_driver_entry(
psa_key_lifetime_t lifetime)
{
size_t i;
psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime);
/* In the driver table, location=0 means an entry that isn't used.
* No driver has a location of 0 because it's a reserved value
* (which designates transparent keys). Make sure we never return
* a driver entry for location 0. */
if (location == 0) {
return NULL;
}
for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
if (driver_table[i].location == location) {
return &driver_table[i];
}
}
return NULL;
}
const psa_drv_se_t *psa_get_se_driver_methods(
const psa_se_drv_table_entry_t *driver)
{
return driver->methods;
}
psa_drv_se_context_t *psa_get_se_driver_context(
psa_se_drv_table_entry_t *driver)
{
return &driver->u.context;
}
int psa_get_se_driver(psa_key_lifetime_t lifetime,
const psa_drv_se_t **p_methods,
psa_drv_se_context_t **p_drv_context)
{
psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);
if (p_methods != NULL) {
*p_methods = (driver ? driver->methods : NULL);
}
if (p_drv_context != NULL) {
*p_drv_context = (driver ? &driver->u.context : NULL);
}
return driver != NULL;
}
/****************************************************************/
/* Persistent data management */
/****************************************************************/
static psa_status_t psa_get_se_driver_its_file_uid(
const psa_se_drv_table_entry_t *driver,
psa_storage_uid_t *uid)
{
if (driver->location > PSA_MAX_SE_LOCATION) {
return PSA_ERROR_NOT_SUPPORTED;
}
/* ITS file sizes are limited to 32 bits. */
if (driver->u.internal.persistent_data_size > UINT32_MAX) {
return PSA_ERROR_NOT_SUPPORTED;
}
/* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */
*uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location;
return PSA_SUCCESS;
}
psa_status_t psa_load_se_persistent_data(
const psa_se_drv_table_entry_t *driver)
{
psa_status_t status;
psa_storage_uid_t uid;
size_t length;
status = psa_get_se_driver_its_file_uid(driver, &uid);
if (status != PSA_SUCCESS) {
return status;
}
/* Read the amount of persistent data that the driver requests.
* If the data in storage is larger, it is truncated. If the data
* in storage is smaller, silently keep what is already at the end
* of the output buffer. */
/* psa_get_se_driver_its_file_uid ensures that the size_t
* persistent_data_size is in range, but compilers don't know that,
* so cast to reassure them. */
return psa_its_get(uid, 0,
(uint32_t) driver->u.internal.persistent_data_size,
driver->u.internal.persistent_data,
&length);
}
psa_status_t psa_save_se_persistent_data(
const psa_se_drv_table_entry_t *driver)
{
psa_status_t status;
psa_storage_uid_t uid;
status = psa_get_se_driver_its_file_uid(driver, &uid);
if (status != PSA_SUCCESS) {
return status;
}
/* psa_get_se_driver_its_file_uid ensures that the size_t
* persistent_data_size is in range, but compilers don't know that,
* so cast to reassure them. */
return psa_its_set(uid,
(uint32_t) driver->u.internal.persistent_data_size,
driver->u.internal.persistent_data,
0);
}
psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location)
{
psa_storage_uid_t uid;
if (location > PSA_MAX_SE_LOCATION) {
return PSA_ERROR_NOT_SUPPORTED;
}
uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location;
return psa_its_remove(uid);
}
psa_status_t psa_find_se_slot_for_key(
const psa_key_attributes_t *attributes,
psa_key_creation_method_t method,
psa_se_drv_table_entry_t *driver,
psa_key_slot_number_t *slot_number)
{
psa_status_t status;
psa_key_location_t key_location =
PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
/* If the location is wrong, it's a bug in the library. */
if (driver->location != key_location) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
/* If the driver doesn't support key creation in any way, give up now. */
if (driver->methods->key_management == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) {
/* The application wants to use a specific slot. Allow it if
* the driver supports it. On a system with isolation,
* the crypto service must check that the application is
* permitted to request this slot. */
psa_drv_se_validate_slot_number_t p_validate_slot_number =
driver->methods->key_management->p_validate_slot_number;
if (p_validate_slot_number == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
status = p_validate_slot_number(&driver->u.context,
driver->u.internal.persistent_data,
attributes, method,
*slot_number);
} else if (method == PSA_KEY_CREATION_REGISTER) {
/* The application didn't specify a slot number. This doesn't
* make sense when registering a slot. */
return PSA_ERROR_INVALID_ARGUMENT;
} else {
/* The application didn't tell us which slot to use. Let the driver
* choose. This is the normal case. */
psa_drv_se_allocate_key_t p_allocate =
driver->methods->key_management->p_allocate;
if (p_allocate == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
status = p_allocate(&driver->u.context,
driver->u.internal.persistent_data,
attributes, method,
slot_number);
}
return status;
}
psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver,
psa_key_slot_number_t slot_number)
{
psa_status_t status;
psa_status_t storage_status;
/* Normally a missing method would mean that the action is not
* supported. But psa_destroy_key() is not supposed to return
* PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should
* be able to destroy it. The only use case for a driver that
* does not have a way to destroy keys at all is if the keys are
* locked in a read-only state: we can use the keys but not
* destroy them. Hence, if the driver doesn't support destroying
* keys, it's really a lack of permission. */
if (driver->methods->key_management == NULL ||
driver->methods->key_management->p_destroy == NULL) {
return PSA_ERROR_NOT_PERMITTED;
}
status = driver->methods->key_management->p_destroy(
&driver->u.context,
driver->u.internal.persistent_data,
slot_number);
storage_status = psa_save_se_persistent_data(driver);
return status == PSA_SUCCESS ? storage_status : status;
}
psa_status_t psa_init_all_se_drivers(void)
{
size_t i;
for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
psa_se_drv_table_entry_t *driver = &driver_table[i];
if (driver->location == 0) {
continue; /* skipping unused entry */
}
const psa_drv_se_t *methods = psa_get_se_driver_methods(driver);
if (methods->p_init != NULL) {
psa_status_t status = methods->p_init(
&driver->u.context,
driver->u.internal.persistent_data,
driver->location);
if (status != PSA_SUCCESS) {
return status;
}
status = psa_save_se_persistent_data(driver);
if (status != PSA_SUCCESS) {
return status;
}
}
}
return PSA_SUCCESS;
}
/****************************************************************/
/* Driver registration */
/****************************************************************/
psa_status_t psa_register_se_driver(
psa_key_location_t location,
const psa_drv_se_t *methods)
{
size_t i;
psa_status_t status;
if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) {
return PSA_ERROR_NOT_SUPPORTED;
}
/* Driver table entries are 0-initialized. 0 is not a valid driver
* location because it means a transparent key. */
MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
"Secure element support requires 0 to mean a local key");
if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (location > PSA_MAX_SE_LOCATION) {
return PSA_ERROR_NOT_SUPPORTED;
}
for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
if (driver_table[i].location == 0) {
break;
}
/* Check that location isn't already in use up to the first free
* entry. Since entries are created in order and never deleted,
* there can't be a used entry after the first free entry. */
if (driver_table[i].location == location) {
return PSA_ERROR_ALREADY_EXISTS;
}
}
if (i == PSA_MAX_SE_DRIVERS) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
driver_table[i].location = location;
driver_table[i].methods = methods;
driver_table[i].u.internal.persistent_data_size =
methods->persistent_data_size;
if (methods->persistent_data_size != 0) {
driver_table[i].u.internal.persistent_data =
mbedtls_calloc(1, methods->persistent_data_size);
if (driver_table[i].u.internal.persistent_data == NULL) {
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto error;
}
/* Load the driver's persistent data. On first use, the persistent
* data does not exist in storage, and is initialized to
* all-bits-zero by the calloc call just above. */
status = psa_load_se_persistent_data(&driver_table[i]);
if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) {
goto error;
}
}
return PSA_SUCCESS;
error:
memset(&driver_table[i], 0, sizeof(driver_table[i]));
return status;
}
void psa_unregister_all_se_drivers(void)
{
size_t i;
for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
if (driver_table[i].u.internal.persistent_data != NULL) {
mbedtls_free(driver_table[i].u.internal.persistent_data);
}
}
memset(driver_table, 0, sizeof(driver_table));
}
/****************************************************************/
/* The end */
/****************************************************************/
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */

File diff suppressed because it is too large Load diff

View file

@ -15,20 +15,26 @@
/** Range of volatile key identifiers.
*
* The last #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation
* The first #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation
* range of key identifiers are reserved for volatile key identifiers.
* A volatile key identifier is equal to #PSA_KEY_ID_VOLATILE_MIN plus the
* index of the key slot containing the volatile key definition.
*
* If \c id is a a volatile key identifier, #PSA_KEY_ID_VOLATILE_MIN - \c id
* indicates the key slot containing the volatile key definition. See
* psa_crypto_slot_management.c for details.
*/
/** The minimum value for a volatile key identifier.
*/
#define PSA_KEY_ID_VOLATILE_MIN (PSA_KEY_ID_VENDOR_MAX - \
MBEDTLS_PSA_KEY_SLOT_COUNT + 1)
#define PSA_KEY_ID_VOLATILE_MIN PSA_KEY_ID_VENDOR_MIN
/** The maximum value for a volatile key identifier.
*/
#define PSA_KEY_ID_VOLATILE_MAX PSA_KEY_ID_VENDOR_MAX
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
#define PSA_KEY_ID_VOLATILE_MAX (MBEDTLS_PSA_KEY_ID_BUILTIN_MIN - 1)
#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
#define PSA_KEY_ID_VOLATILE_MAX \
(PSA_KEY_ID_VOLATILE_MIN + MBEDTLS_PSA_KEY_SLOT_COUNT - 1)
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
/** Test whether a key identifier is a volatile key identifier.
*
@ -58,6 +64,9 @@ static inline int psa_key_id_is_volatile(psa_key_id_t key_id)
* It is the responsibility of the caller to call psa_unregister_read(slot)
* when they have finished reading the contents of the slot.
*
* On failure, `*p_slot` is set to NULL. This ensures that it is always valid
* to call psa_unregister_read on the returned slot.
*
* \param key Key identifier to query.
* \param[out] p_slot On success, `*p_slot` contains a pointer to the
* key slot containing the description of the key
@ -91,6 +100,24 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
*/
psa_status_t psa_initialize_key_slots(void);
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
/* Allow test code to customize the key slice length. We use this in tests
* that exhaust the key store to reach a full key store in reasonable time
* and memory.
*
* The length of each slice must be between 1 and
* (1 << KEY_ID_SLOT_INDEX_WIDTH) inclusive.
*
* The length for a given slice index must not change while
* the key store is initialized.
*/
extern size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(
size_t slice_idx);
/* The number of volatile key slices. */
size_t psa_key_slot_volatile_slice_count(void);
#endif
/** Delete all data from key slots in memory.
* This function is not thread safe, it wipes every key slot regardless of
* state and reader count. It should only be called when no slot is in use.
@ -110,13 +137,22 @@ void psa_wipe_all_key_slots(void);
* If multi-threading is enabled, the caller must hold the
* global key slot mutex.
*
* \param[out] volatile_key_id On success, volatile key identifier
* associated to the returned slot.
* \param[out] volatile_key_id - If null, reserve a cache slot for
* a persistent or built-in key.
* - If non-null, allocate a slot for
* a volatile key. On success,
* \p *volatile_key_id is the
* identifier corresponding to the
* returned slot. It is the caller's
* responsibility to set this key identifier
* in the attributes.
* \param[out] p_slot On success, a pointer to the slot.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* There were no free key slots.
* When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, there was not
* enough memory to allocate more slots.
* \retval #PSA_ERROR_BAD_STATE \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* This function attempted to operate on a key slot which was in an
@ -125,6 +161,29 @@ void psa_wipe_all_key_slots(void);
psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
psa_key_slot_t **p_slot);
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
/** Return a key slot to the free list.
*
* Call this function when a slot obtained from psa_reserve_free_key_slot()
* is no longer in use.
*
* If multi-threading is enabled, the caller must hold the
* global key slot mutex.
*
* \param slice_idx The slice containing the slot.
* This is `slot->slice_index` when the slot
* is obtained from psa_reserve_free_key_slot().
* \param slot The key slot.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* This function attempted to operate on a key slot which was in an
* unexpected state.
*/
psa_status_t psa_free_key_slot(size_t slice_idx,
psa_key_slot_t *slot);
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
/** Change the state of a key slot.
*
* This function changes the state of the key slot from expected_state to
@ -171,10 +230,10 @@ static inline psa_status_t psa_key_slot_state_transition(
static inline psa_status_t psa_register_read(psa_key_slot_t *slot)
{
if ((slot->state != PSA_SLOT_FULL) ||
(slot->registered_readers >= SIZE_MAX)) {
(slot->var.occupied.registered_readers >= SIZE_MAX)) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
slot->registered_readers++;
slot->var.occupied.registered_readers++;
return PSA_SUCCESS;
}

View file

@ -0,0 +1,481 @@
/*
* PSA persistent key storage
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
#include <stdlib.h>
#include <string.h>
#include "psa/crypto.h"
#include "psa_crypto_storage.h"
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PSA_ITS_FILE_C)
#include "psa_crypto_its.h"
#else /* Native ITS implementation */
#include "psa/error.h"
#include "psa/internal_trusted_storage.h"
#endif
#include "mbedtls/platform.h"
/****************************************************************/
/* Key storage */
/****************************************************************/
/* Determine a file name (ITS file identifier) for the given key identifier.
* The file name must be distinct from any file that is used for a purpose
* other than storing a key. Currently, the only such file is the random seed
* file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is
* 0xFFFFFF52. */
static psa_storage_uid_t psa_its_identifier_of_slot(mbedtls_svc_key_id_t key)
{
#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
/* Encode the owner in the upper 32 bits. This means that if
* owner values are nonzero (as they are on a PSA platform),
* no key file will ever have a value less than 0x100000000, so
* the whole range 0..0xffffffff is available for non-key files. */
uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key);
return ((uint64_t) unsigned_owner_id << 32) |
MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
#else
/* Use the key id directly as a file name.
* psa_is_key_id_valid() in psa_crypto_slot_management.c
* is responsible for ensuring that key identifiers do not have a
* value that is reserved for non-key files. */
return key;
#endif
}
/**
* \brief Load persistent data for the given key slot number.
*
* This function reads data from a storage backend and returns the data in a
* buffer.
*
* \param key Persistent identifier of the key to be loaded. This
* should be an occupied storage location.
* \param[out] data Buffer where the data is to be written.
* \param data_size Size of the \c data buffer in bytes.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_DATA_INVALID \emptydescription
* \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
* \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
* \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
*/
static psa_status_t psa_crypto_storage_load(
const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size)
{
psa_status_t status;
psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
struct psa_storage_info_t data_identifier_info;
size_t data_length = 0;
status = psa_its_get_info(data_identifier, &data_identifier_info);
if (status != PSA_SUCCESS) {
return status;
}
status = psa_its_get(data_identifier, 0, (uint32_t) data_size, data, &data_length);
if (data_size != data_length) {
return PSA_ERROR_DATA_INVALID;
}
return status;
}
int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key)
{
psa_status_t ret;
psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
struct psa_storage_info_t data_identifier_info;
ret = psa_its_get_info(data_identifier, &data_identifier_info);
if (ret == PSA_ERROR_DOES_NOT_EXIST) {
return 0;
}
return 1;
}
/**
* \brief Store persistent data for the given key slot number.
*
* This function stores the given data buffer to a persistent storage.
*
* \param key Persistent identifier of the key to be stored. This
* should be an unoccupied storage location.
* \param[in] data Buffer containing the data to be stored.
* \param data_length The number of bytes
* that make up the data.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
* \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
* \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
* \retval #PSA_ERROR_DATA_INVALID \emptydescription
*/
static psa_status_t psa_crypto_storage_store(const mbedtls_svc_key_id_t key,
const uint8_t *data,
size_t data_length)
{
psa_status_t status;
psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
struct psa_storage_info_t data_identifier_info;
if (psa_is_key_present_in_storage(key) == 1) {
return PSA_ERROR_ALREADY_EXISTS;
}
status = psa_its_set(data_identifier, (uint32_t) data_length, data, 0);
if (status != PSA_SUCCESS) {
return PSA_ERROR_DATA_INVALID;
}
status = psa_its_get_info(data_identifier, &data_identifier_info);
if (status != PSA_SUCCESS) {
goto exit;
}
if (data_identifier_info.size != data_length) {
status = PSA_ERROR_DATA_INVALID;
goto exit;
}
exit:
if (status != PSA_SUCCESS) {
/* Remove the file in case we managed to create it but something
* went wrong. It's ok if the file doesn't exist. If the file exists
* but the removal fails, we're already reporting an error so there's
* nothing else we can do. */
(void) psa_its_remove(data_identifier);
}
return status;
}
psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key)
{
psa_status_t ret;
psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
struct psa_storage_info_t data_identifier_info;
ret = psa_its_get_info(data_identifier, &data_identifier_info);
if (ret == PSA_ERROR_DOES_NOT_EXIST) {
return PSA_SUCCESS;
}
if (psa_its_remove(data_identifier) != PSA_SUCCESS) {
return PSA_ERROR_DATA_INVALID;
}
ret = psa_its_get_info(data_identifier, &data_identifier_info);
if (ret != PSA_ERROR_DOES_NOT_EXIST) {
return PSA_ERROR_DATA_INVALID;
}
return PSA_SUCCESS;
}
/**
* \brief Get data length for given key slot number.
*
* \param key Persistent identifier whose stored data length
* is to be obtained.
* \param[out] data_length The number of bytes that make up the data.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
* \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
* \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
*/
static psa_status_t psa_crypto_storage_get_data_length(
const mbedtls_svc_key_id_t key,
size_t *data_length)
{
psa_status_t status;
psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
struct psa_storage_info_t data_identifier_info;
status = psa_its_get_info(data_identifier, &data_identifier_info);
if (status != PSA_SUCCESS) {
return status;
}
*data_length = (size_t) data_identifier_info.size;
return PSA_SUCCESS;
}
/**
* Persistent key storage magic header.
*/
#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY"
#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH (sizeof(PSA_KEY_STORAGE_MAGIC_HEADER))
typedef struct {
uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
uint8_t version[4];
uint8_t lifetime[sizeof(psa_key_lifetime_t)];
uint8_t type[2];
uint8_t bits[2];
uint8_t policy[sizeof(psa_key_policy_t)];
uint8_t data_len[4];
uint8_t key_data[];
} psa_persistent_key_storage_format;
void psa_format_key_data_for_storage(const uint8_t *data,
const size_t data_length,
const psa_key_attributes_t *attr,
uint8_t *storage_data)
{
psa_persistent_key_storage_format *storage_format =
(psa_persistent_key_storage_format *) storage_data;
memcpy(storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER,
PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH);
MBEDTLS_PUT_UINT32_LE(0, storage_format->version, 0);
MBEDTLS_PUT_UINT32_LE(attr->lifetime, storage_format->lifetime, 0);
MBEDTLS_PUT_UINT16_LE((uint16_t) attr->type, storage_format->type, 0);
MBEDTLS_PUT_UINT16_LE((uint16_t) attr->bits, storage_format->bits, 0);
MBEDTLS_PUT_UINT32_LE(attr->policy.usage, storage_format->policy, 0);
MBEDTLS_PUT_UINT32_LE(attr->policy.alg, storage_format->policy, sizeof(uint32_t));
MBEDTLS_PUT_UINT32_LE(attr->policy.alg2, storage_format->policy, 2 * sizeof(uint32_t));
MBEDTLS_PUT_UINT32_LE(data_length, storage_format->data_len, 0);
memcpy(storage_format->key_data, data, data_length);
}
static psa_status_t check_magic_header(const uint8_t *data)
{
if (memcmp(data, PSA_KEY_STORAGE_MAGIC_HEADER,
PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH) != 0) {
return PSA_ERROR_DATA_INVALID;
}
return PSA_SUCCESS;
}
psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data,
size_t storage_data_length,
uint8_t **key_data,
size_t *key_data_length,
psa_key_attributes_t *attr)
{
psa_status_t status;
const psa_persistent_key_storage_format *storage_format =
(const psa_persistent_key_storage_format *) storage_data;
uint32_t version;
if (storage_data_length < sizeof(*storage_format)) {
return PSA_ERROR_DATA_INVALID;
}
status = check_magic_header(storage_data);
if (status != PSA_SUCCESS) {
return status;
}
version = MBEDTLS_GET_UINT32_LE(storage_format->version, 0);
if (version != 0) {
return PSA_ERROR_DATA_INVALID;
}
*key_data_length = MBEDTLS_GET_UINT32_LE(storage_format->data_len, 0);
if (*key_data_length > (storage_data_length - sizeof(*storage_format)) ||
*key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) {
return PSA_ERROR_DATA_INVALID;
}
if (*key_data_length == 0) {
*key_data = NULL;
} else {
*key_data = mbedtls_calloc(1, *key_data_length);
if (*key_data == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
memcpy(*key_data, storage_format->key_data, *key_data_length);
}
attr->lifetime = MBEDTLS_GET_UINT32_LE(storage_format->lifetime, 0);
attr->type = MBEDTLS_GET_UINT16_LE(storage_format->type, 0);
attr->bits = MBEDTLS_GET_UINT16_LE(storage_format->bits, 0);
attr->policy.usage = MBEDTLS_GET_UINT32_LE(storage_format->policy, 0);
attr->policy.alg = MBEDTLS_GET_UINT32_LE(storage_format->policy, sizeof(uint32_t));
attr->policy.alg2 = MBEDTLS_GET_UINT32_LE(storage_format->policy, 2 * sizeof(uint32_t));
return PSA_SUCCESS;
}
psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr,
const uint8_t *data,
const size_t data_length)
{
size_t storage_data_length;
uint8_t *storage_data;
psa_status_t status;
/* All keys saved to persistent storage always have a key context */
if (data == NULL || data_length == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) {
return PSA_ERROR_INSUFFICIENT_STORAGE;
}
storage_data_length = data_length + sizeof(psa_persistent_key_storage_format);
storage_data = mbedtls_calloc(1, storage_data_length);
if (storage_data == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
psa_format_key_data_for_storage(data, data_length, attr, storage_data);
status = psa_crypto_storage_store(attr->id,
storage_data, storage_data_length);
mbedtls_zeroize_and_free(storage_data, storage_data_length);
return status;
}
void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length)
{
mbedtls_zeroize_and_free(key_data, key_data_length);
}
psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr,
uint8_t **data,
size_t *data_length)
{
psa_status_t status = PSA_SUCCESS;
uint8_t *loaded_data;
size_t storage_data_length = 0;
mbedtls_svc_key_id_t key = attr->id;
status = psa_crypto_storage_get_data_length(key, &storage_data_length);
if (status != PSA_SUCCESS) {
return status;
}
loaded_data = mbedtls_calloc(1, storage_data_length);
if (loaded_data == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
status = psa_crypto_storage_load(key, loaded_data, storage_data_length);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_parse_key_data_from_storage(loaded_data, storage_data_length,
data, data_length, attr);
/* All keys saved to persistent storage always have a key context */
if (status == PSA_SUCCESS &&
(*data == NULL || *data_length == 0)) {
status = PSA_ERROR_STORAGE_FAILURE;
}
exit:
mbedtls_zeroize_and_free(loaded_data, storage_data_length);
return status;
}
/****************************************************************/
/* Transactions */
/****************************************************************/
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
psa_crypto_transaction_t psa_crypto_transaction;
psa_status_t psa_crypto_save_transaction(void)
{
struct psa_storage_info_t p_info;
psa_status_t status;
status = psa_its_get_info(PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info);
if (status == PSA_SUCCESS) {
/* This shouldn't happen: we're trying to start a transaction while
* there is still a transaction that hasn't been replayed. */
return PSA_ERROR_CORRUPTION_DETECTED;
} else if (status != PSA_ERROR_DOES_NOT_EXIST) {
return status;
}
return psa_its_set(PSA_CRYPTO_ITS_TRANSACTION_UID,
sizeof(psa_crypto_transaction),
&psa_crypto_transaction,
0);
}
psa_status_t psa_crypto_load_transaction(void)
{
psa_status_t status;
size_t length;
status = psa_its_get(PSA_CRYPTO_ITS_TRANSACTION_UID, 0,
sizeof(psa_crypto_transaction),
&psa_crypto_transaction, &length);
if (status != PSA_SUCCESS) {
return status;
}
if (length != sizeof(psa_crypto_transaction)) {
return PSA_ERROR_DATA_INVALID;
}
return PSA_SUCCESS;
}
psa_status_t psa_crypto_stop_transaction(void)
{
psa_status_t status = psa_its_remove(PSA_CRYPTO_ITS_TRANSACTION_UID);
/* Whether or not updating the storage succeeded, the transaction is
* finished now. It's too late to go back, so zero out the in-memory
* data. */
memset(&psa_crypto_transaction, 0, sizeof(psa_crypto_transaction));
return status;
}
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
/****************************************************************/
/* Random generator state */
/****************************************************************/
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed,
size_t seed_size)
{
psa_status_t status;
struct psa_storage_info_t p_info;
status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info);
if (PSA_ERROR_DOES_NOT_EXIST == status) { /* No seed exists */
status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0);
} else if (PSA_SUCCESS == status) {
/* You should not be here. Seed needs to be injected only once */
status = PSA_ERROR_NOT_PERMITTED;
}
return status;
}
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
/****************************************************************/
/* The end */
/****************************************************************/
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */

View file

@ -0,0 +1,254 @@
/*
* PSA ITS simulator over stdio files.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_ITS_FILE_C)
#include "mbedtls/platform.h"
#if defined(_WIN32)
#include <windows.h>
#endif
#include "psa_crypto_its.h"
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#if !defined(PSA_ITS_STORAGE_PREFIX)
#define PSA_ITS_STORAGE_PREFIX ""
#endif
#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08x%08x"
#define PSA_ITS_STORAGE_SUFFIX ".psa_its"
#define PSA_ITS_STORAGE_FILENAME_LENGTH \
(sizeof(PSA_ITS_STORAGE_PREFIX) - 1 + /*prefix without terminating 0*/ \
16 + /*UID (64-bit number in hex)*/ \
sizeof(PSA_ITS_STORAGE_SUFFIX) - 1 + /*suffix without terminating 0*/ \
1 /*terminating null byte*/)
#define PSA_ITS_STORAGE_TEMP \
PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX
/* The maximum value of psa_storage_info_t.size */
#define PSA_ITS_MAX_SIZE 0xffffffff
#define PSA_ITS_MAGIC_STRING "PSA\0ITS\0"
#define PSA_ITS_MAGIC_LENGTH 8
/* As rename fails on Windows if the new filepath already exists,
* use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead.
* Returns 0 on success, nonzero on failure. */
#if defined(_WIN32)
#define rename_replace_existing(oldpath, newpath) \
(!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
#else
#define rename_replace_existing(oldpath, newpath) rename(oldpath, newpath)
#endif
typedef struct {
uint8_t magic[PSA_ITS_MAGIC_LENGTH];
uint8_t size[sizeof(uint32_t)];
uint8_t flags[sizeof(psa_storage_create_flags_t)];
} psa_its_file_header_t;
static void psa_its_fill_filename(psa_storage_uid_t uid, char *filename)
{
/* Break up the UID into two 32-bit pieces so as not to rely on
* long long support in snprintf. */
mbedtls_snprintf(filename, PSA_ITS_STORAGE_FILENAME_LENGTH,
"%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s",
PSA_ITS_STORAGE_PREFIX,
(unsigned) (uid >> 32),
(unsigned) (uid & 0xffffffff),
PSA_ITS_STORAGE_SUFFIX);
}
static psa_status_t psa_its_read_file(psa_storage_uid_t uid,
struct psa_storage_info_t *p_info,
FILE **p_stream)
{
char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
psa_its_file_header_t header;
size_t n;
*p_stream = NULL;
psa_its_fill_filename(uid, filename);
*p_stream = fopen(filename, "rb");
if (*p_stream == NULL) {
return PSA_ERROR_DOES_NOT_EXIST;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(*p_stream, NULL);
n = fread(&header, 1, sizeof(header), *p_stream);
if (n != sizeof(header)) {
return PSA_ERROR_DATA_CORRUPT;
}
if (memcmp(header.magic, PSA_ITS_MAGIC_STRING,
PSA_ITS_MAGIC_LENGTH) != 0) {
return PSA_ERROR_DATA_CORRUPT;
}
p_info->size = MBEDTLS_GET_UINT32_LE(header.size, 0);
p_info->flags = MBEDTLS_GET_UINT32_LE(header.flags, 0);
return PSA_SUCCESS;
}
psa_status_t psa_its_get_info(psa_storage_uid_t uid,
struct psa_storage_info_t *p_info)
{
psa_status_t status;
FILE *stream = NULL;
status = psa_its_read_file(uid, p_info, &stream);
if (stream != NULL) {
fclose(stream);
}
return status;
}
psa_status_t psa_its_get(psa_storage_uid_t uid,
uint32_t data_offset,
uint32_t data_length,
void *p_data,
size_t *p_data_length)
{
psa_status_t status;
FILE *stream = NULL;
size_t n;
struct psa_storage_info_t info;
status = psa_its_read_file(uid, &info, &stream);
if (status != PSA_SUCCESS) {
goto exit;
}
status = PSA_ERROR_INVALID_ARGUMENT;
if (data_offset + data_length < data_offset) {
goto exit;
}
#if SIZE_MAX < 0xffffffff
if (data_offset + data_length > SIZE_MAX) {
goto exit;
}
#endif
if (data_offset + data_length > info.size) {
goto exit;
}
status = PSA_ERROR_STORAGE_FAILURE;
#if LONG_MAX < 0xffffffff
while (data_offset > LONG_MAX) {
if (fseek(stream, LONG_MAX, SEEK_CUR) != 0) {
goto exit;
}
data_offset -= LONG_MAX;
}
#endif
if (fseek(stream, data_offset, SEEK_CUR) != 0) {
goto exit;
}
n = fread(p_data, 1, data_length, stream);
if (n != data_length) {
goto exit;
}
status = PSA_SUCCESS;
if (p_data_length != NULL) {
*p_data_length = n;
}
exit:
if (stream != NULL) {
fclose(stream);
}
return status;
}
psa_status_t psa_its_set(psa_storage_uid_t uid,
uint32_t data_length,
const void *p_data,
psa_storage_create_flags_t create_flags)
{
if (uid == 0) {
return PSA_ERROR_INVALID_HANDLE;
}
psa_status_t status = PSA_ERROR_STORAGE_FAILURE;
char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
FILE *stream = NULL;
psa_its_file_header_t header;
size_t n;
memcpy(header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH);
MBEDTLS_PUT_UINT32_LE(data_length, header.size, 0);
MBEDTLS_PUT_UINT32_LE(create_flags, header.flags, 0);
psa_its_fill_filename(uid, filename);
stream = fopen(PSA_ITS_STORAGE_TEMP, "wb");
if (stream == NULL) {
goto exit;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(stream, NULL);
status = PSA_ERROR_INSUFFICIENT_STORAGE;
n = fwrite(&header, 1, sizeof(header), stream);
if (n != sizeof(header)) {
goto exit;
}
if (data_length != 0) {
n = fwrite(p_data, 1, data_length, stream);
if (n != data_length) {
goto exit;
}
}
status = PSA_SUCCESS;
exit:
if (stream != NULL) {
int ret = fclose(stream);
if (status == PSA_SUCCESS && ret != 0) {
status = PSA_ERROR_INSUFFICIENT_STORAGE;
}
}
if (status == PSA_SUCCESS) {
if (rename_replace_existing(PSA_ITS_STORAGE_TEMP, filename) != 0) {
status = PSA_ERROR_STORAGE_FAILURE;
}
}
/* The temporary file may still exist, but only in failure cases where
* we're already reporting an error. So there's nothing we can do on
* failure. If the function succeeded, and in some error cases, the
* temporary file doesn't exist and so remove() is expected to fail.
* Thus we just ignore the return status of remove(). */
(void) remove(PSA_ITS_STORAGE_TEMP);
return status;
}
psa_status_t psa_its_remove(psa_storage_uid_t uid)
{
char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
FILE *stream;
psa_its_fill_filename(uid, filename);
stream = fopen(filename, "rb");
if (stream == NULL) {
return PSA_ERROR_DOES_NOT_EXIST;
}
fclose(stream);
if (remove(filename) != 0) {
return PSA_ERROR_STORAGE_FAILURE;
}
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_ITS_FILE_C */

View file

@ -0,0 +1,608 @@
/*
* PSA hashing layer on top of Mbed TLS software crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
/* This is needed for MBEDTLS_ERR_XXX macros */
#include <mbedtls/error.h>
#if defined(MBEDTLS_ASN1_WRITE_C)
#include <mbedtls/asn1write.h>
#include <psa/crypto_sizes.h>
#endif
#include "psa_util_internal.h"
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include <psa/crypto.h>
#if defined(MBEDTLS_MD_LIGHT)
#include <mbedtls/md.h>
#endif
#if defined(MBEDTLS_LMS_C)
#include <mbedtls/lms.h>
#endif
#if defined(MBEDTLS_SSL_TLS_C) && \
(defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
#include <mbedtls/ssl.h>
#endif
#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \
defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
#include <mbedtls/rsa.h>
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
#include <mbedtls/ecp.h>
#endif
#if defined(MBEDTLS_PK_C)
#include <mbedtls/pk.h>
#endif
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
#include <mbedtls/cipher.h>
#endif
#include <mbedtls/entropy.h>
/* PSA_SUCCESS is kept at the top of each error table since
* it's the most common status when everything functions properly. */
#if defined(MBEDTLS_MD_LIGHT)
const mbedtls_error_pair_t psa_to_md_errors[] =
{
{ PSA_SUCCESS, 0 },
{ PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE },
{ PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_MD_BAD_INPUT_DATA },
{ PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_MD_ALLOC_FAILED }
};
#endif
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
const mbedtls_error_pair_t psa_to_cipher_errors[] =
{
{ PSA_SUCCESS, 0 },
{ PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE },
{ PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA },
{ PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_CIPHER_ALLOC_FAILED }
};
#endif
#if defined(MBEDTLS_LMS_C)
const mbedtls_error_pair_t psa_to_lms_errors[] =
{
{ PSA_SUCCESS, 0 },
{ PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL },
{ PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_LMS_BAD_INPUT_DATA }
};
#endif
#if defined(MBEDTLS_SSL_TLS_C) && \
(defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
const mbedtls_error_pair_t psa_to_ssl_errors[] =
{
{ PSA_SUCCESS, 0 },
{ PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_SSL_ALLOC_FAILED },
{ PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE },
{ PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_SSL_INVALID_MAC },
{ PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_SSL_BAD_INPUT_DATA },
{ PSA_ERROR_BAD_STATE, MBEDTLS_ERR_SSL_INTERNAL_ERROR },
{ PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL }
};
#endif
#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \
defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
const mbedtls_error_pair_t psa_to_pk_rsa_errors[] =
{
{ PSA_SUCCESS, 0 },
{ PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
{ PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
{ PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
{ PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE },
{ PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_RSA_RNG_FAILED },
{ PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_RSA_VERIFY_FAILED },
{ PSA_ERROR_INVALID_PADDING, MBEDTLS_ERR_RSA_INVALID_PADDING }
};
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] =
{
{ PSA_SUCCESS, 0 },
{ PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
{ PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
{ PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE },
{ PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL },
{ PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_ECP_RANDOM_FAILED },
{ PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_ECP_VERIFY_FAILED }
};
#endif
int psa_generic_status_to_mbedtls(psa_status_t status)
{
switch (status) {
case PSA_SUCCESS:
return 0;
case PSA_ERROR_NOT_SUPPORTED:
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
case PSA_ERROR_CORRUPTION_DETECTED:
return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
case PSA_ERROR_COMMUNICATION_FAILURE:
case PSA_ERROR_HARDWARE_FAILURE:
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
case PSA_ERROR_NOT_PERMITTED:
default:
return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
}
}
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))
{
for (size_t i = 0; i < local_errors_num; i++) {
if (status == local_translations[i].psa_status) {
return local_translations[i].mbedtls_error;
}
}
return fallback_f(status);
}
#if defined(MBEDTLS_PK_C)
int psa_pk_status_to_mbedtls(psa_status_t status)
{
switch (status) {
case PSA_ERROR_INVALID_HANDLE:
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
case PSA_ERROR_BUFFER_TOO_SMALL:
return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
case PSA_ERROR_NOT_SUPPORTED:
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
case PSA_ERROR_INVALID_ARGUMENT:
return MBEDTLS_ERR_PK_INVALID_ALG;
case PSA_ERROR_NOT_PERMITTED:
return MBEDTLS_ERR_PK_TYPE_MISMATCH;
case PSA_ERROR_INSUFFICIENT_MEMORY:
return MBEDTLS_ERR_PK_ALLOC_FAILED;
case PSA_ERROR_BAD_STATE:
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
case PSA_ERROR_DATA_CORRUPT:
case PSA_ERROR_DATA_INVALID:
case PSA_ERROR_STORAGE_FAILURE:
return MBEDTLS_ERR_PK_FILE_IO_ERROR;
default:
return psa_generic_status_to_mbedtls(status);
}
}
#endif /* MBEDTLS_PK_C */
/****************************************************************/
/* Key management */
/****************************************************************/
#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid,
size_t *bits)
{
switch (grpid) {
#if defined(MBEDTLS_ECP_HAVE_SECP192R1)
case MBEDTLS_ECP_DP_SECP192R1:
*bits = 192;
return PSA_ECC_FAMILY_SECP_R1;
#endif
#if defined(MBEDTLS_ECP_HAVE_SECP224R1)
case MBEDTLS_ECP_DP_SECP224R1:
*bits = 224;
return PSA_ECC_FAMILY_SECP_R1;
#endif
#if defined(MBEDTLS_ECP_HAVE_SECP256R1)
case MBEDTLS_ECP_DP_SECP256R1:
*bits = 256;
return PSA_ECC_FAMILY_SECP_R1;
#endif
#if defined(MBEDTLS_ECP_HAVE_SECP384R1)
case MBEDTLS_ECP_DP_SECP384R1:
*bits = 384;
return PSA_ECC_FAMILY_SECP_R1;
#endif
#if defined(MBEDTLS_ECP_HAVE_SECP521R1)
case MBEDTLS_ECP_DP_SECP521R1:
*bits = 521;
return PSA_ECC_FAMILY_SECP_R1;
#endif
#if defined(MBEDTLS_ECP_HAVE_BP256R1)
case MBEDTLS_ECP_DP_BP256R1:
*bits = 256;
return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
#endif
#if defined(MBEDTLS_ECP_HAVE_BP384R1)
case MBEDTLS_ECP_DP_BP384R1:
*bits = 384;
return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
#endif
#if defined(MBEDTLS_ECP_HAVE_BP512R1)
case MBEDTLS_ECP_DP_BP512R1:
*bits = 512;
return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
#endif
#if defined(MBEDTLS_ECP_HAVE_CURVE25519)
case MBEDTLS_ECP_DP_CURVE25519:
*bits = 255;
return PSA_ECC_FAMILY_MONTGOMERY;
#endif
#if defined(MBEDTLS_ECP_HAVE_SECP192K1)
case MBEDTLS_ECP_DP_SECP192K1:
*bits = 192;
return PSA_ECC_FAMILY_SECP_K1;
#endif
#if defined(MBEDTLS_ECP_HAVE_SECP224K1)
/* secp224k1 is not and will not be supported in PSA (#3541). */
#endif
#if defined(MBEDTLS_ECP_HAVE_SECP256K1)
case MBEDTLS_ECP_DP_SECP256K1:
*bits = 256;
return PSA_ECC_FAMILY_SECP_K1;
#endif
#if defined(MBEDTLS_ECP_HAVE_CURVE448)
case MBEDTLS_ECP_DP_CURVE448:
*bits = 448;
return PSA_ECC_FAMILY_MONTGOMERY;
#endif
default:
*bits = 0;
return 0;
}
}
mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family,
size_t bits)
{
switch (family) {
case PSA_ECC_FAMILY_SECP_R1:
switch (bits) {
#if defined(PSA_WANT_ECC_SECP_R1_192)
case 192:
return MBEDTLS_ECP_DP_SECP192R1;
#endif
#if defined(PSA_WANT_ECC_SECP_R1_224)
case 224:
return MBEDTLS_ECP_DP_SECP224R1;
#endif
#if defined(PSA_WANT_ECC_SECP_R1_256)
case 256:
return MBEDTLS_ECP_DP_SECP256R1;
#endif
#if defined(PSA_WANT_ECC_SECP_R1_384)
case 384:
return MBEDTLS_ECP_DP_SECP384R1;
#endif
#if defined(PSA_WANT_ECC_SECP_R1_521)
case 521:
return MBEDTLS_ECP_DP_SECP521R1;
#endif
}
break;
case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
switch (bits) {
#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
case 256:
return MBEDTLS_ECP_DP_BP256R1;
#endif
#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
case 384:
return MBEDTLS_ECP_DP_BP384R1;
#endif
#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
case 512:
return MBEDTLS_ECP_DP_BP512R1;
#endif
}
break;
case PSA_ECC_FAMILY_MONTGOMERY:
switch (bits) {
#if defined(PSA_WANT_ECC_MONTGOMERY_255)
case 255:
return MBEDTLS_ECP_DP_CURVE25519;
#endif
#if defined(PSA_WANT_ECC_MONTGOMERY_448)
case 448:
return MBEDTLS_ECP_DP_CURVE448;
#endif
}
break;
case PSA_ECC_FAMILY_SECP_K1:
switch (bits) {
#if defined(PSA_WANT_ECC_SECP_K1_192)
case 192:
return MBEDTLS_ECP_DP_SECP192K1;
#endif
#if defined(PSA_WANT_ECC_SECP_K1_224)
/* secp224k1 is not and will not be supported in PSA (#3541). */
#endif
#if defined(PSA_WANT_ECC_SECP_K1_256)
case 256:
return MBEDTLS_ECP_DP_SECP256K1;
#endif
}
break;
}
return MBEDTLS_ECP_DP_NONE;
}
#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
/* Wrapper function allowing the classic API to use the PSA RNG.
*
* `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls
* `psa_generate_random(...)`. The state parameter is ignored since the
* PSA API doesn't support passing an explicit state.
*/
int mbedtls_psa_get_random(void *p_rng,
unsigned char *output,
size_t output_size)
{
/* This function takes a pointer to the RNG state because that's what
* classic mbedtls functions using an RNG expect. The PSA RNG manages
* its own state internally and doesn't let the caller access that state.
* So we just ignore the state parameter, and in practice we'll pass
* NULL. */
(void) p_rng;
psa_status_t status = psa_generate_random(output, output_size);
if (status == PSA_SUCCESS) {
return 0;
} else {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
}
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
/**
* \brief Convert a single raw coordinate to DER ASN.1 format. The output der
* buffer is filled backward (i.e. starting from its end).
*
* \param raw_buf Buffer containing the raw coordinate to be
* converted.
* \param raw_len Length of raw_buf in bytes. This must be > 0.
* \param der_buf_start Pointer to the beginning of the buffer which
* will be filled with the DER converted data.
* \param der_buf_end End of the buffer used to store the DER output.
*
* \return On success, the amount of data (in bytes) written to
* the DER buffer.
* \return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der
* buffer is too small to contain all the converted data.
* \return MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw
* coordinate is null (i.e. all zeros).
*
* \warning Raw and der buffer must not be overlapping.
*/
static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len,
unsigned char *der_buf_start,
unsigned char *der_buf_end)
{
unsigned char *p = der_buf_end;
int len;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* ASN.1 DER encoding requires minimal length, so skip leading 0s.
* Provided input MPIs should not be 0, but as a failsafe measure, still
* detect that and return error in case. */
while (*raw_buf == 0x00) {
++raw_buf;
--raw_len;
if (raw_len == 0) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
}
len = (int) raw_len;
/* Copy the raw coordinate to the end of der_buf. */
if ((p - der_buf_start) < len) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
p -= len;
memcpy(p, raw_buf, len);
/* If MSb is 1, ASN.1 requires that we prepend a 0. */
if (*p & 0x80) {
if ((p - der_buf_start) < 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
--p;
*p = 0x00;
++len;
}
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER));
return len;
}
int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len,
unsigned char *der, size_t der_size, size_t *der_len)
{
unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
const size_t coordinate_len = PSA_BITS_TO_BYTES(bits);
size_t len = 0;
unsigned char *p = der + der_size;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (raw_len != (2 * coordinate_len)) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
if (coordinate_len > sizeof(r)) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
/* Since raw and der buffers might overlap, dump r and s before starting
* the conversion. */
memcpy(r, raw, coordinate_len);
memcpy(s, raw + coordinate_len, coordinate_len);
/* der buffer will initially be written starting from its end so we pick s
* first and then r. */
ret = convert_raw_to_der_single_int(s, coordinate_len, der, p);
if (ret < 0) {
return ret;
}
p -= ret;
len += ret;
ret = convert_raw_to_der_single_int(r, coordinate_len, der, p);
if (ret < 0) {
return ret;
}
p -= ret;
len += ret;
/* Add ASN.1 header (len + tag). */
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der,
MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE));
/* memmove the content of der buffer to its beginnig. */
memmove(der, p, len);
*der_len = len;
return 0;
}
/**
* \brief Convert a single integer from ASN.1 DER format to raw.
*
* \param der Buffer containing the DER integer value to be
* converted.
* \param der_len Length of the der buffer in bytes.
* \param raw Output buffer that will be filled with the
* converted data. This should be at least
* coordinate_size bytes and it must be zeroed before
* calling this function.
* \param coordinate_size Size (in bytes) of a single coordinate in raw
* format.
*
* \return On success, the amount of DER data parsed from the
* provided der buffer.
* \return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag
* is missing in the der buffer.
* \return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer
* is null (i.e. all zeros) or if the output raw buffer
* is too small to contain the converted raw value.
*
* \warning Der and raw buffers must not be overlapping.
*/
static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len,
unsigned char *raw, size_t coordinate_size)
{
unsigned char *p = der;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t unpadded_len, padding_len = 0;
/* Get the length of ASN.1 element (i.e. the integer we need to parse). */
ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len,
MBEDTLS_ASN1_INTEGER);
if (ret != 0) {
return ret;
}
/* It's invalid to have:
* - unpadded_len == 0.
* - MSb set without a leading 0x00 (leading 0x00 is checked below). */
if (((unpadded_len == 0) || (*p & 0x80) != 0)) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
/* Skip possible leading zero */
if (*p == 0x00) {
p++;
unpadded_len--;
/* It is not allowed to have more than 1 leading zero.
* Ignore the case in which unpadded_len = 0 because that's a 0 encoded
* in ASN.1 format (i.e. 020100). */
if ((unpadded_len > 0) && (*p == 0x00)) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
}
if (unpadded_len > coordinate_size) {
/* Parsed number is longer than the maximum expected value. */
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
padding_len = coordinate_size - unpadded_len;
/* raw buffer was already zeroed by the calling function so zero-padding
* operation is skipped here. */
memcpy(raw + padding_len, p, unpadded_len);
p += unpadded_len;
return (int) (p - der);
}
int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len,
unsigned char *raw, size_t raw_size, size_t *raw_len)
{
unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];
unsigned char *p = (unsigned char *) der;
size_t data_len;
size_t coordinate_size = PSA_BITS_TO_BYTES(bits);
int ret;
/* The output raw buffer should be at least twice the size of a raw
* coordinate in order to store r and s. */
if (raw_size < coordinate_size * 2) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
if (2 * coordinate_size > sizeof(raw_tmp)) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
/* Check that the provided input DER buffer has the right header. */
ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return ret;
}
memset(raw_tmp, 0, 2 * coordinate_size);
/* Extract r */
ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size);
if (ret < 0) {
return ret;
}
p += ret;
data_len -= ret;
/* Extract s */
ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size,
coordinate_size);
if (ret < 0) {
return ret;
}
p += ret;
data_len -= ret;
/* Check that we consumed all the input der data. */
if ((size_t) (p - der) != der_len) {
return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
}
memcpy(raw, raw_tmp, 2 * coordinate_size);
*raw_len = 2 * coordinate_size;
return 0;
}
#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */

View file

@ -29,6 +29,7 @@
#include "mbedtls/rsa.h"
#include "bignum_core.h"
#include "bignum_internal.h"
#include "rsa_alt_helpers.h"
#include "rsa_internal.h"
#include "mbedtls/oid.h"
@ -1259,7 +1260,7 @@ int mbedtls_rsa_public(mbedtls_rsa_context *ctx,
}
olen = ctx->len;
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &ctx->E, &ctx->N, &ctx->RN));
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod_unsafe(&T, &T, &ctx->E, &ctx->N, &ctx->RN));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));
cleanup:

View file

@ -44,7 +44,9 @@
#endif /* defined(__clang__) && (__clang_major__ >= 4) */
/* Ensure that SIG_SETMASK is defined when -std=c99 is used. */
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#include "common.h"
@ -150,7 +152,9 @@ static int mbedtls_a64_crypto_sha256_determine_support(void)
return 1;
}
#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <processthreadsapi.h>

View file

@ -84,6 +84,10 @@ void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long d
void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx)
{
if (ctx == NULL) {
return;
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_destroy_key(ctx->psa_hmac_key);
#else

View file

@ -60,7 +60,7 @@ const char *mbedtls_ssl_named_group_to_str( uint16_t in )
return "ffdhe8192";
};
return "UNKOWN";
return "UNKNOWN";
}
const char *mbedtls_ssl_sig_alg_to_str( uint16_t in )
{

View file

@ -1507,7 +1507,7 @@ int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
#if defined(MBEDTLS_SSL_CLI_C)
#if defined(MBEDTLS_SSL_CLI_C) || defined(MBEDTLS_SSL_SRV_C)
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf);
#endif
@ -1674,18 +1674,53 @@ static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl)
}
/*
* Check usage of a certificate wrt extensions:
* keyUsage, extendedKeyUsage (later), and nSCertType (later).
* Verify a certificate.
*
* Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we
* check a cert we received from them)!
* [in/out] ssl: misc. things read
* ssl->session_negotiate->verify_result updated
* [in] authmode: one of MBEDTLS_SSL_VERIFY_{NONE,OPTIONAL,REQUIRED}
* [in] chain: the certificate chain to verify (ie the peer's chain)
* [in] ciphersuite_info: For TLS 1.2, this session's ciphersuite;
* for TLS 1.3, may be left NULL.
* [in] rs_ctx: restart context if restartable ECC is in use;
* leave NULL for no restartable behaviour.
*
* Return:
* - 0 if the handshake should continue. Depending on the
* authmode it means:
* - REQUIRED: the certificate was found to be valid, trusted & acceptable.
* ssl->session_negotiate->verify_result is 0.
* - OPTIONAL: the certificate may or may not be acceptable, but
* ssl->session_negotiate->verify_result was updated with the result.
* - NONE: the certificate wasn't even checked.
* - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED or MBEDTLS_ERR_SSL_BAD_CERTIFICATE if
* the certificate was found to be invalid/untrusted/unacceptable and the
* handshake should be aborted (can only happen with REQUIRED).
* - another error code if another error happened (out-of-memory, etc.)
*/
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl,
int authmode,
mbedtls_x509_crt *chain,
const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
void *rs_ctx);
/*
* Check usage of a certificate wrt usage extensions:
* keyUsage and extendedKeyUsage.
* (Note: nSCertType is deprecated and not standard, we don't check it.)
*
* Note: if tls_version is 1.3, ciphersuite is ignored and can be NULL.
*
* Note: recv_endpoint is the receiver's endpoint.
*
* Return 0 if everything is OK, -1 if not.
*/
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
const mbedtls_ssl_ciphersuite_t *ciphersuite,
int cert_endpoint,
int recv_endpoint,
mbedtls_ssl_protocol_version tls_version,
uint32_t *flags);
#endif /* MBEDTLS_X509_CRT_PARSE_C */
@ -1891,6 +1926,26 @@ static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13(const mbedtls_ssl_confi
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/** \brief Initialize the PSA crypto subsystem if necessary.
*
* Call this function before doing any cryptography in a TLS 1.3 handshake.
*
* This is necessary in Mbed TLS 3.x for backward compatibility.
* Up to Mbed TLS 3.5, in the default configuration, you could perform
* a TLS connection with default parameters without having called
* psa_crypto_init(), since the TLS layer only supported TLS 1.2 and
* did not use PSA crypto. (TLS 1.2 only uses PSA crypto if
* MBEDTLS_USE_PSA_CRYPTO is enabled, which is not the case in the default
* configuration.) Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled
* by default, and the TLS 1.3 layer uses PSA crypto. This means that
* applications that are not otherwise using PSA crypto and that worked
* with Mbed TLS 3.5 started failing in TLS 3.6.0 if they connected to
* a peer that supports TLS 1.3. See
* https://github.com/Mbed-TLS/mbedtls/issues/9072
*/
int mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl);
extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
MBEDTLS_SERVER_HELLO_RANDOM_LEN];
MBEDTLS_CHECK_RETURN_CRITICAL
@ -2914,8 +2969,37 @@ static inline void mbedtls_ssl_tls13_session_clear_ticket_flags(
{
session->ticket_flags &= ~(flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT 0
#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT 1
#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK \
(1 << MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT)
#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK \
(1 << MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT)
static inline int mbedtls_ssl_conf_get_session_tickets(
const mbedtls_ssl_config *conf)
{
return conf->session_tickets & MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK ?
MBEDTLS_SSL_SESSION_TICKETS_ENABLED :
MBEDTLS_SSL_SESSION_TICKETS_DISABLED;
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
static inline int mbedtls_ssl_conf_is_signal_new_session_tickets_enabled(
const mbedtls_ssl_config *conf)
{
return conf->session_tickets & MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK ?
MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED :
MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED;
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl);
#endif

View file

@ -5570,9 +5570,9 @@ static int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl)
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
#if defined(MBEDTLS_SSL_CLI_C)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl)
static int ssl_tls13_is_new_session_ticket(mbedtls_ssl_context *ssl)
{
if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) ||
@ -5580,15 +5580,9 @@ static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl)
return 0;
}
ssl->keep_current_message = 1;
MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received"));
mbedtls_ssl_handshake_set_state(ssl,
MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
return MBEDTLS_ERR_SSL_WANT_READ;
return 1;
}
#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
#endif /* MBEDTLS_SSL_CLI_C */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
@ -5596,14 +5590,29 @@ static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message"));
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
#if defined(MBEDTLS_SSL_CLI_C)
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
int ret = ssl_tls13_check_new_session_ticket(ssl);
if (ret != 0) {
return ret;
if (ssl_tls13_is_new_session_ticket(ssl)) {
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received"));
if (mbedtls_ssl_conf_is_signal_new_session_tickets_enabled(ssl->conf) ==
MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED) {
ssl->keep_current_message = 1;
mbedtls_ssl_handshake_set_state(ssl,
MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
return MBEDTLS_ERR_SSL_WANT_READ;
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Ignoring NewSessionTicket, handling disabled."));
return 0;
}
#else
MBEDTLS_SSL_DEBUG_MSG(3, ("Ignoring NewSessionTicket, not supported."));
return 0;
#endif
}
}
#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
#endif /* MBEDTLS_SSL_CLI_C */
/* Fail in all other cases. */
return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;

View file

@ -534,6 +534,10 @@ cleanup:
*/
void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
{
if (ctx == NULL) {
return;
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_destroy_key(ctx->keys[0].key);
psa_destroy_key(ctx->keys[1].key);

View file

@ -132,7 +132,7 @@ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl,
int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl,
int *enabled,
unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX],
unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX],
size_t *own_cid_len)
{
*enabled = MBEDTLS_SSL_CID_DISABLED;
@ -1354,29 +1354,6 @@ static int ssl_conf_check(const mbedtls_ssl_context *ssl)
return ret;
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* RFC 8446 section 4.4.3
*
* If the verification fails, the receiver MUST terminate the handshake with
* a "decrypt_error" alert.
*
* If the client is configured as TLS 1.3 only with optional verify, return
* bad config.
*
*/
if (mbedtls_ssl_conf_tls13_is_ephemeral_enabled(
(mbedtls_ssl_context *) ssl) &&
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
ssl->conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
ssl->conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
ssl->conf->authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) {
MBEDTLS_SSL_DEBUG_MSG(
1, ("Optional verify auth mode "
"is not available for TLS 1.3 client"));
return MBEDTLS_ERR_SSL_BAD_CONFIG;
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
if (ssl->conf->f_rng == NULL) {
MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
return MBEDTLS_ERR_SSL_NO_RNG;
@ -1760,6 +1737,7 @@ int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
mbedtls_ssl_ciphersuite_from_id(session->ciphersuite);
@ -1770,6 +1748,14 @@ int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session
session->ciphersuite));
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
#else
/*
* If session tickets are not enabled, it is not possible to resume a
* TLS 1.3 session, thus do not make any change to the SSL context in
* the first place.
*/
return 0;
#endif
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
@ -2234,6 +2220,7 @@ static void ssl_remove_psk(mbedtls_ssl_context *ssl)
mbedtls_zeroize_and_free(ssl->handshake->psk,
ssl->handshake->psk_len);
ssl->handshake->psk_len = 0;
ssl->handshake->psk = NULL;
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
}
@ -2999,11 +2986,24 @@ void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf,
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
#if defined(MBEDTLS_SSL_CLI_C)
void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets)
{
conf->session_tickets = use_tickets;
conf->session_tickets &= ~MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK;
conf->session_tickets |= (use_tickets != 0) <<
MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT;
}
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
void mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(
mbedtls_ssl_config *conf, int signal_new_session_tickets)
{
conf->session_tickets &= ~MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK;
conf->session_tickets |= (signal_new_session_tickets != 0) <<
MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT;
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#endif /* MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_SRV_C)
@ -4049,7 +4049,7 @@ static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
}
static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
unsigned char *buf,
const unsigned char *buf,
size_t buf_len)
{
((void) session);
@ -5868,7 +5868,33 @@ int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf,
if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED;
mbedtls_ssl_conf_session_tickets(conf, MBEDTLS_SSL_SESSION_TICKETS_ENABLED);
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* Contrary to TLS 1.2 tickets, TLS 1.3 NewSessionTicket message
* handling is disabled by default in Mbed TLS 3.6.x for backward
* compatibility with client applications developed using Mbed TLS 3.5
* or earlier with the default configuration.
*
* Up to Mbed TLS 3.5, in the default configuration TLS 1.3 was
* disabled, and a Mbed TLS client with the default configuration would
* establish a TLS 1.2 connection with a TLS 1.2 and TLS 1.3 capable
* server.
*
* Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled by default, and thus
* an Mbed TLS client with the default configuration establishes a
* TLS 1.3 connection with a TLS 1.2 and TLS 1.3 capable server. If
* following the handshake the TLS 1.3 server sends NewSessionTicket
* messages and the Mbed TLS client processes them, this results in
* Mbed TLS high level APIs (mbedtls_ssl_read(),
* mbedtls_ssl_handshake(), ...) to eventually return an
* #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET non fatal error code
* (see the documentation of mbedtls_ssl_read() for more information on
* that error code). Applications unaware of that TLS 1.3 specific non
* fatal error code are then failing.
*/
mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(
conf, MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED);
#endif
#endif
}
#endif
@ -6030,6 +6056,10 @@ int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf,
*/
void mbedtls_ssl_config_free(mbedtls_ssl_config *conf)
{
if (conf == NULL) {
return;
}
#if defined(MBEDTLS_DHM_C)
mbedtls_mpi_free(&conf->dhm_P);
mbedtls_mpi_free(&conf->dhm_G);
@ -6344,71 +6374,6 @@ const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id)
}
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C)
int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
const mbedtls_ssl_ciphersuite_t *ciphersuite,
int cert_endpoint,
uint32_t *flags)
{
int ret = 0;
unsigned int usage = 0;
const char *ext_oid;
size_t ext_len;
if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) {
/* Server part of the key exchange */
switch (ciphersuite->key_exchange) {
case MBEDTLS_KEY_EXCHANGE_RSA:
case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
break;
case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
break;
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
usage = MBEDTLS_X509_KU_KEY_AGREEMENT;
break;
/* Don't use default: we want warnings when adding new values */
case MBEDTLS_KEY_EXCHANGE_NONE:
case MBEDTLS_KEY_EXCHANGE_PSK:
case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
usage = 0;
}
} else {
/* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
}
if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) {
*flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;
ret = -1;
}
if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) {
ext_oid = MBEDTLS_OID_SERVER_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
} else {
ext_oid = MBEDTLS_OID_CLIENT_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
}
if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) {
*flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
ret = -1;
}
return ret;
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
const mbedtls_md_type_t md,
@ -7927,196 +7892,6 @@ static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl,
return SSL_CERTIFICATE_EXPECTED;
}
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl,
int authmode,
mbedtls_x509_crt *chain,
void *rs_ctx)
{
int ret = 0;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->handshake->ciphersuite_info;
int have_ca_chain = 0;
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
void *p_vrfy;
if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
return 0;
}
if (ssl->f_vrfy != NULL) {
MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback"));
f_vrfy = ssl->f_vrfy;
p_vrfy = ssl->p_vrfy;
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback"));
f_vrfy = ssl->conf->f_vrfy;
p_vrfy = ssl->conf->p_vrfy;
}
/*
* Main check: verify certificate
*/
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
if (ssl->conf->f_ca_cb != NULL) {
((void) rs_ctx);
have_ca_chain = 1;
MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification"));
ret = mbedtls_x509_crt_verify_with_ca_cb(
chain,
ssl->conf->f_ca_cb,
ssl->conf->p_ca_cb,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
f_vrfy, p_vrfy);
} else
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
{
mbedtls_x509_crt *ca_chain;
mbedtls_x509_crl *ca_crl;
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if (ssl->handshake->sni_ca_chain != NULL) {
ca_chain = ssl->handshake->sni_ca_chain;
ca_crl = ssl->handshake->sni_ca_crl;
} else
#endif
{
ca_chain = ssl->conf->ca_chain;
ca_crl = ssl->conf->ca_crl;
}
if (ca_chain != NULL) {
have_ca_chain = 1;
}
ret = mbedtls_x509_crt_verify_restartable(
chain,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
f_vrfy, p_vrfy, rs_ctx);
}
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
}
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
}
#endif
/*
* Secondary checks: always done, but change 'ret' only if it was 0
*/
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
{
const mbedtls_pk_context *pk = &chain->pk;
/* If certificate uses an EC key, make sure the curve is OK.
* This is a public key, so it can't be opaque, so can_do() is a good
* enough check to ensure pk_ec() is safe to use here. */
if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) {
/* and in the unlikely case the above assumption no longer holds
* we are making sure that pk_ec() here does not return a NULL
*/
mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk);
if (grp_id == MBEDTLS_ECP_DP_NONE) {
MBEDTLS_SSL_DEBUG_MSG(1, ("invalid group ID"));
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) {
ssl->session_negotiate->verify_result |=
MBEDTLS_X509_BADCERT_BAD_KEY;
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)"));
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
}
}
}
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
if (mbedtls_ssl_check_cert_usage(chain,
ciphersuite_info,
!ssl->conf->endpoint,
&ssl->session_negotiate->verify_result) != 0) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
}
/* mbedtls_x509_crt_verify_with_profile is supposed to report a
* verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
* with details encoded in the verification flags. All other kinds
* of error codes, including those from the user provided f_vrfy
* functions, are treated as fatal and lead to a failure of
* ssl_parse_certificate even if verification was optional. */
if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
ret = 0;
}
if (have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
}
if (ret != 0) {
uint8_t alert;
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) {
alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
} else {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
}
mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
alert);
}
#if defined(MBEDTLS_DEBUG_C)
if (ssl->session_negotiate->verify_result != 0) {
MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
(unsigned int) ssl->session_negotiate->verify_result));
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
}
#endif /* MBEDTLS_DEBUG_C */
return ret;
}
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl,
@ -8173,6 +7948,7 @@ int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)
{
int ret = 0;
int crt_expected;
/* Authmode: precedence order is SNI if used else configuration */
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
? ssl->handshake->sni_authmode
@ -8252,8 +8028,9 @@ crt_verify:
}
#endif
ret = ssl_parse_certificate_verify(ssl, authmode,
chain, rs_ctx);
ret = mbedtls_ssl_verify_certificate(ssl, authmode, chain,
ssl->handshake->ciphersuite_info,
rs_ctx);
if (ret != 0) {
goto exit;
}
@ -9919,4 +9696,274 @@ int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,
return 0;
}
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
/*
* The following functions are used by 1.2 and 1.3, client and server.
*/
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
const mbedtls_ssl_ciphersuite_t *ciphersuite,
int recv_endpoint,
mbedtls_ssl_protocol_version tls_version,
uint32_t *flags)
{
int ret = 0;
unsigned int usage = 0;
const char *ext_oid;
size_t ext_len;
/*
* keyUsage
*/
/* Note: don't guard this with MBEDTLS_SSL_CLI_C because the server wants
* to check what a compliant client will think while choosing which cert
* to send to the client. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
recv_endpoint == MBEDTLS_SSL_IS_CLIENT) {
/* TLS 1.2 server part of the key exchange */
switch (ciphersuite->key_exchange) {
case MBEDTLS_KEY_EXCHANGE_RSA:
case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
break;
case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
break;
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
usage = MBEDTLS_X509_KU_KEY_AGREEMENT;
break;
/* Don't use default: we want warnings when adding new values */
case MBEDTLS_KEY_EXCHANGE_NONE:
case MBEDTLS_KEY_EXCHANGE_PSK:
case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
usage = 0;
}
} else
#endif
{
/* This is either TLS 1.3 authentication, which always uses signatures,
* or 1.2 client auth: rsa_sign and mbedtls_ecdsa_sign are the only
* options we implement, both using signatures. */
(void) tls_version;
(void) ciphersuite;
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
}
if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) {
*flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;
ret = -1;
}
/*
* extKeyUsage
*/
if (recv_endpoint == MBEDTLS_SSL_IS_CLIENT) {
ext_oid = MBEDTLS_OID_SERVER_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
} else {
ext_oid = MBEDTLS_OID_CLIENT_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
}
if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) {
*flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
ret = -1;
}
return ret;
}
int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl,
int authmode,
mbedtls_x509_crt *chain,
const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
void *rs_ctx)
{
if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
return 0;
}
/*
* Primary check: use the appropriate X.509 verification function
*/
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
void *p_vrfy;
if (ssl->f_vrfy != NULL) {
MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback"));
f_vrfy = ssl->f_vrfy;
p_vrfy = ssl->p_vrfy;
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback"));
f_vrfy = ssl->conf->f_vrfy;
p_vrfy = ssl->conf->p_vrfy;
}
int ret = 0;
int have_ca_chain_or_callback = 0;
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
if (ssl->conf->f_ca_cb != NULL) {
((void) rs_ctx);
have_ca_chain_or_callback = 1;
MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification"));
ret = mbedtls_x509_crt_verify_with_ca_cb(
chain,
ssl->conf->f_ca_cb,
ssl->conf->p_ca_cb,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
f_vrfy, p_vrfy);
} else
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
{
mbedtls_x509_crt *ca_chain;
mbedtls_x509_crl *ca_crl;
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if (ssl->handshake->sni_ca_chain != NULL) {
ca_chain = ssl->handshake->sni_ca_chain;
ca_crl = ssl->handshake->sni_ca_crl;
} else
#endif
{
ca_chain = ssl->conf->ca_chain;
ca_crl = ssl->conf->ca_crl;
}
if (ca_chain != NULL) {
have_ca_chain_or_callback = 1;
}
ret = mbedtls_x509_crt_verify_restartable(
chain,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
f_vrfy, p_vrfy, rs_ctx);
}
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
}
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
}
#endif
/*
* Secondary checks: always done, but change 'ret' only if it was 0
*/
/* With TLS 1.2 and ECC certs, check that the curve used by the
* certificate is on our list of acceptable curves.
*
* With TLS 1.3 this is not needed because the curve is part of the
* signature algorithm (eg ecdsa_secp256r1_sha256) which is checked when
* we validate the signature made with the key associated to this cert.
*/
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
mbedtls_pk_can_do(&chain->pk, MBEDTLS_PK_ECKEY)) {
if (mbedtls_ssl_check_curve(ssl, mbedtls_pk_get_ec_group_id(&chain->pk)) != 0) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)"));
ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
}
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_PK_HAVE_ECC_KEYS */
/* Check X.509 usage extensions (keyUsage, extKeyUsage) */
if (mbedtls_ssl_check_cert_usage(chain,
ciphersuite_info,
ssl->conf->endpoint,
ssl->tls_version,
&ssl->session_negotiate->verify_result) != 0) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
}
/* With authmode optional, we want to keep going if the certificate was
* unacceptable, but still fail on other errors (out of memory etc),
* including fatal errors from the f_vrfy callback.
*
* The only acceptable errors are:
* - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: cert rejected by primary check;
* - MBEDTLS_ERR_SSL_BAD_CERTIFICATE: cert rejected by secondary checks.
* Anything else is a fatal error. */
if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
ret = 0;
}
/* Return a specific error as this is a user error: inconsistent
* configuration - can't verify without trust anchors. */
if (have_ca_chain_or_callback == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
}
if (ret != 0) {
uint8_t alert;
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) {
alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
} else {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
}
mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
alert);
}
#if defined(MBEDTLS_DEBUG_C)
if (ssl->session_negotiate->verify_result != 0) {
MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
(unsigned int) ssl->session_negotiate->verify_result));
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
}
#endif /* MBEDTLS_DEBUG_C */
return ret;
}
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS_C */

View file

@ -364,7 +364,8 @@ static int ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl,
*olen = 0;
if (ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED) {
if (mbedtls_ssl_conf_get_session_tickets(ssl->conf) ==
MBEDTLS_SSL_SESSION_TICKETS_DISABLED) {
return 0;
}
@ -787,7 +788,8 @@ static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len)
{
if (ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ||
if ((mbedtls_ssl_conf_get_session_tickets(ssl->conf) ==
MBEDTLS_SSL_SESSION_TICKETS_DISABLED) ||
len != 0) {
MBEDTLS_SSL_DEBUG_MSG(1,
("non-matching session ticket extension"));

View file

@ -756,7 +756,9 @@ static int ssl_pick_cert(mbedtls_ssl_context *ssl,
* and decrypting with the same RSA key.
*/
if (mbedtls_ssl_check_cert_usage(cur->cert, ciphersuite_info,
MBEDTLS_SSL_IS_SERVER, &flags) != 0) {
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_VERSION_TLS1_2,
&flags) != 0) {
MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: "
"(extended) key usage extension"));
continue;
@ -2631,13 +2633,8 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
ssl->handshake->xxdh_psa_type = psa_get_key_type(&key_attributes);
ssl->handshake->xxdh_psa_bits = psa_get_key_bits(&key_attributes);
if (pk_type == MBEDTLS_PK_OPAQUE) {
/* Opaque key is created by the user (externally from Mbed TLS)
* so we assume it already has the right algorithm and flags
* set. Just copy its ID as reference. */
ssl->handshake->xxdh_psa_privkey = pk->priv_id;
ssl->handshake->xxdh_psa_privkey_is_external = 1;
} else {
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
if (pk_type != MBEDTLS_PK_OPAQUE) {
/* PK_ECKEY[_DH] and PK_ECDSA instead as parsed from the PK
* module and only have ECDSA capabilities. Since we need
* them for ECDH later, we export and then re-import them with
@ -2665,10 +2662,20 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
/* Set this key as owned by the TLS library: it will be its duty
* to clear it exit. */
ssl->handshake->xxdh_psa_privkey_is_external = 0;
}
ret = 0;
break;
}
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
/* Opaque key is created by the user (externally from Mbed TLS)
* so we assume it already has the right algorithm and flags
* set. Just copy its ID as reference. */
ssl->handshake->xxdh_psa_privkey = pk->priv_id;
ssl->handshake->xxdh_psa_privkey_is_external = 1;
ret = 0;
break;
#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
case MBEDTLS_PK_ECKEY:
case MBEDTLS_PK_ECKEY_DH:
@ -3916,7 +3923,7 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;
uint8_t ecpoint_len;
size_t ecpoint_len;
mbedtls_ssl_handshake_params *handshake = ssl->handshake;

View file

@ -666,6 +666,7 @@ static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl,
return 0;
}
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite)
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL;
@ -678,7 +679,6 @@ static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite)
return PSA_ALG_NONE;
}
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
static int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl)
{
mbedtls_ssl_session *session = ssl->session_negotiate;
@ -1141,6 +1141,11 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
*out_len = 0;
ret = mbedtls_ssl_tls13_crypto_init(ssl);
if (ret != 0) {
return ret;
}
/* Write supported_versions extension
*
* Supported Versions Extension is mandatory with TLS 1.3.

View file

@ -27,7 +27,6 @@
#include "psa/crypto.h"
#include "psa_util_internal.h"
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
/* Define a local translating function to save code size by not using too many
* arguments in each translating place. */
static int local_err_translation(psa_status_t status)
@ -37,7 +36,16 @@ static int local_err_translation(psa_status_t status)
psa_generic_status_to_mbedtls);
}
#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
#endif
int mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl)
{
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
(void) ssl; // unused when debugging is disabled
MBEDTLS_SSL_DEBUG_RET(1, "psa_crypto_init", status);
}
return PSA_TO_MBEDTLS_ERR(status);
}
const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
MBEDTLS_SERVER_HELLO_RANDOM_LEN] =
@ -193,10 +201,12 @@ static void ssl_tls13_create_verify_structure(const unsigned char *transcript_ha
idx = 64;
if (from == MBEDTLS_SSL_IS_CLIENT) {
memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(client_cv));
memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.client_cv,
MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv));
idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv);
} else { /* from == MBEDTLS_SSL_IS_SERVER */
memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(server_cv));
memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.server_cv,
MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv));
idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv);
}
@ -470,6 +480,7 @@ int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
mbedtls_free(ssl->session_negotiate->peer_cert);
}
/* This is used by ssl_tls13_validate_certificate() */
if (certificate_list_len == 0) {
ssl->session_negotiate->peer_cert = NULL;
ret = 0;
@ -625,25 +636,13 @@ int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
{
int ret = 0;
int authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
mbedtls_x509_crt *ca_chain;
mbedtls_x509_crl *ca_crl;
const char *ext_oid;
size_t ext_len;
uint32_t verify_result = 0;
/* If SNI was used, overwrite authentication mode
* from the configuration. */
#if defined(MBEDTLS_SSL_SRV_C)
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) {
authmode = ssl->handshake->sni_authmode;
} else
#endif
authmode = ssl->conf->authmode;
}
/* Authmode: precedence order is SNI if used else configuration */
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
? ssl->handshake->sni_authmode
: ssl->conf->authmode;
#else
const int authmode = ssl->conf->authmode;
#endif
/*
@ -675,6 +674,11 @@ static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_CLI_C)
/* Regardless of authmode, the server is not allowed to send an empty
* certificate chain. (Last paragraph before 4.4.2.1 in RFC 8446: "The
* server's certificate_list MUST always be non-empty.") With authmode
* optional/none, we continue the handshake if we can't validate the
* server's cert, but we still break it if no certificate was sent. */
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT,
MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE);
@ -683,114 +687,9 @@ static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
#endif /* MBEDTLS_SSL_CLI_C */
}
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if (ssl->handshake->sni_ca_chain != NULL) {
ca_chain = ssl->handshake->sni_ca_chain;
ca_crl = ssl->handshake->sni_ca_crl;
} else
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
{
ca_chain = ssl->conf->ca_chain;
ca_crl = ssl->conf->ca_crl;
}
/*
* Main check: verify certificate
*/
ret = mbedtls_x509_crt_verify_with_profile(
ssl->session_negotiate->peer_cert,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
&verify_result,
ssl->conf->f_vrfy, ssl->conf->p_vrfy);
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
}
/*
* Secondary checks: always done, but change 'ret' only if it was 0
*/
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
ext_oid = MBEDTLS_OID_SERVER_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
} else {
ext_oid = MBEDTLS_OID_CLIENT_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
}
if ((mbedtls_x509_crt_check_key_usage(
ssl->session_negotiate->peer_cert,
MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0) ||
(mbedtls_x509_crt_check_extended_key_usage(
ssl->session_negotiate->peer_cert,
ext_oid, ext_len) != 0)) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
}
/* mbedtls_x509_crt_verify_with_profile is supposed to report a
* verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
* with details encoded in the verification flags. All other kinds
* of error codes, including those from the user provided f_vrfy
* functions, are treated as fatal and lead to a failure of
* mbedtls_ssl_tls13_parse_certificate even if verification was optional.
*/
if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
ret = 0;
}
if (ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
}
if (ret != 0) {
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
if (verify_result & MBEDTLS_X509_BADCERT_OTHER) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret);
} else if (verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret);
} else if (verify_result & (MBEDTLS_X509_BADCERT_KEY_USAGE |
MBEDTLS_X509_BADCERT_EXT_KEY_USAGE |
MBEDTLS_X509_BADCERT_NS_CERT_TYPE |
MBEDTLS_X509_BADCERT_BAD_PK |
MBEDTLS_X509_BADCERT_BAD_KEY)) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret);
} else if (verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret);
} else if (verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret);
} else if (verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret);
} else {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret);
}
}
#if defined(MBEDTLS_DEBUG_C)
if (verify_result != 0) {
MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
(unsigned int) verify_result));
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
}
#endif /* MBEDTLS_DEBUG_C */
ssl->session_negotiate->verify_result = verify_result;
return ret;
return mbedtls_ssl_verify_certificate(ssl, authmode,
ssl->session_negotiate->peer_cert,
NULL, NULL);
}
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
MBEDTLS_CHECK_RETURN_CRITICAL
@ -1482,9 +1381,11 @@ int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,
ssl->total_early_data_size)) {
MBEDTLS_SSL_DEBUG_MSG(
2, ("EarlyData: Too much early data received, %u + %" MBEDTLS_PRINTF_SIZET " > %u",
ssl->total_early_data_size, early_data_len,
ssl->session_negotiate->max_early_data_size));
2, ("EarlyData: Too much early data received, "
"%lu + %" MBEDTLS_PRINTF_SIZET " > %lu",
(unsigned long) ssl->total_early_data_size,
early_data_len,
(unsigned long) ssl->session_negotiate->max_early_data_size));
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,

View file

@ -92,8 +92,9 @@ static void ssl_tls13_select_ciphersuite(
return;
}
MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%x",
(unsigned) psk_ciphersuite_id, psk_hash_alg));
MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%lx",
(unsigned) psk_ciphersuite_id,
(unsigned long) psk_hash_alg));
}
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
@ -172,12 +173,12 @@ static int ssl_tls13_parse_key_exchange_modes_ext(mbedtls_ssl_context *ssl,
#define SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE 1
#define SSL_TLS1_3_PSK_IDENTITY_MATCH 0
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl);
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_offered_psks_check_identity_match_ticket(
mbedtls_ssl_context *ssl,
@ -575,10 +576,8 @@ static int ssl_tls13_parse_pre_shared_key_ext(
psa_algorithm_t psk_hash_alg;
int allowed_key_exchange_modes;
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
mbedtls_ssl_session session;
mbedtls_ssl_session_init(&session);
#endif
MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4);
identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0);
@ -1356,19 +1355,23 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
* compression methods and the length of the extensions.
*
* cipher_suites cipher_suites_len bytes
* legacy_compression_methods 2 bytes
* extensions_len 2 bytes
* legacy_compression_methods length 1 byte
*/
MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 2 + 2);
MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 1);
p += cipher_suites_len;
cipher_suites_end = p;
/* Check if we have enough data for legacy_compression_methods
* and the length of the extensions (2 bytes).
*/
MBEDTLS_SSL_CHK_BUF_READ_PTR(p + 1, end, p[0] + 2);
/*
* Search for the supported versions extension and parse it to determine
* if the client supports TLS 1.3.
*/
ret = mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(
ssl, p + 2, end,
ssl, p + 1 + p[0], end,
&supported_versions_data, &supported_versions_data_end);
if (ret < 0) {
MBEDTLS_SSL_DEBUG_RET(1,
@ -1409,6 +1412,12 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
ssl->session_negotiate->endpoint = ssl->conf->endpoint;
/* Before doing any crypto, make sure we can. */
ret = mbedtls_ssl_tls13_crypto_init(ssl);
if (ret != 0) {
return ret;
}
/*
* We are negotiating the version 1.3 of the protocol. Do what we have
* postponed: copy of the client random bytes, copy of the legacy session
@ -3109,6 +3118,7 @@ static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)
return 0;
}
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
/*
* Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET
*/
@ -3138,7 +3148,6 @@ static int ssl_tls13_write_new_session_ticket_coordinate(mbedtls_ssl_context *ss
return SSL_NEW_SESSION_TICKET_WRITE;
}
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,
unsigned char *ticket_nonce,

View file

@ -423,6 +423,9 @@ static const char * const features[] = {
#if defined(MBEDTLS_PSA_CRYPTO_SPM)
"PSA_CRYPTO_SPM", //no-check-names
#endif /* MBEDTLS_PSA_CRYPTO_SPM */
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
"PSA_KEY_STORE_DYNAMIC", //no-check-names
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
"PSA_P256M_DRIVER_ENABLED", //no-check-names
#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */

View file

@ -48,7 +48,9 @@
#if defined(MBEDTLS_HAVE_TIME)
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <time.h>

View file

@ -46,6 +46,10 @@ void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx)
void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_asn1_free_named_data_list(&ctx->subject);
mbedtls_asn1_free_named_data_list(&ctx->issuer);
mbedtls_asn1_free_named_data_list(&ctx->extensions);

View file

@ -43,6 +43,10 @@ void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx)
void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_asn1_free_named_data_list(&ctx->subject);
mbedtls_asn1_free_named_data_list(&ctx->extensions);

View file

@ -1,5 +1,5 @@
diff --git a/thirdparty/mbedtls/include/psa/crypto.h b/thirdparty/mbedtls/include/psa/crypto.h
index 92f9c824e9..1cc2e7e729 100644
index 2bbcea3ee0..96baf8f3ed 100644
--- a/thirdparty/mbedtls/include/psa/crypto.h
+++ b/thirdparty/mbedtls/include/psa/crypto.h
@@ -107,7 +107,9 @@ psa_status_t psa_crypto_init(void);
@ -12,7 +12,7 @@ index 92f9c824e9..1cc2e7e729 100644
/** Declare a key as persistent and set its key identifier.
*
@@ -333,7 +335,9 @@ static void psa_set_key_bits(psa_key_attributes_t *attributes,
@@ -336,7 +338,9 @@ static void psa_set_key_bits(psa_key_attributes_t *attributes,
*
* \return The key type stored in the attribute structure.
*/
@ -22,7 +22,7 @@ index 92f9c824e9..1cc2e7e729 100644
/** Retrieve the key size from key attributes.
*
@@ -936,7 +940,9 @@ typedef struct psa_hash_operation_s psa_hash_operation_t;
@@ -939,7 +943,9 @@ typedef struct psa_hash_operation_s psa_hash_operation_t;
/** Return an initial value for a hash operation object.
*/
@ -32,7 +32,7 @@ index 92f9c824e9..1cc2e7e729 100644
/** Set up a multipart hash operation.
*
@@ -1295,7 +1301,9 @@ typedef struct psa_mac_operation_s psa_mac_operation_t;
@@ -1298,7 +1304,9 @@ typedef struct psa_mac_operation_s psa_mac_operation_t;
/** Return an initial value for a MAC operation object.
*/
@ -42,7 +42,7 @@ index 92f9c824e9..1cc2e7e729 100644
/** Set up a multipart MAC calculation operation.
*
@@ -1708,7 +1716,9 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t;
@@ -1711,7 +1719,9 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t;
/** Return an initial value for a cipher operation object.
*/
@ -52,7 +52,7 @@ index 92f9c824e9..1cc2e7e729 100644
/** Set the key for a multipart symmetric encryption operation.
*
@@ -2226,7 +2236,9 @@ typedef struct psa_aead_operation_s psa_aead_operation_t;
@@ -2229,7 +2239,9 @@ typedef struct psa_aead_operation_s psa_aead_operation_t;
/** Return an initial value for an AEAD operation object.
*/
@ -62,7 +62,7 @@ index 92f9c824e9..1cc2e7e729 100644
/** Set the key for a multipart authenticated encryption operation.
*
@@ -3213,7 +3225,9 @@ typedef struct psa_key_derivation_s psa_key_derivation_operation_t;
@@ -3216,7 +3228,9 @@ typedef struct psa_key_derivation_s psa_key_derivation_operation_t;
/** Return an initial value for a key derivation operation object.
*/
@ -73,10 +73,10 @@ index 92f9c824e9..1cc2e7e729 100644
/** Set up a key derivation operation.
*
diff --git a/thirdparty/mbedtls/include/psa/crypto_extra.h b/thirdparty/mbedtls/include/psa/crypto_extra.h
index 6ed1f6c43a..2686b9d74d 100644
index 0cf42c6055..d276cd4c7f 100644
--- a/thirdparty/mbedtls/include/psa/crypto_extra.h
+++ b/thirdparty/mbedtls/include/psa/crypto_extra.h
@@ -915,7 +915,9 @@ typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t;
@@ -923,7 +923,9 @@ typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t;
/** Return an initial value for a PAKE cipher suite object.
*/
@ -86,7 +86,7 @@ index 6ed1f6c43a..2686b9d74d 100644
/** Retrieve the PAKE algorithm from a PAKE cipher suite.
*
@@ -1048,7 +1050,9 @@ typedef struct psa_jpake_computation_stage_s psa_jpake_computation_stage_t;
@@ -1056,7 +1058,9 @@ typedef struct psa_jpake_computation_stage_s psa_jpake_computation_stage_t;
/** Return an initial value for a PAKE operation object.
*/

View file

@ -1,132 +0,0 @@
diff --git a/thirdparty/mbedtls/include/psa/crypto.h b/thirdparty/mbedtls/include/psa/crypto.h
index 7083bd911b..92f9c824e9 100644
--- a/thirdparty/mbedtls/include/psa/crypto.h
+++ b/thirdparty/mbedtls/include/psa/crypto.h
@@ -3834,12 +3834,14 @@ psa_status_t psa_key_derivation_output_key(
* It is implementation-dependent whether a failure to initialize
* results in this error code.
*/
+#ifndef __cplusplus
psa_status_t psa_key_derivation_output_key_ext(
const psa_key_attributes_t *attributes,
psa_key_derivation_operation_t *operation,
const psa_key_production_parameters_t *params,
size_t params_data_length,
mbedtls_svc_key_id_t *key);
+#endif
/** Compare output data from a key derivation operation to an expected value.
*
@@ -4180,10 +4182,12 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
* It is implementation-dependent whether a failure to initialize
* results in this error code.
*/
+#ifndef __cplusplus
psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
const psa_key_production_parameters_t *params,
size_t params_data_length,
mbedtls_svc_key_id_t *key);
+#endif
/**@}*/
diff --git a/thirdparty/mbedtls/include/psa/crypto_struct.h b/thirdparty/mbedtls/include/psa/crypto_struct.h
index 3913551aa8..e2c227b2eb 100644
--- a/thirdparty/mbedtls/include/psa/crypto_struct.h
+++ b/thirdparty/mbedtls/include/psa/crypto_struct.h
@@ -223,11 +223,13 @@ static inline struct psa_key_derivation_s psa_key_derivation_operation_init(
return v;
}
+#ifndef __cplusplus
struct psa_key_production_parameters_s {
/* Future versions may add other fields in this structure. */
uint32_t flags;
uint8_t data[];
};
+#endif
/** The default production parameters for key generation or key derivation.
*
diff --git a/thirdparty/mbedtls/include/psa/crypto_types.h b/thirdparty/mbedtls/include/psa/crypto_types.h
index c21bad86cc..a36b6ee65d 100644
--- a/thirdparty/mbedtls/include/psa/crypto_types.h
+++ b/thirdparty/mbedtls/include/psa/crypto_types.h
@@ -477,7 +477,9 @@ typedef uint16_t psa_key_derivation_step_t;
* - Other key types: reserved for future use. \c flags must be 0.
*
*/
+#ifndef __cplusplus
typedef struct psa_key_production_parameters_s psa_key_production_parameters_t;
+#endif
/**@}*/
diff --git a/thirdparty/mbedtls/library/psa_crypto_core.h b/thirdparty/mbedtls/library/psa_crypto_core.h
index 9462d2e8be..c059162efe 100644
--- a/thirdparty/mbedtls/library/psa_crypto_core.h
+++ b/thirdparty/mbedtls/library/psa_crypto_core.h
@@ -351,9 +351,11 @@ psa_status_t psa_export_public_key_internal(
* \param[in] params The key production parameters to check.
* \param params_data_length Size of `params->data` in bytes.
*/
+#ifndef __cplusplus
int psa_key_production_parameters_are_default(
const psa_key_production_parameters_t *params,
size_t params_data_length);
+#endif
/**
* \brief Generate a key.
@@ -378,12 +380,14 @@ int psa_key_production_parameters_are_default(
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
*/
+#ifndef __cplusplus
psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes,
const psa_key_production_parameters_t *params,
size_t params_data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length);
+#endif
/** Sign a message with a private key. For hash-and-sign algorithms,
* this includes the hashing step.
diff --git a/thirdparty/mbedtls/library/psa_crypto_driver_wrappers.h b/thirdparty/mbedtls/library/psa_crypto_driver_wrappers.h
index ea6aee32eb..6919971aca 100644
--- a/thirdparty/mbedtls/library/psa_crypto_driver_wrappers.h
+++ b/thirdparty/mbedtls/library/psa_crypto_driver_wrappers.h
@@ -728,6 +728,7 @@ static inline psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data(
}
}
+#ifndef __cplusplus
static inline psa_status_t psa_driver_wrapper_generate_key(
const psa_key_attributes_t *attributes,
const psa_key_production_parameters_t *params, size_t params_data_length,
@@ -832,6 +833,7 @@ static inline psa_status_t psa_driver_wrapper_generate_key(
return( status );
}
+#endif
static inline psa_status_t psa_driver_wrapper_import_key(
const psa_key_attributes_t *attributes,
diff --git a/thirdparty/mbedtls/library/psa_crypto_rsa.h b/thirdparty/mbedtls/library/psa_crypto_rsa.h
index ffeef26be1..6d695ddf50 100644
--- a/thirdparty/mbedtls/library/psa_crypto_rsa.h
+++ b/thirdparty/mbedtls/library/psa_crypto_rsa.h
@@ -130,10 +130,12 @@ psa_status_t mbedtls_psa_rsa_export_public_key(
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
*/
+#ifndef __cplusplus
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
const psa_key_production_parameters_t *params, size_t params_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
+#endif
/** Sign an already-calculated hash with an RSA private key.
*