1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-08-08 17:42:09 +03:00

Merge branch 'development' into driver-wrapper-key-agreement

This commit is contained in:
Aditya Deshpande
2022-11-07 17:23:21 +00:00
179 changed files with 15533 additions and 20903 deletions

View File

@@ -44,6 +44,8 @@ set(src_crypto
hash_info.c
hkdf.c
hmac_drbg.c
lmots.c
lms.c
md.c
md5.c
memory_buffer_alloc.c

View File

@@ -109,6 +109,8 @@ OBJS_CRYPTO= \
hash_info.o \
hkdf.o \
hmac_drbg.o \
lmots.o \
lms.o \
md.o \
md5.o \
memory_buffer_alloc.o \
@@ -197,6 +199,7 @@ all: shared static
endif
static: libmbedcrypto.a libmbedx509.a libmbedtls.a
cd ../tests && echo "This is a seedfile that contains 64 bytes (65 on Windows)......" > seedfile
shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT)

View File

@@ -1690,7 +1690,8 @@ int mbedtls_aes_self_test( int verbose )
unsigned char key[32];
unsigned char buf[64];
const unsigned char *aes_tests;
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
defined(MBEDTLS_CIPHER_MODE_OFB)
unsigned char iv[16];
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)

View File

@@ -888,15 +888,17 @@ static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#define ARIA_SELF_TEST_IF_FAIL \
{ \
if( verbose ) \
mbedtls_printf( "failed\n" ); \
goto exit; \
} else { \
if( verbose ) \
mbedtls_printf( "passed\n" ); \
}
#define ARIA_SELF_TEST_ASSERT( cond ) \
do { \
if( cond ) { \
if( verbose ) \
mbedtls_printf( "failed\n" ); \
goto exit; \
} else { \
if( verbose ) \
mbedtls_printf( "passed\n" ); \
} \
} while( 0 )
/*
* Checkup routine
@@ -930,16 +932,18 @@ int mbedtls_aria_self_test( int verbose )
mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i );
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk );
if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT(
memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE )
!= 0 );
/* test ECB decryption */
if( verbose )
mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i );
mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i );
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk );
if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT(
memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE )
!= 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@@ -958,8 +962,8 @@ int mbedtls_aria_self_test( int verbose )
memset( buf, 0x55, sizeof( buf ) );
mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv,
aria_test2_pt, buf );
if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_cbc_ct[i], 48 )
!= 0 );
/* Test CBC decryption */
if( verbose )
@@ -969,8 +973,7 @@ int mbedtls_aria_self_test( int verbose )
memset( buf, 0xAA, sizeof( buf ) );
mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv,
aria_test2_cbc_ct[i], buf );
if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@@ -989,8 +992,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv,
aria_test2_pt, buf );
if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 );
/* Test CFB decryption */
if( verbose )
@@ -1001,8 +1003,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j,
iv, aria_test2_cfb_ct[i], buf );
if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@@ -1020,8 +1021,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
aria_test2_pt, buf );
if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 );
/* Test CTR decryption */
if( verbose )
@@ -1032,8 +1032,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
aria_test2_ctr_ct[i], buf );
if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );

View File

@@ -72,9 +72,11 @@ int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, size_
return( 4 );
}
int len_is_valid = 1;
#if SIZE_MAX > 0xFFFFFFFF
if( len <= 0xFFFFFFFF )
len_is_valid = ( len <= 0xFFFFFFFF );
#endif
if( len_is_valid )
{
if( *p - start < 5 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
@@ -87,9 +89,7 @@ int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, size_
return( 5 );
}
#if SIZE_MAX > 0xFFFFFFFF
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
#endif
}
int mbedtls_asn1_write_tag( unsigned char **p, const unsigned char *start, unsigned char tag )

View File

@@ -771,42 +771,9 @@ cleanup:
*/
int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
{
size_t i, v0, v1;
mbedtls_mpi_uint r0 = 0, r1;
MPI_VALIDATE_RET( X != NULL );
v0 = count / biL;
v1 = count & (biL - 1);
if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
return mbedtls_mpi_lset( X, 0 );
/*
* shift by count / limb_size
*/
if( v0 > 0 )
{
for( i = 0; i < X->n - v0; i++ )
X->p[i] = X->p[i + v0];
for( ; i < X->n; i++ )
X->p[i] = 0;
}
/*
* shift by count % limb_size
*/
if( v1 > 0 )
{
for( i = X->n; i > 0; i-- )
{
r1 = X->p[i - 1] << (biL - v1);
X->p[i - 1] >>= v1;
X->p[i - 1] |= r0;
r0 = r1;
}
}
if( X->n != 0 )
mbedtls_mpi_core_shift_r( X->p, X->n, count );
return( 0 );
}
@@ -900,8 +867,7 @@ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, j;
mbedtls_mpi_uint *o, *p, c, tmp;
size_t j;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
@@ -915,7 +881,7 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
/*
* X should always be positive as a result of unsigned additions.
* X must always be positive as a result of unsigned additions.
*/
X->s = 1;
@@ -925,27 +891,25 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
o = B->p; p = X->p; c = 0;
/* j is the number of non-zero limbs of B. Add those to X. */
/*
* tmp is used because it might happen that p == o
*/
for( i = 0; i < j; i++, o++, p++ )
{
tmp= *o;
*p += c; c = ( *p < c );
*p += tmp; c += ( *p < tmp );
}
mbedtls_mpi_uint *p = X->p;
mbedtls_mpi_uint c = mbedtls_mpi_core_add( p, p, B->p, j );
p += j;
/* Now propagate any carry */
while( c != 0 )
{
if( i >= X->n )
if( j >= X->n )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
p = X->p + i;
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j + 1 ) );
p = X->p + j;
}
*p += c; c = ( *p < c ); i++; p++;
*p += c; c = ( *p < c ); j++; p++;
}
cleanup:
@@ -1967,39 +1931,11 @@ cleanup:
return( ret );
}
/* Fill X with n_bytes random bytes.
* X must already have room for those bytes.
* The ordering of the bytes returned from the RNG is suitable for
* deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
* The size and sign of X are unchanged.
* n_bytes must not be 0.
*/
static int mpi_fill_random_internal(
mbedtls_mpi *X, size_t n_bytes,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const size_t limbs = CHARS_TO_LIMBS( n_bytes );
const size_t overhead = ( limbs * ciL ) - n_bytes;
if( X->n < limbs )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
memset( X->p, 0, overhead );
memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
mbedtls_mpi_core_bigendian_to_host( X->p, limbs );
cleanup:
return( ret );
}
/*
* Fill X with size bytes of random.
*
* Use a temporary bytes representation to make sure the result is the same
* regardless of the platform endianness (useful when f_rng is actually
* deterministic, eg for tests).
* The bytes returned from the RNG are used in a specific order which
* is suitable for deterministic ECDSA (see the specification of
* mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
*/
int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
int (*f_rng)(void *, unsigned char *, size_t),
@@ -2016,7 +1952,7 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
if( size == 0 )
return( 0 );
ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
ret = mbedtls_mpi_core_fill_random( X->p, X->n, size, f_rng, p_rng );
cleanup:
return( ret );
@@ -2078,7 +2014,9 @@ int mbedtls_mpi_random( mbedtls_mpi *X,
*/
do
{
MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_core_fill_random( X->p, X->n,
n_bytes,
f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
if( --count == 0 )

View File

@@ -25,6 +25,7 @@
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "constant_time_internal.h"
#include "mbedtls/platform.h"
@@ -153,6 +154,36 @@ void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
}
}
void mbedtls_mpi_core_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned char assign )
{
if( X == A )
return;
mbedtls_ct_mpi_uint_cond_assign( limbs, X, A, assign );
}
void mbedtls_mpi_core_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
size_t limbs,
unsigned char swap )
{
if( X == Y )
return;
/* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask( swap );
for( size_t i = 0; i < limbs; i++ )
{
mbedtls_mpi_uint tmp = X[i];
X[i] = ( X[i] & ~limb_mask ) | ( Y[i] & limb_mask );
Y[i] = ( Y[i] & ~limb_mask ) | ( tmp & limb_mask );
}
}
int mbedtls_mpi_core_read_le( mbedtls_mpi_uint *X,
size_t X_limbs,
const unsigned char *input,
@@ -285,6 +316,67 @@ int mbedtls_mpi_core_write_be( const mbedtls_mpi_uint *X,
return( 0 );
}
void mbedtls_mpi_core_shift_r( mbedtls_mpi_uint *X, size_t limbs,
size_t count )
{
size_t i, v0, v1;
mbedtls_mpi_uint r0 = 0, r1;
v0 = count / biL;
v1 = count & (biL - 1);
if( v0 > limbs || ( v0 == limbs && v1 > 0 ) )
{
memset( X, 0, limbs * ciL );
return;
}
/*
* shift by count / limb_size
*/
if( v0 > 0 )
{
for( i = 0; i < limbs - v0; i++ )
X[i] = X[i + v0];
for( ; i < limbs; i++ )
X[i] = 0;
}
/*
* shift by count % limb_size
*/
if( v1 > 0 )
{
for( i = limbs; i > 0; i-- )
{
r1 = X[i - 1] << (biL - v1);
X[i - 1] >>= v1;
X[i - 1] |= r0;
r0 = r1;
}
}
}
mbedtls_mpi_uint mbedtls_mpi_core_add( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs )
{
mbedtls_mpi_uint c = 0;
for( size_t i = 0; i < limbs; i++ )
{
mbedtls_mpi_uint t = c + A[i];
c = ( t < A[i] );
t += B[i];
c += ( t < B[i] );
X[i] = t;
}
return( c );
}
mbedtls_mpi_uint mbedtls_mpi_core_add_if( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
@@ -434,4 +526,98 @@ void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X,
mbedtls_ct_mpi_uint_cond_assign( AN_limbs, X, T, (unsigned char) ( carry ^ borrow ) );
}
int mbedtls_mpi_core_get_mont_r2_unsafe( mbedtls_mpi *X,
const mbedtls_mpi *N )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, N->n * 2 * biL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( X, X, N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( X, N->n ) );
cleanup:
return( ret );
}
void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest,
const mbedtls_mpi_uint *table,
size_t limbs,
size_t count,
size_t index )
{
for( size_t i = 0; i < count; i++, table += limbs )
{
unsigned char assign = mbedtls_ct_size_bool_eq( i, index );
mbedtls_mpi_core_cond_assign( dest, table, limbs, assign );
}
}
/* Fill X with n_bytes random bytes.
* X must already have room for those bytes.
* The ordering of the bytes returned from the RNG is suitable for
* deterministic ECDSA (see RFC 6979 §3.3 and the specification of
* mbedtls_mpi_core_random()).
*/
int mbedtls_mpi_core_fill_random(
mbedtls_mpi_uint *X, size_t X_limbs,
size_t n_bytes,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const size_t limbs = CHARS_TO_LIMBS( n_bytes );
const size_t overhead = ( limbs * ciL ) - n_bytes;
if( X_limbs < limbs )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
memset( X, 0, overhead );
memset( (unsigned char *) X + limbs * ciL, 0, ( X_limbs - limbs ) * ciL );
MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X + overhead, n_bytes ) );
mbedtls_mpi_core_bigendian_to_host( X, limbs );
cleanup:
return( ret );
}
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_C */

View File

@@ -6,6 +6,61 @@
* modules should use the high-level modular bignum interface (bignum_mod.h)
* or the legacy bignum interface (bignum.h).
*
* This module is about processing non-negative integers with a fixed upper
* bound that's of the form 2^n-1 where n is a multiple of #biL.
* These can be thought of integers written in base 2^#biL with a fixed
* number of digits. Digits in this base are called *limbs*.
* Many operations treat these numbers as the principal representation of
* a number modulo 2^n or a smaller bound.
*
* The functions in this module obey the following conventions unless
* explicitly indicated otherwise:
*
* - **Overflow**: some functions indicate overflow from the range
* [0, 2^n-1] by returning carry parameters, while others operate
* modulo and so cannot overflow. This should be clear from the function
* documentation.
* - **Bignum parameters**: Bignums are passed as pointers to an array of
* limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:
* - Bignum parameters called \p A, \p B, ... are inputs, and are
* not modified by the function.
* - For operations modulo some number, the modulus is called \p N
* and is input-only.
* - Bignum parameters called \p X, \p Y are outputs or input-output.
* The initial content of output-only parameters is ignored.
* - Some functions use different names that reflect traditional
* naming of operands of certain operations (e.g.
* divisor/dividend/quotient/remainder).
* - \p T is a temporary storage area. The initial content of such
* parameter is ignored and the final content is unspecified.
* - **Bignum sizes**: bignum sizes are always expressed in limbs.
* Most functions work on bignums of a given size and take a single
* \p limbs parameter that applies to all parameters that are limb arrays.
* All bignum sizes must be at least 1 and must be significantly less than
* #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the
* total size of all parameters overflows #SIZE_MAX is undefined.
* - **Parameter ordering**: for bignum parameters, outputs come before inputs.
* Temporaries come last.
* - **Aliasing**: in general, output bignums may be aliased to one or more
* inputs. As an exception, parameters that are documented as a modulus value
* may not be aliased to an output. Outputs may not be aliased to one another.
* Temporaries may not be aliased to any other parameter.
* - **Overlap**: apart from aliasing of limb array pointers (where two
* arguments are equal pointers), overlap is not supported and may result
* in undefined behavior.
* - **Error handling**: This is a low-level module. Functions generally do not
* try to protect against invalid arguments such as nonsensical sizes or
* null pointers. Note that some functions that operate on bignums of
* different sizes have constraints about their size, and violating those
* constraints may lead to buffer overflows.
* - **Modular representatives**: functions that operate modulo \p N expect
* all modular inputs to be in the range [0, \p N - 1] and guarantee outputs
* in the range [0, \p N - 1]. If an input is out of range, outputs are
* fully unspecified, though bignum values out of range should not cause
* buffer overflows (beware that this is not extensively tested).
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
@@ -31,9 +86,9 @@
#include "mbedtls/bignum.h"
#endif
#define ciL ( sizeof(mbedtls_mpi_uint) ) /* chars in limb */
#define biL ( ciL << 3 ) /* bits in limb */
#define biH ( ciL << 2 ) /* half limb size */
#define ciL ( sizeof(mbedtls_mpi_uint) ) /** chars in limb */
#define biL ( ciL << 3 ) /** bits in limb */
#define biH ( ciL << 2 ) /** half limb size */
/*
* Convert between bits/chars and number of limbs
@@ -74,6 +129,58 @@ size_t mbedtls_mpi_core_bitlen( const mbedtls_mpi_uint *A, size_t A_limbs );
void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
size_t A_limbs );
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether assignment was done or not.
*
* \param[out] X The address of the destination MPI.
* This must be initialized. Must have enough limbs to
* store the full value of \p A.
* \param[in] A The address of the source MPI. This must be initialized.
* \param limbs The number of limbs of \p A.
* \param assign The condition deciding whether to perform the
* assignment or not. Must be either 0 or 1:
* * \c 1: Perform the assignment `X = A`.
* * \c 0: Keep the original value of \p X.
*
* \note This function avoids leaking any information about whether
* the assignment was done or not.
*
* \warning If \p assign is neither 0 nor 1, the result of this function
* is indeterminate, and the resulting value in \p X might be
* neither its original value nor the value in \p A.
*/
void mbedtls_mpi_core_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned char assign );
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
* whether the swap was done or not.
*
* \param[in,out] X The address of the first MPI.
* This must be initialized.
* \param[in,out] Y The address of the second MPI.
* This must be initialized.
* \param limbs The number of limbs of \p X and \p Y.
* \param swap The condition deciding whether to perform
* the swap or not. Must be either 0 or 1:
* * \c 1: Swap the values of \p X and \p Y.
* * \c 0: Keep the original values of \p X and \p Y.
*
* \note This function avoids leaking any information about whether
* the swap was done or not.
*
* \warning If \p swap is neither 0 nor 1, the result of this function
* is indeterminate, and both \p X and \p Y might end up with
* values different to either of the original ones.
*/
void mbedtls_mpi_core_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
size_t limbs,
unsigned char swap );
/** Import X from unsigned binary data, little-endian.
*
* The MPI needs to have enough limbs to store the full value (including any
@@ -155,6 +262,43 @@ int mbedtls_mpi_core_write_be( const mbedtls_mpi_uint *A,
unsigned char *output,
size_t output_length );
/** \brief Shift an MPI right in place by a number of bits.
*
* Shifting by more bits than there are bit positions
* in \p X is valid and results in setting \p X to 0.
*
* This function's execution time depends on the value
* of \p count (and of course \p limbs).
*
* \param[in,out] X The number to shift.
* \param limbs The number of limbs of \p X. This must be at least 1.
* \param count The number of bits to shift by.
*/
void mbedtls_mpi_core_shift_r( mbedtls_mpi_uint *X, size_t limbs,
size_t count );
/**
* \brief Add two fixed-size large unsigned integers, returning the carry.
*
* Calculates `A + B` where `A` and `B` have the same size.
*
* This function operates modulo `2^(biL*limbs)` and returns the carry
* (1 if there was a wraparound, and 0 otherwise).
*
* \p X may be aliased to \p A or \p B.
*
* \param[out] X The result of the addition.
* \param[in] A Little-endian presentation of the left operand.
* \param[in] B Little-endian presentation of the right operand.
* \param limbs Number of limbs of \p X, \p A and \p B.
*
* \return 1 if `A + B >= 2^(biL*limbs)`, 0 otherwise.
*/
mbedtls_mpi_uint mbedtls_mpi_core_add( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs );
/**
* \brief Conditional addition of two fixed-size large unsigned integers,
* returning the carry.
@@ -290,4 +434,104 @@ void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *N, size_t AN_limbs,
mbedtls_mpi_uint mm, mbedtls_mpi_uint *T );
/**
* \brief Calculate the square of the Montgomery constant. (Needed
* for conversion and operations in Montgomery form.)
*
* \param[out] X A pointer to the result of the calculation of
* the square of the Montgomery constant:
* 2^{2*n*biL} mod N.
* \param[in] N Little-endian presentation of the modulus, which must be odd.
*
* \return 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space
* to store the value of Montgomery constant squared.
* \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero.
* \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative.
*/
int mbedtls_mpi_core_get_mont_r2_unsafe( mbedtls_mpi *X,
const mbedtls_mpi *N );
/**
* Copy an MPI from a table without leaking the index.
*
* \param dest The destination buffer. This must point to a writable
* buffer of at least \p limbs limbs.
* \param table The address of the table. This must point to a readable
* array of \p count elements of \p limbs limbs each.
* \param limbs The number of limbs in each table entry.
* \param count The number of entries in \p table.
* \param index The (secret) table index to look up. This must be in the
* range `0 .. count-1`.
*/
void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest,
const mbedtls_mpi_uint *table,
size_t limbs,
size_t count,
size_t index );
/**
* \brief Fill an integer with a number of random bytes.
*
* \param X The destination MPI.
* \param X_limbs The number of limbs of \p X.
* \param bytes The number of random bytes to generate.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG parameter to be passed to \p f_rng. This may be
* \c NULL if \p f_rng doesn't need a context argument.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p X does not have
* enough room for \p bytes bytes.
* \return A negative error code on RNG failure.
*
* \note The bytes obtained from the RNG are interpreted
* as a big-endian representation of an MPI; this can
* be relevant in applications like deterministic ECDSA.
*/
int mbedtls_mpi_core_fill_random( mbedtls_mpi_uint *X, size_t X_limbs,
size_t bytes,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_CORE_H */

View File

@@ -77,7 +77,14 @@ void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m )
switch( m->int_rep )
{
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
mbedtls_free( m->rep.mont );
if (m->rep.mont.rr != NULL)
{
mbedtls_platform_zeroize( (mbedtls_mpi_uint *) m->rep.mont.rr,
m->limbs );
mbedtls_free( (mbedtls_mpi_uint *)m->rep.mont.rr );
m->rep.mont.rr = NULL;
}
m->rep.mont.mm = 0;
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
mbedtls_free( m->rep.ored );
@@ -93,6 +100,41 @@ void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m )
m->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
}
static int set_mont_const_square( const mbedtls_mpi_uint **X,
const mbedtls_mpi_uint *A,
size_t limbs )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi N;
mbedtls_mpi RR;
*X = NULL;
mbedtls_mpi_init( &N );
mbedtls_mpi_init( &RR );
if ( A == NULL || limbs == 0 || limbs >= ( MBEDTLS_MPI_MAX_LIMBS / 2 ) - 2 )
goto cleanup;
if ( mbedtls_mpi_grow( &N, limbs ) )
goto cleanup;
memcpy( N.p, A, sizeof(mbedtls_mpi_uint) * limbs );
ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
if ( ret == 0 )
{
*X = RR.p;
RR.p = NULL;
}
cleanup:
mbedtls_mpi_free(&N);
mbedtls_mpi_free(&RR);
ret = ( ret != 0 ) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
return( ret );
}
int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
const mbedtls_mpi_uint *p,
size_t p_limbs,
@@ -120,7 +162,8 @@ int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
{
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
m->int_rep = int_rep;
m->rep.mont = NULL;
m->rep.mont.mm = mbedtls_mpi_core_montmul_init( m->p );
ret = set_mont_const_square( &m->rep.mont.rr, m->p, m->limbs );
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
m->int_rep = int_rep;
@@ -141,4 +184,44 @@ exit:
return( ret );
}
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_C */

View File

@@ -1,6 +1,10 @@
/**
* Modular bignum functions
*
* This module implements operations on integers modulo some fixed modulus.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
@@ -49,7 +53,11 @@ typedef struct
size_t limbs;
} mbedtls_mpi_mod_residue;
typedef void *mbedtls_mpi_mont_struct;
typedef struct {
mbedtls_mpi_uint const *rr; /* The residue for 2^{2*n*biL} mod N */
mbedtls_mpi_uint mm; /* Montgomery const for -N^{-1} mod 2^{ciL} */
} mbedtls_mpi_mont_struct;
typedef void *mbedtls_mpi_opt_red_struct;
typedef struct {
@@ -140,4 +148,44 @@ int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
*/
void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m );
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_MOD_H */

View File

@@ -33,6 +33,22 @@
#include "bignum_mod.h"
#include "constant_time_internal.h"
void mbedtls_mpi_mod_raw_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign )
{
mbedtls_mpi_core_cond_assign( X, A, N->limbs, assign );
}
void mbedtls_mpi_mod_raw_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap )
{
mbedtls_mpi_core_cond_swap( X, Y, N->limbs, swap );
}
int mbedtls_mpi_mod_raw_read( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m,
const unsigned char *input,
@@ -86,4 +102,44 @@ int mbedtls_mpi_mod_raw_write( const mbedtls_mpi_uint *A,
}
}
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_C */

View File

@@ -6,6 +6,14 @@
* modules should use the high-level modular bignum interface (bignum_mod.h)
* or the legacy bignum interface (bignum.h).
*
* This is a low-level interface to operations on integers modulo which
* has no protection against passing invalid arguments such as arrays of
* the wrong size. The functions in bignum_mod.h provide a higher-level
* interface that includes protections against accidental misuse, at the
* expense of code size and sometimes more cumbersome memory management.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
@@ -33,6 +41,60 @@
#include "bignum_mod.h"
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether the assignment was done or not.
*
* The size to copy is determined by \p N.
*
* \param[out] X The address of the destination MPI.
* This must be initialized. Must have enough limbs to
* store the full value of \p A.
* \param[in] A The address of the source MPI. This must be initialized.
* \param[in] N The address of the modulus related to \p X and \p A.
* \param assign The condition deciding whether to perform the
* assignment or not. Must be either 0 or 1:
* * \c 1: Perform the assignment `X = A`.
* * \c 0: Keep the original value of \p X.
*
* \note This function avoids leaking any information about whether
* the assignment was done or not.
*
* \warning If \p assign is neither 0 nor 1, the result of this function
* is indeterminate, and the resulting value in \p X might be
* neither its original value nor the value in \p A.
*/
void mbedtls_mpi_mod_raw_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign );
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
* whether the swap was done or not.
*
* The size to swap is determined by \p N.
*
* \param[in,out] X The address of the first MPI. This must be initialized.
* \param[in,out] Y The address of the second MPI. This must be initialized.
* \param[in] N The address of the modulus related to \p X and \p Y.
* \param swap The condition deciding whether to perform
* the swap or not. Must be either 0 or 1:
* * \c 1: Swap the values of \p X and \p Y.
* * \c 0: Keep the original values of \p X and \p Y.
*
* \note This function avoids leaking any information about whether
* the swap was done or not.
*
* \warning If \p swap is neither 0 nor 1, the result of this function
* is indeterminate, and both \p X and \p Y might end up with
* values different to either of the original ones.
*/
void mbedtls_mpi_mod_raw_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap );
/** Import X from unsigned binary data.
*
* The MPI needs to have enough limbs to store the full value (including any
@@ -76,4 +138,44 @@ int mbedtls_mpi_mod_raw_write( const mbedtls_mpi_uint *A,
unsigned char *output,
size_t output_length );
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_MOD_RAW_H */

View File

@@ -30,6 +30,7 @@
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#include "bignum_core.h"
#endif
#if defined(MBEDTLS_SSL_TLS_C)
@@ -678,21 +679,19 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X,
unsigned char assign )
{
int ret = 0;
size_t i;
mbedtls_mpi_uint limb_mask;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( Y != NULL );
/* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
limb_mask = mbedtls_ct_mpi_uint_mask( assign );;
mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask( assign );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
X->s = mbedtls_ct_cond_select_sign( assign, Y->s, X->s );
mbedtls_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign );
mbedtls_mpi_core_cond_assign( X->p, Y->p, Y->n, assign );
for( i = Y->n; i < X->n; i++ )
for( size_t i = Y->n; i < X->n; i++ )
X->p[i] &= ~limb_mask;
cleanup:
@@ -709,19 +708,14 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
mbedtls_mpi *Y,
unsigned char swap )
{
int ret, s;
size_t i;
mbedtls_mpi_uint limb_mask;
mbedtls_mpi_uint tmp;
int ret = 0;
int s;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( Y != NULL );
if( X == Y )
return( 0 );
/* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
limb_mask = mbedtls_ct_mpi_uint_mask( swap );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
@@ -729,13 +723,7 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
X->s = mbedtls_ct_cond_select_sign( swap, Y->s, X->s );
Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s );
for( i = 0; i < X->n; i++ )
{
tmp = X->p[i];
X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
}
mbedtls_mpi_core_cond_swap( X->p, Y->p, X->n, swap );
cleanup:
return( ret );

View File

@@ -46,7 +46,7 @@
*/
unsigned mbedtls_ct_uint_mask( unsigned value );
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
/** Turn a value into a mask:
* - if \p value == 0, return the all-bits 0 mask, aka 0
@@ -61,7 +61,7 @@ unsigned mbedtls_ct_uint_mask( unsigned value );
*/
size_t mbedtls_ct_size_mask( size_t value );
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
#if defined(MBEDTLS_BIGNUM_C)

View File

@@ -71,10 +71,12 @@ static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* If multiplication is in progress, we already generated a privkey */
int restarting = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx == NULL || rs_ctx->rsm == NULL )
restarting = ( rs_ctx != NULL && rs_ctx->rsm != NULL );
#endif
/* If multiplication is in progress, we already generated a privkey */
if( !restarting )
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,

View File

@@ -2279,12 +2279,14 @@ cleanup:
mbedtls_free( T );
}
/* don't free R while in progress in case R == P */
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
#endif
/* prevent caller from using invalid value */
if( ret != 0 )
int should_free_R = ( ret != 0 );
#if defined(MBEDTLS_ECP_RESTARTABLE)
/* don't free R while in progress in case R == P */
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
should_free_R = 0;
#endif
if( should_free_R )
mbedtls_ecp_point_free( R );
ECP_RS_LEAVE( rsm );
@@ -2459,7 +2461,7 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
/* Loop invariant: R = result so far, RP = R + P */
i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */
while( i-- > 0 )
{
b = mbedtls_mpi_get_bit( m, i );
@@ -2529,10 +2531,12 @@ static int ecp_mul_restartable_internal( mbedtls_ecp_group *grp, mbedtls_ecp_poi
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
int restarting = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
/* skip argument check when restarting */
if( rs_ctx == NULL || rs_ctx->rsm == NULL )
restarting = ( rs_ctx != NULL && rs_ctx->rsm != NULL );
#endif
/* skip argument check when restarting */
if( !restarting )
{
/* check_privkey is free */
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
@@ -2658,14 +2662,17 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
if( mbedtls_mpi_cmp_int( m, 0 ) == 0 )
{
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_set_zero( R ) );
}
else if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
{
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
}
else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
{
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
MPI_ECP_NEG( &R->Y );
}

826
library/lmots.c Normal file
View File

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

322
library/lmots.h Normal file
View File

@@ -0,0 +1,322 @@
/**
* \file lmots.h
*
* \brief This file provides an API for the LM-OTS post-quantum-safe one-time
* public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.
* This implementation currently only supports a single parameter set
* MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_LMOTS_H
#define MBEDTLS_LMOTS_H
#include "mbedtls/build_info.h"
#include "psa/crypto.h"
#include "mbedtls/lms.h"
#include <stdint.h>
#include <stddef.h>
#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \
MBEDTLS_LMOTS_I_KEY_ID_LEN + \
MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \
MBEDTLS_LMOTS_N_HASH_LEN(type))
#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0)
#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \
MBEDTLS_LMOTS_TYPE_LEN)
#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type))
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_TEST_HOOKS)
extern int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * );
#endif /* defined(MBEDTLS_TEST_HOOKS) */
/**
* \brief This function converts an unsigned int into a
* network-byte-order (big endian) string.
*
* \param val The unsigned integer value
* \param len The length of the string.
* \param bytes The string to output into.
*/
void mbedtls_lms_unsigned_int_to_network_bytes( unsigned int val, size_t len,
unsigned char *bytes );
/**
* \brief This function converts a network-byte-order
* (big endian) string into an unsigned integer.
*
* \param len The length of the string.
* \param bytes The string.
*
* \return The corresponding LMS error code.
*/
unsigned int mbedtls_lms_network_bytes_to_unsigned_int( size_t len,
const unsigned char *bytes );
/**
* \brief This function converts a \ref psa_status_t to a
* low-level LMS error code.
*
* \param status The psa_status_t to convert
*
* \return The corresponding LMS error code.
*/
int mbedtls_lms_error_from_psa( psa_status_t status );
/**
* \brief This function initializes a public LMOTS context
*
* \param ctx The uninitialized LMOTS context that will then be
* initialized.
*/
void mbedtls_lmots_public_init( mbedtls_lmots_public_t *ctx );
/**
* \brief This function uninitializes a public LMOTS context
*
* \param ctx The initialized LMOTS context that will then be
* uninitialized.
*/
void mbedtls_lmots_public_free( mbedtls_lmots_public_t *ctx );
/**
* \brief This function imports an LMOTS public key into a
* LMOTS context.
*
* \note Before this function is called, the context must
* have been initialized.
*
* \note See IETF RFC8554 for details of the encoding of
* this public key.
*
* \param ctx The initialized LMOTS context store the key in.
* \param key The buffer from which the key will be read.
* #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read
* from this.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx,
const unsigned char *key, size_t key_size );
/**
* \brief This function exports an LMOTS public key from a
* LMOTS context that already contains a public key.
*
* \note Before this function is called, the context must
* have been initialized and the context must contain
* a public key.
*
* \note See IETF RFC8554 for details of the encoding of
* this public key.
*
* \param ctx The initialized LMOTS context that contains the
* publc key.
* \param key The buffer into which the key will be output. Must
* be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx,
unsigned char *key, size_t key_size,
size_t *key_len );
/**
* \brief This function creates a candidate public key from
* an LMOTS signature. This can then be compared to
* the real public key to determine the validity of
* the signature.
*
* \note This function is exposed publicly to be used in LMS
* signature verification, it is expected that
* mbedtls_lmots_verify will be used for LMOTS
* signature verification.
*
* \param params The LMOTS parameter set, q and I values as an
* mbedtls_lmots_parameters_t struct.
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buffer from which the signature will be read.
* #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
* this.
* \param out The buffer where the candidate public key will be
* stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN
* bytes in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters_t *params,
const unsigned char *msg,
size_t msg_size,
const unsigned char *sig,
size_t sig_size,
unsigned char *out,
size_t out_size,
size_t *out_len );
/**
* \brief This function verifies a LMOTS signature, using a
* LMOTS context that contains a public key.
*
* \warning This function is **not intended for use in
* production**, due to as-yet unsolved problems with
* handling stateful keys. The API for this function
* may change considerably in future versions.
*
* \note Before this function is called, the context must
* have been initialized and must contain a public key
* (either by import or calculation from a private
* key).
*
* \param ctx The initialized LMOTS context from which the public
* key will be read.
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buf from which the signature will be read.
* #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
* this.
*
* \return \c 0 on successful verification.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx,
const unsigned char *msg,
size_t msg_size, const unsigned char *sig,
size_t sig_size );
#if defined(MBEDTLS_LMS_PRIVATE)
/**
* \brief This function initializes a private LMOTS context
*
* \param ctx The uninitialized LMOTS context that will then be
* initialized.
*/
void mbedtls_lmots_private_init( mbedtls_lmots_private_t *ctx );
/**
* \brief This function uninitializes a private LMOTS context
*
* \param ctx The initialized LMOTS context that will then be
* uninitialized.
*/
void mbedtls_lmots_private_free( mbedtls_lmots_private_t *ctx );
/**
* \brief This function calculates an LMOTS private key, and
* stores in into an LMOTS context.
*
* \warning This function is **not intended for use in
* production**, due to as-yet unsolved problems with
* handling stateful keys. The API for this function
* may change considerably in future versions.
*
* \note The seed must have at least 256 bits of entropy.
*
* \param ctx The initialized LMOTS context to generate the key
* into.
* \param I_key_identifier The key identifier of the key, as a 16-byte string.
* \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is
* not being used as part of an LMS key, this should
* be set to 0.
* \param seed The seed used to deterministically generate the
* key.
* \param seed_size The length of the seed.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx,
mbedtls_lmots_algorithm_type_t type,
const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
uint32_t q_leaf_identifier,
const unsigned char *seed,
size_t seed_size );
/**
* \brief This function generates an LMOTS public key from a
* LMOTS context that already contains a private key.
*
* \note Before this function is called, the context must
* have been initialized and the context must contain
* a private key.
*
* \param ctx The initialized LMOTS context to generate the key
* from and store it into.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx,
const mbedtls_lmots_private_t *priv_ctx );
/**
* \brief This function creates a LMOTS signature, using a
* LMOTS context that contains a private key.
*
* \note Before this function is called, the context must
* have been initialized and must contain a private
* key.
*
* \note LMOTS private keys can only be used once, otherwise
* attackers may be able to create forged signatures.
* If the signing operation is successful, the private
* key in the context will be erased, and no further
* signing will be possible until another private key
* is loaded
*
* \param ctx The initialized LMOTS context from which the
* private key will be read.
* \param f_rng The RNG function to be used for signature
* generation.
* \param p_rng The RNG context to be passed to f_rng
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buf into which the signature will be stored.
* Must be at least #MBEDTLS_LMOTS_SIG_LEN in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, const unsigned char *msg, size_t msg_size,
unsigned char *sig, size_t sig_size, size_t* sig_len );
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_LMOTS_H */

789
library/lms.c Normal file
View File

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

View File

@@ -24,6 +24,7 @@
#include "psa_crypto_aead.h"
#include "psa_crypto_core.h"
#include "psa_crypto_cipher.h"
#include <string.h>
#include "mbedtls/platform.h"

View File

@@ -1,5 +1,5 @@
/*
* PSA cipher driver entry points
* PSA cipher driver entry points and associated auxiliary functions
*/
/*
* Copyright The Mbed TLS Contributors

View File

@@ -246,22 +246,6 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot,
*/
psa_status_t mbedtls_to_psa_error( int ret );
/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier
* as well as the PSA type and size of the key to be used with the cipher
* algorithm.
*
* \param alg PSA cipher algorithm identifier
* \param key_type PSA key type
* \param key_bits Size of the key in bits
* \param[out] cipher_id Mbed TLS cipher algorithm identifier
*
* \return The Mbed TLS cipher information of the cipher algorithm.
* \c NULL if the PSA cipher algorithm is not supported.
*/
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits,
mbedtls_cipher_id_t *cipher_id );
/** Import a key in binary format.
*
* \note The signature of this function is that of a PSA driver

View File

@@ -24,6 +24,7 @@
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_cipher.h"
#include "psa_crypto_mac.h"
#include <mbedtls/md.h>

View File

@@ -230,7 +230,7 @@ psa_status_t psa_pake_setup( psa_pake_operation_t *operation,
operation->input_step = PSA_PAKE_STEP_X1_X2;
operation->output_step = PSA_PAKE_STEP_X1_X2;
mbedtls_platform_zeroize( operation->buffer, PSA_PAKE_BUFFER_SIZE );
mbedtls_platform_zeroize( operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE );
operation->buffer_length = 0;
operation->buffer_offset = 0;
@@ -385,7 +385,8 @@ static psa_status_t psa_pake_ecjpake_setup( psa_pake_operation_t *operation )
}
#endif
psa_status_t psa_pake_output( psa_pake_operation_t *operation,
static psa_status_t psa_pake_output_internal(
psa_pake_operation_t *operation,
psa_pake_step_t step,
uint8_t *output,
size_t output_size,
@@ -427,10 +428,7 @@ psa_status_t psa_pake_output( psa_pake_operation_t *operation,
if( operation->state == PSA_PAKE_STATE_SETUP ) {
status = psa_pake_ecjpake_setup( operation );
if( status != PSA_SUCCESS )
{
psa_pake_abort( operation );
return( status );
}
}
if( operation->state != PSA_PAKE_STATE_READY &&
@@ -491,15 +489,12 @@ psa_status_t psa_pake_output( psa_pake_operation_t *operation,
{
ret = mbedtls_ecjpake_write_round_one( &operation->ctx.ecjpake,
operation->buffer,
PSA_PAKE_BUFFER_SIZE,
MBEDTLS_PSA_PAKE_BUFFER_SIZE,
&operation->buffer_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE );
if( ret != 0 )
{
psa_pake_abort( operation );
return( mbedtls_ecjpake_to_psa_error( ret ) );
}
operation->buffer_offset = 0;
}
@@ -508,68 +503,47 @@ psa_status_t psa_pake_output( psa_pake_operation_t *operation,
{
ret = mbedtls_ecjpake_write_round_two( &operation->ctx.ecjpake,
operation->buffer,
PSA_PAKE_BUFFER_SIZE,
MBEDTLS_PSA_PAKE_BUFFER_SIZE,
&operation->buffer_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE );
if( ret != 0 )
{
psa_pake_abort( operation );
return( mbedtls_ecjpake_to_psa_error( ret ) );
}
operation->buffer_offset = 0;
}
/*
* Steps sequences are stored as:
* struct {
* opaque point <1..2^8-1>;
* } ECPoint;
* mbedtls_ecjpake_write_round_xxx() outputs thing in the format
* defined by draft-cragie-tls-ecjpake-01 section 7. The summary is
* that the data for each step is prepended with a length byte, and
* then they're concatenated. Additionally, the server's second round
* output is prepended with a 3-bytes ECParameters structure.
*
* Where byte 0 stores the ECPoint curve point length.
*
* The sequence length is equal to:
* - data length extracted from byte 0
* - byte 0 size (1)
* In PSA, we output each step separately, and don't prepend the
* output with a length byte, even less a curve identifier, as that
* information is already available.
*/
if( operation->state == PSA_PAKE_OUTPUT_X2S &&
operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE )
operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE &&
operation->role == PSA_PAKE_ROLE_SERVER )
{
if( operation->role == PSA_PAKE_ROLE_SERVER )
/*
* The X2S KEY SHARE Server steps sequence is stored as:
* struct {
* ECPoint X;
* opaque r <1..2^8-1>;
* } ECSchnorrZKP;
*
* And MbedTLS uses a 3 bytes Ephemeral public key ECPoint,
* so byte 3 stores the r Schnorr signature length.
*
* The sequence length is equal to:
* - curve storage size (3)
* - data length extracted from byte 3
* - byte 3 size (1)
*/
length = 3 + operation->buffer[3] + 1;
else
length = operation->buffer[0] + 1;
/* Skip ECParameters, with is 3 bytes (RFC 8422) */
operation->buffer_offset += 3;
}
else
length = operation->buffer[operation->buffer_offset] + 1;
if( length > operation->buffer_length )
/* Read the length byte then move past it to the data */
length = operation->buffer[operation->buffer_offset];
operation->buffer_offset += 1;
if( operation->buffer_offset + length > operation->buffer_length )
return( PSA_ERROR_DATA_CORRUPT );
if( output_size < length )
{
psa_pake_abort( operation );
return( PSA_ERROR_BUFFER_TOO_SMALL );
}
memcpy( output,
operation->buffer + operation->buffer_offset,
operation->buffer + operation->buffer_offset,
length );
*output_length = length;
@@ -581,7 +555,7 @@ psa_status_t psa_pake_output( psa_pake_operation_t *operation,
( operation->state == PSA_PAKE_OUTPUT_X2S &&
operation->sequence == PSA_PAKE_X1_STEP_ZK_PROOF ) )
{
mbedtls_platform_zeroize( operation->buffer, PSA_PAKE_BUFFER_SIZE );
mbedtls_platform_zeroize( operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE );
operation->buffer_length = 0;
operation->buffer_offset = 0;
@@ -599,14 +573,29 @@ psa_status_t psa_pake_output( psa_pake_operation_t *operation,
return( PSA_ERROR_NOT_SUPPORTED );
}
psa_status_t psa_pake_input( psa_pake_operation_t *operation,
psa_status_t psa_pake_output( psa_pake_operation_t *operation,
psa_pake_step_t step,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
psa_status_t status = psa_pake_output_internal(
operation, step, output, output_size, output_length );
if( status != PSA_SUCCESS )
psa_pake_abort( operation );
return( status );
}
static psa_status_t psa_pake_input_internal(
psa_pake_operation_t *operation,
psa_pake_step_t step,
const uint8_t *input,
size_t input_length )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t buffer_remain;
if( operation->alg == PSA_ALG_NONE ||
operation->state == PSA_PAKE_STATE_INVALID )
@@ -638,14 +627,16 @@ psa_status_t psa_pake_input( psa_pake_operation_t *operation,
step != PSA_PAKE_STEP_ZK_PROOF )
return( PSA_ERROR_INVALID_ARGUMENT );
const psa_pake_primitive_t prim = PSA_PAKE_PRIMITIVE(
PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256 );
if( input_length > (size_t) PSA_PAKE_INPUT_SIZE( PSA_ALG_JPAKE, prim, step ) )
return( PSA_ERROR_INVALID_ARGUMENT );
if( operation->state == PSA_PAKE_STATE_SETUP )
{
status = psa_pake_ecjpake_setup( operation );
if( status != PSA_SUCCESS )
{
psa_pake_abort( operation );
return( status );
}
}
if( operation->state != PSA_PAKE_STATE_READY &&
@@ -675,15 +666,6 @@ psa_status_t psa_pake_input( psa_pake_operation_t *operation,
operation->sequence = PSA_PAKE_X1_STEP_KEY_SHARE;
}
buffer_remain = PSA_PAKE_BUFFER_SIZE - operation->buffer_length;
if( input_length == 0 ||
input_length > buffer_remain )
{
psa_pake_abort( operation );
return( PSA_ERROR_INSUFFICIENT_MEMORY );
}
/* Check if step matches current sequence */
switch( operation->sequence )
{
@@ -709,7 +691,35 @@ psa_status_t psa_pake_input( psa_pake_operation_t *operation,
return( PSA_ERROR_BAD_STATE );
}
/* Copy input to local buffer */
/*
* Copy input to local buffer and format it as the Mbed TLS API
* expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7.
* The summary is that the data for each step is prepended with a
* length byte, and then they're concatenated. Additionally, the
* server's second round output is prepended with a 3-bytes
* ECParameters structure - which means we have to prepend that when
* we're a client.
*/
if( operation->state == PSA_PAKE_INPUT_X4S &&
operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE &&
operation->role == PSA_PAKE_ROLE_CLIENT )
{
/* We only support secp256r1. */
/* This is the ECParameters structure defined by RFC 8422. */
unsigned char ecparameters[3] = {
3, /* named_curve */
0, 23 /* secp256r1 */
};
memcpy( operation->buffer + operation->buffer_length,
ecparameters, sizeof( ecparameters ) );
operation->buffer_length += sizeof( ecparameters );
}
/* Write the length byte */
operation->buffer[operation->buffer_length] = (uint8_t) input_length;
operation->buffer_length += 1;
/* Finally copy the data */
memcpy( operation->buffer + operation->buffer_length,
input, input_length );
operation->buffer_length += input_length;
@@ -722,14 +732,11 @@ psa_status_t psa_pake_input( psa_pake_operation_t *operation,
operation->buffer,
operation->buffer_length );
mbedtls_platform_zeroize( operation->buffer, PSA_PAKE_BUFFER_SIZE );
mbedtls_platform_zeroize( operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE );
operation->buffer_length = 0;
if( ret != 0 )
{
psa_pake_abort( operation );
return( mbedtls_ecjpake_to_psa_error( ret ) );
}
}
else if( operation->state == PSA_PAKE_INPUT_X4S &&
operation->sequence == PSA_PAKE_X1_STEP_ZK_PROOF )
@@ -738,14 +745,11 @@ psa_status_t psa_pake_input( psa_pake_operation_t *operation,
operation->buffer,
operation->buffer_length );
mbedtls_platform_zeroize( operation->buffer, PSA_PAKE_BUFFER_SIZE );
mbedtls_platform_zeroize( operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE );
operation->buffer_length = 0;
if( ret != 0 )
{
psa_pake_abort( operation );
return( mbedtls_ecjpake_to_psa_error( ret ) );
}
}
if( ( operation->state == PSA_PAKE_INPUT_X1_X2 &&
@@ -767,6 +771,20 @@ psa_status_t psa_pake_input( psa_pake_operation_t *operation,
return( PSA_ERROR_NOT_SUPPORTED );
}
psa_status_t psa_pake_input( psa_pake_operation_t *operation,
psa_pake_step_t step,
const uint8_t *input,
size_t input_length )
{
psa_status_t status = psa_pake_input_internal(
operation, step, input, input_length );
if( status != PSA_SUCCESS )
psa_pake_abort( operation );
return( status );
}
psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation,
psa_key_derivation_operation_t *output)
{
@@ -784,7 +802,7 @@ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation,
{
ret = mbedtls_ecjpake_write_shared_key( &operation->ctx.ecjpake,
operation->buffer,
PSA_PAKE_BUFFER_SIZE,
MBEDTLS_PSA_PAKE_BUFFER_SIZE,
&operation->buffer_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE );
@@ -799,7 +817,7 @@ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation,
operation->buffer,
operation->buffer_length );
mbedtls_platform_zeroize( operation->buffer, PSA_PAKE_BUFFER_SIZE );
mbedtls_platform_zeroize( operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE );
psa_pake_abort( operation );
@@ -824,7 +842,7 @@ psa_status_t psa_pake_abort(psa_pake_operation_t * operation)
operation->output_step = PSA_PAKE_STEP_INVALID;
operation->password = MBEDTLS_SVC_KEY_ID_INIT;
operation->role = PSA_PAKE_ROLE_NONE;
mbedtls_platform_zeroize( operation->buffer, PSA_PAKE_BUFFER_SIZE );
mbedtls_platform_zeroize( operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE );
operation->buffer_length = 0;
operation->buffer_offset = 0;
mbedtls_ecjpake_free( &operation->ctx.ecjpake );

View File

@@ -655,9 +655,11 @@ int mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
MBEDTLS_PUT_UINT32_BE( ctx->state[5], output, 20 );
MBEDTLS_PUT_UINT32_BE( ctx->state[6], output, 24 );
int truncated = 0;
#if defined(MBEDTLS_SHA224_C)
if( ctx->is224 == 0 )
truncated = ctx->is224;
#endif
if( !truncated )
MBEDTLS_PUT_UINT32_BE( ctx->state[7], output, 28 );
return( 0 );

View File

@@ -810,9 +810,11 @@ int mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
sha512_put_uint64_be( ctx->state[4], output, 32 );
sha512_put_uint64_be( ctx->state[5], output, 40 );
int truncated = 0;
#if defined(MBEDTLS_SHA384_C)
if( ctx->is384 == 0 )
truncated = ctx->is384;
#endif
if( !truncated )
{
sha512_put_uint64_be( ctx->state[6], output, 48 );
sha512_put_uint64_be( ctx->state[7], output, 56 );

View File

@@ -370,9 +370,11 @@ static int ssl_write_client_hello_cipher_suites(
/*
* Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
*/
int renegotiating = 0;
#if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
renegotiating = ( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE );
#endif
if( !renegotiating )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) );
MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
@@ -608,7 +610,7 @@ static int ssl_write_client_hello_body( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
if(
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
( propose_tls13 && mbedtls_ssl_conf_tls13_ephemeral_enabled( ssl ) ) ||
@@ -623,7 +625,7 @@ static int ssl_write_client_hello_body( mbedtls_ssl_context *ssl,
return( ret );
p += output_len;
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( propose_tls12 )
@@ -637,8 +639,7 @@ static int ssl_write_client_hello_body( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/* The "pre_shared_key" extension (RFC 8446 Section 4.2.11)
* MUST be the last extension in the ClientHello.
*/
@@ -650,7 +651,7 @@ static int ssl_write_client_hello_body( mbedtls_ssl_context *ssl,
return( ret );
p += output_len;
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
/* Write the length of the list of extensions. */
extensions_len = p - p_extensions_len - 2;
@@ -812,9 +813,12 @@ static int ssl_prepare_client_hello( mbedtls_ssl_context *ssl )
* RFC 5077 section 3.4: "When presenting a ticket, the client MAY
* generate and include a Session ID in the TLS ClientHello."
*/
int renegotiating = 0;
#if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
renegotiating = 1;
#endif
if( !renegotiating )
{
if( ( session_negotiate->ticket != NULL ) &&
( session_negotiate->ticket_len != 0 ) )
@@ -957,8 +961,7 @@ int mbedtls_ssl_write_client_hello( mbedtls_ssl_context *ssl )
mbedtls_ssl_add_hs_hdr_to_checksum( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO,
msg_len );
ssl->handshake->update_checksum( ssl, buf, msg_len - binders_len );
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
if( binders_len > 0 )
{
MBEDTLS_SSL_PROC_CHK(
@@ -967,7 +970,7 @@ int mbedtls_ssl_write_client_hello( mbedtls_ssl_context *ssl )
ssl->handshake->update_checksum( ssl, buf + msg_len - binders_len,
binders_len );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg( ssl,
buf_len,

View File

@@ -38,8 +38,8 @@
#include <string.h>
/*
* If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is
* available. Try SHA-256 first, 512 wastes resources
* If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-384 is
* available. Try SHA-256 first, 384 wastes resources
*/
#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
#define COOKIE_MD MBEDTLS_MD_SHA224

View File

@@ -245,7 +245,7 @@
#define MBEDTLS_RECEIVED_SIG_ALGS_SIZE 20
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#define MBEDTLS_TLS_SIG_NONE MBEDTLS_TLS1_3_SIG_NONE
@@ -255,7 +255,7 @@
#define MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg >> 8)
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
/*
* Check that we obey the standard's message size bounds
@@ -600,8 +600,6 @@ struct mbedtls_ssl_handshake_params
size_t ecrs_n; /*!< place for saving a length */
#endif
size_t pmslen; /*!< premaster length */
mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
@@ -621,7 +619,7 @@ struct mbedtls_ssl_handshake_params
#if defined(MBEDTLS_SSL_SRV_C)
/** selected_group of key_share extension in HelloRetryRequest message. */
uint16_t hrr_selected_group;
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
@@ -631,7 +629,7 @@ struct mbedtls_ssl_handshake_params
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
uint16_t received_sig_algs[MBEDTLS_RECEIVED_SIG_ALGS_SIZE];
#endif
@@ -677,7 +675,7 @@ struct mbedtls_ssl_handshake_params
const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
mbedtls_svc_key_id_t psk_opaque; /*!< Opaque PSK from the callback */
uint8_t psk_opaque_is_internal;
@@ -686,7 +684,7 @@ struct mbedtls_ssl_handshake_params
size_t psk_len; /*!< Length of PSK from callback */
#endif /* MBEDTLS_USE_PSA_CRYPTO */
uint16_t selected_identity;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */
@@ -853,15 +851,18 @@ struct mbedtls_ssl_handshake_params
unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN +
MBEDTLS_SERVER_HELLO_RANDOM_LEN];
/*!< random bytes */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
unsigned char premaster[MBEDTLS_PREMASTER_SIZE];
/*!< premaster secret */
size_t pmslen; /*!< premaster length */
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
int extensions_present; /*!< extension presence; Each bitfield
represents an extension and defined
as \c MBEDTLS_SSL_EXT_XXX */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
unsigned char certificate_request_context_len;
unsigned char *certificate_request_context;
#endif
@@ -1365,11 +1366,13 @@ MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl,
mbedtls_key_exchange_type_t key_ex );
#endif /* !MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
#if defined(MBEDTLS_SSL_CLI_C)
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_conf_has_static_psk( mbedtls_ssl_config const *conf );
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* Get the first defined opaque PSK by order of precedence:
@@ -1422,7 +1425,7 @@ static inline int mbedtls_ssl_get_psk( const mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
#if defined(MBEDTLS_PK_C)
unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk );
@@ -1784,7 +1787,8 @@ static inline int mbedtls_ssl_conf_tls13_some_psk_enabled( mbedtls_ssl_context *
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL ) );
}
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_SRV_C) && \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/**
* Given a list of key exchange modes, check if at least one of them is
* supported.
@@ -1831,7 +1835,8 @@ static inline int mbedtls_ssl_tls13_some_psk_enabled( mbedtls_ssl_context *ssl )
return( ! mbedtls_ssl_tls13_check_kex_modes( ssl,
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL ) );
}
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_SRV_C &&
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
/*
* Helper functions to check the selected key exchange mode.
@@ -1871,7 +1876,7 @@ int mbedtls_ssl_tls13_fetch_handshake_msg( mbedtls_ssl_context *ssl,
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
/*
* Handler of TLS 1.3 write Certificate message
*/
@@ -1884,7 +1889,7 @@ int mbedtls_ssl_tls13_write_certificate( mbedtls_ssl_context *ssl );
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_tls13_write_certificate_verify( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
/*
* Generic handler of Certificate Verify
@@ -1914,7 +1919,7 @@ int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
/*
* Parse TLS Signature Algorithm extension
*/
@@ -1922,7 +1927,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_parse_sig_alg_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
const unsigned char *end );
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
/* Get handshake transcript */
MBEDTLS_CHECK_RETURN_CRITICAL
@@ -2042,7 +2047,7 @@ static inline int mbedtls_ssl_named_group_is_supported( uint16_t named_group )
static inline const void *mbedtls_ssl_get_sig_algs(
const mbedtls_ssl_context *ssl )
{
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
if( ssl->handshake != NULL &&
@@ -2054,17 +2059,14 @@ static inline const void *mbedtls_ssl_get_sig_algs(
#endif
return( ssl->conf->sig_algs );
#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#else /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
((void) ssl);
return( NULL );
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
static inline int mbedtls_ssl_sig_alg_is_received( const mbedtls_ssl_context *ssl,
uint16_t own_sig_alg )
{
@@ -2079,61 +2081,7 @@ static inline int mbedtls_ssl_sig_alg_is_received( const mbedtls_ssl_context *ss
}
return( 0 );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
static inline int mbedtls_ssl_sig_alg_is_offered( const mbedtls_ssl_context *ssl,
uint16_t proposed_sig_alg )
{
const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs( ssl );
if( sig_alg == NULL )
return( 0 );
for( ; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++ )
{
if( *sig_alg == proposed_sig_alg )
return( 1 );
}
return( 0 );
}
static inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(
uint16_t sig_alg, mbedtls_pk_type_t *pk_type, mbedtls_md_type_t *md_alg )
{
*pk_type = mbedtls_ssl_pk_alg_from_sig( sig_alg & 0xff );
*md_alg = mbedtls_ssl_md_alg_from_hash( ( sig_alg >> 8 ) & 0xff );
if( *pk_type != MBEDTLS_PK_NONE && *md_alg != MBEDTLS_MD_NONE )
return( 0 );
switch( sig_alg )
{
#if defined(MBEDTLS_PKCS1_V21)
#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:
*md_alg = MBEDTLS_MD_SHA256;
*pk_type = MBEDTLS_PK_RSASSA_PSS;
break;
#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:
*md_alg = MBEDTLS_MD_SHA384;
*pk_type = MBEDTLS_PK_RSASSA_PSS;
break;
#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:
*md_alg = MBEDTLS_MD_SHA512;
*pk_type = MBEDTLS_PK_RSASSA_PSS;
break;
#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
#endif /* MBEDTLS_PKCS1_V21 */
default:
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
return( 0 );
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
static inline int mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(
const uint16_t sig_alg )
{
@@ -2201,7 +2149,63 @@ static inline int mbedtls_ssl_tls13_sig_alg_is_supported(
return( 1 );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_tls13_check_sig_alg_cert_key_match( uint16_t sig_alg,
mbedtls_pk_context *key );
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
static inline int mbedtls_ssl_sig_alg_is_offered( const mbedtls_ssl_context *ssl,
uint16_t proposed_sig_alg )
{
const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs( ssl );
if( sig_alg == NULL )
return( 0 );
for( ; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++ )
{
if( *sig_alg == proposed_sig_alg )
return( 1 );
}
return( 0 );
}
static inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(
uint16_t sig_alg, mbedtls_pk_type_t *pk_type, mbedtls_md_type_t *md_alg )
{
*pk_type = mbedtls_ssl_pk_alg_from_sig( sig_alg & 0xff );
*md_alg = mbedtls_ssl_md_alg_from_hash( ( sig_alg >> 8 ) & 0xff );
if( *pk_type != MBEDTLS_PK_NONE && *md_alg != MBEDTLS_MD_NONE )
return( 0 );
switch( sig_alg )
{
#if defined(MBEDTLS_PKCS1_V21)
#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:
*md_alg = MBEDTLS_MD_SHA256;
*pk_type = MBEDTLS_PK_RSASSA_PSS;
break;
#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:
*md_alg = MBEDTLS_MD_SHA384;
*pk_type = MBEDTLS_PK_RSASSA_PSS;
break;
#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:
*md_alg = MBEDTLS_MD_SHA512;
*pk_type = MBEDTLS_PK_RSASSA_PSS;
break;
#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
#endif /* MBEDTLS_PKCS1_V21 */
default:
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
return( 0 );
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
static inline int mbedtls_ssl_tls12_sig_alg_is_supported(
@@ -2279,26 +2283,17 @@ static inline int mbedtls_ssl_sig_alg_is_supported(
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
if( ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 )
{
return( mbedtls_ssl_tls13_sig_alg_is_supported( sig_alg ) );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#endif
((void) ssl);
((void) sig_alg);
return( 0 );
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_tls13_check_sig_alg_cert_key_match( uint16_t sig_alg,
mbedtls_pk_context *key );
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* Corresponding PSA algorithm for MBEDTLS_CIPHER_NULL.
@@ -2459,7 +2454,7 @@ int mbedtls_ssl_check_dtls_clihlo_cookie(
unsigned char *obuf, size_t buf_len, size_t *olen );
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/**
* \brief Given an SSL context and its associated configuration, write the TLS
* 1.3 specific Pre-Shared key extension.
@@ -2492,7 +2487,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(
mbedtls_ssl_context *ssl,
unsigned char *buf, unsigned char *end );
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
defined(MBEDTLS_SSL_SESSION_TICKETS) && \

View File

@@ -1665,15 +1665,15 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
/*
* The next two sizes are the minimum and maximum values of
* data_len over all padlen values.
*
* They're independent of padlen, since we previously did
* data_len -= padlen.
*
* Note that max_len + maclen is never more than the buffer
* length, as we previously did in_msglen -= maclen too.
*/
* The next two sizes are the minimum and maximum values of
* data_len over all padlen values.
*
* They're independent of padlen, since we previously did
* data_len -= padlen.
*
* Note that max_len + maclen is never more than the buffer
* length, as we previously did in_msglen -= maclen too.
*/
const size_t max_len = rec->data_len + padlen;
const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
@@ -3847,8 +3847,8 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
if( ssl_record_is_in_progress( ssl ) == 0 )
{
int dtls_have_buffered = 0;
#if defined(MBEDTLS_SSL_PROTO_DTLS)
int have_buffered = 0;
/* We only check for buffered messages if the
* current datagram is fully consumed. */
@@ -3856,11 +3856,11 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
ssl_next_record_is_in_datagram( ssl ) == 0 )
{
if( ssl_load_buffered_message( ssl ) == 0 )
have_buffered = 1;
dtls_have_buffered = 1;
}
if( have_buffered == 0 )
#endif /* MBEDTLS_SSL_PROTO_DTLS */
if( dtls_have_buffered == 0 )
{
ret = ssl_get_next_record( ssl );
if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )

View File

@@ -604,6 +604,12 @@ static void ssl_update_checksum_start( mbedtls_ssl_context *ssl,
mbedtls_sha512_update( &ssl->handshake->fin_sha384, buf, len );
#endif
#endif
#if !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
!defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
(void) ssl;
(void) buf;
(void) len;
#endif
}
#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
@@ -837,7 +843,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
/* Heap allocate and translate sig_hashes from internal hash identifiers to
@@ -903,7 +909,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl )
ssl->handshake->sig_algs_heap_allocated = 0;
}
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
return( 0 );
}
@@ -1006,6 +1012,30 @@ static int ssl_conf_check(const mbedtls_ssl_context *ssl)
if( ret != 0 )
return( ret );
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* RFC 8446 section 4.4.3
*
* If the verification fails, the receiver MUST terminate the handshake with
* a "decrypt_error" alert.
*
* If the client is configured as TLS 1.3 only with optional verify, return
* bad config.
*
*/
if( mbedtls_ssl_conf_tls13_ephemeral_enabled(
(mbedtls_ssl_context *)ssl ) &&
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
ssl->conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
ssl->conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
ssl->conf->authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
{
MBEDTLS_SSL_DEBUG_MSG(
1, ( "Optional verify auth mode "
"is not available for TLS 1.3 client" ) );
return( MBEDTLS_ERR_SSL_BAD_CONFIG );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
/* Space for further checks */
return( 0 );
@@ -1218,9 +1248,11 @@ int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
int free_cli_id = 1;
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
if( partial == 0 )
free_cli_id = ( partial == 0 );
#endif
if( free_cli_id )
{
mbedtls_free( ssl->cli_id );
ssl->cli_id = NULL;
@@ -1419,6 +1451,14 @@ void mbedtls_ssl_conf_tls13_key_exchange_modes( mbedtls_ssl_config *conf,
{
conf->tls13_kex_modes = kex_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL;
}
#if defined(MBEDTLS_SSL_EARLY_DATA)
void mbedtls_ssl_tls13_conf_early_data( mbedtls_ssl_config *conf,
int early_data_enabled )
{
conf->early_data_enabled = early_data_enabled;
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -1593,16 +1633,21 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_psk_is_configured( mbedtls_ssl_config const *conf )
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
int mbedtls_ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
{
if( conf->psk_identity == NULL ||
conf->psk_identity_len == 0 )
{
return( 0 );
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( !mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
return( 1 );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( conf->psk != NULL )
if( conf->psk != NULL && conf->psk_len != 0 )
return( 1 );
return( 0 );
@@ -1648,6 +1693,7 @@ static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf,
{
/* Identity len will be encoded on two bytes */
if( psk_identity == NULL ||
psk_identity_len == 0 ||
( psk_identity_len >> 16 ) != 0 ||
psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
@@ -1671,7 +1717,7 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* We currently only support one PSK, raw or opaque. */
if( ssl_conf_psk_is_configured( conf ) )
if( mbedtls_ssl_conf_has_static_psk( conf ) )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
/* Check and set raw PSK */
@@ -1789,7 +1835,7 @@ int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* We currently only support one PSK, raw or opaque. */
if( ssl_conf_psk_is_configured( conf ) )
if( mbedtls_ssl_conf_has_static_psk( conf ) )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
/* Check and set opaque PSK */
@@ -1830,7 +1876,7 @@ void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf,
}
#endif /* MBEDTLS_SSL_SRV_C */
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode(
@@ -2383,7 +2429,7 @@ void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf,
}
#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
/*
* Set allowed/preferred hashes for handshake signatures
@@ -2404,7 +2450,7 @@ void mbedtls_ssl_conf_sig_algs( mbedtls_ssl_config *conf,
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
conf->sig_algs = sig_algs;
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_ECP_C)
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
@@ -3575,7 +3621,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
if ( ssl->handshake->sig_algs_heap_allocated )
mbedtls_free( (void*) handshake->sig_algs );
@@ -3587,7 +3633,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
mbedtls_free( (void*) handshake->certificate_request_context );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 )
@@ -3633,7 +3679,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
mbedtls_free( (void *) handshake->curves );
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
{
@@ -3653,7 +3699,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
mbedtls_free( handshake->psk );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@@ -4046,6 +4092,9 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
const unsigned char * const end = buf + len;
size_t session_len;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
tls_prf_fn prf_func = NULL;
#endif
/*
* The context should have been freshly setup or reset.
@@ -4131,17 +4180,22 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
ssl->transform_out = ssl->transform;
ssl->transform_negotiate = NULL;
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
prf_func = ssl_tls12prf_from_cs( ssl->session->ciphersuite );
if( prf_func == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
/* Read random bytes and populate structure */
if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
ret = ssl_tls12_populate_transform( ssl->transform,
ssl->session->ciphersuite,
ssl->session->master,
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
ssl->session->encrypt_then_mac,
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
ssl_tls12prf_from_cs( ssl->session->ciphersuite ),
prf_func,
p, /* currently pointing to randbytes */
MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */
ssl->conf->endpoint,
@@ -4445,7 +4499,7 @@ static int ssl_preset_suiteb_ciphersuites[] = {
0
};
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
/* NOTICE:
* For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following
@@ -4590,7 +4644,7 @@ static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = {
};
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
static uint16_t ssl_preset_suiteb_groups[] = {
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
@@ -4602,7 +4656,7 @@ static uint16_t ssl_preset_suiteb_groups[] = {
MBEDTLS_SSL_IANA_TLS_GROUP_NONE
};
#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs`
* to make sure there are no duplicated signature algorithm entries. */
MBEDTLS_CHECK_RETURN_CRITICAL
@@ -4626,7 +4680,7 @@ static int ssl_check_no_sig_alg_duplication( uint16_t * sig_algs )
return( ret );
}
#endif /* MBEDTLS_DEBUG_C && MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
/*
* Load default in mbedtls_ssl_config
@@ -4638,7 +4692,7 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#endif
#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
if( ssl_check_no_sig_alg_duplication( ssl_preset_suiteb_sig_algs ) )
{
mbedtls_printf( "ssl_preset_suiteb_sig_algs has duplicated entries\n" );
@@ -4664,7 +4718,7 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
#endif /* MBEDTLS_DEBUG_C && MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
/* Use the functions here so that they are covered in tests,
* but otherwise access member directly for efficiency */
@@ -4795,14 +4849,14 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
conf->cert_profile = &mbedtls_x509_crt_profile_suiteb;
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( mbedtls_ssl_conf_is_tls12_only( conf ) )
conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs;
else
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
conf->sig_algs = ssl_preset_suiteb_sig_algs;
#endif
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
conf->curve_list = NULL;
@@ -4821,14 +4875,14 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
conf->cert_profile = &mbedtls_x509_crt_profile_default;
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( mbedtls_ssl_conf_is_tls12_only( conf ) )
conf->sig_algs = ssl_tls12_preset_default_sig_algs;
else
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
conf->sig_algs = ssl_preset_default_sig_algs;
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
conf->curve_list = NULL;
@@ -4853,7 +4907,7 @@ void mbedtls_ssl_config_free( mbedtls_ssl_config *conf )
mbedtls_mpi_free( &conf->dhm_G );
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
{
@@ -4875,7 +4929,7 @@ void mbedtls_ssl_config_free( mbedtls_ssl_config *conf )
conf->psk_identity = NULL;
conf->psk_identity_len = 0;
}
#endif
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
ssl_key_cert_free( conf->key_cert );
@@ -5157,6 +5211,10 @@ int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
goto exit;
exit:
#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
!defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
(void) ssl;
#endif
return( psa_ssl_status_to_mbedtls( status ) );
}
#else /* MBEDTLS_USE_PSA_CRYPTO */
@@ -5243,6 +5301,13 @@ int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
default:
#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
!defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
(void) ssl;
(void) dst;
(void) dst_len;
(void) olen;
#endif
break;
}
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
@@ -5250,7 +5315,7 @@ int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
#endif /* !MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
/* mbedtls_ssl_parse_sig_alg_ext()
*
* The `extension_data` field of signature algorithm contains a `SignatureSchemeList`
@@ -5358,7 +5423,7 @@ int mbedtls_ssl_parse_sig_alg_ext( mbedtls_ssl_context *ssl,
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
@@ -5429,6 +5494,8 @@ static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* de
return( PSA_SUCCESS );
}
#if defined(PSA_WANT_ALG_SHA_384) || \
defined(PSA_WANT_ALG_SHA_256)
MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_generic( mbedtls_md_type_t md_type,
const unsigned char *secret, size_t slen,
@@ -5503,9 +5570,12 @@ static int tls_prf_generic( mbedtls_md_type_t md_type,
return( 0 );
}
#endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */
#else /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_MD_C) && \
( defined(MBEDTLS_SHA256_C) || \
defined(MBEDTLS_SHA384_C) )
MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_generic( mbedtls_md_type_t md_type,
const unsigned char *secret, size_t slen,
@@ -5589,13 +5659,16 @@ static int tls_prf_generic( mbedtls_md_type_t md_type,
exit:
mbedtls_md_free( &md_ctx );
mbedtls_platform_zeroize( tmp, tmp_len );
if ( tmp != NULL )
mbedtls_platform_zeroize( tmp, tmp_len );
mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
mbedtls_free( tmp );
return( ret );
}
#endif /* MBEDTLS_MD_C && ( MBEDTLS_SHA256_C || MBEDTLS_SHA384_C ) */
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
@@ -5909,7 +5982,10 @@ int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md )
default:
return( -1 );
}
#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
!defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
(void) ssl;
#endif
return( 0 );
}
@@ -7430,16 +7506,25 @@ exit:
*/
static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id )
{
#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
if( ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
return( tls_prf_sha384 );
#else
(void) ciphersuite_id;
else
#endif
return( tls_prf_sha256 );
#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
{
if( ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256 )
return( tls_prf_sha256 );
}
#endif
#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
!defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
(void) ciphersuite_info;
#endif
return( NULL );
}
#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
@@ -7676,11 +7761,16 @@ static int ssl_tls12_populate_transform( mbedtls_ssl_transform *transform,
* sequence number).
*/
transform->ivlen = 12;
int is_chachapoly = 0;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( key_type == PSA_KEY_TYPE_CHACHA20 )
is_chachapoly = ( key_type == PSA_KEY_TYPE_CHACHA20 );
#else
if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CHACHAPOLY )
is_chachapoly = ( mbedtls_cipher_info_get_mode( cipher_info )
== MBEDTLS_MODE_CHACHAPOLY );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( is_chachapoly )
transform->fixed_ivlen = 12;
else
transform->fixed_ivlen = 4;
@@ -8550,7 +8640,7 @@ int mbedtls_ssl_validate_ciphersuite(
return( 0 );
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
/*
* Function for writing a signature algorithm extension.
*
@@ -8653,7 +8743,7 @@ int mbedtls_ssl_write_sig_alg_ext( mbedtls_ssl_context *ssl, unsigned char *buf,
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
/*

View File

@@ -49,27 +49,6 @@
#include "hash_info.h"
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
int mbedtls_ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
{
if( conf->psk_identity == NULL ||
conf->psk_identity_len == 0 )
{
return( 0 );
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
return( 1 );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( conf->psk != NULL && conf->psk_len != 0 )
return( 1 );
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_RENEGOTIATION)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
@@ -1771,10 +1750,10 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
unsigned char **p,
@@ -1839,7 +1818,15 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
#else
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
{
@@ -1869,6 +1856,15 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
unsigned char **p,
@@ -1904,11 +1900,10 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
return( ret );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || \
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
#endif /* !MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
@@ -2465,9 +2460,11 @@ start_processing:
if( ret != 0 )
{
int send_alert_msg = 1;
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
send_alert_msg = ( ret != MBEDTLS_ERR_ECP_IN_PROGRESS );
#endif
if( send_alert_msg )
mbedtls_ssl_send_alert_message(
ssl,
MBEDTLS_SSL_ALERT_LEVEL_FATAL,

View File

@@ -708,11 +708,13 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
#endif
list = ssl->conf->key_cert;
int pk_alg_is_none = 0;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( pk_alg == PSA_ALG_NONE )
pk_alg_is_none = ( pk_alg == PSA_ALG_NONE );
#else
if( pk_alg == MBEDTLS_PK_NONE )
pk_alg_is_none = ( pk_alg == MBEDTLS_PK_NONE );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( pk_alg_is_none )
return( 0 );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) );
@@ -729,18 +731,21 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
cur->cert );
int key_type_matches = 0;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ( ssl->conf->f_async_sign_start == NULL &&
ssl->conf->f_async_decrypt_start == NULL &&
! mbedtls_pk_can_do_ext( cur->key, pk_alg, pk_usage ) ) ||
! mbedtls_pk_can_do_ext( &cur->cert->pk, pk_alg, pk_usage ) )
key_type_matches = ( ( ssl->conf->f_async_sign_start != NULL ||
ssl->conf->f_async_decrypt_start != NULL ||
mbedtls_pk_can_do_ext( cur->key, pk_alg, pk_usage ) ) &&
mbedtls_pk_can_do_ext( &cur->cert->pk, pk_alg, pk_usage ) );
#else
if( ! mbedtls_pk_can_do_ext( cur->key, pk_alg, pk_usage ) )
key_type_matches = (
mbedtls_pk_can_do_ext( cur->key, pk_alg, pk_usage ) );
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#else
if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) )
key_type_matches = mbedtls_pk_can_do( &cur->cert->pk, pk_alg );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( !key_type_matches )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
continue;
@@ -917,6 +922,8 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
int renegotiating;
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
read_record_header:
#endif
@@ -925,9 +932,11 @@ read_record_header:
* otherwise read it ourselves manually in order to support SSLv2
* ClientHello, which doesn't use the same record layer format.
*/
renegotiating = 0;
#if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
renegotiating = ( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE );
#endif
if( !renegotiating )
{
if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 )
{

View File

@@ -210,6 +210,7 @@ static int ssl_tls13_reset_key_share( mbedtls_ssl_context *ssl )
/*
* Functions for writing key_share extension.
*/
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_get_default_group_id( mbedtls_ssl_context *ssl,
uint16_t *group_id )
@@ -364,7 +365,7 @@ cleanup:
return( ret );
}
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
/*
* ssl_tls13_parse_hrr_key_share_ext()
@@ -379,6 +380,7 @@ static int ssl_tls13_parse_hrr_key_share_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
const unsigned char *end )
{
#if defined(MBEDTLS_ECDH_C)
const mbedtls_ecp_curve_info *curve_info = NULL;
const unsigned char *p = buf;
int selected_group;
@@ -435,6 +437,12 @@ static int ssl_tls13_parse_hrr_key_share_ext( mbedtls_ssl_context *ssl,
ssl->handshake->offered_group_id = selected_group;
return( 0 );
#else
(void) ssl;
(void) buf;
(void) end;
return( MBEDTLS_ERR_SSL_BAD_CONFIG );
#endif
}
/*
@@ -595,7 +603,7 @@ static int ssl_tls13_write_cookie_ext( mbedtls_ssl_context *ssl,
return( 0 );
}
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/*
* ssl_tls13_write_psk_key_exchange_modes_ext() structure:
*
@@ -640,14 +648,6 @@ static int ssl_tls13_write_psk_key_exchange_modes_ext( mbedtls_ssl_context *ssl,
*/
p += 5;
if( mbedtls_ssl_conf_tls13_psk_enabled( ssl ) )
{
*p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE;
ke_modes_len++;
MBEDTLS_SSL_DEBUG_MSG( 4, ( "Adding pure PSK key exchange mode" ) );
}
if( mbedtls_ssl_conf_tls13_psk_ephemeral_enabled( ssl ) )
{
*p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE;
@@ -656,6 +656,14 @@ static int ssl_tls13_write_psk_key_exchange_modes_ext( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_MSG( 4, ( "Adding PSK-ECDHE key exchange mode" ) );
}
if( mbedtls_ssl_conf_tls13_psk_enabled( ssl ) )
{
*p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE;
ke_modes_len++;
MBEDTLS_SSL_DEBUG_MSG( 4, ( "Adding pure PSK key exchange mode" ) );
}
/* Now write the extension and ke_modes length */
MBEDTLS_PUT_UINT16_BE( ke_modes_len + 1, buf, 2 );
buf[4] = ke_modes_len;
@@ -721,11 +729,6 @@ static int ssl_tls13_ticket_get_psk( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
static int ssl_tls13_has_configured_psk( const mbedtls_ssl_config *conf )
{
return( conf->psk != NULL && conf->psk_identity != NULL );
}
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_psk_get_identity( mbedtls_ssl_context *ssl,
psa_algorithm_t *hash_alg,
@@ -733,7 +736,7 @@ static int ssl_tls13_psk_get_identity( mbedtls_ssl_context *ssl,
size_t *identity_len )
{
if( !ssl_tls13_has_configured_psk( ssl->conf ) )
if( ! mbedtls_ssl_conf_has_static_psk( ssl->conf ) )
return( -1 );
*hash_alg = PSA_ALG_SHA_256;
@@ -749,7 +752,7 @@ static int ssl_tls13_psk_get_psk( mbedtls_ssl_context *ssl,
size_t *psk_len )
{
if( !ssl_tls13_has_configured_psk( ssl->conf ) )
if( ! mbedtls_ssl_conf_has_static_psk( ssl->conf ) )
return( -1 );
*hash_alg = PSA_ALG_SHA_256;
@@ -768,7 +771,7 @@ static int ssl_tls13_get_configured_psk_count( mbedtls_ssl_context *ssl )
configured_psk_count++;
}
#endif
if( ssl_tls13_has_configured_psk( ssl->conf ) )
if( mbedtls_ssl_conf_has_static_psk( ssl->conf ) )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK is configured" ) );
configured_psk_count++;
@@ -1087,7 +1090,7 @@ static int ssl_tls13_parse_server_pre_shared_key_ext( mbedtls_ssl_context *ssl,
}
else
#endif
if( ssl_tls13_has_configured_psk( ssl->conf ) )
if( mbedtls_ssl_conf_has_static_psk( ssl->conf ) )
{
ret = ssl_tls13_psk_get_psk( ssl, &hash_alg, &psk, &psk_len );
}
@@ -1110,8 +1113,7 @@ static int ssl_tls13_parse_server_pre_shared_key_ext( mbedtls_ssl_context *ssl,
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl,
unsigned char *buf,
@@ -1141,6 +1143,7 @@ int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl,
return( ret );
p += ext_len;
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
if( mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) )
{
ret = ssl_tls13_write_key_share_ext( ssl, p, end, &ext_len );
@@ -1148,8 +1151,9 @@ int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl,
return( ret );
p += ext_len;
}
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/* For PSK-based key exchange we need the pre_shared_key extension
* and the psk_key_exchange_modes extension.
*
@@ -1163,7 +1167,7 @@ int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl,
if( ret != 0 )
return( ret );
p += ext_len;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif
*out_len = p - buf;
@@ -1679,7 +1683,7 @@ static int ssl_tls13_parse_server_hello( mbedtls_ssl_context *ssl,
goto cleanup;
break;
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found pre_shared_key extension" ) );
if( is_hrr )
@@ -1696,7 +1700,7 @@ static int ssl_tls13_parse_server_hello( mbedtls_ssl_context *ssl,
return( ret );
}
break;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif
case MBEDTLS_TLS_EXT_KEY_SHARE:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found key_shares extension" ) );
@@ -2063,7 +2067,7 @@ static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl )
mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
buf, buf_len );
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
if( mbedtls_ssl_tls13_key_exchange_mode_with_psk( ssl ) )
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
else
@@ -2080,7 +2084,7 @@ cleanup:
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
/*
* STATE HANDLING: CertificateRequest
*
@@ -2317,7 +2321,7 @@ static int ssl_tls13_process_certificate_verify( mbedtls_ssl_context *ssl )
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
/*
* Handler for MBEDTLS_SSL_SERVER_FINISHED
@@ -2363,7 +2367,7 @@ static int ssl_tls13_write_client_certificate( mbedtls_ssl_context *ssl )
( "Switch to handshake traffic keys for outbound traffic" ) );
mbedtls_ssl_set_outbound_transform( ssl, ssl->handshake->transform_handshake );
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
if( ssl->handshake->client_auth )
{
int ret = mbedtls_ssl_tls13_write_certificate( ssl );
@@ -2393,7 +2397,7 @@ static int ssl_tls13_write_client_certificate( mbedtls_ssl_context *ssl )
return( 0 );
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
/*
* Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY
*/
@@ -2407,7 +2411,7 @@ static int ssl_tls13_write_client_certificate_verify( mbedtls_ssl_context *ssl )
return( ret );
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
/*
* Handler for MBEDTLS_SSL_CLIENT_FINISHED
@@ -2720,7 +2724,7 @@ int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl )
ret = ssl_tls13_process_encrypted_extensions( ssl );
break;
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
case MBEDTLS_SSL_CERTIFICATE_REQUEST:
ret = ssl_tls13_process_certificate_request( ssl );
break;
@@ -2732,7 +2736,7 @@ int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl )
case MBEDTLS_SSL_CERTIFICATE_VERIFY:
ret = ssl_tls13_process_certificate_verify( ssl );
break;
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
case MBEDTLS_SSL_SERVER_FINISHED:
ret = ssl_tls13_process_server_finished( ssl );
@@ -2742,11 +2746,11 @@ int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl )
ret = ssl_tls13_write_client_certificate( ssl );
break;
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:
ret = ssl_tls13_write_client_certificate_verify( ssl );
break;
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
case MBEDTLS_SSL_CLIENT_FINISHED:
ret = ssl_tls13_write_client_finished( ssl );

View File

@@ -83,7 +83,7 @@ cleanup:
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
/*
* STATE HANDLING: Read CertificateVerify
*/
@@ -285,12 +285,12 @@ error:
return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
int mbedtls_ssl_tls13_process_certificate_verify( mbedtls_ssl_context *ssl )
{
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE];
size_t verify_buffer_len;
@@ -348,7 +348,7 @@ cleanup:
((void) ssl);
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
}
/*
@@ -357,7 +357,7 @@ cleanup:
*
*/
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
/*
* Structure of Certificate message:
@@ -534,9 +534,9 @@ int mbedtls_ssl_tls13_parse_certificate( mbedtls_ssl_context *ssl,
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
/* Validate certificate chain sent by the server. */
MBEDTLS_CHECK_RETURN_CRITICAL
@@ -727,14 +727,14 @@ static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
unsigned char *buf;
size_t buf_len;
@@ -752,12 +752,12 @@ int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl )
buf, buf_len );
cleanup:
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
/*
* enum {
* X509(0),
@@ -1078,7 +1078,7 @@ cleanup:
return( ret );
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
/*
*

View File

@@ -331,9 +331,12 @@ int mbedtls_ssl_tls13_evolve_secret(
int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
size_t hlen, ilen;
size_t hlen;
unsigned char tmp_secret[ PSA_MAC_MAX_SIZE ] = { 0 };
unsigned char tmp_input [ MBEDTLS_ECP_MAX_BYTES ] = { 0 };
const unsigned char all_zeroes_input[ MBEDTLS_TLS1_3_MD_MAX_SIZE ] = { 0 };
const unsigned char *l_input = NULL;
size_t l_input_len;
psa_key_derivation_operation_t operation =
PSA_KEY_DERIVATION_OPERATION_INIT;
@@ -361,12 +364,13 @@ int mbedtls_ssl_tls13_evolve_secret(
if( input != NULL && input_len != 0 )
{
memcpy( tmp_input, input, input_len );
ilen = input_len;
l_input = input;
l_input_len = input_len;
}
else
{
ilen = hlen;
l_input = all_zeroes_input;
l_input_len = hlen;
}
status = psa_key_derivation_setup( &operation,
@@ -385,8 +389,7 @@ int mbedtls_ssl_tls13_evolve_secret(
status = psa_key_derivation_input_bytes( &operation,
PSA_KEY_DERIVATION_INPUT_SECRET,
tmp_input,
ilen );
l_input, l_input_len );
if( status != PSA_SUCCESS )
goto cleanup;
@@ -403,7 +406,6 @@ int mbedtls_ssl_tls13_evolve_secret(
status = ( status == PSA_SUCCESS ? abort_status : status );
ret = ( ret == 0 ? psa_ssl_status_to_mbedtls ( status ) : ret );
mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) );
mbedtls_platform_zeroize( tmp_input, sizeof(tmp_input) );
return( ret );
}
@@ -1065,7 +1067,7 @@ int mbedtls_ssl_tls13_key_schedule_stage_early( mbedtls_ssl_context *ssl )
}
hash_alg = mbedtls_hash_info_psa_from_md( handshake->ciphersuite_info->mac );
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
if( mbedtls_ssl_tls13_key_exchange_mode_with_psk( ssl ) )
{
ret = mbedtls_ssl_tls13_export_handshake_psk( ssl, &psk, &psk_len );
@@ -1081,7 +1083,7 @@ int mbedtls_ssl_tls13_key_schedule_stage_early( mbedtls_ssl_context *ssl )
ret = mbedtls_ssl_tls13_evolve_secret( hash_alg, NULL, psk, psk_len,
handshake->tls13_master_secrets.early );
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
mbedtls_free( (void*)psk );
#endif
if( ret != 0 )
@@ -1248,14 +1250,13 @@ exit:
int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) && defined(MBEDTLS_ECDH_C)
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED && MBEDTLS_ECDH_C */
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
psa_algorithm_t const hash_alg = mbedtls_hash_info_psa_from_md(
handshake->ciphersuite_info->mac );
unsigned char *shared_secret = NULL;
size_t shared_secret_len = 0;
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
/*
* Compute ECDHE secret used to compute the handshake secret from which
* client_handshake_traffic_secret and server_handshake_traffic_secret
@@ -1267,60 +1268,75 @@ int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl )
{
#if defined(MBEDTLS_ECDH_C)
/* Compute ECDH shared secret. */
status = psa_raw_key_agreement(
PSA_ALG_ECDH, handshake->ecdh_psa_privkey,
handshake->ecdh_psa_peerkey, handshake->ecdh_psa_peerkey_len,
handshake->premaster, sizeof( handshake->premaster ),
&handshake->pmslen );
if( status != PSA_SUCCESS )
{
ret = psa_ssl_status_to_mbedtls( status );
MBEDTLS_SSL_DEBUG_RET( 1, "psa_raw_key_agreement", ret );
return( ret );
}
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
status = psa_destroy_key( handshake->ecdh_psa_privkey );
if( status != PSA_SUCCESS )
{
ret = psa_ssl_status_to_mbedtls( status );
MBEDTLS_SSL_DEBUG_RET( 1, "psa_destroy_key", ret );
return( ret );
}
status = psa_get_key_attributes( handshake->ecdh_psa_privkey,
&key_attributes );
if( status != PSA_SUCCESS )
ret = psa_ssl_status_to_mbedtls( status );
handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
shared_secret_len = PSA_BITS_TO_BYTES(
psa_get_key_bits( &key_attributes ) );
shared_secret = mbedtls_calloc( 1, shared_secret_len );
if( shared_secret == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
status = psa_raw_key_agreement(
PSA_ALG_ECDH, handshake->ecdh_psa_privkey,
handshake->ecdh_psa_peerkey, handshake->ecdh_psa_peerkey_len,
shared_secret, shared_secret_len, &shared_secret_len );
if( status != PSA_SUCCESS )
{
ret = psa_ssl_status_to_mbedtls( status );
MBEDTLS_SSL_DEBUG_RET( 1, "psa_raw_key_agreement", ret );
goto cleanup;
}
status = psa_destroy_key( handshake->ecdh_psa_privkey );
if( status != PSA_SUCCESS )
{
ret = psa_ssl_status_to_mbedtls( status );
MBEDTLS_SSL_DEBUG_RET( 1, "psa_destroy_key", ret );
goto cleanup;
}
handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
#endif /* MBEDTLS_ECDH_C */
}
else if( mbedtls_ssl_tls13_named_group_is_dhe( handshake->offered_group_id ) )
else
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHE not supported." ) );
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Group not supported." ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
}
#else
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
/*
* Compute the Handshake Secret
*/
ret = mbedtls_ssl_tls13_evolve_secret( hash_alg,
handshake->tls13_master_secrets.early,
handshake->premaster, handshake->pmslen,
shared_secret, shared_secret_len,
handshake->tls13_master_secrets.handshake );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_evolve_secret", ret );
return( ret );
goto cleanup;
}
MBEDTLS_SSL_DEBUG_BUF( 4, "Handshake secret",
handshake->tls13_master_secrets.handshake,
PSA_HASH_LENGTH( hash_alg ) );
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
mbedtls_platform_zeroize( handshake->premaster, sizeof( handshake->premaster ) );
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */
return( 0 );
cleanup:
if( shared_secret != NULL )
{
mbedtls_platform_zeroize( shared_secret, shared_secret_len );
mbedtls_free( shared_secret );
}
return( ret );
}
/* Generate application traffic keys since any records following a 1-RTT Finished message
@@ -1598,7 +1614,7 @@ cleanup:
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
int mbedtls_ssl_tls13_export_handshake_psk( mbedtls_ssl_context *ssl,
unsigned char **psk,
size_t *psk_len )
@@ -1639,7 +1655,7 @@ int mbedtls_ssl_tls13_export_handshake_psk( mbedtls_ssl_context *ssl,
return( 0 );
#endif /* !MBEDTLS_USE_PSA_CRYPTO */
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */

View File

@@ -691,7 +691,7 @@ int mbedtls_ssl_tls13_compute_handshake_transform( mbedtls_ssl_context *ssl );
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_tls13_compute_application_transform( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/**
* \brief Export TLS 1.3 PSK from handshake context
*
@@ -707,7 +707,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_tls13_export_handshake_psk( mbedtls_ssl_context *ssl,
unsigned char **psk,
size_t *psk_len );
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */

View File

@@ -59,7 +59,7 @@ static const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite(
return( ciphersuite_info );
}
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/* From RFC 8446:
*
* enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
@@ -674,11 +674,13 @@ static int ssl_tls13_write_server_pre_shared_key_ext( mbedtls_ssl_context *ssl,
*olen = 0;
int not_using_psk = 0;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
not_using_psk = ( mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) );
#else
if( ssl->handshake->psk == NULL )
not_using_psk = ( ssl->handshake->psk == NULL );
#endif
if( not_using_psk )
{
/* We shouldn't have called this extension writer unless we've
* chosen to use a PSK. */
@@ -701,7 +703,7 @@ static int ssl_tls13_write_server_pre_shared_key_ext( mbedtls_ssl_context *ssl,
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
/* From RFC 8446:
* struct {
@@ -993,7 +995,7 @@ static int ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(
MBEDTLS_SSL_EXT_SIG_ALG ) );
}
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_client_hello_has_exts_for_psk_key_exchange(
mbedtls_ssl_context *ssl )
@@ -1015,7 +1017,7 @@ static int ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(
MBEDTLS_SSL_EXT_PRE_SHARED_KEY |
MBEDTLS_SSL_EXT_PSK_KEY_EXCHANGE_MODES ) );
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_check_ephemeral_key_exchange( mbedtls_ssl_context *ssl )
@@ -1027,7 +1029,7 @@ static int ssl_tls13_check_ephemeral_key_exchange( mbedtls_ssl_context *ssl )
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_check_psk_key_exchange( mbedtls_ssl_context *ssl )
{
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
return( mbedtls_ssl_conf_tls13_psk_enabled( ssl ) &&
mbedtls_ssl_tls13_psk_enabled( ssl ) &&
ssl_tls13_client_hello_has_exts_for_psk_key_exchange( ssl ) );
@@ -1040,7 +1042,7 @@ static int ssl_tls13_check_psk_key_exchange( mbedtls_ssl_context *ssl )
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_check_psk_ephemeral_key_exchange( mbedtls_ssl_context *ssl )
{
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
return( mbedtls_ssl_conf_tls13_psk_ephemeral_enabled( ssl ) &&
mbedtls_ssl_tls13_psk_ephemeral_enabled( ssl ) &&
ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange( ssl ) );
@@ -1104,7 +1106,7 @@ static int ssl_tls13_determine_key_exchange_mode( mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
static psa_algorithm_t ssl_tls13_iana_sig_alg_to_psa_alg( uint16_t sig_alg )
@@ -1229,7 +1231,7 @@ static int ssl_tls13_pick_key_cert( mbedtls_ssl_context *ssl )
return( -1 );
}
#endif /* MBEDTLS_X509_CRT_PARSE_C &&
MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
/*
*
@@ -1289,11 +1291,11 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
const unsigned char *extensions_end;
int hrr_required = 0;
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
const unsigned char *cipher_suites;
const unsigned char *pre_shared_key_ext = NULL;
const unsigned char *pre_shared_key_ext_end = NULL;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif
ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
@@ -1400,7 +1402,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
* with CipherSuite defined as:
* uint8 CipherSuite[2];
*/
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
cipher_suites = p;
#endif
cipher_suites_end = p + cipher_suites_len;
@@ -1581,7 +1583,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS;
break;
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found psk key exchange modes extension" ) );
@@ -1596,7 +1598,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_PSK_KEY_EXCHANGE_MODES;
break;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif
case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found pre_shared_key extension" ) );
@@ -1608,14 +1610,14 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
}
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/* Delay processing of the PSK identity once we have
* found out which algorithms to use. We keep a pointer
* to the buffer and the size for later processing.
*/
pre_shared_key_ext = p;
pre_shared_key_ext_end = extension_data_end;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif
ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_PRE_SHARED_KEY;
break;
@@ -1634,7 +1636,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
break;
#endif /* MBEDTLS_SSL_ALPN */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
case MBEDTLS_TLS_EXT_SIG_ALG:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
@@ -1649,7 +1651,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
}
ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SIG_ALG;
break;
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
default:
MBEDTLS_SSL_DEBUG_MSG( 3,
@@ -1669,7 +1671,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_HS_CLIENT_HELLO,
p - buf );
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/* Update checksum with either
* - The entire content of the CH message, if no PSK extension is present
* - The content up to but excluding the PSK extension, if present.
@@ -1698,7 +1700,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
}
}
else
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
{
ssl->handshake->update_checksum( ssl, buf, p - buf );
}
@@ -2154,7 +2156,7 @@ static int ssl_tls13_write_server_hello_body( mbedtls_ssl_context *ssl,
p += output_len;
}
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
if( !is_hrr && mbedtls_ssl_tls13_key_exchange_mode_with_psk( ssl ) )
{
ret = ssl_tls13_write_server_pre_shared_key_ext( ssl, p, end, &output_len );
@@ -2166,7 +2168,7 @@ static int ssl_tls13_write_server_hello_body( mbedtls_ssl_context *ssl,
}
p += output_len;
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif
MBEDTLS_PUT_UINT16_BE( p - p_extensions_len - 2, p_extensions_len, 0 );
@@ -2390,7 +2392,7 @@ static int ssl_tls13_write_encrypted_extensions( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg(
ssl, buf_len, msg_len ) );
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
if( mbedtls_ssl_tls13_key_exchange_mode_with_psk( ssl ) )
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
else
@@ -2405,7 +2407,7 @@ cleanup:
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
#define SSL_CERTIFICATE_REQUEST_SEND_REQUEST 0
#define SSL_CERTIFICATE_REQUEST_SKIP 1
/* Coordination:
@@ -2429,7 +2431,10 @@ static int ssl_tls13_certificate_request_coordinate( mbedtls_ssl_context *ssl )
authmode = ssl->conf->authmode;
if( authmode == MBEDTLS_SSL_VERIFY_NONE )
{
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
return( SSL_CERTIFICATE_REQUEST_SKIP );
}
ssl->handshake->certificate_request_sent = 1;
@@ -2573,7 +2578,7 @@ static int ssl_tls13_write_certificate_verify( mbedtls_ssl_context *ssl )
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
/*
* Handler for MBEDTLS_SSL_SERVER_FINISHED
@@ -2984,7 +2989,7 @@ int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl )
}
break;
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
case MBEDTLS_SSL_CERTIFICATE_REQUEST:
ret = ssl_tls13_write_certificate_request( ssl );
break;
@@ -2996,7 +3001,7 @@ int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl )
case MBEDTLS_SSL_CERTIFICATE_VERIFY:
ret = ssl_tls13_write_certificate_verify( ssl );
break;
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
/*
* Injection of dummy-CCS's for middlebox compatibility
@@ -3027,6 +3032,7 @@ int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl )
ret = ssl_tls13_handshake_wrapup( ssl );
break;
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
case MBEDTLS_SSL_CLIENT_CERTIFICATE:
ret = mbedtls_ssl_tls13_process_certificate( ssl );
if( ret == 0 )
@@ -3053,6 +3059,7 @@ int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl )
ssl, MBEDTLS_SSL_CLIENT_FINISHED );
}
break;
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
case MBEDTLS_SSL_NEW_SESSION_TICKET:

View File

@@ -459,6 +459,11 @@ static int x509_get_attr_type_value( unsigned char **p,
* For the general case we still use a flat list, but we mark elements of the
* same set so that they are "merged" together in the functions that consume
* this list, eg mbedtls_x509_dn_gets().
*
* On success, this function may allocate a linked list starting at cur->next
* that must later be free'd by the caller using mbedtls_free(). In error
* cases, this function frees all allocated memory internally and the caller
* has no freeing responsibilities.
*/
int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
mbedtls_x509_name *cur )
@@ -466,6 +471,8 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t set_len;
const unsigned char *end_set;
mbedtls_x509_name *head = cur;
mbedtls_x509_name *prev, *allocated;
/* don't use recursion, we'd risk stack overflow if not optimized */
while( 1 )
@@ -475,14 +482,17 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
*/
if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
{
ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret );
goto error;
}
end_set = *p + set_len;
while( 1 )
{
if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
return( ret );
goto error;
if( *p == end_set )
break;
@@ -493,7 +503,10 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
if( cur->next == NULL )
return( MBEDTLS_ERR_X509_ALLOC_FAILED );
{
ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
goto error;
}
cur = cur->next;
}
@@ -507,10 +520,30 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
if( cur->next == NULL )
return( MBEDTLS_ERR_X509_ALLOC_FAILED );
{
ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
goto error;
}
cur = cur->next;
}
error:
/* Skip the first element as we did not allocate it */
allocated = head->next;
while( allocated != NULL )
{
prev = allocated;
allocated = allocated->next;
mbedtls_platform_zeroize( prev, sizeof( *prev ) );
mbedtls_free( prev );
}
mbedtls_platform_zeroize( head, sizeof( *head ) );
return( ret );
}
static int x509_parse_int( unsigned char **p, size_t n, int *res )

View File

@@ -296,6 +296,43 @@ int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
return( 0 );
}
int mbedtls_x509write_crt_set_ext_key_usage( mbedtls_x509write_cert *ctx,
const mbedtls_asn1_sequence *exts )
{
unsigned char buf[256];
unsigned char *c = buf + sizeof(buf);
int ret;
size_t len = 0;
const mbedtls_asn1_sequence *last_ext = NULL;
const mbedtls_asn1_sequence *ext;
memset( buf, 0, sizeof(buf) );
/* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */
if( exts == NULL )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
/* Iterate over exts backwards, so we write them out in the requested order */
while( last_ext != exts )
{
for( ext = exts; ext->next != last_ext; ext = ext->next ) {}
if( ext->buf.tag != MBEDTLS_ASN1_OID )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( &c, buf, ext->buf.p, ext->buf.len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, ext->buf.len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OID ) );
last_ext = ext;
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
return mbedtls_x509write_crt_set_extension( ctx,
MBEDTLS_OID_EXTENDED_KEY_USAGE,
MBEDTLS_OID_SIZE( MBEDTLS_OID_EXTENDED_KEY_USAGE ),
1, c, len );
}
int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
unsigned char ns_cert_type )
{