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:
@ -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)
|
||||
|
@ -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)
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
@ -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
50
library/bignum_internal.h
Normal 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 */
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
Reference in New Issue
Block a user