1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-29 11:41:15 +03:00

Merge remote-tracking branch 'mbedtls-3.6' into mbedtls-3.6-restricted

This commit is contained in:
Gilles Peskine
2024-08-23 11:15:11 +02:00
102 changed files with 1978 additions and 636 deletions

View File

@ -197,11 +197,11 @@ else()
endif()
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations")
endif(CMAKE_COMPILER_IS_GNUCC)
if(CMAKE_COMPILER_IS_CLANG)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code")
endif(CMAKE_COMPILER_IS_CLANG)
if(CMAKE_COMPILER_IS_MSVC)

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 */

50
library/bignum_internal.h Normal file
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

@ -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)

View File

@ -1210,15 +1210,15 @@ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot)
case PSA_SLOT_PENDING_DELETION:
/* In this state psa_wipe_key_slot() must only be called if the
* caller is the last reader. */
if (slot->registered_readers != 1) {
MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 1);
if (slot->var.occupied.registered_readers != 1) {
MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 1);
status = PSA_ERROR_CORRUPTION_DETECTED;
}
break;
case PSA_SLOT_FILLING:
/* In this state registered_readers must be 0. */
if (slot->registered_readers != 0) {
MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 0);
if (slot->var.occupied.registered_readers != 0) {
MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 0);
status = PSA_ERROR_CORRUPTION_DETECTED;
}
break;
@ -1232,6 +1232,11 @@ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot)
status = PSA_ERROR_CORRUPTION_DETECTED;
}
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
size_t slice_index = slot->slice_index;
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
/* Multipart operations may still be using the key. This is safe
* because all multipart operation objects are independent from
* the key slot: if they need to access the key after the setup
@ -1242,6 +1247,17 @@ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot)
* zeroize because the metadata is not particularly sensitive.
* This memset also sets the slot's state to PSA_SLOT_EMPTY. */
memset(slot, 0, sizeof(*slot));
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
/* If the slot is already corrupted, something went deeply wrong,
* like a thread still using the slot or a stray pointer leading
* to the slot's memory being used for another object. Let the slot
* leak rather than make the corruption worse. */
if (status == PSA_SUCCESS) {
status = psa_free_key_slot(slice_index, slot);
}
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
return status;
}
@ -1753,8 +1769,6 @@ static psa_status_t psa_start_key_creation(
psa_se_drv_table_entry_t **p_drv)
{
psa_status_t status;
psa_key_id_t volatile_key_id;
psa_key_slot_t *slot;
(void) method;
*p_drv = NULL;
@ -1764,11 +1778,16 @@ static psa_status_t psa_start_key_creation(
return status;
}
int key_is_volatile = PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime);
psa_key_id_t volatile_key_id;
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
&mbedtls_threading_key_slot_mutex));
#endif
status = psa_reserve_free_key_slot(&volatile_key_id, p_slot);
status = psa_reserve_free_key_slot(
key_is_volatile ? &volatile_key_id : NULL,
p_slot);
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
@ -1776,7 +1795,7 @@ static psa_status_t psa_start_key_creation(
if (status != PSA_SUCCESS) {
return status;
}
slot = *p_slot;
psa_key_slot_t *slot = *p_slot;
/* We're storing the declared bit-size of the key. It's up to each
* creation mechanism to verify that this information is correct.
@ -1787,7 +1806,7 @@ static psa_status_t psa_start_key_creation(
* definition. */
slot->attr = *attributes;
if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
if (key_is_volatile) {
#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
slot->attr.id = volatile_key_id;
#else
@ -2149,6 +2168,14 @@ psa_status_t mbedtls_psa_register_se_key(
return PSA_ERROR_NOT_SUPPORTED;
}
/* Not usable with volatile keys, even with an appropriate location,
* due to the API design.
* https://github.com/Mbed-TLS/mbedtls/issues/9253
*/
if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(attributes))) {
return PSA_ERROR_INVALID_ARGUMENT;
}
status = psa_start_key_creation(PSA_KEY_CREATION_REGISTER, attributes,
&slot, &driver);
if (status != PSA_SUCCESS) {

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)

View File

@ -27,8 +27,166 @@
#include "mbedtls/threading.h"
#endif
/* Make sure we have distinct ranges of key identifiers for distinct
* purposes. */
MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MIN < PSA_KEY_ID_USER_MAX,
"Empty user key ID range");
MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN < PSA_KEY_ID_VENDOR_MAX,
"Empty vendor key ID range");
MBEDTLS_STATIC_ASSERT(MBEDTLS_PSA_KEY_ID_BUILTIN_MIN < MBEDTLS_PSA_KEY_ID_BUILTIN_MAX,
"Empty builtin key ID range");
MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MIN < PSA_KEY_ID_VOLATILE_MAX,
"Empty volatile key ID range");
MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MAX < PSA_KEY_ID_VENDOR_MIN ||
PSA_KEY_ID_VENDOR_MAX < PSA_KEY_ID_USER_MIN,
"Overlap between user key IDs and vendor key IDs");
MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN &&
MBEDTLS_PSA_KEY_ID_BUILTIN_MAX <= PSA_KEY_ID_VENDOR_MAX,
"Builtin key identifiers are not in the vendor range");
MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= PSA_KEY_ID_VOLATILE_MIN &&
PSA_KEY_ID_VOLATILE_MAX <= PSA_KEY_ID_VENDOR_MAX,
"Volatile key identifiers are not in the vendor range");
MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MAX < MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ||
MBEDTLS_PSA_KEY_ID_BUILTIN_MAX < PSA_KEY_ID_VOLATILE_MIN,
"Overlap between builtin key IDs and volatile key IDs");
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
/* Dynamic key store.
*
* The key store consists of multiple slices.
*
* The volatile keys are stored in variable-sized tables called slices.
* Slices are allocated on demand and deallocated when possible.
* The size of slices increases exponentially, so the average overhead
* (number of slots that are allocated but not used) is roughly
* proportional to the number of keys (with a factor that grows
* when the key store is fragmented).
*
* One slice is dedicated to the cache of persistent and built-in keys.
* For simplicity, they are separated from volatile keys. This cache
* slice has a fixed size and has the slice index KEY_SLOT_CACHE_SLICE_INDEX,
* located after the slices for volatile keys.
*/
/* Size of the last slice containing the cache of persistent and built-in keys. */
#define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT
/* Volatile keys are stored in slices 0 through
* (KEY_SLOT_VOLATILE_SLICE_COUNT - 1) inclusive.
* Each slice is twice the size of the previous slice.
* Volatile key identifiers encode the slice number as follows:
* bits 30..31: 0b10 (mandated by the PSA Crypto specification).
* bits 25..29: slice index (0...KEY_SLOT_VOLATILE_SLICE_COUNT-1)
* bits 0..24: slot index in slice
*/
#define KEY_ID_SLOT_INDEX_WIDTH 25u
#define KEY_ID_SLICE_INDEX_WIDTH 5u
#define KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH 16u
#define KEY_SLOT_VOLATILE_SLICE_COUNT 22u
#define KEY_SLICE_COUNT (KEY_SLOT_VOLATILE_SLICE_COUNT + 1u)
#define KEY_SLOT_CACHE_SLICE_INDEX KEY_SLOT_VOLATILE_SLICE_COUNT
/* Check that the length of the largest slice (calculated as
* KEY_SLICE_LENGTH_MAX below) does not overflow size_t. We use
* an indirect method in case the calculation of KEY_SLICE_LENGTH_MAX
* itself overflows uintmax_t: if (BASE_LENGTH << c)
* overflows size_t then BASE_LENGTH > SIZE_MAX >> c.
*/
#if (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH > \
SIZE_MAX >> (KEY_SLOT_VOLATILE_SLICE_COUNT - 1))
#error "Maximum slice length overflows size_t"
#endif
#if KEY_ID_SLICE_INDEX_WIDTH + KEY_ID_SLOT_INDEX_WIDTH > 30
#error "Not enough room in volatile key IDs for slice index and slot index"
#endif
#if KEY_SLOT_VOLATILE_SLICE_COUNT > (1 << KEY_ID_SLICE_INDEX_WIDTH)
#error "Too many slices to fit the slice index in a volatile key ID"
#endif
#define KEY_SLICE_LENGTH_MAX \
(KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << (KEY_SLOT_VOLATILE_SLICE_COUNT - 1))
#if KEY_SLICE_LENGTH_MAX > 1 << KEY_ID_SLOT_INDEX_WIDTH
#error "Not enough room in volatile key IDs for a slot index in the largest slice"
#endif
#if KEY_ID_SLICE_INDEX_WIDTH > 8
#error "Slice index does not fit in uint8_t for psa_key_slot_t::slice_index"
#endif
/* Calculate the volatile key id to use for a given slot.
* This function assumes valid parameter values. */
static psa_key_id_t volatile_key_id_of_index(size_t slice_idx,
size_t slot_idx)
{
/* We assert above that the slice and slot indexes fit in separate
* bit-fields inside psa_key_id_t, which is a 32-bit type per the
* PSA Cryptography specification. */
return (psa_key_id_t) (0x40000000u |
(slice_idx << KEY_ID_SLOT_INDEX_WIDTH) |
slot_idx);
}
/* Calculate the slice containing the given volatile key.
* This function assumes valid parameter values. */
static size_t slice_index_of_volatile_key_id(psa_key_id_t key_id)
{
size_t mask = (1LU << KEY_ID_SLICE_INDEX_WIDTH) - 1;
return (key_id >> KEY_ID_SLOT_INDEX_WIDTH) & mask;
}
/* Calculate the index of the slot containing the given volatile key.
* This function assumes valid parameter values. */
static size_t slot_index_of_volatile_key_id(psa_key_id_t key_id)
{
return key_id & ((1LU << KEY_ID_SLOT_INDEX_WIDTH) - 1);
}
/* In global_data.first_free_slot_index, use this special value to
* indicate that the slice is full. */
#define FREE_SLOT_INDEX_NONE ((size_t) -1)
#if defined(MBEDTLS_TEST_HOOKS)
size_t psa_key_slot_volatile_slice_count(void)
{
return KEY_SLOT_VOLATILE_SLICE_COUNT;
}
#endif
#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
/* Static key store.
*
* All the keys (volatile or persistent) are in a single slice.
* We only use slices as a concept to allow some differences between
* static and dynamic key store management to be buried in auxiliary
* functions.
*/
#define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT
#define KEY_SLICE_COUNT 1u
#define KEY_SLOT_CACHE_SLICE_INDEX 0
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
typedef struct {
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
psa_key_slot_t *key_slices[KEY_SLICE_COUNT];
size_t first_free_slot_index[KEY_SLOT_VOLATILE_SLICE_COUNT];
#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
uint8_t key_slots_initialized;
} psa_global_data_t;
@ -51,6 +209,125 @@ static uint8_t psa_get_key_slots_initialized(void)
return initialized;
}
/** The length of the given slice in the key slot table.
*
* \param slice_idx The slice number. It must satisfy
* 0 <= slice_idx < KEY_SLICE_COUNT.
*
* \return The number of elements in the given slice.
*/
static inline size_t key_slice_length(size_t slice_idx);
/** Get a pointer to the slot where the given volatile key is located.
*
* \param key_id The key identifier. It must be a valid volatile key
* identifier.
* \return A pointer to the only slot that the given key
* can be in. Note that the slot may be empty or
* contain a different key.
*/
static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id);
/** Get a pointer to an entry in the persistent key cache.
*
* \param slot_idx The index in the table. It must satisfy
* 0 <= slot_idx < PERSISTENT_KEY_CACHE_COUNT.
* \return A pointer to the slot containing the given
* persistent key cache entry.
*/
static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx);
/** Get a pointer to a slot given by slice and index.
*
* \param slice_idx The slice number. It must satisfy
* 0 <= slice_idx < KEY_SLICE_COUNT.
* \param slot_idx An index in the given slice. It must satisfy
* 0 <= slot_idx < key_slice_length(slice_idx).
*
* \return A pointer to the given slot.
*/
static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx);
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
#if defined(MBEDTLS_TEST_HOOKS)
size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(size_t slice_idx) = NULL;
#endif
static inline size_t key_slice_length(size_t slice_idx)
{
if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) {
return PERSISTENT_KEY_CACHE_COUNT;
} else {
#if defined(MBEDTLS_TEST_HOOKS)
if (mbedtls_test_hook_psa_volatile_key_slice_length != NULL) {
return mbedtls_test_hook_psa_volatile_key_slice_length(slice_idx);
}
#endif
return KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << slice_idx;
}
}
static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id)
{
size_t slice_idx = slice_index_of_volatile_key_id(key_id);
if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) {
return NULL;
}
size_t slot_idx = slot_index_of_volatile_key_id(key_id);
if (slot_idx >= key_slice_length(slice_idx)) {
return NULL;
}
psa_key_slot_t *slice = global_data.key_slices[slice_idx];
if (slice == NULL) {
return NULL;
}
return &slice[slot_idx];
}
static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx)
{
return &global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX][slot_idx];
}
static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx)
{
return &global_data.key_slices[slice_idx][slot_idx];
}
#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
static inline size_t key_slice_length(size_t slice_idx)
{
(void) slice_idx;
return ARRAY_LENGTH(global_data.key_slots);
}
static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id)
{
MBEDTLS_STATIC_ASSERT(ARRAY_LENGTH(global_data.key_slots) <=
PSA_KEY_ID_VOLATILE_MAX - PSA_KEY_ID_VOLATILE_MIN + 1,
"The key slot array is larger than the volatile key ID range");
return &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN];
}
static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx)
{
return &global_data.key_slots[slot_idx];
}
static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx)
{
(void) slice_idx;
return &global_data.key_slots[slot_idx];
}
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok)
{
psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
@ -112,12 +389,13 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory(
psa_key_slot_t *slot = NULL;
if (psa_key_id_is_volatile(key_id)) {
slot = &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN];
slot = get_volatile_key_slot(key_id);
/* Check if both the PSA key identifier key_id and the owner
* identifier of key match those of the key slot. */
if ((slot->state == PSA_SLOT_FULL) &&
(mbedtls_svc_key_id_equal(key, slot->attr.id))) {
if (slot != NULL &&
slot->state == PSA_SLOT_FULL &&
mbedtls_svc_key_id_equal(key, slot->attr.id)) {
status = PSA_SUCCESS;
} else {
status = PSA_ERROR_DOES_NOT_EXIST;
@ -127,8 +405,8 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory(
return PSA_ERROR_INVALID_HANDLE;
}
for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
slot = &global_data.key_slots[slot_idx];
for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) {
slot = get_persistent_key_slot(slot_idx);
/* Only consider slots which are in a full state. */
if ((slot->state == PSA_SLOT_FULL) &&
(mbedtls_svc_key_id_equal(key, slot->attr.id))) {
@ -151,29 +429,169 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory(
psa_status_t psa_initialize_key_slots(void)
{
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] =
mbedtls_calloc(PERSISTENT_KEY_CACHE_COUNT,
sizeof(*global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX]));
if (global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
/* Nothing to do: program startup and psa_wipe_all_key_slots() both
* guarantee that the key slots are initialized to all-zero, which
* means that all the key slots are in a valid, empty state. The global
* data mutex is already held when calling this function, so no need to
* lock it here, to set the flag. */
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
global_data.key_slots_initialized = 1;
return PSA_SUCCESS;
}
void psa_wipe_all_key_slots(void)
{
size_t slot_idx;
for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
psa_key_slot_t *slot = &global_data.key_slots[slot_idx];
slot->registered_readers = 1;
slot->state = PSA_SLOT_PENDING_DELETION;
(void) psa_wipe_key_slot(slot);
for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) {
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
if (global_data.key_slices[slice_idx] == NULL) {
continue;
}
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) {
psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx);
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
/* When MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled, calling
* psa_wipe_key_slot() on an unused slot is useless, but it
* happens to work (because we flip the state to PENDING_DELETION).
*
* When MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled,
* psa_wipe_key_slot() needs to have a valid slice_index
* field, but that value might not be correct in a
* free slot, so we must not call it.
*
* Bypass the call to psa_wipe_key_slot() if the slot is empty,
* but only if MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, to save
* a few bytes of code size otherwise.
*/
if (slot->state == PSA_SLOT_EMPTY) {
continue;
}
#endif
slot->var.occupied.registered_readers = 1;
slot->state = PSA_SLOT_PENDING_DELETION;
(void) psa_wipe_key_slot(slot);
}
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
mbedtls_free(global_data.key_slices[slice_idx]);
global_data.key_slices[slice_idx] = NULL;
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
}
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
for (size_t slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) {
global_data.first_free_slot_index[slice_idx] = 0;
}
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
/* The global data mutex is already held when calling this function. */
global_data.key_slots_initialized = 0;
}
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
static psa_status_t psa_allocate_volatile_key_slot(psa_key_id_t *key_id,
psa_key_slot_t **p_slot)
{
size_t slice_idx;
for (slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) {
if (global_data.first_free_slot_index[slice_idx] != FREE_SLOT_INDEX_NONE) {
break;
}
}
if (slice_idx == KEY_SLOT_VOLATILE_SLICE_COUNT) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
if (global_data.key_slices[slice_idx] == NULL) {
global_data.key_slices[slice_idx] =
mbedtls_calloc(key_slice_length(slice_idx),
sizeof(psa_key_slot_t));
if (global_data.key_slices[slice_idx] == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
}
psa_key_slot_t *slice = global_data.key_slices[slice_idx];
size_t slot_idx = global_data.first_free_slot_index[slice_idx];
*key_id = volatile_key_id_of_index(slice_idx, slot_idx);
psa_key_slot_t *slot = &slice[slot_idx];
size_t next_free = slot_idx + 1 + slot->var.free.next_free_relative_to_next;
if (next_free >= key_slice_length(slice_idx)) {
next_free = FREE_SLOT_INDEX_NONE;
}
global_data.first_free_slot_index[slice_idx] = next_free;
/* The .next_free field is not meaningful when the slot is not free,
* so give it the same content as freshly initialized memory. */
slot->var.free.next_free_relative_to_next = 0;
psa_status_t status = psa_key_slot_state_transition(slot,
PSA_SLOT_EMPTY,
PSA_SLOT_FILLING);
if (status != PSA_SUCCESS) {
/* The only reason for failure is if the slot state was not empty.
* This indicates that something has gone horribly wrong.
* In this case, we leave the slot out of the free list, and stop
* modifying it. This minimizes any further corruption. The slot
* is a memory leak, but that's a lesser evil. */
return status;
}
*p_slot = slot;
/* We assert at compile time that the slice index fits in uint8_t. */
slot->slice_index = (uint8_t) slice_idx;
return PSA_SUCCESS;
}
psa_status_t psa_free_key_slot(size_t slice_idx,
psa_key_slot_t *slot)
{
if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) {
/* This is a cache entry. We don't maintain a free list, so
* there's nothing to do. */
return PSA_SUCCESS;
}
if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
psa_key_slot_t *slice = global_data.key_slices[slice_idx];
psa_key_slot_t *slice_end = slice + key_slice_length(slice_idx);
if (slot < slice || slot >= slice_end) {
/* The slot isn't actually in the slice! We can't detect that
* condition for sure, because the pointer comparison itself is
* undefined behavior in that case. That same condition makes the
* subtraction to calculate the slot index also UB.
* Give up now to avoid causing further corruption.
*/
return PSA_ERROR_CORRUPTION_DETECTED;
}
size_t slot_idx = slot - slice;
size_t next_free = global_data.first_free_slot_index[slice_idx];
if (next_free >= key_slice_length(slice_idx)) {
/* The slot was full. The newly freed slot thus becomes the
* end of the free list. */
next_free = key_slice_length(slice_idx);
}
global_data.first_free_slot_index[slice_idx] = slot_idx;
slot->var.free.next_free_relative_to_next =
(int32_t) next_free - (int32_t) slot_idx - 1;
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
psa_key_slot_t **p_slot)
{
@ -186,9 +604,19 @@ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
goto error;
}
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
if (volatile_key_id != NULL) {
return psa_allocate_volatile_key_slot(volatile_key_id, p_slot);
}
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
/* With a dynamic key store, allocate an entry in the cache slice,
* applicable only to non-volatile keys that get cached in RAM.
* With a static key store, allocate an entry in the sole slice,
* applicable to all keys. */
selected_slot = unused_persistent_key_slot = NULL;
for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
psa_key_slot_t *slot = &global_data.key_slots[slot_idx];
for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) {
psa_key_slot_t *slot = get_key_slot(KEY_SLOT_CACHE_SLICE_INDEX, slot_idx);
if (slot->state == PSA_SLOT_EMPTY) {
selected_slot = slot;
break;
@ -226,8 +654,18 @@ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
goto error;
}
*volatile_key_id = PSA_KEY_ID_VOLATILE_MIN +
((psa_key_id_t) (selected_slot - global_data.key_slots));
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
selected_slot->slice_index = KEY_SLOT_CACHE_SLICE_INDEX;
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
#if !defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
if (volatile_key_id != NULL) {
/* Refresh slot_idx, for when the slot is not the original
* selected_slot but rather unused_persistent_key_slot. */
slot_idx = selected_slot - global_data.key_slots;
*volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + slot_idx;
}
#endif
*p_slot = selected_slot;
return PSA_SUCCESS;
@ -236,7 +674,6 @@ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
error:
*p_slot = NULL;
*volatile_key_id = 0;
return status;
}
@ -395,9 +832,8 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
/* Loading keys from storage requires support for such a mechanism */
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
psa_key_id_t volatile_key_id;
status = psa_reserve_free_key_slot(&volatile_key_id, p_slot);
status = psa_reserve_free_key_slot(NULL, p_slot);
if (status != PSA_SUCCESS) {
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
@ -465,12 +901,12 @@ psa_status_t psa_unregister_read(psa_key_slot_t *slot)
/* If we are the last reader and the slot is marked for deletion,
* we must wipe the slot here. */
if ((slot->state == PSA_SLOT_PENDING_DELETION) &&
(slot->registered_readers == 1)) {
(slot->var.occupied.registered_readers == 1)) {
return psa_wipe_key_slot(slot);
}
if (psa_key_slot_has_readers(slot)) {
slot->registered_readers--;
slot->var.occupied.registered_readers--;
return PSA_SUCCESS;
}
@ -604,7 +1040,7 @@ psa_status_t psa_close_key(psa_key_handle_t handle)
return status;
}
if (slot->registered_readers == 1) {
if (slot->var.occupied.registered_readers == 1) {
status = psa_wipe_key_slot(slot);
} else {
status = psa_unregister_read(slot);
@ -639,7 +1075,7 @@ psa_status_t psa_purge_key(mbedtls_svc_key_id_t key)
}
if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
(slot->registered_readers == 1)) {
(slot->var.occupied.registered_readers == 1)) {
status = psa_wipe_key_slot(slot);
} else {
status = psa_unregister_read(slot);
@ -654,34 +1090,39 @@ psa_status_t psa_purge_key(mbedtls_svc_key_id_t key)
void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats)
{
size_t slot_idx;
memset(stats, 0, sizeof(*stats));
for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
const psa_key_slot_t *slot = &global_data.key_slots[slot_idx];
if (psa_key_slot_has_readers(slot)) {
++stats->locked_slots;
}
if (slot->state == PSA_SLOT_EMPTY) {
++stats->empty_slots;
for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) {
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
if (global_data.key_slices[slice_idx] == NULL) {
continue;
}
if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
++stats->volatile_slots;
} else {
psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
++stats->persistent_slots;
if (id > stats->max_open_internal_key_id) {
stats->max_open_internal_key_id = id;
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) {
const psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx);
if (slot->state == PSA_SLOT_EMPTY) {
++stats->empty_slots;
continue;
}
}
if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) !=
PSA_KEY_LOCATION_LOCAL_STORAGE) {
psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
++stats->external_slots;
if (id > stats->max_open_external_key_id) {
stats->max_open_external_key_id = id;
if (psa_key_slot_has_readers(slot)) {
++stats->locked_slots;
}
if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
++stats->volatile_slots;
} else {
psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
++stats->persistent_slots;
if (id > stats->max_open_internal_key_id) {
stats->max_open_internal_key_id = id;
}
}
if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) !=
PSA_KEY_LOCATION_LOCAL_STORAGE) {
psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
++stats->external_slots;
if (id > stats->max_open_external_key_id) {
stats->max_open_external_key_id = id;
}
}
}
}

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.
*
@ -94,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.
@ -113,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
@ -128,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
@ -174,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

@ -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

@ -152,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

@ -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

View File

@ -3923,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

@ -1355,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,

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>