Merge branch 'development_3.0' into drop_old_tls_options

This commit is contained in:
Mateusz Starzyk 2021-04-15 13:55:20 +02:00
commit c301bd56f0
278 changed files with 23729 additions and 8655 deletions

View file

@ -46,6 +46,8 @@ set(src_crypto
md4.c
md5.c
memory_buffer_alloc.c
mps_reader.c
mps_trace.c
nist_kw.c
oid.c
padlock.c
@ -60,14 +62,19 @@ set(src_crypto
platform_util.c
poly1305.c
psa_crypto.c
psa_crypto_cipher.c
psa_crypto_client.c
psa_crypto_driver_wrappers.c
psa_crypto_ecp.c
psa_crypto_hash.c
psa_crypto_rsa.c
psa_crypto_se.c
psa_crypto_slot_management.c
psa_crypto_storage.c
psa_its_file.c
ripemd160.c
rsa.c
rsa_internal.c
rsa_alt_helpers.c
sha1.c
sha256.c
sha512.c
@ -81,7 +88,6 @@ set(src_crypto
list(APPEND src_crypto ${thirdparty_src})
set(src_x509
certs.c
pkcs11.c
x509.c
x509_create.c
@ -188,15 +194,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY)
if(USE_SHARED_MBEDTLS_LIBRARY)
add_library(${mbedcrypto_target} SHARED ${src_crypto})
set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.25.0 SOVERSION 6)
set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.26.0 SOVERSION 6)
target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
add_library(${mbedx509_target} SHARED ${src_x509})
set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.25.0 SOVERSION 1)
set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.26.0 SOVERSION 1)
target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
add_library(${mbedtls_target} SHARED ${src_tls})
set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.25.0 SOVERSION 13)
set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.26.0 SOVERSION 13)
target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
endif(USE_SHARED_MBEDTLS_LIBRARY)

View file

@ -2,7 +2,7 @@
# Also see "include/mbedtls/config.h"
CFLAGS ?= -O2
WARNING_CFLAGS ?= -Wall -Wextra
WARNING_CFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
LDFLAGS ?=
# Include ../include for public headers and . for private headers.
@ -103,6 +103,8 @@ OBJS_CRYPTO= \
md4.o \
md5.o \
memory_buffer_alloc.o \
mps_reader.o \
mps_trace.o \
nist_kw.o \
oid.o \
padlock.o \
@ -117,14 +119,19 @@ OBJS_CRYPTO= \
platform_util.o \
poly1305.o \
psa_crypto.o \
psa_crypto_cipher.o \
psa_crypto_client.o \
psa_crypto_driver_wrappers.o \
psa_crypto_ecp.o \
psa_crypto_hash.o \
psa_crypto_rsa.o \
psa_crypto_se.o \
psa_crypto_slot_management.o \
psa_crypto_storage.o \
psa_its_file.o \
ripemd160.o \
rsa.o \
rsa_internal.o \
rsa_alt_helpers.o \
sha1.o \
sha256.o \
sha512.o \
@ -140,7 +147,6 @@ LOCAL_CFLAGS+=$(THIRDPARTY_INCLUDES)
OBJS_CRYPTO+=$(THIRDPARTY_CRYPTO_OBJECTS)
OBJS_X509= \
certs.o \
pkcs11.o \
x509.o \
x509_create.o \

View file

@ -34,10 +34,10 @@
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h"
#include "padlock.h"
#endif
#if defined(MBEDTLS_AESNI_C)
#include "mbedtls/aesni.h"
#include "aesni.h"
#endif
#if defined(MBEDTLS_SELF_TEST)

View file

@ -32,7 +32,7 @@
#endif
#endif
#include "mbedtls/aesni.h"
#include "aesni.h"
#include <string.h>

136
library/aesni.h Normal file
View file

@ -0,0 +1,136 @@
/**
* \file aesni.h
*
* \brief AES-NI for hardware AES acceleration on some Intel processors
*
* \warning These functions are only for internal use by other library
* functions; you must not call them directly.
*/
/*
* 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_AESNI_H
#define MBEDTLS_AESNI_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/aes.h"
#define MBEDTLS_AESNI_AES 0x02000000u
#define MBEDTLS_AESNI_CLMUL 0x00000002u
#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
( defined(__amd64__) || defined(__x86_64__) ) && \
! defined(MBEDTLS_HAVE_X86_64)
#define MBEDTLS_HAVE_X86_64
#endif
#if defined(MBEDTLS_HAVE_X86_64)
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Internal function to detect the AES-NI feature in CPUs.
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param what The feature to detect
* (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL)
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
int mbedtls_aesni_has_support( unsigned int what );
/**
* \brief Internal AES-NI AES-ECB block encryption and decryption
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 on success (cannot fail)
*/
int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Internal GCM multiplication: c = a * b in GF(2^128)
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param c Result
* \param a First operand
* \param b Second operand
*
* \note Both operands and result are bit strings interpreted as
* elements of GF(2^128) as per the GCM spec.
*/
void mbedtls_aesni_gcm_mult( unsigned char c[16],
const unsigned char a[16],
const unsigned char b[16] );
/**
* \brief Internal round key inversion. This function computes
* decryption round keys from the encryption round keys.
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param invkey Round keys for the equivalent inverse cipher
* \param fwdkey Original round keys (for encryption)
* \param nr Number of rounds (that is, number of round keys minus one)
*/
void mbedtls_aesni_inverse_key( unsigned char *invkey,
const unsigned char *fwdkey,
int nr );
/**
* \brief Internal key expansion for encryption
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param rk Destination buffer where the round keys are written
* \param key Encryption key
* \param bits Key size in bits (must be 128, 192 or 256)
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aesni_setkey_enc( unsigned char *rk,
const unsigned char *key,
size_t bits );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_HAVE_X86_64 */
#endif /* MBEDTLS_AESNI_H */

View file

@ -65,6 +65,99 @@ static const unsigned char base64_dec_map[128] =
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
/*
* Constant flow conditional assignment to unsigned char
*/
static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
unsigned char condition )
{
/* MSVC has a warning about unary minus on unsigned integer types,
* but this is well-defined and precisely what we want to do here. */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
/* Generate bitmask from condition, mask will either be 0xFF or 0 */
unsigned char mask = ( condition | -condition );
mask >>= 7;
mask = -mask;
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
*dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
}
/*
* Constant flow conditional assignment to uint_32
*/
static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
uint32_t condition )
{
/* MSVC has a warning about unary minus on unsigned integer types,
* but this is well-defined and precisely what we want to do here. */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
/* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
uint32_t mask = ( condition | -condition );
mask >>= 31;
mask = -mask;
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
*dest = ( src & mask ) | ( ( *dest ) & ~mask );
}
/*
* Constant flow check for equality
*/
static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
{
size_t difference = in_a ^ in_b;
/* MSVC has a warning about unary minus on unsigned integer types,
* but this is well-defined and precisely what we want to do here. */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
difference |= -difference;
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
/* cope with the varying size of size_t per platform */
difference >>= ( sizeof( difference ) * 8 - 1 );
return (unsigned char) ( 1 ^ difference );
}
/*
* Constant flow lookup into table.
*/
static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
const size_t table_size, const size_t table_index )
{
size_t i;
unsigned char result = 0;
for( i = 0; i < table_size; ++i )
{
mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
}
return result;
}
/*
* Encode a buffer into base64 format
*/
@ -105,10 +198,17 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
C2 = *src++;
C3 = *src++;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
*p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
*p++ = base64_enc_map[C3 & 0x3F];
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( C1 >> 2 ) & 0x3F ) );
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( C3 & 0x3F ) );
}
if( i < slen )
@ -116,11 +216,15 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
C1 = *src++;
C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( C1 >> 2 ) & 0x3F ) );
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
if( ( i + 1 ) < slen )
*p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
else *p++ = '=';
*p++ = '=';
@ -141,6 +245,7 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
size_t i, n;
uint32_t j, x;
unsigned char *p;
unsigned char dec_map_lookup;
/* First pass: check for validity and get output length */
for( i = n = j = 0; i < slen; i++ )
@ -171,10 +276,12 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
if( src[i] == '=' && ++j > 2 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
if( src[i] > 127 || dec_map_lookup == 127 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
if( base64_dec_map[src[i]] < 64 && j != 0 )
if( dec_map_lookup < 64 && j != 0 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
n++;
@ -204,8 +311,10 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
if( *src == '\r' || *src == '\n' || *src == ' ' )
continue;
j -= ( base64_dec_map[*src] == 64 );
x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
x = ( x << 6 ) | ( dec_map_lookup & 0x3F );
if( ++n == 4 )
{

View file

@ -38,7 +38,7 @@
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#include "mbedtls/bn_mul.h"
#include "bn_mul.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
@ -1339,29 +1339,32 @@ cleanup:
/**
* Helper for mbedtls_mpi subtraction.
*
* Calculate d - s where d and s have the same size.
* Calculate l - r where l and r have the same size.
* This function operates modulo (2^ciL)^n and returns the carry
* (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
* (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
*
* \param n Number of limbs of \p d and \p s.
* \param[in,out] d On input, the left operand.
* On output, the result of the subtraction:
* \param[in] s The right operand.
* d may be aliased to l or r.
*
* \return 1 if `d < s`.
* 0 if `d >= s`.
* \param n Number of limbs of \p d, \p l and \p r.
* \param[out] d The result of the subtraction.
* \param[in] l The left operand.
* \param[in] r The right operand.
*
* \return 1 if `l < r`.
* 0 if `l >= r`.
*/
static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
mbedtls_mpi_uint *d,
const mbedtls_mpi_uint *s )
const mbedtls_mpi_uint *l,
const mbedtls_mpi_uint *r )
{
size_t i;
mbedtls_mpi_uint c, z;
mbedtls_mpi_uint c = 0, t, z;
for( i = c = 0; i < n; i++, s++, d++ )
for( i = 0; i < n; i++ )
{
z = ( *d < c ); *d -= c;
c = ( *d < *s ) + z; *d -= *s;
z = ( l[i] < c ); t = l[i] - c;
c = ( t < r[i] ) + z; d[i] = t - r[i];
}
return( c );
@ -1372,7 +1375,6 @@ static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
*/
int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
mbedtls_mpi TB;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
mbedtls_mpi_uint carry;
@ -1380,29 +1382,27 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
mbedtls_mpi_init( &TB );
if( X == B )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
B = &TB;
}
if( X != A )
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
/*
* X should always be positive as a result of unsigned subtractions.
*/
X->s = 1;
ret = 0;
for( n = B->n; n > 0; n-- )
if( B->p[n - 1] != 0 )
break;
if( n > A->n )
{
/* B >= (2^ciL)^n > A */
ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
goto cleanup;
}
carry = mpi_sub_hlp( n, X->p, B->p );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
/* Set the high limbs of X to match A. Don't touch the lower limbs
* because X might be aliased to B, and we must not overwrite the
* significant digits of B. */
if( A->n > n )
memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
if( X->n > A->n )
memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
carry = mpi_sub_hlp( n, X->p, A->p, B->p );
if( carry != 0 )
{
/* Propagate the carry to the first nonzero limb of X. */
@ -1418,10 +1418,10 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
--X->p[n];
}
/* X should always be positive as a result of unsigned subtractions. */
X->s = 1;
cleanup:
mbedtls_mpi_free( &TB );
return( ret );
}
@ -1531,8 +1531,21 @@ int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint
return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
}
/*
* Helper for mbedtls_mpi multiplication
/** Helper for mbedtls_mpi multiplication.
*
* Add \p b * \p s to \p d.
*
* \param i The number of limbs of \p s.
* \param[in] s A bignum to multiply, of size \p i.
* It may overlap with \p d, but only if
* \p d <= \p s.
* Its leading limb must not be \c 0.
* \param[in,out] d The bignum to add to.
* It must be sufficiently large to store the
* result of the multiplication. This means
* \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
* is not known a priori.
* \param b A scalar to multiply.
*/
static
#if defined(__APPLE__) && defined(__arm__)
@ -1542,7 +1555,10 @@ static
*/
__attribute__ ((noinline))
#endif
void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
void mpi_mul_hlp( size_t i,
const mbedtls_mpi_uint *s,
mbedtls_mpi_uint *d,
mbedtls_mpi_uint b )
{
mbedtls_mpi_uint c = 0, t = 0;
@ -1597,10 +1613,10 @@ void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mp
t++;
do {
while( c != 0 )
{
*d += c; c = ( *d < c ); d++;
}
while( c != 0 );
}
/*
@ -1648,17 +1664,38 @@ cleanup:
*/
int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
{
mbedtls_mpi _B;
mbedtls_mpi_uint p[1];
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
_B.s = 1;
_B.n = 1;
_B.p = p;
p[0] = b;
/* mpi_mul_hlp can't deal with a leading 0. */
size_t n = A->n;
while( n > 0 && A->p[n - 1] == 0 )
--n;
return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
/* The general method below doesn't work if n==0 or b==0. By chance
* calculating the result is trivial in those cases. */
if( b == 0 || n == 0 )
{
mbedtls_mpi_lset( X, 0 );
return( 0 );
}
/* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* In general, A * b requires 1 limb more than b. If
* A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
* number of limbs as A and the call to grow() is not required since
* copy() will take care of the growth if needed. However, experimentally,
* making the call to grow() unconditional causes slightly fewer
* calls to calloc() in ECP code, presumably because it reuses the
* same mpi for a while and this way the mpi is more likely to directly
* grow to its final size. */
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
mpi_mul_hlp( n, A->p, X->p, b - 1 );
cleanup:
return( ret );
}
/*
@ -1799,7 +1836,7 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
k = mbedtls_mpi_bitlen( &Y ) % biL;
if( k < biL - 1 )
@ -2065,7 +2102,7 @@ static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi
* do the calculation without using conditional tests. */
/* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
d[n] += 1;
d[n] -= mpi_sub_hlp( n, d, N->p );
d[n] -= mpi_sub_hlp( n, d, d, N->p );
/* If d0 < N then d < (2^biL)^n
* so d[n] == 0 and we want to keep A as it is.
* If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n

938
library/bn_mul.h Normal file
View file

@ -0,0 +1,938 @@
/**
* \file bn_mul.h
*
* \brief Multi-precision integer library
*/
/*
* 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.
*/
/*
* Multiply source vector [s] with b, add result
* to destination vector [d] and set carry c.
*
* Currently supports:
*
* . IA-32 (386+) . AMD64 / EM64T
* . IA-32 (SSE2) . Motorola 68000
* . PowerPC, 32-bit . MicroBlaze
* . PowerPC, 64-bit . TriCore
* . SPARC v8 . ARM v3+
* . Alpha . MIPS32
* . C, longlong . C, generic
*/
#ifndef MBEDTLS_BN_MUL_H
#define MBEDTLS_BN_MUL_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/bignum.h"
#if defined(MBEDTLS_HAVE_ASM)
#ifndef asm
#define asm __asm
#endif
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
#if defined(__GNUC__) && \
( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
/*
* Disable use of the i386 assembly code below if option -O0, to disable all
* compiler optimisations, is passed, detected with __OPTIMIZE__
* This is done as the number of registers used in the assembly code doesn't
* work with the -O0 option.
*/
#if defined(__i386__) && defined(__OPTIMIZE__)
#define MULADDC_INIT \
asm( \
"movl %%ebx, %0 \n\t" \
"movl %5, %%esi \n\t" \
"movl %6, %%edi \n\t" \
"movl %7, %%ecx \n\t" \
"movl %8, %%ebx \n\t"
#define MULADDC_CORE \
"lodsl \n\t" \
"mull %%ebx \n\t" \
"addl %%ecx, %%eax \n\t" \
"adcl $0, %%edx \n\t" \
"addl (%%edi), %%eax \n\t" \
"adcl $0, %%edx \n\t" \
"movl %%edx, %%ecx \n\t" \
"stosl \n\t"
#if defined(MBEDTLS_HAVE_SSE2)
#define MULADDC_HUIT \
"movd %%ecx, %%mm1 \n\t" \
"movd %%ebx, %%mm0 \n\t" \
"movd (%%edi), %%mm3 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd (%%esi), %%mm2 \n\t" \
"pmuludq %%mm0, %%mm2 \n\t" \
"movd 4(%%esi), %%mm4 \n\t" \
"pmuludq %%mm0, %%mm4 \n\t" \
"movd 8(%%esi), %%mm6 \n\t" \
"pmuludq %%mm0, %%mm6 \n\t" \
"movd 12(%%esi), %%mm7 \n\t" \
"pmuludq %%mm0, %%mm7 \n\t" \
"paddq %%mm2, %%mm1 \n\t" \
"movd 4(%%edi), %%mm3 \n\t" \
"paddq %%mm4, %%mm3 \n\t" \
"movd 8(%%edi), %%mm5 \n\t" \
"paddq %%mm6, %%mm5 \n\t" \
"movd 12(%%edi), %%mm4 \n\t" \
"paddq %%mm4, %%mm7 \n\t" \
"movd %%mm1, (%%edi) \n\t" \
"movd 16(%%esi), %%mm2 \n\t" \
"pmuludq %%mm0, %%mm2 \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd 20(%%esi), %%mm4 \n\t" \
"pmuludq %%mm0, %%mm4 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd 24(%%esi), %%mm6 \n\t" \
"pmuludq %%mm0, %%mm6 \n\t" \
"movd %%mm1, 4(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd 28(%%esi), %%mm3 \n\t" \
"pmuludq %%mm0, %%mm3 \n\t" \
"paddq %%mm5, %%mm1 \n\t" \
"movd 16(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm2 \n\t" \
"movd %%mm1, 8(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm7, %%mm1 \n\t" \
"movd 20(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm4 \n\t" \
"movd %%mm1, 12(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm2, %%mm1 \n\t" \
"movd 24(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm6 \n\t" \
"movd %%mm1, 16(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm4, %%mm1 \n\t" \
"movd 28(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm3 \n\t" \
"movd %%mm1, 20(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm6, %%mm1 \n\t" \
"movd %%mm1, 24(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd %%mm1, 28(%%edi) \n\t" \
"addl $32, %%edi \n\t" \
"addl $32, %%esi \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd %%mm1, %%ecx \n\t"
#define MULADDC_STOP \
"emms \n\t" \
"movl %4, %%ebx \n\t" \
"movl %%ecx, %1 \n\t" \
"movl %%edi, %2 \n\t" \
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ebx", "ecx", "edx", "esi", "edi" \
);
#else
#define MULADDC_STOP \
"movl %4, %%ebx \n\t" \
"movl %%ecx, %1 \n\t" \
"movl %%edi, %2 \n\t" \
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ebx", "ecx", "edx", "esi", "edi" \
);
#endif /* SSE2 */
#endif /* i386 */
#if defined(__amd64__) || defined (__x86_64__)
#define MULADDC_INIT \
asm( \
"xorq %%r8, %%r8\n"
#define MULADDC_CORE \
"movq (%%rsi), %%rax\n" \
"mulq %%rbx\n" \
"addq $8, %%rsi\n" \
"addq %%rcx, %%rax\n" \
"movq %%r8, %%rcx\n" \
"adcq $0, %%rdx\n" \
"nop \n" \
"addq %%rax, (%%rdi)\n" \
"adcq %%rdx, %%rcx\n" \
"addq $8, %%rdi\n"
#define MULADDC_STOP \
: "+c" (c), "+D" (d), "+S" (s) \
: "b" (b) \
: "rax", "rdx", "r8" \
);
#endif /* AMD64 */
#if defined(__aarch64__)
#define MULADDC_INIT \
asm(
#define MULADDC_CORE \
"ldr x4, [%2], #8 \n\t" \
"ldr x5, [%1] \n\t" \
"mul x6, x4, %3 \n\t" \
"umulh x7, x4, %3 \n\t" \
"adds x5, x5, x6 \n\t" \
"adc x7, x7, xzr \n\t" \
"adds x5, x5, %0 \n\t" \
"adc %0, x7, xzr \n\t" \
"str x5, [%1], #8 \n\t"
#define MULADDC_STOP \
: "+r" (c), "+r" (d), "+r" (s) \
: "r" (b) \
: "x4", "x5", "x6", "x7", "cc" \
);
#endif /* Aarch64 */
#if defined(__mc68020__) || defined(__mcpu32__)
#define MULADDC_INIT \
asm( \
"movl %3, %%a2 \n\t" \
"movl %4, %%a3 \n\t" \
"movl %5, %%d3 \n\t" \
"movl %6, %%d2 \n\t" \
"moveq #0, %%d0 \n\t"
#define MULADDC_CORE \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"moveq #0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"addxl %%d4, %%d3 \n\t"
#define MULADDC_STOP \
"movl %%d3, %0 \n\t" \
"movl %%a3, %1 \n\t" \
"movl %%a2, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "d0", "d1", "d2", "d3", "d4", "a2", "a3" \
);
#define MULADDC_HUIT \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"addxl %%d0, %%d3 \n\t"
#endif /* MC68000 */
#if defined(__powerpc64__) || defined(__ppc64__)
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
asm( \
"ld r3, %3 \n\t" \
"ld r4, %4 \n\t" \
"ld r5, %5 \n\t" \
"ld r6, %6 \n\t" \
"addi r3, r3, -8 \n\t" \
"addi r4, r4, -8 \n\t" \
"addic r5, r5, 0 \n\t"
#define MULADDC_CORE \
"ldu r7, 8(r3) \n\t" \
"mulld r8, r7, r6 \n\t" \
"mulhdu r9, r7, r6 \n\t" \
"adde r8, r8, r5 \n\t" \
"ld r7, 8(r4) \n\t" \
"addze r5, r9 \n\t" \
"addc r8, r8, r7 \n\t" \
"stdu r8, 8(r4) \n\t"
#define MULADDC_STOP \
"addze r5, r5 \n\t" \
"addi r4, r4, 8 \n\t" \
"addi r3, r3, 8 \n\t" \
"std r5, %0 \n\t" \
"std r4, %1 \n\t" \
"std r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#else /* __MACH__ && __APPLE__ */
#define MULADDC_INIT \
asm( \
"ld %%r3, %3 \n\t" \
"ld %%r4, %4 \n\t" \
"ld %%r5, %5 \n\t" \
"ld %%r6, %6 \n\t" \
"addi %%r3, %%r3, -8 \n\t" \
"addi %%r4, %%r4, -8 \n\t" \
"addic %%r5, %%r5, 0 \n\t"
#define MULADDC_CORE \
"ldu %%r7, 8(%%r3) \n\t" \
"mulld %%r8, %%r7, %%r6 \n\t" \
"mulhdu %%r9, %%r7, %%r6 \n\t" \
"adde %%r8, %%r8, %%r5 \n\t" \
"ld %%r7, 8(%%r4) \n\t" \
"addze %%r5, %%r9 \n\t" \
"addc %%r8, %%r8, %%r7 \n\t" \
"stdu %%r8, 8(%%r4) \n\t"
#define MULADDC_STOP \
"addze %%r5, %%r5 \n\t" \
"addi %%r4, %%r4, 8 \n\t" \
"addi %%r3, %%r3, 8 \n\t" \
"std %%r5, %0 \n\t" \
"std %%r4, %1 \n\t" \
"std %%r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#endif /* __MACH__ && __APPLE__ */
#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
asm( \
"lwz r3, %3 \n\t" \
"lwz r4, %4 \n\t" \
"lwz r5, %5 \n\t" \
"lwz r6, %6 \n\t" \
"addi r3, r3, -4 \n\t" \
"addi r4, r4, -4 \n\t" \
"addic r5, r5, 0 \n\t"
#define MULADDC_CORE \
"lwzu r7, 4(r3) \n\t" \
"mullw r8, r7, r6 \n\t" \
"mulhwu r9, r7, r6 \n\t" \
"adde r8, r8, r5 \n\t" \
"lwz r7, 4(r4) \n\t" \
"addze r5, r9 \n\t" \
"addc r8, r8, r7 \n\t" \
"stwu r8, 4(r4) \n\t"
#define MULADDC_STOP \
"addze r5, r5 \n\t" \
"addi r4, r4, 4 \n\t" \
"addi r3, r3, 4 \n\t" \
"stw r5, %0 \n\t" \
"stw r4, %1 \n\t" \
"stw r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#else /* __MACH__ && __APPLE__ */
#define MULADDC_INIT \
asm( \
"lwz %%r3, %3 \n\t" \
"lwz %%r4, %4 \n\t" \
"lwz %%r5, %5 \n\t" \
"lwz %%r6, %6 \n\t" \
"addi %%r3, %%r3, -4 \n\t" \
"addi %%r4, %%r4, -4 \n\t" \
"addic %%r5, %%r5, 0 \n\t"
#define MULADDC_CORE \
"lwzu %%r7, 4(%%r3) \n\t" \
"mullw %%r8, %%r7, %%r6 \n\t" \
"mulhwu %%r9, %%r7, %%r6 \n\t" \
"adde %%r8, %%r8, %%r5 \n\t" \
"lwz %%r7, 4(%%r4) \n\t" \
"addze %%r5, %%r9 \n\t" \
"addc %%r8, %%r8, %%r7 \n\t" \
"stwu %%r8, 4(%%r4) \n\t"
#define MULADDC_STOP \
"addze %%r5, %%r5 \n\t" \
"addi %%r4, %%r4, 4 \n\t" \
"addi %%r3, %%r3, 4 \n\t" \
"stw %%r5, %0 \n\t" \
"stw %%r4, %1 \n\t" \
"stw %%r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#endif /* __MACH__ && __APPLE__ */
#endif /* PPC32 */
/*
* The Sparc(64) assembly is reported to be broken.
* Disable it for now, until we're able to fix it.
*/
#if 0 && defined(__sparc__)
#if defined(__sparc64__)
#define MULADDC_INIT \
asm( \
"ldx %3, %%o0 \n\t" \
"ldx %4, %%o1 \n\t" \
"ld %5, %%o2 \n\t" \
"ld %6, %%o3 \n\t"
#define MULADDC_CORE \
"ld [%%o0], %%o4 \n\t" \
"inc 4, %%o0 \n\t" \
"ld [%%o1], %%o5 \n\t" \
"umul %%o3, %%o4, %%o4 \n\t" \
"addcc %%o4, %%o2, %%o4 \n\t" \
"rd %%y, %%g1 \n\t" \
"addx %%g1, 0, %%g1 \n\t" \
"addcc %%o4, %%o5, %%o4 \n\t" \
"st %%o4, [%%o1] \n\t" \
"addx %%g1, 0, %%o2 \n\t" \
"inc 4, %%o1 \n\t"
#define MULADDC_STOP \
"st %%o2, %0 \n\t" \
"stx %%o1, %1 \n\t" \
"stx %%o0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "g1", "o0", "o1", "o2", "o3", "o4", \
"o5" \
);
#else /* __sparc64__ */
#define MULADDC_INIT \
asm( \
"ld %3, %%o0 \n\t" \
"ld %4, %%o1 \n\t" \
"ld %5, %%o2 \n\t" \
"ld %6, %%o3 \n\t"
#define MULADDC_CORE \
"ld [%%o0], %%o4 \n\t" \
"inc 4, %%o0 \n\t" \
"ld [%%o1], %%o5 \n\t" \
"umul %%o3, %%o4, %%o4 \n\t" \
"addcc %%o4, %%o2, %%o4 \n\t" \
"rd %%y, %%g1 \n\t" \
"addx %%g1, 0, %%g1 \n\t" \
"addcc %%o4, %%o5, %%o4 \n\t" \
"st %%o4, [%%o1] \n\t" \
"addx %%g1, 0, %%o2 \n\t" \
"inc 4, %%o1 \n\t"
#define MULADDC_STOP \
"st %%o2, %0 \n\t" \
"st %%o1, %1 \n\t" \
"st %%o0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "g1", "o0", "o1", "o2", "o3", "o4", \
"o5" \
);
#endif /* __sparc64__ */
#endif /* __sparc__ */
#if defined(__microblaze__) || defined(microblaze)
#define MULADDC_INIT \
asm( \
"lwi r3, %3 \n\t" \
"lwi r4, %4 \n\t" \
"lwi r5, %5 \n\t" \
"lwi r6, %6 \n\t" \
"andi r7, r6, 0xffff \n\t" \
"bsrli r6, r6, 16 \n\t"
#define MULADDC_CORE \
"lhui r8, r3, 0 \n\t" \
"addi r3, r3, 2 \n\t" \
"lhui r9, r3, 0 \n\t" \
"addi r3, r3, 2 \n\t" \
"mul r10, r9, r6 \n\t" \
"mul r11, r8, r7 \n\t" \
"mul r12, r9, r7 \n\t" \
"mul r13, r8, r6 \n\t" \
"bsrli r8, r10, 16 \n\t" \
"bsrli r9, r11, 16 \n\t" \
"add r13, r13, r8 \n\t" \
"add r13, r13, r9 \n\t" \
"bslli r10, r10, 16 \n\t" \
"bslli r11, r11, 16 \n\t" \
"add r12, r12, r10 \n\t" \
"addc r13, r13, r0 \n\t" \
"add r12, r12, r11 \n\t" \
"addc r13, r13, r0 \n\t" \
"lwi r10, r4, 0 \n\t" \
"add r12, r12, r10 \n\t" \
"addc r13, r13, r0 \n\t" \
"add r12, r12, r5 \n\t" \
"addc r5, r13, r0 \n\t" \
"swi r12, r4, 0 \n\t" \
"addi r4, r4, 4 \n\t"
#define MULADDC_STOP \
"swi r5, %0 \n\t" \
"swi r4, %1 \n\t" \
"swi r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", \
"r9", "r10", "r11", "r12", "r13" \
);
#endif /* MicroBlaze */
#if defined(__tricore__)
#define MULADDC_INIT \
asm( \
"ld.a %%a2, %3 \n\t" \
"ld.a %%a3, %4 \n\t" \
"ld.w %%d4, %5 \n\t" \
"ld.w %%d1, %6 \n\t" \
"xor %%d5, %%d5 \n\t"
#define MULADDC_CORE \
"ld.w %%d0, [%%a2+] \n\t" \
"madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \
"ld.w %%d0, [%%a3] \n\t" \
"addx %%d2, %%d2, %%d0 \n\t" \
"addc %%d3, %%d3, 0 \n\t" \
"mov %%d4, %%d3 \n\t" \
"st.w [%%a3+], %%d2 \n\t"
#define MULADDC_STOP \
"st.w %0, %%d4 \n\t" \
"st.a %1, %%a3 \n\t" \
"st.a %2, %%a2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "d0", "d1", "e2", "d4", "a2", "a3" \
);
#endif /* TriCore */
/*
* Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about
* our use of r7 below, unless -fomit-frame-pointer is passed.
*
* On the other hand, -fomit-frame-pointer is implied by any -Ox options with
* x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
* clang and armcc5 under the same conditions).
*
* So, only use the optimized assembly below for optimized build, which avoids
* the build error and is pretty reasonable anyway.
*/
#if defined(__GNUC__) && !defined(__OPTIMIZE__)
#define MULADDC_CANNOT_USE_R7
#endif
#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7)
#if defined(__thumb__) && !defined(__thumb2__)
#define MULADDC_INIT \
asm( \
"ldr r0, %3 \n\t" \
"ldr r1, %4 \n\t" \
"ldr r2, %5 \n\t" \
"ldr r3, %6 \n\t" \
"lsr r7, r3, #16 \n\t" \
"mov r9, r7 \n\t" \
"lsl r7, r3, #16 \n\t" \
"lsr r7, r7, #16 \n\t" \
"mov r8, r7 \n\t"
#define MULADDC_CORE \
"ldmia r0!, {r6} \n\t" \
"lsr r7, r6, #16 \n\t" \
"lsl r6, r6, #16 \n\t" \
"lsr r6, r6, #16 \n\t" \
"mov r4, r8 \n\t" \
"mul r4, r6 \n\t" \
"mov r3, r9 \n\t" \
"mul r6, r3 \n\t" \
"mov r5, r9 \n\t" \
"mul r5, r7 \n\t" \
"mov r3, r8 \n\t" \
"mul r7, r3 \n\t" \
"lsr r3, r6, #16 \n\t" \
"add r5, r5, r3 \n\t" \
"lsr r3, r7, #16 \n\t" \
"add r5, r5, r3 \n\t" \
"add r4, r4, r2 \n\t" \
"mov r2, #0 \n\t" \
"adc r5, r2 \n\t" \
"lsl r3, r6, #16 \n\t" \
"add r4, r4, r3 \n\t" \
"adc r5, r2 \n\t" \
"lsl r3, r7, #16 \n\t" \
"add r4, r4, r3 \n\t" \
"adc r5, r2 \n\t" \
"ldr r3, [r1] \n\t" \
"add r4, r4, r3 \n\t" \
"adc r2, r5 \n\t" \
"stmia r1!, {r4} \n\t"
#define MULADDC_STOP \
"str r2, %0 \n\t" \
"str r1, %1 \n\t" \
"str r0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "r8", "r9", "cc" \
);
#elif (__ARM_ARCH >= 6) && \
defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)
#define MULADDC_INIT \
asm(
#define MULADDC_CORE \
"ldr r0, [%0], #4 \n\t" \
"ldr r1, [%1] \n\t" \
"umaal r1, %2, %3, r0 \n\t" \
"str r1, [%1], #4 \n\t"
#define MULADDC_STOP \
: "=r" (s), "=r" (d), "=r" (c) \
: "r" (b), "0" (s), "1" (d), "2" (c) \
: "r0", "r1", "memory" \
);
#else
#define MULADDC_INIT \
asm( \
"ldr r0, %3 \n\t" \
"ldr r1, %4 \n\t" \
"ldr r2, %5 \n\t" \
"ldr r3, %6 \n\t"
#define MULADDC_CORE \
"ldr r4, [r0], #4 \n\t" \
"mov r5, #0 \n\t" \
"ldr r6, [r1] \n\t" \
"umlal r2, r5, r3, r4 \n\t" \
"adds r7, r6, r2 \n\t" \
"adc r2, r5, #0 \n\t" \
"str r7, [r1], #4 \n\t"
#define MULADDC_STOP \
"str r2, %0 \n\t" \
"str r1, %1 \n\t" \
"str r0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "cc" \
);
#endif /* Thumb */
#endif /* ARMv3 */
#if defined(__alpha__)
#define MULADDC_INIT \
asm( \
"ldq $1, %3 \n\t" \
"ldq $2, %4 \n\t" \
"ldq $3, %5 \n\t" \
"ldq $4, %6 \n\t"
#define MULADDC_CORE \
"ldq $6, 0($1) \n\t" \
"addq $1, 8, $1 \n\t" \
"mulq $6, $4, $7 \n\t" \
"umulh $6, $4, $6 \n\t" \
"addq $7, $3, $7 \n\t" \
"cmpult $7, $3, $3 \n\t" \
"ldq $5, 0($2) \n\t" \
"addq $7, $5, $7 \n\t" \
"cmpult $7, $5, $5 \n\t" \
"stq $7, 0($2) \n\t" \
"addq $2, 8, $2 \n\t" \
"addq $6, $3, $3 \n\t" \
"addq $5, $3, $3 \n\t"
#define MULADDC_STOP \
"stq $3, %0 \n\t" \
"stq $2, %1 \n\t" \
"stq $1, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "$1", "$2", "$3", "$4", "$5", "$6", "$7" \
);
#endif /* Alpha */
#if defined(__mips__) && !defined(__mips64)
#define MULADDC_INIT \
asm( \
"lw $10, %3 \n\t" \
"lw $11, %4 \n\t" \
"lw $12, %5 \n\t" \
"lw $13, %6 \n\t"
#define MULADDC_CORE \
"lw $14, 0($10) \n\t" \
"multu $13, $14 \n\t" \
"addi $10, $10, 4 \n\t" \
"mflo $14 \n\t" \
"mfhi $9 \n\t" \
"addu $14, $12, $14 \n\t" \
"lw $15, 0($11) \n\t" \
"sltu $12, $14, $12 \n\t" \
"addu $15, $14, $15 \n\t" \
"sltu $14, $15, $14 \n\t" \
"addu $12, $12, $9 \n\t" \
"sw $15, 0($11) \n\t" \
"addu $12, $12, $14 \n\t" \
"addi $11, $11, 4 \n\t"
#define MULADDC_STOP \
"sw $12, %0 \n\t" \
"sw $11, %1 \n\t" \
"sw $10, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \
);
#endif /* MIPS */
#endif /* GNUC */
#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
#define MULADDC_INIT \
__asm mov esi, s \
__asm mov edi, d \
__asm mov ecx, c \
__asm mov ebx, b
#define MULADDC_CORE \
__asm lodsd \
__asm mul ebx \
__asm add eax, ecx \
__asm adc edx, 0 \
__asm add eax, [edi] \
__asm adc edx, 0 \
__asm mov ecx, edx \
__asm stosd
#if defined(MBEDTLS_HAVE_SSE2)
#define EMIT __asm _emit
#define MULADDC_HUIT \
EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
EMIT 0x0F EMIT 0x6E EMIT 0x1F \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x16 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
EMIT 0x0F EMIT 0x7E EMIT 0x0F \
EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x7E EMIT 0xC9
#define MULADDC_STOP \
EMIT 0x0F EMIT 0x77 \
__asm mov c, ecx \
__asm mov d, edi \
__asm mov s, esi \
#else
#define MULADDC_STOP \
__asm mov c, ecx \
__asm mov d, edi \
__asm mov s, esi \
#endif /* SSE2 */
#endif /* MSVC */
#endif /* MBEDTLS_HAVE_ASM */
#if !defined(MULADDC_CORE)
#if defined(MBEDTLS_HAVE_UDBL)
#define MULADDC_INIT \
{ \
mbedtls_t_udbl r; \
mbedtls_mpi_uint r0, r1;
#define MULADDC_CORE \
r = *(s++) * (mbedtls_t_udbl) b; \
r0 = (mbedtls_mpi_uint) r; \
r1 = (mbedtls_mpi_uint)( r >> biL ); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#else
#define MULADDC_INIT \
{ \
mbedtls_mpi_uint s0, s1, b0, b1; \
mbedtls_mpi_uint r0, r1, rx, ry; \
b0 = ( b << biH ) >> biH; \
b1 = ( b >> biH );
#define MULADDC_CORE \
s0 = ( *s << biH ) >> biH; \
s1 = ( *s >> biH ); s++; \
rx = s0 * b1; r0 = s0 * b0; \
ry = s1 * b0; r1 = s1 * b1; \
r1 += ( rx >> biH ); \
r1 += ( ry >> biH ); \
rx <<= biH; ry <<= biH; \
r0 += rx; r1 += (r0 < rx); \
r0 += ry; r1 += (r0 < ry); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#endif /* C (generic) */
#endif /* C (longlong) */
#endif /* bn_mul.h */

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,19 @@
#ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H
#define MBEDTLS_CHECK_CRYPTO_CONFIG_H
#if defined(PSA_WANT_ALG_CCM) && \
!( defined(PSA_WANT_KEY_TYPE_AES) || \
defined(PSA_WANT_KEY_TYPE_CAMELLIA) )
#error "PSA_WANT_ALG_CCM defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_CMAC) && \
!( defined(PSA_WANT_KEY_TYPE_AES) || \
defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \
defined(PSA_WANT_KEY_TYPE_DES) )
#error "PSA_WANT_ALG_CMAC defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \
!( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) )
@ -40,6 +53,12 @@
#error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_GCM) && \
!( defined(PSA_WANT_KEY_TYPE_AES) || \
defined(PSA_WANT_KEY_TYPE_CAMELLIA) )
#error "PSA_WANT_ALG_GCM defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \
!( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )

View file

@ -26,7 +26,7 @@
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher.h"
#include "mbedtls/cipher_internal.h"
#include "cipher_wrap.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"

View file

@ -25,7 +25,7 @@
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher_internal.h"
#include "cipher_wrap.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_CHACHAPOLY_C)

150
library/cipher_wrap.h Normal file
View file

@ -0,0 +1,150 @@
/**
* \file cipher_wrap.h
*
* \brief Cipher wrappers.
*
* \author Adriaan de Jong <dejong@fox-it.com>
*/
/*
* 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_CIPHER_WRAP_H
#define MBEDTLS_CIPHER_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#ifdef __cplusplus
extern "C" {
#endif
/**
* Base cipher information. The non-mode specific functions and values.
*/
struct mbedtls_cipher_base_t
{
/** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */
mbedtls_cipher_id_t cipher;
/** Encrypt using ECB */
int (*ecb_func)( void *ctx, mbedtls_operation_t mode,
const unsigned char *input, unsigned char *output );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/** Encrypt using CBC */
int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length,
unsigned char *iv, const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/** Encrypt using CFB (Full length) */
int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off,
unsigned char *iv, const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
/** Encrypt using OFB (Full length) */
int (*ofb_func)( void *ctx, size_t length, size_t *iv_off,
unsigned char *iv,
const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/** Encrypt using CTR */
int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
unsigned char *nonce_counter, unsigned char *stream_block,
const unsigned char *input, unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/** Encrypt or decrypt using XTS. */
int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length,
const unsigned char data_unit[16],
const unsigned char *input, unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
/** Encrypt using STREAM */
int (*stream_func)( void *ctx, size_t length,
const unsigned char *input, unsigned char *output );
#endif
/** Set key for encryption purposes */
int (*setkey_enc_func)( void *ctx, const unsigned char *key,
unsigned int key_bitlen );
/** Set key for decryption purposes */
int (*setkey_dec_func)( void *ctx, const unsigned char *key,
unsigned int key_bitlen);
/** Allocate a new context */
void * (*ctx_alloc_func)( void );
/** Free the given context */
void (*ctx_free_func)( void *ctx );
};
typedef struct
{
mbedtls_cipher_type_t type;
const mbedtls_cipher_info_t *info;
} mbedtls_cipher_definition_t;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
typedef enum
{
MBEDTLS_CIPHER_PSA_KEY_UNSET = 0,
MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */
/* use raw key material internally imported */
/* as a volatile key, and which hence need */
/* to destroy that key when the context is */
/* freed. */
MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */
/* which use a key provided by the */
/* user, and which hence will not be */
/* destroyed when the context is freed. */
} mbedtls_cipher_psa_key_ownership;
typedef struct
{
psa_algorithm_t alg;
psa_key_id_t slot;
mbedtls_cipher_psa_key_ownership slot_state;
} mbedtls_cipher_context_psa;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
extern int mbedtls_cipher_supported[];
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CIPHER_WRAP_H */

View file

@ -45,22 +45,10 @@
#include "mbedtls/cmac.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "mbedtls/platform.h"
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#if defined(MBEDTLS_SELF_TEST)
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
/*
@ -793,6 +781,18 @@ static int cmac_test_subkeys( int verbose,
if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
MBEDTLS_ENCRYPT ) ) != 0 )
{
/* When CMAC is implemented by an alternative implementation, or
* the underlying primitive itself is implemented alternatively,
* AES-192 may be unavailable. This should not cause the selftest
* function to fail. */
if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) &&
cipher_type == MBEDTLS_CIPHER_AES_192_ECB ) {
if( verbose != 0 )
mbedtls_printf( "skipped\n" );
goto next_test;
}
if( verbose != 0 )
mbedtls_printf( "test execution failed\n" );
@ -820,6 +820,7 @@ static int cmac_test_subkeys( int verbose,
if( verbose != 0 )
mbedtls_printf( "passed\n" );
next_test:
mbedtls_cipher_free( &ctx );
}
@ -864,6 +865,18 @@ static int cmac_test_wth_cipher( int verbose,
if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
message_lengths[i], output ) ) != 0 )
{
/* When CMAC is implemented by an alternative implementation, or
* the underlying primitive itself is implemented alternatively,
* AES-192 may be unavailable. This should not cause the selftest
* function to fail. */
if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) &&
cipher_type == MBEDTLS_CIPHER_AES_192_ECB ) {
if( verbose != 0 )
mbedtls_printf( "skipped\n" );
continue;
}
if( verbose != 0 )
mbedtls_printf( "failed\n" );
goto exit;

View file

@ -56,10 +56,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
ctx->reseed_counter = -1;
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
}
/*
@ -72,15 +68,14 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
return;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &ctx->mutex );
/* The mutex is initialized iff f_entropy is set. */
if( ctx->f_entropy != NULL )
mbedtls_mutex_free( &ctx->mutex );
#endif
mbedtls_aes_free( &ctx->aes_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
ctx->reseed_counter = -1;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
}
void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
@ -464,6 +459,11 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
/* The mutex is initialized iff f_entropy is set. */
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
mbedtls_aes_init( &ctx->aes_ctx );
ctx->f_entropy = f_entropy;

View file

@ -74,6 +74,7 @@ static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level,
#endif
}
MBEDTLS_PRINTF_ATTRIBUTE(5, 6)
void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const char *format, ... )

View file

@ -217,6 +217,9 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
#endif /* MBEDTLS_ECP_RESTARTABLE */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \
!defined(MBEDTLS_ECDSA_SIGN_ALT) || \
!defined(MBEDTLS_ECDSA_VERIFY_ALT)
/*
* Derive a suitable integer for group grp from a buffer of length len
* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
@ -239,6 +242,7 @@ static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
cleanup:
return( ret );
}
#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
#if !defined(MBEDTLS_ECDSA_SIGN_ALT)
/*
@ -466,6 +470,8 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
sign:
#endif
#if defined(MBEDTLS_ECDSA_SIGN_ALT)
(void) f_rng_blind;
(void) p_rng_blind;
ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
mbedtls_hmac_drbg_random, p_rng );
#else
@ -766,6 +772,8 @@ int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
(void) md_alg;
#if defined(MBEDTLS_ECDSA_SIGN_ALT)
(void) rs_ctx;
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
hash, hlen, f_rng, p_rng ) );
#else
@ -874,6 +882,8 @@ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
goto cleanup;
}
#if defined(MBEDTLS_ECDSA_VERIFY_ALT)
(void) rs_ctx;
if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
&ctx->Q, &r, &s ) ) != 0 )
goto cleanup;

View file

@ -97,7 +97,7 @@
#define mbedtls_free free
#endif
#include "mbedtls/ecp_internal.h"
#include "ecp_alt.h"
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
#if defined(MBEDTLS_HMAC_DRBG_C)
@ -1243,6 +1243,13 @@ cleanup:
while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
#if ( defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \
!( defined(MBEDTLS_ECP_NO_FALLBACK) && \
defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
defined(MBEDTLS_ECP_ADD_MIXED_ALT) ) ) || \
( defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) && \
!( defined(MBEDTLS_ECP_NO_FALLBACK) && \
defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) ) )
static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp,
mbedtls_mpi *X,
const mbedtls_mpi *A,
@ -1254,6 +1261,7 @@ static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp,
cleanup:
return( ret );
}
#endif /* All functions referencing mbedtls_mpi_sub_mod() are alt-implemented without fallback */
/*
* Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int.
@ -1276,6 +1284,10 @@ cleanup:
return( ret );
}
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \
!( defined(MBEDTLS_ECP_NO_FALLBACK) && \
defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
defined(MBEDTLS_ECP_ADD_MIXED_ALT) )
static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp,
mbedtls_mpi *X,
size_t count )
@ -1286,6 +1298,7 @@ static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp,
cleanup:
return( ret );
}
#endif /* All functions referencing mbedtls_mpi_shift_l_mod() are alt-implemented without fallback */
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
/*
@ -1302,9 +1315,6 @@ cleanup:
*/
static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi Zi, ZZi;
if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
return( 0 );
@ -1313,6 +1323,11 @@ static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p
return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#else
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi Zi, ZZi;
mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
/*
@ -1338,6 +1353,7 @@ cleanup:
mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
return( ret );
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */
}
/*
@ -1354,10 +1370,6 @@ cleanup:
static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *T[], size_t T_size )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi *c, u, Zi, ZZi;
if( T_size < 2 )
return( ecp_normalize_jac( grp, *T ) );
@ -1366,6 +1378,13 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
#endif
#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#else
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi *c, u, Zi, ZZi;
if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
@ -1433,6 +1452,7 @@ cleanup:
mbedtls_free( c );
return( ret );
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) */
}
/*
@ -1477,9 +1497,6 @@ cleanup:
static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_ecp_point *P )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi M, S, T, U;
#if defined(MBEDTLS_SELF_TEST)
dbl_count++;
#endif
@ -1489,6 +1506,12 @@ static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#else
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi M, S, T, U;
mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U );
/* Special case for A = -3 */
@ -1550,6 +1573,7 @@ cleanup:
mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U );
return( ret );
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */
}
/*
@ -1573,9 +1597,6 @@ cleanup:
static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
#if defined(MBEDTLS_SELF_TEST)
add_count++;
#endif
@ -1585,6 +1606,12 @@ static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_ADD_MIXED_ALT)
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#else
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
/*
* Trivial cases: P == 0 or Q == 0 (case 1)
*/
@ -1649,6 +1676,7 @@ cleanup:
mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
return( ret );
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */
}
/*
@ -1661,17 +1689,19 @@ cleanup:
static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi l, ll;
size_t p_size;
int count = 0;
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
if( mbedtls_internal_ecp_grp_capable( grp ) )
return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
p_size = ( grp->pbits + 7 ) / 8;
#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#else
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi l, ll;
int count = 0;
size_t p_size = ( grp->pbits + 7 ) / 8;
mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
/* Generate l such that 1 < l < p */
@ -1705,6 +1735,7 @@ cleanup:
mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
return( ret );
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */
}
/*
@ -2413,19 +2444,22 @@ cleanup:
*/
static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
if( mbedtls_internal_ecp_grp_capable( grp ) )
return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#else
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &P->Z ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
cleanup:
return( ret );
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) */
}
/*
@ -2439,17 +2473,18 @@ cleanup:
static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi l;
size_t p_size;
int count = 0;
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
if( mbedtls_internal_ecp_grp_capable( grp ) )
return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
p_size = ( grp->pbits + 7 ) / 8;
#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#else
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi l;
int count = 0;
size_t p_size = ( grp->pbits + 7 ) / 8;
mbedtls_mpi_init( &l );
/* Generate l such that 1 < l < p */
@ -2475,6 +2510,7 @@ cleanup:
mbedtls_mpi_free( &l );
return( ret );
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */
}
/*
@ -2497,14 +2533,17 @@ static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
const mbedtls_mpi *d )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
if( mbedtls_internal_ecp_grp_capable( grp ) )
return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
#else
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
@ -2534,6 +2573,7 @@ cleanup:
mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
return( ret );
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */
}
/*

297
library/ecp_alt.h Normal file
View file

@ -0,0 +1,297 @@
/**
* \file ecp_alt.h
*
* \brief Function declarations for alternative implementation of elliptic curve
* point arithmetic.
*/
/*
* 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.
*/
/*
* References:
*
* [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records.
* <http://cr.yp.to/ecdh/curve25519-20060209.pdf>
*
* [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
* for elliptic curve cryptosystems. In : Cryptographic Hardware and
* Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
* <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
*
* [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
* render ECC resistant against Side Channel Attacks. IACR Cryptology
* ePrint Archive, 2004, vol. 2004, p. 342.
* <http://eprint.iacr.org/2004/342.pdf>
*
* [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters.
* <http://www.secg.org/sec2-v2.pdf>
*
* [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic
* Curve Cryptography.
*
* [6] Digital Signature Standard (DSS), FIPS 186-4.
* <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf>
*
* [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer
* Security (TLS), RFC 4492.
* <https://tools.ietf.org/search/rfc4492>
*
* [8] <http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html>
*
* [9] COHEN, Henri. A Course in Computational Algebraic Number Theory.
* Springer Science & Business Media, 1 Aug 2000
*/
#ifndef MBEDTLS_ECP_INTERNAL_H
#define MBEDTLS_ECP_INTERNAL_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
/**
* \brief Indicate if the Elliptic Curve Point module extension can
* handle the group.
*
* \param grp The pointer to the elliptic curve group that will be the
* basis of the cryptographic computations.
*
* \return Non-zero if successful.
*/
unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp );
/**
* \brief Initialise the Elliptic Curve Point module extension.
*
* If mbedtls_internal_ecp_grp_capable returns true for a
* group, this function has to be able to initialise the
* module for it.
*
* This module can be a driver to a crypto hardware
* accelerator, for which this could be an initialise function.
*
* \param grp The pointer to the group the module needs to be
* initialised for.
*
* \return 0 if successful.
*/
int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp );
/**
* \brief Frees and deallocates the Elliptic Curve Point module
* extension.
*
* \param grp The pointer to the group the module was initialised for.
*/
void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp );
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
/**
* \brief Randomize jacobian coordinates:
* (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l.
*
* \param grp Pointer to the group representing the curve.
*
* \param pt The point on the curve to be randomised, given with Jacobian
* coordinates.
*
* \param f_rng A function pointer to the random number generator.
*
* \param p_rng A pointer to the random number generator state.
*
* \return 0 if successful.
*/
int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
#endif
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
/**
* \brief Addition: R = P + Q, mixed affine-Jacobian coordinates.
*
* The coordinates of Q must be normalized (= affine),
* but those of P don't need to. R is not normalized.
*
* This function is used only as a subrutine of
* ecp_mul_comb().
*
* Special cases: (1) P or Q is zero, (2) R is zero,
* (3) P == Q.
* None of these cases can happen as intermediate step in
* ecp_mul_comb():
* - at each step, P, Q and R are multiples of the base
* point, the factor being less than its order, so none of
* them is zero;
* - Q is an odd multiple of the base point, P an even
* multiple, due to the choice of precomputed points in the
* modified comb method.
* So branches for these cases do not leak secret information.
*
* We accept Q->Z being unset (saving memory in tables) as
* meaning 1.
*
* Cost in field operations if done by [5] 3.22:
* 1A := 8M + 3S
*
* \param grp Pointer to the group representing the curve.
*
* \param R Pointer to a point structure to hold the result.
*
* \param P Pointer to the first summand, given with Jacobian
* coordinates
*
* \param Q Pointer to the second summand, given with affine
* coordinates.
*
* \return 0 if successful.
*/
int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *R, const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q );
#endif
/**
* \brief Point doubling R = 2 P, Jacobian coordinates.
*
* Cost: 1D := 3M + 4S (A == 0)
* 4M + 4S (A == -3)
* 3M + 6S + 1a otherwise
* when the implementation is based on the "dbl-1998-cmo-2"
* doubling formulas in [8] and standard optimizations are
* applied when curve parameter A is one of { 0, -3 }.
*
* \param grp Pointer to the group representing the curve.
*
* \param R Pointer to a point structure to hold the result.
*
* \param P Pointer to the point that has to be doubled, given with
* Jacobian coordinates.
*
* \return 0 if successful.
*/
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *R, const mbedtls_ecp_point *P );
#endif
/**
* \brief Normalize jacobian coordinates of an array of (pointers to)
* points.
*
* Using Montgomery's trick to perform only one inversion mod P
* the cost is:
* 1N(t) := 1I + (6t - 3)M + 1S
* (See for example Algorithm 10.3.4. in [9])
*
* This function is used only as a subrutine of
* ecp_mul_comb().
*
* Warning: fails (returning an error) if one of the points is
* zero!
* This should never happen, see choice of w in ecp_mul_comb().
*
* \param grp Pointer to the group representing the curve.
*
* \param T Array of pointers to the points to normalise.
*
* \param t_len Number of elements in the array.
*
* \return 0 if successful,
* an error if one of the points is zero.
*/
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *T[], size_t t_len );
#endif
/**
* \brief Normalize jacobian coordinates so that Z == 0 || Z == 1.
*
* Cost in field operations if done by [5] 3.2.1:
* 1N := 1I + 3M + 1S
*
* \param grp Pointer to the group representing the curve.
*
* \param pt pointer to the point to be normalised. This is an
* input/output parameter.
*
* \return 0 if successful.
*/
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *pt );
#endif
#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d );
#endif
/**
* \brief Randomize projective x/z coordinates:
* (X, Z) -> (l X, l Z) for random l
*
* \param grp pointer to the group representing the curve
*
* \param P the point on the curve to be randomised given with
* projective coordinates. This is an input/output parameter.
*
* \param f_rng a function pointer to the random number generator
*
* \param p_rng a pointer to the random number generator state
*
* \return 0 if successful
*/
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
#endif
/**
* \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1.
*
* \param grp pointer to the group representing the curve
*
* \param P pointer to the point to be normalised. This is an
* input/output parameter.
*
* \return 0 if successful
*/
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *P );
#endif
#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
#endif /* ecp_alt.h */

View file

@ -1000,25 +1000,20 @@ static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
#define ADD( j ) add32( &cur, A( j ), &c );
#define SUB( j ) sub32( &cur, A( j ), &c );
#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
#define biL (ciL << 3) /* bits in limb */
/*
* Helpers for the main 'loop'
* (see fix_negative for the motivation of C)
*/
#define INIT( b ) \
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \
signed char c = 0, cc; \
uint32_t cur; \
size_t i = 0, bits = (b); \
mbedtls_mpi C; \
mbedtls_mpi_uint Cp[ (b) / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \
\
C.s = 1; \
C.n = (b) / 8 / sizeof( mbedtls_mpi_uint) + 1; \
C.p = Cp; \
memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \
\
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, (b) * 2 / 8 / \
sizeof( mbedtls_mpi_uint ) ) ); \
/* N is the size of the product of two b-bit numbers, plus one */ \
/* limb for fix_negative */ \
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, ( b ) * 2 / biL + 1 ) ); \
LOAD32;
#define NEXT \
@ -1033,33 +1028,32 @@ static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
STORE32; i++; \
cur = c > 0 ? c : 0; STORE32; \
cur = 0; while( ++i < MAX32 ) { STORE32; } \
if( c < 0 ) MBEDTLS_MPI_CHK( fix_negative( N, c, &C, bits ) );
if( c < 0 ) fix_negative( N, c, bits );
/*
* If the result is negative, we get it in the form
* c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
*/
static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits )
static inline void fix_negative( mbedtls_mpi *N, signed char c, size_t bits )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
/* C = - c * 2^(bits + 32) */
#if !defined(MBEDTLS_HAVE_INT64)
((void) bits);
#else
if( bits == 224 )
C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32;
else
#endif
C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c;
/* N = - ( C - N ) */
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) );
/* Set N := N - 2^bits */
--N->p[0];
for( i = 0; i <= bits / 8 / sizeof( mbedtls_mpi_uint ); i++ )
{
N->p[i] = ~(mbedtls_mpi_uint)0 - N->p[i];
}
N->s = -1;
cleanup:
return( ret );
/* Add |c| * 2^(bits + 32) to the absolute value. Since c and N are
* negative, this adds c * 2^(bits + 32). */
mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c;
#if defined(MBEDTLS_HAVE_INT64)
if( bits == 224 )
msw <<= 32;
#endif
N->p[bits / 8 / sizeof( mbedtls_mpi_uint)] += msw;
}
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)

View file

@ -28,7 +28,7 @@
#endif
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#include "entropy_poll.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
@ -105,6 +105,11 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
{
/* If the context was already free, don't call free() again.
* This is important for mutexes which don't allow double-free. */
if( ctx->accumulator_started == -1 )
return;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &ctx->mutex );
#endif
@ -118,7 +123,7 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
#endif
ctx->source_count = 0;
mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
ctx->accumulator_started = 0;
ctx->accumulator_started = -1;
}
int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
@ -452,15 +457,21 @@ int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
#if defined(MBEDTLS_FS_IO)
int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
{
int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
FILE *f;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
FILE *f = NULL;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
if( ( f = fopen( path, "wb" ) ) == NULL )
return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
{
ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
goto exit;
}
if( ( f = fopen( path, "wb" ) ) == NULL )
{
ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
goto exit;
}
if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
{
@ -473,7 +484,9 @@ int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *p
exit:
mbedtls_platform_zeroize( buf, sizeof( buf ) );
fclose( f );
if( f != NULL )
fclose( f );
return( ret );
}

View file

@ -29,7 +29,7 @@
#if defined(MBEDTLS_ENTROPY_C)
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#include "entropy_poll.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_TIMING_C)
@ -106,6 +106,21 @@ static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
#endif /* SYS_getrandom */
#endif /* __linux__ || __midipix__ */
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/param.h>
#if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \
(defined(__DragonFly__) && __DragonFly_version >= 500700)
#include <errno.h>
#include <sys/random.h>
#define HAVE_GETRANDOM
static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
{
return getrandom( buf, buflen, flags );
}
#endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) ||
(__DragonFly__ && __DragonFly_version >= 500700) */
#endif /* __FreeBSD__ || __DragonFly__ */
/*
* Some BSD systems provide KERN_ARND.
* This is equivalent to reading from /dev/urandom, only it doesn't require an
@ -202,13 +217,13 @@ int mbedtls_null_entropy_poll( void *data,
{
((void) data);
((void) output);
*olen = 0;
*olen = 0;
if( len < sizeof(unsigned char) )
return( 0 );
output[0] = 0;
*olen = sizeof(unsigned char);
return( 0 );
}
#endif

97
library/entropy_poll.h Normal file
View file

@ -0,0 +1,97 @@
/**
* \file entropy_poll.h
*
* \brief Platform-specific and custom entropy polling functions
*/
/*
* 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_ENTROPY_POLL_H
#define MBEDTLS_ENTROPY_POLL_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Default thresholds for built-in sources, in bytes
*/
#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */
#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */
#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE)
#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */
#endif
/**
* \brief Entropy poll callback that provides 0 entropy.
*/
#if defined(MBEDTLS_TEST_NULL_ENTROPY)
int mbedtls_null_entropy_poll( void *data,
unsigned char *output, size_t len, size_t *olen );
#endif
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
/**
* \brief Platform-specific entropy poll callback
*/
int mbedtls_platform_entropy_poll( void *data,
unsigned char *output, size_t len, size_t *olen );
#endif
#if defined(MBEDTLS_TIMING_C)
/**
* \brief mbedtls_timing_hardclock-based entropy poll callback
*/
int mbedtls_hardclock_poll( void *data,
unsigned char *output, size_t len, size_t *olen );
#endif
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
/**
* \brief Entropy poll callback for a hardware source
*
* \warning This is not provided by mbed TLS!
* See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h.
*
* \note This must accept NULL as its first argument.
*/
int mbedtls_hardware_poll( void *data,
unsigned char *output, size_t len, size_t *olen );
#endif
#if defined(MBEDTLS_ENTROPY_NV_SEED)
/**
* \brief Entropy poll callback for a non-volatile seed file
*
* \note This must accept NULL as its first argument.
*/
int mbedtls_nv_seed_poll( void *data,
unsigned char *output, size_t len, size_t *olen );
#endif
#ifdef __cplusplus
}
#endif
#endif /* entropy_poll.h */

View file

@ -146,10 +146,6 @@
#include "mbedtls/oid.h"
#endif
#if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h"
#endif
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
#include "mbedtls/pem.h"
#endif
@ -820,11 +816,6 @@ const char * mbedtls_low_level_strerr( int error_code )
return( "OID - output buffer is too small" );
#endif /* MBEDTLS_OID_C */
#if defined(MBEDTLS_PADLOCK_C)
case -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED):
return( "PADLOCK - Input data should be aligned" );
#endif /* MBEDTLS_PADLOCK_C */
#if defined(MBEDTLS_PLATFORM_C)
case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED):
return( "PLATFORM - Hardware accelerator failed" );

View file

@ -38,7 +38,7 @@
#include <string.h>
#if defined(MBEDTLS_AESNI_C)
#include "mbedtls/aesni.h"
#include "aesni.h"
#endif
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
@ -819,6 +819,15 @@ int mbedtls_gcm_self_test( int verbose )
add_len_test_data[i],
pt_test_data[pt_index_test_data[i]],
buf, 16, tag_buf );
#if defined(MBEDTLS_GCM_ALT)
/* Allow alternative implementations to only support 12-byte nonces. */
if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
iv_len_test_data[i] != 12 )
{
mbedtls_printf( "skipped\n" );
break;
}
#endif /* defined(MBEDTLS_GCM_ALT) */
if( ret != 0 )
goto exit;

View file

@ -54,10 +54,6 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
}
/*
@ -129,6 +125,10 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
return( ret );
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
/*
* Set initial working state.
* Use the V memory location, which is currently all 0, to initialize the
@ -254,6 +254,11 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
return( ret );
/* The mutex is initialized iff the md context is set up. */
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
md_size = mbedtls_md_get_size( md_info );
/*
@ -421,14 +426,13 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
return;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &ctx->mutex );
/* The mutex is initialized iff the md context is set up. */
if( ctx->md_ctx.md_info != NULL )
mbedtls_mutex_free( &ctx->mutex );
#endif
mbedtls_md_free( &ctx->md_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
}
#if defined(MBEDTLS_FS_IO)

View file

@ -1,5 +1,5 @@
/**
* \file mbedtls_md.c
* \file md.c
*
* \brief Generic message digest wrapper for mbed TLS
*
@ -26,7 +26,7 @@
#if defined(MBEDTLS_MD_C)
#include "mbedtls/md.h"
#include "mbedtls/md_internal.h"
#include "md_wrap.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"

90
library/md_wrap.h Normal file
View file

@ -0,0 +1,90 @@
/**
* \file md_wrap.h
*
* \brief Message digest wrappers.
*
* \warning This in an internal header. Do not include directly.
*
* \author Adriaan de Jong <dejong@fox-it.com>
*/
/*
* 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_MD_WRAP_H
#define MBEDTLS_MD_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/md.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Message digest information.
* Allows message digest functions to be called in a generic way.
*/
struct mbedtls_md_info_t
{
/** Name of the message digest */
const char * name;
/** Digest identifier */
mbedtls_md_type_t type;
/** Output length of the digest function in bytes */
unsigned char size;
/** Block length of the digest function in bytes */
unsigned char block_size;
};
#if defined(MBEDTLS_MD2_C)
extern const mbedtls_md_info_t mbedtls_md2_info;
#endif
#if defined(MBEDTLS_MD4_C)
extern const mbedtls_md_info_t mbedtls_md4_info;
#endif
#if defined(MBEDTLS_MD5_C)
extern const mbedtls_md_info_t mbedtls_md5_info;
#endif
#if defined(MBEDTLS_RIPEMD160_C)
extern const mbedtls_md_info_t mbedtls_ripemd160_info;
#endif
#if defined(MBEDTLS_SHA1_C)
extern const mbedtls_md_info_t mbedtls_sha1_info;
#endif
#if defined(MBEDTLS_SHA256_C)
extern const mbedtls_md_info_t mbedtls_sha224_info;
extern const mbedtls_md_info_t mbedtls_sha256_info;
#endif
#if defined(MBEDTLS_SHA512_C)
#if !defined(MBEDTLS_SHA512_NO_SHA384)
extern const mbedtls_md_info_t mbedtls_sha384_info;
#endif
extern const mbedtls_md_info_t mbedtls_sha512_info;
#endif
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_MD_WRAP_H */

195
library/mps_common.h Normal file
View file

@ -0,0 +1,195 @@
/*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/**
* \file mps_common.h
*
* \brief Common functions and macros used by MPS
*/
#ifndef MBEDTLS_MPS_COMMON_H
#define MBEDTLS_MPS_COMMON_H
#include "mps_error.h"
#include <stdio.h>
/**
* \name SECTION: MPS Configuration
*
* \{
*/
/*! This flag controls whether the MPS-internal components
* (reader, writer, Layer 1-3) perform validation of the
* expected abstract state at the entry of API calls.
*
* Context: All MPS API functions impose assumptions/preconditions on the
* context on which they operate. For example, every structure has a notion of
* state integrity which is established by `xxx_init()` and preserved by any
* calls to the MPS API which satisfy their preconditions and either succeed,
* or fail with an error code which is explicitly documented to not corrupt
* structure integrity (such as WANT_READ and WANT_WRITE);
* apart from `xxx_init()` any function assumes state integrity as a
* precondition (but usually more). If any of the preconditions is violated,
* the function's behavior is entirely undefined.
* In addition to state integrity, all MPS structures have a more refined
* notion of abstract state that the API operates on. For example, all layers
* have a notion of 'abtract read state' which indicates if incoming data has
* been passed to the user, e.g. through mps_l2_read_start() for Layer 2
* or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to
* call these reading functions again until the incoming data has been
* explicitly 'consumed', e.g. through mps_l2_read_consume() for Layer 2 or
* mps_l3_read_consume() on Layer 3. However, even if it doesn't make sense,
* it's a design choice whether the API should fail gracefully on such
* non-sensical calls or not, and that's what this option is about:
*
* This option determines whether the expected abstract state
* is part of the API preconditions or not: If the option is set,
* then the abstract state is not part of the precondition and is
* thus required to be validated by the implementation. If an unexpected
* abstract state is encountered, the implementation must fail gracefully
* with error #MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED.
* Conversely, if this option is not set, then the expected abstract state
* is included in the preconditions of the respective API calls, and
* an implementation's behaviour is undefined if the abstract state is
* not as expected.
*
* For example: Enabling this makes mps_l2_read_done() fail if
* no incoming record is currently open; disabling this would
* lead to undefined behavior in this case.
*
* Comment this to remove state validation.
*/
#define MBEDTLS_MPS_STATE_VALIDATION
/*! This flag enables/disables assertions on the internal state of MPS.
*
* Assertions are sanity checks that should never trigger when MPS
* is used within the bounds of its API and preconditions.
*
* Enabling this increases security by limiting the scope of
* potential bugs, but comes at the cost of increased code size.
*
* Note: So far, there is no guiding principle as to what
* expected conditions merit an assertion, and which don't.
*
* Comment this to disable assertions.
*/
#define MBEDTLS_MPS_ENABLE_ASSERTIONS
/*! This flag controls whether tracing for MPS should be enabled. */
//#define MBEDTLS_MPS_ENABLE_TRACE
#if defined(MBEDTLS_MPS_STATE_VALIDATION)
#define MBEDTLS_MPS_STATE_VALIDATE_RAW( cond, string ) \
do \
{ \
if( !(cond) ) \
{ \
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, string ); \
MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED ); \
} \
} while( 0 )
#else /* MBEDTLS_MPS_STATE_VALIDATION */
#define MBEDTLS_MPS_STATE_VALIDATE_RAW( cond, string ) \
do \
{ \
( cond ); \
} while( 0 )
#endif /* MBEDTLS_MPS_STATE_VALIDATION */
#if defined(MBEDTLS_MPS_ENABLE_ASSERTIONS)
#define MBEDTLS_MPS_ASSERT_RAW( cond, string ) \
do \
{ \
if( !(cond) ) \
{ \
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, string ); \
MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_INTERNAL_ERROR ); \
} \
} while( 0 )
#else /* MBEDTLS_MPS_ENABLE_ASSERTIONS */
#define MBEDTLS_MPS_ASSERT_RAW( cond, string ) do {} while( 0 )
#endif /* MBEDTLS_MPS_ENABLE_ASSERTIONS */
/* \} name SECTION: MPS Configuration */
/**
* \name SECTION: Common types
*
* Various common types used throughout MPS.
* \{
*/
/** \brief The type of buffer sizes and offsets used in MPS structures.
*
* This is an unsigned integer type that should be large enough to
* hold the length of any buffer or message processed by MPS.
*
* The reason to pick a value as small as possible here is
* to reduce the size of MPS structures.
*
* \warning Care has to be taken when using a narrower type
* than ::mbedtls_mps_size_t here because of
* potential truncation during conversion.
*
* \warning Handshake messages in TLS may be up to 2^24 ~ 16Mb in size.
* If mbedtls_mps_[opt_]stored_size_t is smaller than that, the
* maximum handshake message is restricted accordingly.
*
* For now, we use the default type of size_t throughout, and the use of
* smaller types or different types for ::mbedtls_mps_size_t and
* ::mbedtls_mps_stored_size_t is not yet supported.
*
*/
typedef size_t mbedtls_mps_stored_size_t;
#define MBEDTLS_MPS_STORED_SIZE_MAX ( (mbedtls_mps_stored_size_t) -1 )
/** \brief The type of buffer sizes and offsets used in the MPS API
* and implementation.
*
* This must be at least as wide as ::mbedtls_stored_size_t but
* may be chosen to be strictly larger if more suitable for the
* target architecture.
*
* For example, in a test build for ARM Thumb, using uint_fast16_t
* instead of uint16_t reduced the code size from 1060 Byte to 962 Byte,
* so almost 10%.
*/
typedef size_t mbedtls_mps_size_t;
#define MBEDTLS_MPS_SIZE_MAX ( (mbedtls_mps_size_t) -1 )
#if MBEDTLS_MPS_STORED_SIZE_MAX > MBEDTLS_MPS_SIZE_MAX
#error "Misconfiguration of mbedtls_mps_size_t and mbedtls_mps_stored_size_t."
#endif
/* \} SECTION: Common types */
#endif /* MBEDTLS_MPS_COMMON_H */

103
library/mps_error.h Normal file
View file

@ -0,0 +1,103 @@
/*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/**
* \file mps_error.h
*
* \brief Error codes used by MPS
*/
#ifndef MBEDTLS_MPS_ERROR_H
#define MBEDTLS_MPS_ERROR_H
/* TODO: The error code allocation needs to be revisited:
*
* - Should we make (some of) the MPS Reader error codes public?
* If so, we need to adjust MBEDTLS_MPS_READER_MAKE_ERROR() to hit
* a gap in the Mbed TLS public error space.
* If not, we have to make sure we don't forward those errors
* at the level of the public API -- no risk at the moment as
* long as MPS is an experimental component not accessible from
* public API.
*/
/**
* \name SECTION: MPS general error codes
*
* \{
*/
#ifndef MBEDTLS_MPS_ERR_BASE
#define MBEDTLS_MPS_ERR_BASE ( 0 )
#endif
#define MBEDTLS_MPS_MAKE_ERROR(code) \
( -( MBEDTLS_MPS_ERR_BASE | (code) ) )
#define MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED MBEDTLS_MPS_MAKE_ERROR( 0x1 )
#define MBEDTLS_ERR_MPS_INTERNAL_ERROR MBEDTLS_MPS_MAKE_ERROR( 0x2 )
/* \} name SECTION: MPS general error codes */
/**
* \name SECTION: MPS Reader error codes
*
* \{
*/
#ifndef MBEDTLS_MPS_READER_ERR_BASE
#define MBEDTLS_MPS_READER_ERR_BASE ( 1 << 8 )
#endif
#define MBEDTLS_MPS_READER_MAKE_ERROR(code) \
( -( MBEDTLS_MPS_READER_ERR_BASE | (code) ) )
/*! An attempt to reclaim the data buffer from a reader failed because
* the user hasn't yet read and committed all of it. */
#define MBEDTLS_ERR_MPS_READER_DATA_LEFT MBEDTLS_MPS_READER_MAKE_ERROR( 0x1 )
/*! An invalid argument was passed to the reader. */
#define MBEDTLS_ERR_MPS_READER_INVALID_ARG MBEDTLS_MPS_READER_MAKE_ERROR( 0x2 )
/*! An attempt to move a reader to consuming mode through mbedtls_mps_reader_feed()
* after pausing failed because the provided data is not sufficient to serve the
* read requests that led to the pausing. */
#define MBEDTLS_ERR_MPS_READER_NEED_MORE MBEDTLS_MPS_READER_MAKE_ERROR( 0x3 )
/*! A get request failed because not enough data is available in the reader. */
#define MBEDTLS_ERR_MPS_READER_OUT_OF_DATA MBEDTLS_MPS_READER_MAKE_ERROR( 0x4 )
/*!< A get request after pausing and reactivating the reader failed because
* the request is not in line with the request made prior to pausing. The user
* must not change it's 'strategy' after pausing and reactivating a reader. */
#define MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS MBEDTLS_MPS_READER_MAKE_ERROR( 0x5 )
/*! An attempt to reclaim the data buffer from a reader failed because the reader
* has no accumulator it can use to backup the data that hasn't been processed. */
#define MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR MBEDTLS_MPS_READER_MAKE_ERROR( 0x6 )
/*! An attempt to reclaim the data buffer from a reader failed because the
* accumulator passed to the reader is not large enough to hold both the
* data that hasn't been processed and the excess of the last read-request. */
#define MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL MBEDTLS_MPS_READER_MAKE_ERROR( 0x7 )
/* \} name SECTION: MPS Reader error codes */
#endif /* MBEDTLS_MPS_ERROR_H */

564
library/mps_reader.c Normal file
View file

@ -0,0 +1,564 @@
/*
* Message Processing Stack, Reader implementation
*
* 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.
*
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
#include "common.h"
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
#include "mps_reader.h"
#include "mps_common.h"
#include "mps_trace.h"
#include <string.h>
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
#endif
#if defined(MBEDTLS_MPS_ENABLE_TRACE)
static int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER;
#endif /* MBEDTLS_MPS_ENABLE_TRACE */
/*
* GENERAL NOTE ON CODING STYLE
*
* The following code intentionally separates memory loads
* and stores from other operations (arithmetic or branches).
* This leads to the introduction of many local variables
* and significantly increases the C-code line count, but
* should not increase the size of generated assembly.
*
* The reason for this is twofold:
* (1) It will ease verification efforts using the VST
* (Verified Software Toolchain)
* whose program logic cannot directly reason
* about instructions containing a load or store in
* addition to other operations (e.g. *p = *q or
* tmp = *p + 42).
* (2) Operating on local variables and writing the results
* back to the target contexts on success only
* allows to maintain structure invariants even
* on failure - this in turn has two benefits:
* (2.a) If for some reason an error code is not caught
* and operation continues, functions are nonetheless
* called with sane contexts, reducing the risk
* of dangerous behavior.
* (2.b) Randomized testing is easier if structures
* remain intact even in the face of failing
* and/or non-sensical calls.
* Moreover, it might even reduce code-size because
* the compiler need not write back temporary results
* to memory in case of failure.
*
*/
static inline int mps_reader_is_accumulating(
mbedtls_mps_reader const *rd )
{
mbedtls_mps_size_t acc_remaining;
if( rd->acc == NULL )
return( 0 );
acc_remaining = rd->acc_share.acc_remaining;
return( acc_remaining > 0 );
}
static inline int mps_reader_is_producing(
mbedtls_mps_reader const *rd )
{
unsigned char *frag = rd->frag;
return( frag == NULL );
}
static inline int mps_reader_is_consuming(
mbedtls_mps_reader const *rd )
{
return( !mps_reader_is_producing( rd ) );
}
static inline mbedtls_mps_size_t mps_reader_get_fragment_offset(
mbedtls_mps_reader const *rd )
{
unsigned char *acc = rd->acc;
mbedtls_mps_size_t frag_offset;
if( acc == NULL )
return( 0 );
frag_offset = rd->acc_share.frag_offset;
return( frag_offset );
}
static inline mbedtls_mps_size_t mps_reader_serving_from_accumulator(
mbedtls_mps_reader const *rd )
{
mbedtls_mps_size_t frag_offset, end;
frag_offset = mps_reader_get_fragment_offset( rd );
end = rd->end;
return( end < frag_offset );
}
static inline void mps_reader_zero( mbedtls_mps_reader *rd )
{
/* A plain memset() would likely be more efficient,
* but the current way of zeroing makes it harder
* to overlook fields which should not be zero-initialized.
* It's also more suitable for FV efforts since it
* doesn't require reasoning about structs being
* interpreted as unstructured binary blobs. */
static mbedtls_mps_reader const zero =
{ .frag = NULL,
.frag_len = 0,
.commit = 0,
.end = 0,
.pending = 0,
.acc = NULL,
.acc_len = 0,
.acc_available = 0,
.acc_share = { .acc_remaining = 0 }
};
*rd = zero;
}
int mbedtls_mps_reader_init( mbedtls_mps_reader *rd,
unsigned char *acc,
mbedtls_mps_size_t acc_len )
{
MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_init" );
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"* Accumulator size: %u bytes", (unsigned) acc_len );
mps_reader_zero( rd );
rd->acc = acc;
rd->acc_len = acc_len;
MBEDTLS_MPS_TRACE_RETURN( 0 );
}
int mbedtls_mps_reader_free( mbedtls_mps_reader *rd )
{
MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_free" );
mps_reader_zero( rd );
MBEDTLS_MPS_TRACE_RETURN( 0 );
}
int mbedtls_mps_reader_feed( mbedtls_mps_reader *rd,
unsigned char *new_frag,
mbedtls_mps_size_t new_frag_len )
{
mbedtls_mps_size_t copy_to_acc;
MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_feed" );
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"* Fragment length: %u bytes", (unsigned) new_frag_len );
if( new_frag == NULL )
MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_INVALID_ARG );
MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_producing( rd ),
"mbedtls_mps_reader_feed() requires reader to be in producing mode" );
if( mps_reader_is_accumulating( rd ) )
{
unsigned char *acc = rd->acc;
mbedtls_mps_size_t acc_remaining = rd->acc_share.acc_remaining;
mbedtls_mps_size_t acc_available = rd->acc_available;
/* Skip over parts of the accumulator that have already been filled. */
acc += acc_available;
copy_to_acc = acc_remaining;
if( copy_to_acc > new_frag_len )
copy_to_acc = new_frag_len;
/* Copy new contents to accumulator. */
memcpy( acc, new_frag, copy_to_acc );
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Copy new data of size %u of %u into accumulator at offset %u",
(unsigned) copy_to_acc, (unsigned) new_frag_len, (unsigned) acc_available );
/* Check if, with the new fragment, we have enough data. */
acc_remaining -= copy_to_acc;
if( acc_remaining > 0 )
{
/* We need to accumulate more data. Stay in producing mode. */
acc_available += copy_to_acc;
rd->acc_share.acc_remaining = acc_remaining;
rd->acc_available = acc_available;
MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_NEED_MORE );
}
/* We have filled the accumulator: Move to consuming mode. */
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Enough data available to serve user request" );
/* Remember overlap of accumulator and fragment. */
rd->acc_share.frag_offset = acc_available;
acc_available += copy_to_acc;
rd->acc_available = acc_available;
}
else /* Not accumulating */
{
rd->acc_share.frag_offset = 0;
}
rd->frag = new_frag;
rd->frag_len = new_frag_len;
rd->commit = 0;
rd->end = 0;
MBEDTLS_MPS_TRACE_RETURN( 0 );
}
int mbedtls_mps_reader_get( mbedtls_mps_reader *rd,
mbedtls_mps_size_t desired,
unsigned char **buffer,
mbedtls_mps_size_t *buflen )
{
unsigned char *frag;
mbedtls_mps_size_t frag_len, frag_offset, end, frag_fetched, frag_remaining;
MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_get" );
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"* Bytes requested: %u", (unsigned) desired );
MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ),
"mbedtls_mps_reader_get() requires reader to be in consuming mode" );
end = rd->end;
frag_offset = mps_reader_get_fragment_offset( rd );
/* Check if we're still serving from the accumulator. */
if( mps_reader_serving_from_accumulator( rd ) )
{
/* Illustration of supported and unsupported cases:
*
* - Allowed #1
*
* +-----------------------------------+
* | frag |
* +-----------------------------------+
*
* end end+desired
* | |
* +-----v-------v-------------+
* | acc |
* +---------------------------+
* | |
* frag_offset acc_available
*
* - Allowed #2
*
* +-----------------------------------+
* | frag |
* +-----------------------------------+
*
* end end+desired
* | |
* +----------v----------------v
* | acc |
* +---------------------------+
* | |
* frag_offset acc_available
*
* - Not allowed #1 (could be served, but we don't actually use it):
*
* +-----------------------------------+
* | frag |
* +-----------------------------------+
*
* end end+desired
* | |
* +------v-------------v------+
* | acc |
* +---------------------------+
* | |
* frag_offset acc_available
*
*
* - Not allowed #2 (can't be served with a contiguous buffer):
*
* +-----------------------------------+
* | frag |
* +-----------------------------------+
*
* end end + desired
* | |
* +------v--------------------+ v
* | acc |
* +---------------------------+
* | |
* frag_offset acc_available
*
* In case of Allowed #2 we're switching to serve from
* `frag` starting from the next call to mbedtls_mps_reader_get().
*/
unsigned char *acc;
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Serve the request from the accumulator" );
if( frag_offset - end < desired )
{
mbedtls_mps_size_t acc_available;
acc_available = rd->acc_available;
if( acc_available - end != desired )
{
/* It might be possible to serve some of these situations by
* making additional space in the accumulator, removing those
* parts that have already been committed.
* On the other hand, this brings additional complexity and
* enlarges the code size, while there doesn't seem to be a use
* case where we don't attempt exactly the same `get` calls when
* resuming on a reader than what we tried before pausing it.
* If we believe we adhere to this restricted usage throughout
* the library, this check is a good opportunity to
* validate this. */
MBEDTLS_MPS_TRACE_RETURN(
MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS );
}
}
acc = rd->acc;
acc += end;
*buffer = acc;
if( buflen != NULL )
*buflen = desired;
end += desired;
rd->end = end;
rd->pending = 0;
MBEDTLS_MPS_TRACE_RETURN( 0 );
}
/* Attempt to serve the request from the current fragment */
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Serve the request from the current fragment." );
frag_len = rd->frag_len;
frag_fetched = end - frag_offset; /* The amount of data from the current
* fragment that has already been passed
* to the user. */
frag_remaining = frag_len - frag_fetched; /* Remaining data in fragment */
/* Check if we can serve the read request from the fragment. */
if( frag_remaining < desired )
{
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"There's not enough data in the current fragment "
"to serve the request." );
/* There's not enough data in the current fragment,
* so either just RETURN what we have or fail. */
if( buflen == NULL )
{
if( frag_remaining > 0 )
{
rd->pending = desired - frag_remaining;
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Remember to collect %u bytes before re-opening",
(unsigned) rd->pending );
}
MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
}
desired = frag_remaining;
}
/* There's enough data in the current fragment to serve the
* (potentially modified) read request. */
frag = rd->frag;
frag += frag_fetched;
*buffer = frag;
if( buflen != NULL )
*buflen = desired;
end += desired;
rd->end = end;
rd->pending = 0;
MBEDTLS_MPS_TRACE_RETURN( 0 );
}
int mbedtls_mps_reader_commit( mbedtls_mps_reader *rd )
{
mbedtls_mps_size_t end;
MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_commit" );
MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ),
"mbedtls_mps_reader_commit() requires reader to be in consuming mode" );
end = rd->end;
rd->commit = end;
MBEDTLS_MPS_TRACE_RETURN( 0 );
}
int mbedtls_mps_reader_reclaim( mbedtls_mps_reader *rd,
int *paused )
{
unsigned char *frag, *acc;
mbedtls_mps_size_t pending, commit;
mbedtls_mps_size_t acc_len, frag_offset, frag_len;
MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_reclaim" );
if( paused != NULL )
*paused = 0;
MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ),
"mbedtls_mps_reader_reclaim() requires reader to be in consuming mode" );
frag = rd->frag;
acc = rd->acc;
pending = rd->pending;
commit = rd->commit;
frag_len = rd->frag_len;
frag_offset = mps_reader_get_fragment_offset( rd );
if( pending == 0 )
{
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"No unsatisfied read-request has been logged." );
/* Check if there's data left to be consumed. */
if( commit < frag_offset || commit - frag_offset < frag_len )
{
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"There is data left to be consumed." );
rd->end = commit;
MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_DATA_LEFT );
}
rd->acc_available = 0;
rd->acc_share.acc_remaining = 0;
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Fragment has been fully processed and committed." );
}
else
{
int overflow;
mbedtls_mps_size_t acc_backup_offset;
mbedtls_mps_size_t acc_backup_len;
mbedtls_mps_size_t frag_backup_offset;
mbedtls_mps_size_t frag_backup_len;
mbedtls_mps_size_t backup_len;
mbedtls_mps_size_t acc_len_needed;
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"There has been an unsatisfied read with %u bytes overhead.",
(unsigned) pending );
if( acc == NULL )
{
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"No accumulator present" );
MBEDTLS_MPS_TRACE_RETURN(
MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR );
}
acc_len = rd->acc_len;
/* Check if the upper layer has already fetched
* and committed the contents of the accumulator. */
if( commit < frag_offset )
{
/* No, accumulator is still being processed. */
frag_backup_offset = 0;
frag_backup_len = frag_len;
acc_backup_offset = commit;
acc_backup_len = frag_offset - commit;
}
else
{
/* Yes, the accumulator is already processed. */
frag_backup_offset = commit - frag_offset;
frag_backup_len = frag_len - frag_backup_offset;
acc_backup_offset = 0;
acc_backup_len = 0;
}
backup_len = acc_backup_len + frag_backup_len;
acc_len_needed = backup_len + pending;
overflow = 0;
overflow |= ( backup_len < acc_backup_len );
overflow |= ( acc_len_needed < backup_len );
if( overflow || acc_len < acc_len_needed )
{
/* Except for the different return code, we behave as if
* there hadn't been a call to mbedtls_mps_reader_get()
* since the last commit. */
rd->end = commit;
rd->pending = 0;
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR,
"The accumulator is too small to handle the backup." );
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR,
"* Size: %u", (unsigned) acc_len );
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR,
"* Needed: %u (%u + %u)",
(unsigned) acc_len_needed,
(unsigned) backup_len, (unsigned) pending );
MBEDTLS_MPS_TRACE_RETURN(
MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL );
}
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Fragment backup: %u", (unsigned) frag_backup_len );
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Accumulator backup: %u", (unsigned) acc_backup_len );
/* Move uncommitted parts from the accumulator to the front
* of the accumulator. */
memmove( acc, acc + acc_backup_offset, acc_backup_len );
/* Copy uncmmitted parts of the current fragment to the
* accumulator. */
memcpy( acc + acc_backup_len,
frag + frag_backup_offset, frag_backup_len );
rd->acc_available = backup_len;
rd->acc_share.acc_remaining = pending;
if( paused != NULL )
*paused = 1;
}
rd->frag = NULL;
rd->frag_len = 0;
rd->commit = 0;
rd->end = 0;
rd->pending = 0;
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Final state: aa %u, al %u, ar %u",
(unsigned) rd->acc_available, (unsigned) rd->acc_len,
(unsigned) rd->acc_share.acc_remaining );
MBEDTLS_MPS_TRACE_RETURN( 0 );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */

382
library/mps_reader.h Normal file
View file

@ -0,0 +1,382 @@
/*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/**
* \file mps_reader.h
*
* \brief This file defines reader objects, which together with their
* sibling writer objects form the basis for the communication
* between the various layers of the Mbed TLS messaging stack,
* as well as the communication between the messaging stack and
* the (D)TLS handshake protocol implementation.
*
* Readers provide a means of transferring incoming data from
* a 'producer' providing it in chunks of arbitrary size, to
* a 'consumer' which fetches and processes it in chunks of
* again arbitrary, and potentially different, size.
*
* Readers can thus be seen as datagram-to-stream converters,
* and they abstract away the following two tasks from the user:
* 1. The pointer arithmetic of stepping through a producer-
* provided chunk in smaller chunks.
* 2. The merging of incoming data chunks in case the
* consumer requests data in larger chunks than what the
* producer provides.
*
* The basic abstract flow of operation is the following:
* - Initially, the reader is in 'producing mode'.
* - The producer hands an incoming data buffer to the reader,
* moving it from 'producing' to 'consuming' mode.
* - The consumer subsequently fetches and processes the buffer
* content. Once that's done -- or partially done and a consumer's
* request can't be fulfilled -- the producer revokes the reader's
* access to the incoming data buffer, putting the reader back to
* producing mode.
* - The producer subsequently gathers more incoming data and hands
* it to the reader until it switches back to consuming mode
* if enough data is available for the last consumer request to
* be satisfiable.
* - Repeat the above.
*
* The abstract states of the reader from the producer's and
* consumer's perspective are as follows:
*
* - From the perspective of the consumer, the state of the
* reader consists of the following:
* - A byte stream representing (concatenation of) the data
* received through calls to mbedtls_mps_reader_get(),
* - A marker within that byte stream indicating which data
* can be considered processed, and hence need not be retained,
* when the reader is passed back to the producer via
* mbedtls_mps_reader_reclaim().
* The marker is set via mbedtls_mps_reader_commit()
* which places it at the end of the current byte stream.
* The consumer need not be aware of the distinction between consumer
* and producer mode, because it only interfaces with the reader
* when the latter is in consuming mode.
*
* - From the perspective of the producer, the reader's state is one of:
* - Attached: The reader is in consuming mode.
* - Unset: No incoming data buffer is currently managed by the reader,
* and all previously handed incoming data buffers have been
* fully processed. More data needs to be fed into the reader
* via mbedtls_mps_reader_feed().
*
* - Accumulating: No incoming data buffer is currently managed by the
* reader, but some data from the previous incoming data
* buffer hasn't been processed yet and is internally
* held back.
* The Attached state belongs to consuming mode, while the Unset and
* Accumulating states belong to producing mode.
*
* Transitioning from the Unset or Accumulating state to Attached is
* done via successful calls to mbedtls_mps_reader_feed(), while
* transitioning from Attached to either Unset or Accumulating (depending
* on what has been processed) is done via mbedtls_mps_reader_reclaim().
*
* The following diagram depicts the producer-state progression:
*
* +------------------+ reclaim
* | Unset +<-------------------------------------+ get
* +--------|---------+ | +------+
* | | | |
* | | | |
* | feed +---------+---+--+ |
* +--------------------------------------> <---+
* | Attached |
* +--------------------------------------> <---+
* | feed, enough data available +---------+---+--+ |
* | to serve previous consumer request | | |
* | | | |
* +--------+---------+ | +------+
* +----> Accumulating |<-------------------------------------+ commit
* | +---+--------------+ reclaim, previous read request
* | | couldn't be fulfilled
* | |
* +--------+
* feed, need more data to serve
* previous consumer request
* |
* |
* producing mode | consuming mode
* |
*
*/
#ifndef MBEDTLS_READER_H
#define MBEDTLS_READER_H
#include <stdio.h>
#include "mps_common.h"
#include "mps_error.h"
struct mbedtls_mps_reader;
typedef struct mbedtls_mps_reader mbedtls_mps_reader;
/*
* Structure definitions
*/
struct mbedtls_mps_reader
{
unsigned char *frag; /*!< The fragment of incoming data managed by
* the reader; it is provided to the reader
* through mbedtls_mps_reader_feed(). The reader
* does not own the fragment and does not
* perform any allocation operations on it,
* but does have read and write access to it.
*
* The reader is in consuming mode if
* and only if \c frag is not \c NULL. */
mbedtls_mps_stored_size_t frag_len;
/*!< The length of the current fragment.
* Must be 0 if \c frag == \c NULL. */
mbedtls_mps_stored_size_t commit;
/*!< The offset of the last commit, relative
* to the first byte in the fragment, if
* no accumulator is present. If an accumulator
* is present, it is viewed as a prefix to the
* current fragment, and this variable contains
* an offset from the beginning of the accumulator.
*
* This is only used when the reader is in
* consuming mode, i.e. \c frag != \c NULL;
* otherwise, its value is \c 0. */
mbedtls_mps_stored_size_t end;
/*!< The offset of the end of the last chunk
* passed to the user through a call to
* mbedtls_mps_reader_get(), relative to the first
* byte in the fragment, if no accumulator is
* present. If an accumulator is present, it is
* viewed as a prefix to the current fragment, and
* this variable contains an offset from the
* beginning of the accumulator.
*
* This is only used when the reader is in
* consuming mode, i.e. \c frag != \c NULL;
* otherwise, its value is \c 0. */
mbedtls_mps_stored_size_t pending;
/*!< The amount of incoming data missing on the
* last call to mbedtls_mps_reader_get().
* In particular, it is \c 0 if the last call
* was successful.
* If a reader is reclaimed after an
* unsuccessful call to mbedtls_mps_reader_get(),
* this variable is used to have the reader
* remember how much data should be accumulated
* so that the call to mbedtls_mps_reader_get()
* succeeds next time.
* This is only used when the reader is in
* consuming mode, i.e. \c frag != \c NULL;
* otherwise, its value is \c 0. */
/* The accumulator is only needed if we need to be able to pause
* the reader. A few bytes could be saved by moving this to a
* separate struct and using a pointer here. */
unsigned char *acc; /*!< The accumulator is used to gather incoming
* data if a read-request via mbedtls_mps_reader_get()
* cannot be served from the current fragment. */
mbedtls_mps_stored_size_t acc_len;
/*!< The total size of the accumulator. */
mbedtls_mps_stored_size_t acc_available;
/*!< The number of bytes currently gathered in
* the accumulator. This is both used in
* producing and in consuming mode:
* While producing, it is increased until
* it reaches the value of \c acc_remaining below.
* While consuming, it is used to judge if a
* get request can be served from the
* accumulator or not.
* Must not be larger than \c acc_len. */
union
{
mbedtls_mps_stored_size_t acc_remaining;
/*!< This indicates the amount of data still
* to be gathered in the accumulator. It is
* only used in producing mode.
* Must be at most acc_len - acc_available. */
mbedtls_mps_stored_size_t frag_offset;
/*!< If an accumulator is present and in use, this
* field indicates the offset of the current
* fragment from the beginning of the
* accumulator. If no accumulator is present
* or the accumulator is not in use, this is \c 0.
* It is only used in consuming mode.
* Must not be larger than \c acc_available. */
} acc_share;
};
/*
* API organization:
* A reader object is usually prepared and maintained
* by some lower layer and passed for usage to an upper
* layer, and the API naturally splits according to which
* layer is supposed to use the respective functions.
*/
/*
* Maintenance API (Lower layer)
*/
/**
* \brief Initialize a reader object
*
* \param reader The reader to be initialized.
* \param acc The buffer to be used as a temporary accumulator
* in case get requests through mbedtls_mps_reader_get()
* exceed the buffer provided by mbedtls_mps_reader_feed().
* This buffer is owned by the caller and exclusive use
* for reading and writing is given to the reader for the
* duration of the reader's lifetime. It is thus the caller's
* responsibility to maintain (and not touch) the buffer for
* the lifetime of the reader, and to properly zeroize and
* free the memory after the reader has been destroyed.
* \param acc_len The size in Bytes of \p acc.
*
* \return \c 0 on success.
* \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
*/
int mbedtls_mps_reader_init( mbedtls_mps_reader *reader,
unsigned char *acc,
mbedtls_mps_size_t acc_len );
/**
* \brief Free a reader object
*
* \param reader The reader to be freed.
*
* \return \c 0 on success.
* \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
*/
int mbedtls_mps_reader_free( mbedtls_mps_reader *reader );
/**
* \brief Pass chunk of data for the reader to manage.
*
* \param reader The reader context to use. The reader must be
* in producing mode.
* \param buf The buffer to be managed by the reader.
* \param buflen The size in Bytes of \p buffer.
*
* \return \c 0 on success. In this case, the reader will be
* moved to consuming mode and obtains read access
* of \p buf until mbedtls_mps_reader_reclaim()
* is called. It is the responsibility of the caller
* to ensure that the \p buf persists and is not changed
* between successful calls to mbedtls_mps_reader_feed()
* and mbedtls_mps_reader_reclaim().
* \return \c MBEDTLS_ERR_MPS_READER_NEED_MORE if more input data is
* required to fulfill a previous request to mbedtls_mps_reader_get().
* In this case, the reader remains in producing mode and
* takes no ownership of the provided buffer (an internal copy
* is made instead).
* \return Another negative \c MBEDTLS_ERR_READER_XXX error code on
* different kinds of failures.
*/
int mbedtls_mps_reader_feed( mbedtls_mps_reader *reader,
unsigned char *buf,
mbedtls_mps_size_t buflen );
/**
* \brief Reclaim reader's access to the current input buffer.
*
* \param reader The reader context to use. The reader must be
* in consuming mode.
* \param paused If not \c NULL, the integer at address \p paused will be
* modified to indicate whether the reader has been paused
* (value \c 1) or not (value \c 0). Pausing happens if there
* is uncommitted data and a previous request to
* mbedtls_mps_reader_get() has exceeded the bounds of the
* input buffer.
*
* \return \c 0 on success.
* \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
*/
int mbedtls_mps_reader_reclaim( mbedtls_mps_reader *reader,
int *paused );
/*
* Usage API (Upper layer)
*/
/**
* \brief Request data from the reader.
*
* \param reader The reader context to use. The reader must
* be in consuming mode.
* \param desired The desired amount of data to be read, in Bytes.
* \param buffer The address to store the buffer pointer in.
* This must not be \c NULL.
* \param buflen The address to store the actual buffer
* length in, or \c NULL.
*
* \return \c 0 on success. In this case, \c *buf holds the
* address of a buffer of size \c *buflen
* (if \c buflen != \c NULL) or \c desired
* (if \c buflen == \c NULL). The user has read access
* to the buffer and guarantee of stability of the data
* until the next call to mbedtls_mps_reader_reclaim().
* \return #MBEDTLS_ERR_MPS_READER_OUT_OF_DATA if there is not enough
* data available to serve the get request. In this case, the
* reader remains intact and in consuming mode, and the consumer
* should retry the call after a successful cycle of
* mbedtls_mps_reader_reclaim() and mbedtls_mps_reader_feed().
* If, after such a cycle, the consumer requests a different
* amount of data, the result is implementation-defined;
* progress is guaranteed only if the same amount of data
* is requested after a mbedtls_mps_reader_reclaim() and
* mbedtls_mps_reader_feed() cycle.
* \return Another negative \c MBEDTLS_ERR_READER_XXX error
* code for different kinds of failure.
*
* \note Passing \c NULL as \p buflen is a convenient way to
* indicate that fragmentation is not tolerated.
* It's functionally equivalent to passing a valid
* address as buflen and checking \c *buflen == \c desired
* afterwards.
*/
int mbedtls_mps_reader_get( mbedtls_mps_reader *reader,
mbedtls_mps_size_t desired,
unsigned char **buffer,
mbedtls_mps_size_t *buflen );
/**
* \brief Mark data obtained from mbedtls_mps_reader_get() as processed.
*
* This call indicates that all data received from prior calls to
* mbedtls_mps_reader_get() has been or will have been
* processed when mbedtls_mps_reader_reclaim() is called,
* and thus need not be backed up.
*
* This function has no user observable effect until
* mbedtls_mps_reader_reclaim() is called. In particular,
* buffers received from mbedtls_mps_reader_get() remain
* valid until mbedtls_mps_reader_reclaim() is called.
*
* \param reader The reader context to use.
*
* \return \c 0 on success.
* \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
*
*/
int mbedtls_mps_reader_commit( mbedtls_mps_reader *reader );
#endif /* MBEDTLS_READER_H */

127
library/mps_trace.c Normal file
View file

@ -0,0 +1,127 @@
/*
* Message Processing Stack, Trace module
*
* 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.
*
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
#include "common.h"
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
#include "mps_common.h"
#if defined(MBEDTLS_MPS_ENABLE_TRACE)
#include "mps_trace.h"
#include <stdarg.h>
static int trace_depth = 0;
#define color_default "\x1B[0m"
#define color_red "\x1B[1;31m"
#define color_green "\x1B[1;32m"
#define color_yellow "\x1B[1;33m"
#define color_blue "\x1B[1;34m"
#define color_magenta "\x1B[1;35m"
#define color_cyan "\x1B[1;36m"
#define color_white "\x1B[1;37m"
static char const * colors[] =
{
color_default,
color_green,
color_yellow,
color_magenta,
color_cyan,
color_blue,
color_white
};
#define MPS_TRACE_BUF_SIZE 100
void mbedtls_mps_trace_print_msg( int id, int line, const char *format, ... )
{
int ret;
char str[MPS_TRACE_BUF_SIZE];
va_list argp;
va_start( argp, format );
ret = mbedtls_vsnprintf( str, MPS_TRACE_BUF_SIZE, format, argp );
va_end( argp );
if( ret >= 0 && ret < MPS_TRACE_BUF_SIZE )
{
str[ret] = '\0';
mbedtls_printf( "[%d|L%d]: %s\n", id, line, str );
}
}
int mbedtls_mps_trace_get_depth()
{
return trace_depth;
}
void mbedtls_mps_trace_dec_depth()
{
trace_depth--;
}
void mbedtls_mps_trace_inc_depth()
{
trace_depth++;
}
void mbedtls_mps_trace_color( int id )
{
if( id > (int) ( sizeof( colors ) / sizeof( *colors ) ) )
return;
printf( "%s", colors[ id ] );
}
void mbedtls_mps_trace_indent( int level, mbedtls_mps_trace_type ty )
{
if( level > 0 )
{
while( --level )
printf( "| " );
printf( "| " );
}
switch( ty )
{
case MBEDTLS_MPS_TRACE_TYPE_COMMENT:
mbedtls_printf( "@ " );
break;
case MBEDTLS_MPS_TRACE_TYPE_CALL:
mbedtls_printf( "+--> " );
break;
case MBEDTLS_MPS_TRACE_TYPE_ERROR:
mbedtls_printf( "E " );
break;
case MBEDTLS_MPS_TRACE_TYPE_RETURN:
mbedtls_printf( "< " );
break;
default:
break;
}
}
#endif /* MBEDTLS_MPS_ENABLE_TRACE */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */

175
library/mps_trace.h Normal file
View file

@ -0,0 +1,175 @@
/*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/**
* \file mps_trace.h
*
* \brief Tracing module for MPS
*/
#ifndef MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H
#define MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H
#include "common.h"
#include "mps_common.h"
#include "mps_trace.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#define mbedtls_vsnprintf vsnprintf
#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_MPS_ENABLE_TRACE)
/*
* Adapt this to enable/disable tracing output
* from the various layers of the MPS.
*/
#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_1
#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_2
#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_3
#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_4
#define MBEDTLS_MPS_TRACE_ENABLE_READER
#define MBEDTLS_MPS_TRACE_ENABLE_WRITER
/*
* To use the existing trace module, only change
* MBEDTLS_MPS_TRACE_ENABLE_XXX above, but don't modify the
* rest of this file.
*/
typedef enum
{
MBEDTLS_MPS_TRACE_TYPE_COMMENT,
MBEDTLS_MPS_TRACE_TYPE_CALL,
MBEDTLS_MPS_TRACE_TYPE_ERROR,
MBEDTLS_MPS_TRACE_TYPE_RETURN
} mbedtls_mps_trace_type;
#define MBEDTLS_MPS_TRACE_BIT_LAYER_1 1
#define MBEDTLS_MPS_TRACE_BIT_LAYER_2 2
#define MBEDTLS_MPS_TRACE_BIT_LAYER_3 3
#define MBEDTLS_MPS_TRACE_BIT_LAYER_4 4
#define MBEDTLS_MPS_TRACE_BIT_WRITER 5
#define MBEDTLS_MPS_TRACE_BIT_READER 6
#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_1)
#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_1 )
#else
#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_2)
#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_2 )
#else
#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_3)
#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_3 )
#else
#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_4)
#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_4 )
#else
#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_READER)
#define MBEDTLS_MPS_TRACE_MASK_READER (1u << MBEDTLS_MPS_TRACE_BIT_READER )
#else
#define MBEDTLS_MPS_TRACE_MASK_READER 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_WRITER)
#define MBEDTLS_MPS_TRACE_MASK_WRITER (1u << MBEDTLS_MPS_TRACE_BIT_WRITER )
#else
#define MBEDTLS_MPS_TRACE_MASK_WRITER 0
#endif
#define MBEDTLS_MPS_TRACE_MASK ( MBEDTLS_MPS_TRACE_MASK_LAYER_1 | \
MBEDTLS_MPS_TRACE_MASK_LAYER_2 | \
MBEDTLS_MPS_TRACE_MASK_LAYER_3 | \
MBEDTLS_MPS_TRACE_MASK_LAYER_4 | \
MBEDTLS_MPS_TRACE_MASK_READER | \
MBEDTLS_MPS_TRACE_MASK_WRITER )
/* We have to avoid globals because E-ACSL chokes on them...
* Wrap everything in stub functions. */
int mbedtls_mps_trace_get_depth( void );
void mbedtls_mps_trace_inc_depth( void );
void mbedtls_mps_trace_dec_depth( void );
void mbedtls_mps_trace_color( int id );
void mbedtls_mps_trace_indent( int level, mbedtls_mps_trace_type ty );
void mbedtls_mps_trace_print_msg( int id, int line, const char *format, ... );
#define MBEDTLS_MPS_TRACE( type, ... ) \
do { \
if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) ) \
break; \
mbedtls_mps_trace_indent( mbedtls_mps_trace_get_depth(), type ); \
mbedtls_mps_trace_color( mbedtls_mps_trace_id ); \
mbedtls_mps_trace_print_msg( mbedtls_mps_trace_id, __LINE__, __VA_ARGS__ ); \
mbedtls_mps_trace_color( 0 ); \
} while( 0 )
#define MBEDTLS_MPS_TRACE_INIT( ... ) \
do { \
if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) ) \
break; \
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_CALL, __VA_ARGS__ ); \
mbedtls_mps_trace_inc_depth(); \
} while( 0 )
#define MBEDTLS_MPS_TRACE_END( val ) \
do { \
if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) ) \
break; \
MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_RETURN, "%d (-%#04x)", \
(int) (val), -((unsigned)(val)) ); \
mbedtls_mps_trace_dec_depth(); \
} while( 0 )
#define MBEDTLS_MPS_TRACE_RETURN( val ) \
do { \
/* Breaks tail recursion. */ \
int ret__ = val; \
MBEDTLS_MPS_TRACE_END( ret__ ); \
return( ret__ ); \
} while( 0 )
#else /* MBEDTLS_MPS_TRACE */
#define MBEDTLS_MPS_TRACE( type, ... ) do { } while( 0 )
#define MBEDTLS_MPS_TRACE_INIT( ... ) do { } while( 0 )
#define MBEDTLS_MPS_TRACE_END do { } while( 0 )
#define MBEDTLS_MPS_TRACE_RETURN( val ) return( val );
#endif /* MBEDTLS_MPS_TRACE */
#endif /* MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H */

View file

@ -465,6 +465,13 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
/* A limitation of select() is that it only works with file descriptors
* that are strictly less than FD_SETSIZE. This is a limitation of the
* fd_set type. Error out early, because attempting to call FD_SET on a
* large file descriptor is a buffer overflow on typical platforms. */
if( fd >= FD_SETSIZE )
return( MBEDTLS_ERR_NET_POLL_FAILED );
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
/* Ensure that memory sanitizers consider read_fds and write_fds as
@ -584,6 +591,13 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
/* A limitation of select() is that it only works with file descriptors
* that are strictly less than FD_SETSIZE. This is a limitation of the
* fd_set type. Error out early, because attempting to call FD_SET on a
* large file descriptor is a buffer overflow on typical platforms. */
if( fd >= FD_SETSIZE )
return( MBEDTLS_ERR_NET_POLL_FAILED );
FD_ZERO( &read_fds );
FD_SET( fd, &read_fds );

View file

@ -27,7 +27,7 @@
#if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h"
#include "padlock.h"
#include <string.h>

124
library/padlock.h Normal file
View file

@ -0,0 +1,124 @@
/**
* \file padlock.h
*
* \brief VIA PadLock ACE for HW encryption/decryption supported by some
* processors
*
* \warning These functions are only for internal use by other library
* functions; you must not call them directly.
*/
/*
* 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_PADLOCK_H
#define MBEDTLS_PADLOCK_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/aes.h"
#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
#define MBEDTLS_HAVE_ASAN
#endif
#endif
/* Some versions of ASan result in errors about not enough registers */
#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \
!defined(MBEDTLS_HAVE_ASAN)
#ifndef MBEDTLS_HAVE_X86
#define MBEDTLS_HAVE_X86
#endif
#include <stdint.h>
#define MBEDTLS_PADLOCK_RNG 0x000C
#define MBEDTLS_PADLOCK_ACE 0x00C0
#define MBEDTLS_PADLOCK_PHE 0x0C00
#define MBEDTLS_PADLOCK_PMM 0x3000
#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15))
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Internal PadLock detection routine
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param feature The feature to detect
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
int mbedtls_padlock_has_support( int feature );
/**
* \brief Internal PadLock AES-ECB block en(de)cryption
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if success, 1 if operation failed
*/
int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Internal PadLock AES-CBC buffer en(de)cryption
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if success, 1 if operation failed
*/
int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#ifdef __cplusplus
}
#endif
#endif /* HAVE_X86 */
#endif /* padlock.h */

View file

@ -21,7 +21,7 @@
#if defined(MBEDTLS_PK_C)
#include "mbedtls/pk.h"
#include "mbedtls/pk_internal.h"
#include "pk_wrap.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"

View file

@ -20,7 +20,7 @@
#include "common.h"
#if defined(MBEDTLS_PK_C)
#include "mbedtls/pk_internal.h"
#include "pk_wrap.h"
#include "mbedtls/error.h"
/* Even if RSA not activated, for the sake of RSA-alt */

140
library/pk_wrap.h Normal file
View file

@ -0,0 +1,140 @@
/**
* \file pk_wrap.h
*
* \brief Public Key abstraction layer: wrapper functions
*/
/*
* 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_PK_WRAP_H
#define MBEDTLS_PK_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/pk.h"
struct mbedtls_pk_info_t
{
/** Public key type */
mbedtls_pk_type_t type;
/** Type name */
const char *name;
/** Get key size in bits */
size_t (*get_bitlen)( const void * );
/** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */
int (*can_do)( mbedtls_pk_type_t type );
/** Verify signature */
int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len );
/** Make signature */
int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/** Verify signature (restartable) */
int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
void *rs_ctx );
/** Make signature (restartable) */
int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, void *rs_ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/** Decrypt message */
int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/** Encrypt message */
int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/** Check public-private key pair */
int (*check_pair_func)( const void *pub, const void *prv );
/** Allocate a new context */
void * (*ctx_alloc_func)( void );
/** Free the given context */
void (*ctx_free_func)( void *ctx );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/** Allocate the restart context */
void * (*rs_alloc_func)( void );
/** Free the restart context */
void (*rs_free_func)( void *rs_ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/** Interface with the debug module */
void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items );
};
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/* Container for RSA-alt */
typedef struct
{
void *key;
mbedtls_pk_rsa_alt_decrypt_func decrypt_func;
mbedtls_pk_rsa_alt_sign_func sign_func;
mbedtls_pk_rsa_alt_key_len_func key_len_func;
} mbedtls_rsa_alt_context;
#endif
#if defined(MBEDTLS_RSA_C)
extern const mbedtls_pk_info_t mbedtls_rsa_info;
#endif
#if defined(MBEDTLS_ECP_C)
extern const mbedtls_pk_info_t mbedtls_eckey_info;
extern const mbedtls_pk_info_t mbedtls_eckeydh_info;
#endif
#if defined(MBEDTLS_ECDSA_C)
extern const mbedtls_pk_info_t mbedtls_ecdsa_info;
#endif
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
extern const mbedtls_pk_info_t mbedtls_rsa_alt_info;
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
extern const mbedtls_pk_info_t mbedtls_pk_opaque_info;
#endif
#endif /* MBEDTLS_PK_WRAP_H */

View file

@ -487,7 +487,7 @@ int mbedtls_pk_write_key_der( const mbedtls_pk_context *key, unsigned char *buf,
* publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1
* }
*/
#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE
#define RSA_PUB_DER_MAX_BYTES ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE )
/*
* RSA private keys:
@ -504,10 +504,10 @@ int mbedtls_pk_write_key_der( const mbedtls_pk_context *key, unsigned char *buf,
* otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported)
* }
*/
#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \
MBEDTLS_MPI_MAX_SIZE % 2
#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
+ 5 * MPI_MAX_SIZE_2
#define MPI_MAX_SIZE_2 ( MBEDTLS_MPI_MAX_SIZE / 2 + \
MBEDTLS_MPI_MAX_SIZE % 2 )
#define RSA_PRV_DER_MAX_BYTES ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
+ 5 * MPI_MAX_SIZE_2 )
#else /* MBEDTLS_RSA_C */
@ -528,7 +528,7 @@ int mbedtls_pk_write_key_der( const mbedtls_pk_context *key, unsigned char *buf,
* + 2 * ECP_MAX (coords) [1]
* }
*/
#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES
#define ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES )
/*
* EC private keys:
@ -539,7 +539,7 @@ int mbedtls_pk_write_key_der( const mbedtls_pk_context *key, unsigned char *buf,
* publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above
* }
*/
#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES
#define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES )
#else /* MBEDTLS_ECP_C */
@ -548,10 +548,10 @@ int mbedtls_pk_write_key_der( const mbedtls_pk_context *key, unsigned char *buf,
#endif /* MBEDTLS_ECP_C */
#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
#define PUB_DER_MAX_BYTES ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES )
#define PRV_DER_MAX_BYTES ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES )
int mbedtls_pk_write_pubkey_pem( const mbedtls_pk_context *key, unsigned char *buf, size_t size )
{

File diff suppressed because it is too large Load diff

561
library/psa_crypto_cipher.c Normal file
View file

@ -0,0 +1,561 @@
/*
* PSA cipher driver entry points
*/
/*
* 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.
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa_crypto_cipher.h>
#include "psa_crypto_core.h"
#include "psa_crypto_random_impl.h"
#include "mbedtls/cipher.h"
#include "mbedtls/error.h"
#include <string.h>
#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) ) )
#define BUILTIN_KEY_TYPE_DES 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) ) )
#define BUILTIN_ALG_CBC_NO_PADDING 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) ) )
#define BUILTIN_ALG_CBC_PKCS7 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) ) )
#define BUILTIN_KEY_TYPE_CHACHA20 1
#endif
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
psa_algorithm_t alg,
psa_key_type_t key_type,
size_t key_bits,
mbedtls_cipher_id_t* cipher_id )
{
mbedtls_cipher_mode_t mode;
mbedtls_cipher_id_t cipher_id_tmp;
if( PSA_ALG_IS_AEAD( alg ) )
alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 );
if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) )
{
switch( alg )
{
case PSA_ALG_STREAM_CIPHER:
mode = MBEDTLS_MODE_STREAM;
break;
case PSA_ALG_CTR:
mode = MBEDTLS_MODE_CTR;
break;
case PSA_ALG_CFB:
mode = MBEDTLS_MODE_CFB;
break;
case PSA_ALG_OFB:
mode = MBEDTLS_MODE_OFB;
break;
case PSA_ALG_ECB_NO_PADDING:
mode = MBEDTLS_MODE_ECB;
break;
case PSA_ALG_CBC_NO_PADDING:
mode = MBEDTLS_MODE_CBC;
break;
case PSA_ALG_CBC_PKCS7:
mode = MBEDTLS_MODE_CBC;
break;
case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
mode = MBEDTLS_MODE_CCM;
break;
case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
mode = MBEDTLS_MODE_GCM;
break;
case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
mode = MBEDTLS_MODE_CHACHAPOLY;
break;
default:
return( NULL );
}
}
else if( alg == PSA_ALG_CMAC )
mode = MBEDTLS_MODE_ECB;
else
return( NULL );
switch( key_type )
{
case PSA_KEY_TYPE_AES:
cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
break;
case PSA_KEY_TYPE_DES:
/* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
* and 192 for three-key Triple-DES. */
if( key_bits == 64 )
cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
else
cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
/* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
* but two-key Triple-DES is functionally three-key Triple-DES
* with K1=K3, so that's how we present it to mbedtls. */
if( key_bits == 128 )
key_bits = 192;
break;
case PSA_KEY_TYPE_CAMELLIA:
cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
break;
case PSA_KEY_TYPE_ARC4:
cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4;
break;
case PSA_KEY_TYPE_CHACHA20:
cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
break;
default:
return( NULL );
}
if( cipher_id != NULL )
*cipher_id = cipher_id_tmp;
return( mbedtls_cipher_info_from_values( cipher_id_tmp,
(int) key_bits, mode ) );
}
#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) || defined(PSA_CRYPTO_DRIVER_TEST)
static psa_status_t cipher_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
mbedtls_operation_t cipher_operation )
{
int ret = 0;
size_t key_bits;
const mbedtls_cipher_info_t *cipher_info = NULL;
psa_key_type_t key_type = attributes->core.type;
(void)key_buffer_size;
/* Proceed with initializing an mbed TLS cipher context if no driver is
* available for the given algorithm & key. */
mbedtls_cipher_init( &operation->cipher );
operation->alg = alg;
key_bits = attributes->core.bits;
cipher_info = mbedtls_cipher_info_from_psa( alg, key_type,
key_bits, NULL );
if( cipher_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
ret = mbedtls_cipher_setup( &operation->cipher, cipher_info );
if( ret != 0 )
goto exit;
#if defined(BUILTIN_KEY_TYPE_DES)
if( key_type == PSA_KEY_TYPE_DES && key_bits == 128 )
{
/* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
uint8_t keys[24];
memcpy( keys, key_buffer, 16 );
memcpy( keys + 16, key_buffer, 8 );
ret = mbedtls_cipher_setkey( &operation->cipher,
keys,
192, cipher_operation );
}
else
#endif
{
ret = mbedtls_cipher_setkey( &operation->cipher, key_buffer,
(int) key_bits, cipher_operation );
}
if( ret != 0 )
goto exit;
#if defined(BUILTIN_ALG_CBC_NO_PADDING) || \
defined(BUILTIN_ALG_CBC_PKCS7)
switch( alg )
{
case PSA_ALG_CBC_NO_PADDING:
ret = mbedtls_cipher_set_padding_mode( &operation->cipher,
MBEDTLS_PADDING_NONE );
break;
case PSA_ALG_CBC_PKCS7:
ret = mbedtls_cipher_set_padding_mode( &operation->cipher,
MBEDTLS_PADDING_PKCS7 );
break;
default:
/* The algorithm doesn't involve padding. */
ret = 0;
break;
}
if( ret != 0 )
goto exit;
#endif /* BUILTIN_ALG_CBC_NO_PADDING || BUILTIN_ALG_CBC_PKCS7 */
operation->block_length = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) );
operation->iv_length = PSA_CIPHER_IV_LENGTH( key_type, alg );
exit:
return( mbedtls_to_psa_error( ret ) );
}
static psa_status_t cipher_encrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg )
{
return( cipher_setup( operation, attributes,
key_buffer, key_buffer_size,
alg, MBEDTLS_ENCRYPT ) );
}
static psa_status_t cipher_decrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg )
{
return( cipher_setup( operation, attributes,
key_buffer, key_buffer_size,
alg, MBEDTLS_DECRYPT ) );
}
static psa_status_t cipher_set_iv( mbedtls_psa_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length )
{
if( iv_length != operation->iv_length )
return( PSA_ERROR_INVALID_ARGUMENT );
return( mbedtls_to_psa_error(
mbedtls_cipher_set_iv( &operation->cipher,
iv, iv_length ) ) );
}
/* Process input for which the algorithm is set to ECB mode. This requires
* manual processing, since the PSA API is defined as being able to process
* arbitrary-length calls to psa_cipher_update() with ECB mode, but the
* underlying mbedtls_cipher_update only takes full blocks. */
static psa_status_t psa_cipher_update_ecb(
mbedtls_cipher_context_t *ctx,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t block_size = ctx->cipher_info->block_size;
size_t internal_output_length = 0;
*output_length = 0;
if( input_length == 0 )
{
status = PSA_SUCCESS;
goto exit;
}
if( ctx->unprocessed_len > 0 )
{
/* Fill up to block size, and run the block if there's a full one. */
size_t bytes_to_copy = block_size - ctx->unprocessed_len;
if( input_length < bytes_to_copy )
bytes_to_copy = input_length;
memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
input, bytes_to_copy );
input_length -= bytes_to_copy;
input += bytes_to_copy;
ctx->unprocessed_len += bytes_to_copy;
if( ctx->unprocessed_len == block_size )
{
status = mbedtls_to_psa_error(
mbedtls_cipher_update( ctx,
ctx->unprocessed_data,
block_size,
output, &internal_output_length ) );
if( status != PSA_SUCCESS )
goto exit;
output += internal_output_length;
output_size -= internal_output_length;
*output_length += internal_output_length;
ctx->unprocessed_len = 0;
}
}
while( input_length >= block_size )
{
/* Run all full blocks we have, one by one */
status = mbedtls_to_psa_error(
mbedtls_cipher_update( ctx, input,
block_size,
output, &internal_output_length ) );
if( status != PSA_SUCCESS )
goto exit;
input_length -= block_size;
input += block_size;
output += internal_output_length;
output_size -= internal_output_length;
*output_length += internal_output_length;
}
if( input_length > 0 )
{
/* Save unprocessed bytes for later processing */
memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
input, input_length );
ctx->unprocessed_len += input_length;
}
status = PSA_SUCCESS;
exit:
return( status );
}
static psa_status_t cipher_update( mbedtls_psa_cipher_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t expected_output_size;
if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) )
{
/* Take the unprocessed partial block left over from previous
* update calls, if any, plus the input to this call. Remove
* the last partial block, if any. You get the data that will be
* output in this call. */
expected_output_size =
( operation->cipher.unprocessed_len + input_length )
/ operation->block_length * operation->block_length;
}
else
{
expected_output_size = input_length;
}
if( output_size < expected_output_size )
return( PSA_ERROR_BUFFER_TOO_SMALL );
if( operation->alg == PSA_ALG_ECB_NO_PADDING )
{
/* mbedtls_cipher_update has an API inconsistency: it will only
* process a single block at a time in ECB mode. Abstract away that
* inconsistency here to match the PSA API behaviour. */
status = psa_cipher_update_ecb( &operation->cipher,
input,
input_length,
output,
output_size,
output_length );
}
else
{
status = mbedtls_to_psa_error(
mbedtls_cipher_update( &operation->cipher, input,
input_length, output, output_length ) );
}
return( status );
}
static psa_status_t cipher_finish( mbedtls_psa_cipher_operation_t *operation,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
if( operation->cipher.unprocessed_len != 0 )
{
if( operation->alg == PSA_ALG_ECB_NO_PADDING ||
operation->alg == PSA_ALG_CBC_NO_PADDING )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
}
status = mbedtls_to_psa_error(
mbedtls_cipher_finish( &operation->cipher,
temp_output_buffer,
output_length ) );
if( status != PSA_SUCCESS )
goto exit;
if( *output_length == 0 )
; /* Nothing to copy. Note that output may be NULL in this case. */
else if( output_size >= *output_length )
memcpy( output, temp_output_buffer, *output_length );
else
status = PSA_ERROR_BUFFER_TOO_SMALL;
exit:
mbedtls_platform_zeroize( temp_output_buffer,
sizeof( temp_output_buffer ) );
return( status );
}
static psa_status_t cipher_abort( mbedtls_psa_cipher_operation_t *operation )
{
/* Sanity check (shouldn't happen: operation->alg should
* always have been initialized to a valid value). */
if( ! PSA_ALG_IS_CIPHER( operation->alg ) )
return( PSA_ERROR_BAD_STATE );
mbedtls_cipher_free( &operation->cipher );
return( PSA_SUCCESS );
}
#endif /* MBEDTLS_PSA_BUILTIN_CIPHER || PSA_CRYPTO_DRIVER_TEST */
#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
psa_status_t mbedtls_psa_cipher_encrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg )
{
return( cipher_encrypt_setup(
operation, attributes, key_buffer, key_buffer_size, alg ) );
}
psa_status_t mbedtls_psa_cipher_decrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg )
{
return( cipher_decrypt_setup(
operation, attributes, key_buffer, key_buffer_size, alg ) );
}
psa_status_t mbedtls_psa_cipher_set_iv( mbedtls_psa_cipher_operation_t *operation,
const uint8_t *iv,
size_t iv_length )
{
return( cipher_set_iv( operation, iv, iv_length ) );
}
psa_status_t mbedtls_psa_cipher_update( mbedtls_psa_cipher_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
return( cipher_update( operation, input, input_length,
output, output_size, output_length ) );
}
psa_status_t mbedtls_psa_cipher_finish( mbedtls_psa_cipher_operation_t *operation,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
return( cipher_finish( operation, output, output_size, output_length ) );
}
psa_status_t mbedtls_psa_cipher_abort( mbedtls_psa_cipher_operation_t *operation )
{
return( cipher_abort( operation ) );
}
#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
psa_status_t mbedtls_transparent_test_driver_cipher_encrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg )
{
return( cipher_encrypt_setup(
operation, attributes, key_buffer, key_buffer_size, alg ) );
}
psa_status_t mbedtls_transparent_test_driver_cipher_decrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg )
{
return( cipher_decrypt_setup(
operation, attributes, key_buffer, key_buffer_size, alg ) );
}
psa_status_t mbedtls_transparent_test_driver_cipher_set_iv(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length )
{
return( cipher_set_iv( operation, iv, iv_length ) );
}
psa_status_t mbedtls_transparent_test_driver_cipher_update(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length )
{
return( cipher_update( operation, input, input_length,
output, output_size, output_length ) );
}
psa_status_t mbedtls_transparent_test_driver_cipher_finish(
mbedtls_psa_cipher_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length )
{
return( cipher_finish( operation, output, output_size, output_length ) );
}
psa_status_t mbedtls_transparent_test_driver_cipher_abort(
mbedtls_psa_cipher_operation_t *operation )
{
return( cipher_abort( operation ) );
}
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* MBEDTLS_PSA_CRYPTO_C */

236
library/psa_crypto_cipher.h Normal file
View file

@ -0,0 +1,236 @@
/*
* PSA cipher driver entry points
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PSA_CRYPTO_CIPHER_H
#define PSA_CRYPTO_CIPHER_H
#include <mbedtls/cipher.h>
#include <psa/crypto.h>
/** 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 );
/**
* \brief Set the key for a multipart symmetric encryption operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_encrypt_setup entry point. This function behaves as a
* cipher_encrypt_setup entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation The operation object to set up. It has been
* initialized as per the documentation for
* #psa_cipher_operation_t and not yet in use.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg The cipher algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_CIPHER(\p alg) is true).
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_cipher_encrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg );
/**
* \brief Set the key for a multipart symmetric decryption operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_decrypt_setup entry point. This function behaves as a
* cipher_decrypt_setup entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation The operation object to set up. It has been
* initialized as per the documentation for
* #psa_cipher_operation_t and not yet in use.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg The cipher algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_CIPHER(\p alg) is true).
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_cipher_decrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg );
/** Set the IV for a symmetric encryption or decryption operation.
*
* This function sets the IV (initialization vector), nonce
* or initial counter value for the encryption or decryption operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_set_iv entry point. This function behaves as a
* cipher_set_iv entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation Active cipher operation.
* \param[in] iv Buffer containing the IV to use.
* \param[in] iv_length Size of the IV in bytes. It is guaranteed by
* the core to be less or equal to
* PSA_CIPHER_IV_MAX_SIZE.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The size of \p iv is not acceptable for the chosen algorithm,
* or the chosen algorithm does not use an IV.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t mbedtls_psa_cipher_set_iv(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length );
/** Encrypt or decrypt a message fragment in an active cipher operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_update entry point. This function behaves as a
* cipher_update entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation Active cipher operation.
* \param[in] input Buffer containing the message fragment to
* encrypt or decrypt.
* \param[in] input_length Size of the \p input buffer in bytes.
* \param[out] output Buffer where the output is to be written.
* \param[in] output_size Size of the \p output buffer in bytes.
* \param[out] output_length On success, the number of bytes
* that make up the returned output.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p output buffer is too small.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t mbedtls_psa_cipher_update(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length );
/** Finish encrypting or decrypting a message in a cipher operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_finish entry point. This function behaves as a
* cipher_finish entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation Active cipher operation.
* \param[out] output Buffer where the output is to be written.
* \param[in] output_size Size of the \p output buffer in bytes.
* \param[out] output_length On success, the number of bytes
* that make up the returned output.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The total input size passed to this operation is not valid for
* this particular algorithm. For example, the algorithm is a based
* on block cipher and requires a whole number of blocks, but the
* total input size is not a multiple of the block size.
* \retval #PSA_ERROR_INVALID_PADDING
* This is a decryption operation for an algorithm that includes
* padding, and the ciphertext does not contain valid padding.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p output buffer is too small.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t mbedtls_psa_cipher_finish(
mbedtls_psa_cipher_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length );
/** Abort a cipher operation.
*
* Aborting an operation frees all associated resources except for the
* \p operation structure itself. Once aborted, the operation object
* can be reused for another operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_abort entry point. This function behaves as a
* cipher_abort entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation Initialized cipher operation.
*
* \retval #PSA_SUCCESS
*/
psa_status_t mbedtls_psa_cipher_abort( mbedtls_psa_cipher_operation_t *operation );
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
psa_status_t mbedtls_transparent_test_driver_cipher_encrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg );
psa_status_t mbedtls_transparent_test_driver_cipher_decrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg );
psa_status_t mbedtls_transparent_test_driver_cipher_set_iv(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length );
psa_status_t mbedtls_transparent_test_driver_cipher_update(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length );
psa_status_t mbedtls_transparent_test_driver_cipher_finish(
mbedtls_psa_cipher_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length );
psa_status_t mbedtls_transparent_test_driver_cipher_abort(
mbedtls_psa_cipher_operation_t *operation );
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_CIPHER_H */

View file

@ -0,0 +1,83 @@
/*
* PSA crypto client code
*/
/*
* 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.
*/
#include "common.h"
#include "psa_crypto_service_integration.h"
#include "psa/crypto.h"
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_PLATFORM_C)
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
void psa_reset_key_attributes( psa_key_attributes_t *attributes )
{
mbedtls_free( attributes->domain_parameters );
memset( attributes, 0, sizeof( *attributes ) );
}
psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes,
psa_key_type_t type,
const uint8_t *data,
size_t data_length )
{
uint8_t *copy = NULL;
if( data_length != 0 )
{
copy = mbedtls_calloc( 1, data_length );
if( copy == NULL )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
memcpy( copy, data, data_length );
}
/* After this point, this function is guaranteed to succeed, so it
* can start modifying `*attributes`. */
if( attributes->domain_parameters != NULL )
{
mbedtls_free( attributes->domain_parameters );
attributes->domain_parameters = NULL;
attributes->domain_parameters_size = 0;
}
attributes->domain_parameters = copy;
attributes->domain_parameters_size = data_length;
attributes->core.type = type;
return( PSA_SUCCESS );
}
psa_status_t psa_get_key_domain_parameters(
const psa_key_attributes_t *attributes,
uint8_t *data, size_t data_size, size_t *data_length )
{
if( attributes->domain_parameters_size > data_size )
return( PSA_ERROR_BUFFER_TOO_SMALL );
*data_length = attributes->domain_parameters_size;
if( attributes->domain_parameters_size != 0 )
memcpy( data, attributes->domain_parameters,
attributes->domain_parameters_size );
return( PSA_SUCCESS );
}
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */

View file

@ -62,23 +62,13 @@ typedef struct
*/
size_t lock_count;
union
/* Dynamically allocated key data buffer.
* Format as specified in psa_export_key(). */
struct key_data
{
/* Dynamically allocated key data buffer.
* Format as specified in psa_export_key(). */
struct key_data
{
uint8_t *data;
size_t bytes;
} key;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* Any key type in a secure element */
struct se
{
psa_key_slot_number_t slot_number;
} se;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
} data;
uint8_t *data;
size_t bytes;
} key;
} psa_key_slot_t;
/* A mask of key attribute flags used only internally.
@ -163,6 +153,20 @@ static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot,
slot->attr.flags &= ~mask;
}
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/** Get the SE slot number of a key from the key slot storing its description.
*
* \param[in] slot The key slot to query. This must be a key slot storing
* the description of a key of a dynamically registered
* secure element, otherwise the behaviour is undefined.
*/
static inline psa_key_slot_number_t psa_key_slot_get_slot_number(
const psa_key_slot_t *slot )
{
return( *( (psa_key_slot_number_t *)( slot->key.data ) ) );
}
#endif
/** Completely wipe a slot in memory, including its policy.
*
* Persistent storage is not affected.
@ -208,4 +212,192 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot,
*/
psa_status_t mbedtls_to_psa_error( int ret );
/** Import a key in binary format.
*
* \note The signature of this function is that of a PSA driver
* import_key entry point. This function behaves as an import_key
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes for the key to import.
* \param[in] data The buffer containing the key data in import
* format.
* \param[in] data_length Size of the \p data buffer in bytes.
* \param[out] key_buffer The buffer to contain the key data in output
* format upon successful return.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This
* size is greater or equal to \p data_length.
* \param[out] key_buffer_length The length of the data written in \p
* key_buffer in bytes.
* \param[out] bits The key size in number of bits.
*
* \retval #PSA_SUCCESS The key was imported successfully.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key data is not correctly formatted.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t psa_import_key_into_slot(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits );
/** Export a key in binary format
*
* \note The signature of this function is that of a PSA driver export_key
* entry point. This function behaves as an export_key entry point as
* defined in the PSA driver interface specification.
*
* \param[in] attributes The attributes for the key to export.
* \param[in] key_buffer Material or context of the key to export.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[out] data Buffer where the key data is to be written.
* \param[in] data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes written in
* \p data
*
* \retval #PSA_SUCCESS The key was exported successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t psa_export_key_internal(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
/** Export a public key or the public part of a key pair in binary format.
*
* \note The signature of this function is that of a PSA driver
* export_public_key entry point. This function behaves as an
* export_public_key entry point as defined in the PSA driver interface
* specification.
*
* \param[in] attributes The attributes for the key to export.
* \param[in] key_buffer Material or context of the key to export.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[out] data Buffer where the key data is to be written.
* \param[in] data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes written in
* \p data
*
* \retval #PSA_SUCCESS The public key was exported successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t psa_export_public_key_internal(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
/**
* \brief Generate a key.
*
* \note The signature of the function is that of a PSA driver generate_key
* entry point.
*
* \param[in] attributes The attributes for the key to generate.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
* \p key_buffer.
*
* \retval #PSA_SUCCESS
* The key was generated successfully.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_NOT_SUPPORTED
* Key size in bits or type not supported.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
*/
psa_status_t psa_generate_key_internal( const psa_key_attributes_t *attributes,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length );
/** Sign an already-calculated hash with a private key.
*
* \note The signature of this function is that of a PSA driver
* sign_hash entry point. This function behaves as a sign_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* the type of the key.
* \param[in] hash The hash or message to sign.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[out] signature Buffer where the signature is to be written.
* \param[in] signature_size Size of the \p signature buffer in bytes.
* \param[out] signature_length On success, the number of bytes
* that make up the returned signature value.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p signature buffer is too small. You can
* determine a sufficient buffer size by calling
* #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
* where \c key_type and \c key_bits are the type and bit-size
* respectively of the key.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
*/
psa_status_t psa_sign_hash_internal(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length );
/**
* \brief Verify the signature a hash or short message using a public key.
*
* \note The signature of this function is that of a PSA driver
* verify_hash entry point. This function behaves as a verify_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* the type of the key.
* \param[in] hash The hash or message whose signature is to be
* verified.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[in] signature Buffer containing the signature to verify.
* \param[in] signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS
* The signature is valid.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The calculation was performed successfully, but the passed
* signature is not a valid signature.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t psa_verify_hash_internal(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length );
#endif /* PSA_CRYPTO_CORE_H */

File diff suppressed because it is too large Load diff

View file

@ -28,37 +28,45 @@
/*
* Signature functions
*/
psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot,
psa_algorithm_t alg,
const uint8_t *hash,
size_t hash_length,
uint8_t *signature,
size_t signature_size,
size_t *signature_length );
psa_status_t psa_driver_wrapper_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length );
psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot,
psa_algorithm_t alg,
const uint8_t *hash,
size_t hash_length,
const uint8_t *signature,
size_t signature_length );
psa_status_t psa_driver_wrapper_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length );
/*
* Key handling functions
*/
psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
psa_key_slot_t *slot );
psa_status_t psa_driver_wrapper_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits );
psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
size_t *bits );
psa_status_t psa_driver_wrapper_export_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot,
uint8_t *data,
size_t data_size,
size_t *data_length );
psa_status_t psa_driver_wrapper_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
psa_status_t psa_driver_wrapper_get_key_buffer_size(
const psa_key_attributes_t *attributes,
size_t *key_buffer_size );
psa_status_t psa_driver_wrapper_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
/*
* Cipher functions
@ -82,28 +90,24 @@ psa_status_t psa_driver_wrapper_cipher_decrypt(
size_t *output_length );
psa_status_t psa_driver_wrapper_cipher_encrypt_setup(
psa_operation_driver_context_t *operation,
psa_key_slot_t *slot,
psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg );
psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
psa_operation_driver_context_t *operation,
psa_key_slot_t *slot,
psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg );
psa_status_t psa_driver_wrapper_cipher_generate_iv(
psa_operation_driver_context_t *operation,
uint8_t *iv,
size_t iv_size,
size_t *iv_length );
psa_status_t psa_driver_wrapper_cipher_set_iv(
psa_operation_driver_context_t *operation,
psa_cipher_operation_t *operation,
const uint8_t *iv,
size_t iv_length );
psa_status_t psa_driver_wrapper_cipher_update(
psa_operation_driver_context_t *operation,
psa_cipher_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
@ -111,13 +115,46 @@ psa_status_t psa_driver_wrapper_cipher_update(
size_t *output_length );
psa_status_t psa_driver_wrapper_cipher_finish(
psa_operation_driver_context_t *operation,
psa_cipher_operation_t *operation,
uint8_t *output,
size_t output_size,
size_t *output_length );
psa_status_t psa_driver_wrapper_cipher_abort(
psa_operation_driver_context_t *operation );
psa_cipher_operation_t *operation );
/*
* Hashing functions
*/
psa_status_t psa_driver_wrapper_hash_compute(
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *hash,
size_t hash_size,
size_t *hash_length);
psa_status_t psa_driver_wrapper_hash_setup(
psa_hash_operation_t *operation,
psa_algorithm_t alg );
psa_status_t psa_driver_wrapper_hash_clone(
const psa_hash_operation_t *source_operation,
psa_hash_operation_t *target_operation );
psa_status_t psa_driver_wrapper_hash_update(
psa_hash_operation_t *operation,
const uint8_t *input,
size_t input_length );
psa_status_t psa_driver_wrapper_hash_finish(
psa_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length );
psa_status_t psa_driver_wrapper_hash_abort(
psa_hash_operation_t *operation );
#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */

668
library/psa_crypto_ecp.c Normal file
View file

@ -0,0 +1,668 @@
/*
* PSA ECP layer on top of Mbed TLS crypto
*/
/*
* 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.
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_ecp.h"
#include "psa_crypto_random_impl.h"
#include "psa_crypto_hash.h"
#include <stdlib.h>
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_PLATFORM_C)
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include <mbedtls/ecdsa.h>
#include <mbedtls/ecp.h>
#include <mbedtls/error.h>
#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) ) )
#define BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) ) )
#define BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) && \
defined(MBEDTLS_ECDSA_C) ) )
#define BUILTIN_ALG_ECDSA 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) && \
defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) ) )
#define BUILTIN_ALG_DETERMINISTIC_ECDSA 1
#endif
#if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
defined(BUILTIN_ALG_ECDSA) || \
defined(BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
psa_status_t mbedtls_psa_ecp_load_representation(
psa_key_type_t type, size_t curve_bits,
const uint8_t *data, size_t data_length,
mbedtls_ecp_keypair **p_ecp )
{
mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
psa_status_t status;
mbedtls_ecp_keypair *ecp = NULL;
size_t curve_bytes = data_length;
int explicit_bits = ( curve_bits != 0 );
if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) &&
PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY )
{
/* A Weierstrass public key is represented as:
* - The byte 0x04;
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
* So its data length is 2m+1 where m is the curve size in bits.
*/
if( ( data_length & 1 ) == 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
curve_bytes = data_length / 2;
/* Montgomery public keys are represented in compressed format, meaning
* their curve_bytes is equal to the amount of input. */
/* Private keys are represented in uncompressed private random integer
* format, meaning their curve_bytes is equal to the amount of input. */
}
if( explicit_bits )
{
/* With an explicit bit-size, the data must have the matching length. */
if( curve_bytes != PSA_BITS_TO_BYTES( curve_bits ) )
return( PSA_ERROR_INVALID_ARGUMENT );
}
else
{
/* We need to infer the bit-size from the data. Since the only
* information we have is the length in bytes, the value of curve_bits
* at this stage is rounded up to the nearest multiple of 8. */
curve_bits = PSA_BYTES_TO_BITS( curve_bytes );
}
/* Allocate and initialize a key representation. */
ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
if( ecp == NULL )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
mbedtls_ecp_keypair_init( ecp );
/* Load the group. */
grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ),
curve_bits, !explicit_bits );
if( grp_id == MBEDTLS_ECP_DP_NONE )
{
/* We can't distinguish between a nonsensical family/size combination
* (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a
* well-regarded curve that Mbed TLS just doesn't know about (which
* would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how
* curves that Mbed TLS knows about but for which support is disabled
* at build time, return NOT_SUPPORTED. */
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
if( status != PSA_SUCCESS )
goto exit;
/* Load the key material. */
if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
{
/* Load the public value. */
status = mbedtls_to_psa_error(
mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q,
data,
data_length ) );
if( status != PSA_SUCCESS )
goto exit;
/* Check that the point is on the curve. */
status = mbedtls_to_psa_error(
mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) );
if( status != PSA_SUCCESS )
goto exit;
}
else
{
/* Load and validate the secret value. */
status = mbedtls_to_psa_error(
mbedtls_ecp_read_key( ecp->grp.id,
ecp,
data,
data_length ) );
if( status != PSA_SUCCESS )
goto exit;
}
*p_ecp = ecp;
exit:
if( status != PSA_SUCCESS )
{
mbedtls_ecp_keypair_free( ecp );
mbedtls_free( ecp );
}
return( status );
}
#endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
* defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
* defined(BUILTIN_ALG_ECDSA) ||
* defined(BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
#if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
static psa_status_t ecp_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits )
{
psa_status_t status;
mbedtls_ecp_keypair *ecp = NULL;
/* Parse input */
status = mbedtls_psa_ecp_load_representation( attributes->core.type,
attributes->core.bits,
data,
data_length,
&ecp );
if( status != PSA_SUCCESS )
goto exit;
if( PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) ==
PSA_ECC_FAMILY_MONTGOMERY )
*bits = ecp->grp.nbits + 1;
else
*bits = ecp->grp.nbits;
/* Re-export the data to PSA export format. There is currently no support
* for other input formats then the export format, so this is a 1-1
* copy operation. */
status = mbedtls_psa_ecp_export_key( attributes->core.type,
ecp,
key_buffer,
key_buffer_size,
key_buffer_length );
exit:
/* Always free the PK object (will also free contained ECP context) */
mbedtls_ecp_keypair_free( ecp );
mbedtls_free( ecp );
return( status );
}
psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type,
mbedtls_ecp_keypair *ecp,
uint8_t *data,
size_t data_size,
size_t *data_length )
{
psa_status_t status;
if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
{
/* Check whether the public part is loaded */
if( mbedtls_ecp_is_zero( &ecp->Q ) )
{
/* Calculate the public key */
status = mbedtls_to_psa_error(
mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE ) );
if( status != PSA_SUCCESS )
return( status );
}
status = mbedtls_to_psa_error(
mbedtls_ecp_point_write_binary( &ecp->grp, &ecp->Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
data_length,
data,
data_size ) );
if( status != PSA_SUCCESS )
memset( data, 0, data_size );
return( status );
}
else
{
if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) )
return( PSA_ERROR_BUFFER_TOO_SMALL );
status = mbedtls_to_psa_error(
mbedtls_ecp_write_key( ecp,
data,
PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) );
if( status == PSA_SUCCESS )
*data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits );
else
memset( data, 0, data_size );
return( status );
}
}
static psa_status_t ecp_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
status = mbedtls_psa_ecp_load_representation(
attributes->core.type, attributes->core.bits,
key_buffer, key_buffer_size, &ecp );
if( status != PSA_SUCCESS )
return( status );
status = mbedtls_psa_ecp_export_key(
PSA_KEY_TYPE_ECC_PUBLIC_KEY(
PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) ),
ecp, data, data_size, data_length );
mbedtls_ecp_keypair_free( ecp );
mbedtls_free( ecp );
return( status );
}
#endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
* defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
#if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
static psa_status_t ecp_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
attributes->core.type );
mbedtls_ecp_group_id grp_id =
mbedtls_ecc_group_of_psa( curve, attributes->core.bits, 0 );
const mbedtls_ecp_curve_info *curve_info =
mbedtls_ecp_curve_info_from_grp_id( grp_id );
mbedtls_ecp_keypair ecp;
if( attributes->domain_parameters_size != 0 )
return( PSA_ERROR_NOT_SUPPORTED );
if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
mbedtls_ecp_keypair_init( &ecp );
ret = mbedtls_ecp_gen_key( grp_id, &ecp,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE );
if( ret != 0 )
{
mbedtls_ecp_keypair_free( &ecp );
return( mbedtls_to_psa_error( ret ) );
}
status = mbedtls_to_psa_error(
mbedtls_ecp_write_key( &ecp, key_buffer, key_buffer_size ) );
mbedtls_ecp_keypair_free( &ecp );
if( status == PSA_SUCCESS )
*key_buffer_length = key_buffer_size;
return( status );
}
#endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
/****************************************************************/
/* ECDSA sign/verify */
/****************************************************************/
#if defined(BUILTIN_ALG_ECDSA) || \
defined(BUILTIN_ALG_DETERMINISTIC_ECDSA)
static psa_status_t ecdsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t curve_bytes;
mbedtls_mpi r, s;
status = mbedtls_psa_ecp_load_representation( attributes->core.type,
attributes->core.bits,
key_buffer,
key_buffer_size,
&ecp );
if( status != PSA_SUCCESS )
return( status );
curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
mbedtls_mpi_init( &r );
mbedtls_mpi_init( &s );
if( signature_size < 2 * curve_bytes )
{
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
goto cleanup;
}
if( PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) )
{
#if defined(BUILTIN_ALG_DETERMINISTIC_ECDSA)
psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info );
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext(
&ecp->grp, &r, &s,
&ecp->d, hash,
hash_length, md_alg,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE ) );
#else
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
goto cleanup;
#endif /* defined(BUILTIN_ALG_DETERMINISTIC_ECDSA) */
}
else
{
(void) alg;
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d,
hash, hash_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE ) );
}
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r,
signature,
curve_bytes ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s,
signature + curve_bytes,
curve_bytes ) );
cleanup:
mbedtls_mpi_free( &r );
mbedtls_mpi_free( &s );
if( ret == 0 )
*signature_length = 2 * curve_bytes;
mbedtls_ecp_keypair_free( ecp );
mbedtls_free( ecp );
return( mbedtls_to_psa_error( ret ) );
}
static psa_status_t ecdsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t curve_bytes;
mbedtls_mpi r, s;
(void)alg;
status = mbedtls_psa_ecp_load_representation( attributes->core.type,
attributes->core.bits,
key_buffer,
key_buffer_size,
&ecp );
if( status != PSA_SUCCESS )
return( status );
curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
mbedtls_mpi_init( &r );
mbedtls_mpi_init( &s );
if( signature_length != 2 * curve_bytes )
{
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
signature,
curve_bytes ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
signature + curve_bytes,
curve_bytes ) );
/* Check whether the public part is loaded. If not, load it. */
if( mbedtls_ecp_is_zero( &ecp->Q ) )
{
MBEDTLS_MPI_CHK(
mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) );
}
ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length,
&ecp->Q, &r, &s );
cleanup:
mbedtls_mpi_free( &r );
mbedtls_mpi_free( &s );
mbedtls_ecp_keypair_free( ecp );
mbedtls_free( ecp );
return( mbedtls_to_psa_error( ret ) );
}
#endif /* defined(BUILTIN_ALG_ECDSA) || \
* defined(BUILTIN_ALG_DETERMINISTIC_ECDSA) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
psa_status_t mbedtls_psa_ecp_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits )
{
return( ecp_import_key( attributes, data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits ) );
}
psa_status_t mbedtls_psa_ecp_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length )
{
return( ecp_export_public_key( attributes, key_buffer, key_buffer_size,
data, data_size, data_length ) );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
psa_status_t mbedtls_psa_ecp_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
return( ecp_generate_key( attributes, key_buffer, key_buffer_size,
key_buffer_length ) );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
psa_status_t mbedtls_psa_ecdsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length )
{
return( ecdsa_sign_hash( attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length ) );
}
psa_status_t mbedtls_psa_ecdsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length )
{
return( ecdsa_verify_hash( attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length ) );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
psa_status_t mbedtls_transparent_test_driver_ecp_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits )
{
return( ecp_import_key( attributes, data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits ) );
}
psa_status_t mbedtls_transparent_test_driver_ecp_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length )
{
return( ecp_export_public_key( attributes, key_buffer, key_buffer_size,
data, data_size, data_length ) );
}
#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) ||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && \
defined(MBEDTLS_GENPRIME)
psa_status_t mbedtls_transparent_test_driver_ecp_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
return( ecp_generate_key( attributes, key_buffer, key_buffer_size,
key_buffer_length ) );
}
#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) &&
defined(MBEDTLS_GENPRIME) */
#if defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) || \
defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
psa_status_t mbedtls_transparent_test_driver_ecdsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length )
{
#if defined(MBEDTLS_ECDSA_C)
return( ecdsa_sign_hash( attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length ) );
#else
(void)attributes;
(void)key_buffer;
(void)key_buffer_size;
(void)alg;
(void)hash;
(void)hash_length;
(void)signature;
(void)signature_size;
(void)signature_length;
return( PSA_ERROR_NOT_SUPPORTED );
#endif
}
psa_status_t mbedtls_transparent_test_driver_ecdsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length )
{
#if defined(MBEDTLS_ECDSA_C)
return( ecdsa_verify_hash( attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length ) );
#else
(void)attributes;
(void)key_buffer;
(void)key_buffer_size;
(void)alg;
(void)hash;
(void)hash_length;
(void)signature;
(void)signature_length;
return( PSA_ERROR_NOT_SUPPORTED );
#endif
}
#endif /* defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) ||
* defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* MBEDTLS_PSA_CRYPTO_C */

256
library/psa_crypto_ecp.h Normal file
View file

@ -0,0 +1,256 @@
/*
* PSA ECP layer on top of Mbed TLS crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PSA_CRYPTO_ECP_H
#define PSA_CRYPTO_ECP_H
#include <psa/crypto.h>
#include <mbedtls/ecp.h>
/** Load the contents of a key buffer into an internal ECP representation
*
* \param[in] type The type of key contained in \p data.
* \param[in] curve_bits The nominal bit-size of the curve.
* It must be consistent with the representation
* passed in \p data.
* This can be 0, in which case the bit-size
* is inferred from \p data_length (which is possible
* for all key types and representation formats
* formats that are currently supported or will
* be in the foreseeable future).
* \param[in] data The buffer from which to load the representation.
* \param[in] data_length The size in bytes of \p data.
* \param[out] p_ecp Returns a pointer to an ECP context on success.
* The caller is responsible for freeing both the
* contents of the context and the context itself
* when done.
*/
psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type,
size_t curve_bits,
const uint8_t *data,
size_t data_length,
mbedtls_ecp_keypair **p_ecp );
/** Import an ECP key in binary format.
*
* \note The signature of this function is that of a PSA driver
* import_key entry point. This function behaves as an import_key
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes for the key to import.
* \param[in] data The buffer containing the key data in import
* format.
* \param[in] data_length Size of the \p data buffer in bytes.
* \param[out] key_buffer The buffer containing the key data in output
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This
* size is greater or equal to \p data_length.
* \param[out] key_buffer_length The length of the data written in \p
* key_buffer in bytes.
* \param[out] bits The key size in number of bits.
*
* \retval #PSA_SUCCESS The ECP key was imported successfully.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key data is not correctly formatted.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_ecp_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits );
/** Export an ECP key to export representation
*
* \param[in] type The type of key (public/private) to export
* \param[in] ecp The internal ECP representation from which to export
* \param[out] data The buffer to export to
* \param[in] data_size The length of the buffer to export to
* \param[out] data_length The amount of bytes written to \p data
*/
psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type,
mbedtls_ecp_keypair *ecp,
uint8_t *data,
size_t data_size,
size_t *data_length );
/** Export an ECP public key or the public part of an ECP key pair in binary
* format.
*
* \note The signature of this function is that of a PSA driver
* export_public_key entry point. This function behaves as an
* export_public_key entry point as defined in the PSA driver interface
* specification.
*
* \param[in] attributes The attributes for the key to export.
* \param[in] key_buffer Material or context of the key to export.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[out] data Buffer where the key data is to be written.
* \param[in] data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes written in
* \p data
*
* \retval #PSA_SUCCESS The ECP public key was exported successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t mbedtls_psa_ecp_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
/**
* \brief Generate an ECP key.
*
* \note The signature of the function is that of a PSA driver generate_key
* entry point.
*
* \param[in] attributes The attributes for the ECP key to generate.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
* \p key_buffer.
*
* \retval #PSA_SUCCESS
* The key was successfully generated.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Key length or type not supported.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
*/
psa_status_t mbedtls_psa_ecp_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
/** Sign an already-calculated hash with ECDSA.
*
* \note The signature of this function is that of a PSA driver
* sign_hash entry point. This function behaves as a sign_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the ECC key to use for the
* operation.
* \param[in] key_buffer The buffer containing the ECC key context.
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg Randomized or deterministic ECDSA algorithm.
* \param[in] hash The hash or message to sign.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[out] signature Buffer where the signature is to be written.
* \param[in] signature_size Size of the \p signature buffer in bytes.
* \param[out] signature_length On success, the number of bytes
* that make up the returned signature value.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p signature buffer is too small. You can
* determine a sufficient buffer size by calling
* #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_ECC_KEY_PAIR, \c key_bits,
* \p alg) where \c key_bits is the bit-size of the ECC key.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
*/
psa_status_t mbedtls_psa_ecdsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length );
/**
* \brief Verify an ECDSA hash or short message signature.
*
* \note The signature of this function is that of a PSA driver
* verify_hash entry point. This function behaves as a verify_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the ECC key to use for the
* operation.
* \param[in] key_buffer The buffer containing the ECC key context.
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg Randomized or deterministic ECDSA algorithm.
* \param[in] hash The hash or message whose signature is to be
* verified.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[in] signature Buffer containing the signature to verify.
* \param[in] signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS
* The signature is valid.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The calculation was performed successfully, but the passed
* signature is not a valid signature.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t mbedtls_psa_ecdsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length );
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
psa_status_t mbedtls_transparent_test_driver_ecp_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits );
psa_status_t mbedtls_transparent_test_driver_ecp_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
psa_status_t mbedtls_transparent_test_driver_ecp_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
psa_status_t mbedtls_transparent_test_driver_ecdsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length );
psa_status_t mbedtls_transparent_test_driver_ecdsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length );
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ECP_H */

697
library/psa_crypto_hash.c Normal file
View file

@ -0,0 +1,697 @@
/*
* PSA hashing layer on top of Mbed TLS software crypto
*/
/*
* 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.
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_hash.h"
#include <mbedtls/error.h>
#include <string.h>
/* Use builtin defines specific to this compilation unit, since the test driver
* relies on the software driver. */
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_MD2) ) )
#define BUILTIN_ALG_MD2 1
#endif
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_MD4) ) )
#define BUILTIN_ALG_MD4 1
#endif
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_MD5) ) )
#define BUILTIN_ALG_MD5 1
#endif
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) ) )
#define BUILTIN_ALG_RIPEMD160 1
#endif
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) ) )
#define BUILTIN_ALG_SHA_1 1
#endif
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) ) )
#define BUILTIN_ALG_SHA_224 1
#endif
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) ) )
#define BUILTIN_ALG_SHA_256 1
#endif
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) ) )
#define BUILTIN_ALG_SHA_384 1
#endif
#if( defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) ) )
#define BUILTIN_ALG_SHA_512 1
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )
{
switch( alg )
{
#if defined(MBEDTLS_MD2_C)
case PSA_ALG_MD2:
return( &mbedtls_md2_info );
#endif
#if defined(MBEDTLS_MD4_C)
case PSA_ALG_MD4:
return( &mbedtls_md4_info );
#endif
#if defined(MBEDTLS_MD5_C)
case PSA_ALG_MD5:
return( &mbedtls_md5_info );
#endif
#if defined(MBEDTLS_RIPEMD160_C)
case PSA_ALG_RIPEMD160:
return( &mbedtls_ripemd160_info );
#endif
#if defined(MBEDTLS_SHA1_C)
case PSA_ALG_SHA_1:
return( &mbedtls_sha1_info );
#endif
#if defined(MBEDTLS_SHA256_C)
case PSA_ALG_SHA_224:
return( &mbedtls_sha224_info );
#endif
#if defined(MBEDTLS_SHA256_C)
case PSA_ALG_SHA_256:
return( &mbedtls_sha256_info );
#endif
#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
case PSA_ALG_SHA_384:
return( &mbedtls_sha384_info );
#endif
#if defined(MBEDTLS_SHA512_C)
case PSA_ALG_SHA_512:
return( &mbedtls_sha512_info );
#endif
default:
return( NULL );
}
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
/* Implement the PSA driver hash interface on top of mbed TLS if either the
* software driver or the test driver requires it. */
#if defined(MBEDTLS_PSA_BUILTIN_HASH) || defined(PSA_CRYPTO_DRIVER_TEST)
static psa_status_t hash_abort(
mbedtls_psa_hash_operation_t *operation )
{
switch( operation->alg )
{
case 0:
/* The object has (apparently) been initialized but it is not
* in use. It's ok to call abort on such an object, and there's
* nothing to do. */
break;
#if defined(BUILTIN_ALG_MD2)
case PSA_ALG_MD2:
mbedtls_md2_free( &operation->ctx.md2 );
break;
#endif
#if defined(BUILTIN_ALG_MD4)
case PSA_ALG_MD4:
mbedtls_md4_free( &operation->ctx.md4 );
break;
#endif
#if defined(BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
mbedtls_md5_free( &operation->ctx.md5 );
break;
#endif
#if defined(BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
mbedtls_ripemd160_free( &operation->ctx.ripemd160 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
mbedtls_sha1_free( &operation->ctx.sha1 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
mbedtls_sha256_free( &operation->ctx.sha256 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
mbedtls_sha256_free( &operation->ctx.sha256 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
mbedtls_sha512_free( &operation->ctx.sha512 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
mbedtls_sha512_free( &operation->ctx.sha512 );
break;
#endif
default:
return( PSA_ERROR_BAD_STATE );
}
operation->alg = 0;
return( PSA_SUCCESS );
}
static psa_status_t hash_setup(
mbedtls_psa_hash_operation_t *operation,
psa_algorithm_t alg )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* A context must be freshly initialized before it can be set up. */
if( operation->alg != 0 )
{
return( PSA_ERROR_BAD_STATE );
}
switch( alg )
{
#if defined(BUILTIN_ALG_MD2)
case PSA_ALG_MD2:
mbedtls_md2_init( &operation->ctx.md2 );
ret = mbedtls_md2_starts_ret( &operation->ctx.md2 );
break;
#endif
#if defined(BUILTIN_ALG_MD4)
case PSA_ALG_MD4:
mbedtls_md4_init( &operation->ctx.md4 );
ret = mbedtls_md4_starts_ret( &operation->ctx.md4 );
break;
#endif
#if defined(BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
mbedtls_md5_init( &operation->ctx.md5 );
ret = mbedtls_md5_starts_ret( &operation->ctx.md5 );
break;
#endif
#if defined(BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
mbedtls_ripemd160_init( &operation->ctx.ripemd160 );
ret = mbedtls_ripemd160_starts_ret( &operation->ctx.ripemd160 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
mbedtls_sha1_init( &operation->ctx.sha1 );
ret = mbedtls_sha1_starts_ret( &operation->ctx.sha1 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
mbedtls_sha256_init( &operation->ctx.sha256 );
ret = mbedtls_sha256_starts_ret( &operation->ctx.sha256, 1 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
mbedtls_sha256_init( &operation->ctx.sha256 );
ret = mbedtls_sha256_starts_ret( &operation->ctx.sha256, 0 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
mbedtls_sha512_init( &operation->ctx.sha512 );
ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 1 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
mbedtls_sha512_init( &operation->ctx.sha512 );
ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 0 );
break;
#endif
default:
return( PSA_ALG_IS_HASH( alg ) ?
PSA_ERROR_NOT_SUPPORTED :
PSA_ERROR_INVALID_ARGUMENT );
}
if( ret == 0 )
operation->alg = alg;
else
hash_abort( operation );
return( mbedtls_to_psa_error( ret ) );
}
static psa_status_t hash_clone(
const mbedtls_psa_hash_operation_t *source_operation,
mbedtls_psa_hash_operation_t *target_operation )
{
switch( source_operation->alg )
{
case 0:
return( PSA_ERROR_BAD_STATE );
#if defined(BUILTIN_ALG_MD2)
case PSA_ALG_MD2:
mbedtls_md2_clone( &target_operation->ctx.md2,
&source_operation->ctx.md2 );
break;
#endif
#if defined(BUILTIN_ALG_MD4)
case PSA_ALG_MD4:
mbedtls_md4_clone( &target_operation->ctx.md4,
&source_operation->ctx.md4 );
break;
#endif
#if defined(BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
mbedtls_md5_clone( &target_operation->ctx.md5,
&source_operation->ctx.md5 );
break;
#endif
#if defined(BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
mbedtls_ripemd160_clone( &target_operation->ctx.ripemd160,
&source_operation->ctx.ripemd160 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
mbedtls_sha1_clone( &target_operation->ctx.sha1,
&source_operation->ctx.sha1 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
mbedtls_sha256_clone( &target_operation->ctx.sha256,
&source_operation->ctx.sha256 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
mbedtls_sha256_clone( &target_operation->ctx.sha256,
&source_operation->ctx.sha256 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
mbedtls_sha512_clone( &target_operation->ctx.sha512,
&source_operation->ctx.sha512 );
break;
#endif
#if defined(BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
mbedtls_sha512_clone( &target_operation->ctx.sha512,
&source_operation->ctx.sha512 );
break;
#endif
default:
(void) source_operation;
(void) target_operation;
return( PSA_ERROR_NOT_SUPPORTED );
}
target_operation->alg = source_operation->alg;
return( PSA_SUCCESS );
}
static psa_status_t hash_update(
mbedtls_psa_hash_operation_t *operation,
const uint8_t *input,
size_t input_length )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
switch( operation->alg )
{
#if defined(BUILTIN_ALG_MD2)
case PSA_ALG_MD2:
ret = mbedtls_md2_update_ret( &operation->ctx.md2,
input, input_length );
break;
#endif
#if defined(BUILTIN_ALG_MD4)
case PSA_ALG_MD4:
ret = mbedtls_md4_update_ret( &operation->ctx.md4,
input, input_length );
break;
#endif
#if defined(BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
ret = mbedtls_md5_update_ret( &operation->ctx.md5,
input, input_length );
break;
#endif
#if defined(BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
ret = mbedtls_ripemd160_update_ret( &operation->ctx.ripemd160,
input, input_length );
break;
#endif
#if defined(BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
ret = mbedtls_sha1_update_ret( &operation->ctx.sha1,
input, input_length );
break;
#endif
#if defined(BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
ret = mbedtls_sha256_update_ret( &operation->ctx.sha256,
input, input_length );
break;
#endif
#if defined(BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
ret = mbedtls_sha256_update_ret( &operation->ctx.sha256,
input, input_length );
break;
#endif
#if defined(BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
ret = mbedtls_sha512_update_ret( &operation->ctx.sha512,
input, input_length );
break;
#endif
#if defined(BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
ret = mbedtls_sha512_update_ret( &operation->ctx.sha512,
input, input_length );
break;
#endif
default:
(void) input;
(void) input_length;
return( PSA_ERROR_BAD_STATE );
}
return( mbedtls_to_psa_error( ret ) );
}
static psa_status_t hash_finish(
mbedtls_psa_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length )
{
psa_status_t status;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t actual_hash_length = PSA_HASH_LENGTH( operation->alg );
/* Fill the output buffer with something that isn't a valid hash
* (barring an attack on the hash and deliberately-crafted input),
* in case the caller doesn't check the return status properly. */
*hash_length = hash_size;
/* If hash_size is 0 then hash may be NULL and then the
* call to memset would have undefined behavior. */
if( hash_size != 0 )
memset( hash, '!', hash_size );
if( hash_size < actual_hash_length )
{
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
switch( operation->alg )
{
#if defined(BUILTIN_ALG_MD2)
case PSA_ALG_MD2:
ret = mbedtls_md2_finish_ret( &operation->ctx.md2, hash );
break;
#endif
#if defined(BUILTIN_ALG_MD4)
case PSA_ALG_MD4:
ret = mbedtls_md4_finish_ret( &operation->ctx.md4, hash );
break;
#endif
#if defined(BUILTIN_ALG_MD5)
case PSA_ALG_MD5:
ret = mbedtls_md5_finish_ret( &operation->ctx.md5, hash );
break;
#endif
#if defined(BUILTIN_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
ret = mbedtls_ripemd160_finish_ret( &operation->ctx.ripemd160, hash );
break;
#endif
#if defined(BUILTIN_ALG_SHA_1)
case PSA_ALG_SHA_1:
ret = mbedtls_sha1_finish_ret( &operation->ctx.sha1, hash );
break;
#endif
#if defined(BUILTIN_ALG_SHA_224)
case PSA_ALG_SHA_224:
ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash );
break;
#endif
#if defined(BUILTIN_ALG_SHA_256)
case PSA_ALG_SHA_256:
ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash );
break;
#endif
#if defined(BUILTIN_ALG_SHA_384)
case PSA_ALG_SHA_384:
ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash );
break;
#endif
#if defined(BUILTIN_ALG_SHA_512)
case PSA_ALG_SHA_512:
ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash );
break;
#endif
default:
(void) hash;
return( PSA_ERROR_BAD_STATE );
}
status = mbedtls_to_psa_error( ret );
exit:
if( status == PSA_SUCCESS )
*hash_length = actual_hash_length;
return( status );
}
static psa_status_t hash_compute(
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *hash,
size_t hash_size,
size_t *hash_length)
{
mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
*hash_length = hash_size;
status = hash_setup( &operation, alg );
if( status != PSA_SUCCESS )
goto exit;
status = hash_update( &operation, input, input_length );
if( status != PSA_SUCCESS )
goto exit;
status = hash_finish( &operation, hash, hash_size, hash_length );
if( status != PSA_SUCCESS )
goto exit;
exit:
abort_status = hash_abort( &operation );
if( status == PSA_SUCCESS )
return( abort_status );
else
return( status );
}
#endif /* MBEDTLS_PSA_BUILTIN_HASH || PSA_CRYPTO_DRIVER_TEST */
#if defined(MBEDTLS_PSA_BUILTIN_HASH)
psa_status_t mbedtls_psa_hash_compute(
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *hash,
size_t hash_size,
size_t *hash_length)
{
return( hash_compute( alg, input, input_length,
hash, hash_size, hash_length ) );
}
psa_status_t mbedtls_psa_hash_setup(
mbedtls_psa_hash_operation_t *operation,
psa_algorithm_t alg )
{
return( hash_setup( operation, alg ) );
}
psa_status_t mbedtls_psa_hash_clone(
const mbedtls_psa_hash_operation_t *source_operation,
mbedtls_psa_hash_operation_t *target_operation )
{
return( hash_clone( source_operation, target_operation ) );
}
psa_status_t mbedtls_psa_hash_update(
mbedtls_psa_hash_operation_t *operation,
const uint8_t *input,
size_t input_length )
{
return( hash_update( operation, input, input_length ) );
}
psa_status_t mbedtls_psa_hash_finish(
mbedtls_psa_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length )
{
return( hash_finish( operation, hash, hash_size, hash_length ) );
}
psa_status_t mbedtls_psa_hash_abort(
mbedtls_psa_hash_operation_t *operation )
{
return( hash_abort( operation ) );
}
#endif /* MBEDTLS_PSA_BUILTIN_HASH */
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
psa_status_t is_hash_accelerated( psa_algorithm_t alg )
{
switch( alg )
{
#if defined(MBEDTLS_PSA_ACCEL_ALG_MD2)
case PSA_ALG_MD2:
return( PSA_SUCCESS );
#endif
#if defined(MBEDTLS_PSA_ACCEL_ALG_MD4)
case PSA_ALG_MD4:
return( PSA_SUCCESS );
#endif
#if defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
case PSA_ALG_MD5:
return( PSA_SUCCESS );
#endif
#if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
case PSA_ALG_RIPEMD160:
return( PSA_SUCCESS );
#endif
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)
case PSA_ALG_SHA_1:
return( PSA_SUCCESS );
#endif
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
case PSA_ALG_SHA_224:
return( PSA_SUCCESS );
#endif
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
case PSA_ALG_SHA_256:
return( PSA_SUCCESS );
#endif
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
case PSA_ALG_SHA_384:
return( PSA_SUCCESS );
#endif
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
case PSA_ALG_SHA_512:
return( PSA_SUCCESS );
#endif
default:
return( PSA_ERROR_NOT_SUPPORTED );
}
}
psa_status_t mbedtls_transparent_test_driver_hash_compute(
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *hash,
size_t hash_size,
size_t *hash_length)
{
if( is_hash_accelerated( alg ) == PSA_SUCCESS )
return( hash_compute( alg, input, input_length,
hash, hash_size, hash_length ) );
else
return( PSA_ERROR_NOT_SUPPORTED );
}
psa_status_t mbedtls_transparent_test_driver_hash_setup(
mbedtls_transparent_test_driver_hash_operation_t *operation,
psa_algorithm_t alg )
{
if( is_hash_accelerated( alg ) == PSA_SUCCESS )
return( hash_setup( operation, alg ) );
else
return( PSA_ERROR_NOT_SUPPORTED );
}
psa_status_t mbedtls_transparent_test_driver_hash_clone(
const mbedtls_transparent_test_driver_hash_operation_t *source_operation,
mbedtls_transparent_test_driver_hash_operation_t *target_operation )
{
if( is_hash_accelerated( source_operation->alg ) == PSA_SUCCESS )
return( hash_clone( source_operation, target_operation ) );
else
return( PSA_ERROR_BAD_STATE );
}
psa_status_t mbedtls_transparent_test_driver_hash_update(
mbedtls_transparent_test_driver_hash_operation_t *operation,
const uint8_t *input,
size_t input_length )
{
if( is_hash_accelerated( operation->alg ) == PSA_SUCCESS )
return( hash_update( operation, input, input_length ) );
else
return( PSA_ERROR_BAD_STATE );
}
psa_status_t mbedtls_transparent_test_driver_hash_finish(
mbedtls_transparent_test_driver_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length )
{
if( is_hash_accelerated( operation->alg ) == PSA_SUCCESS )
return( hash_finish( operation, hash, hash_size, hash_length ) );
else
return( PSA_ERROR_BAD_STATE );
}
psa_status_t mbedtls_transparent_test_driver_hash_abort(
mbedtls_transparent_test_driver_hash_operation_t *operation )
{
return( hash_abort( operation ) );
}
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* MBEDTLS_PSA_CRYPTO_C */

273
library/psa_crypto_hash.h Normal file
View file

@ -0,0 +1,273 @@
/*
* PSA hashing layer on top of Mbed TLS software crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PSA_CRYPTO_HASH_H
#define PSA_CRYPTO_HASH_H
#include <psa/crypto.h>
#include <psa/crypto_builtin_hash.h>
#include "md_wrap.h"
/** Get Mbed TLS MD information of a hash algorithm given its PSA identifier
*
* \param[in] alg PSA hash algorithm identifier
*
* \return The Mbed TLS MD information of the hash algorithm. \c NULL if the
* PSA hash algorithm is not supported.
*/
const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg );
/** Calculate the hash (digest) of a message using Mbed TLS routines.
*
* \note The signature of this function is that of a PSA driver hash_compute
* entry point. This function behaves as a hash_compute entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* \param alg The hash algorithm to compute (\c PSA_ALG_XXX value
* such that #PSA_ALG_IS_HASH(\p alg) is true).
* \param[in] input Buffer containing the message to hash.
* \param input_length Size of the \p input buffer in bytes.
* \param[out] hash Buffer where the hash is to be written.
* \param hash_size Size of the \p hash buffer in bytes.
* \param[out] hash_length On success, the number of bytes
* that make up the hash value. This is always
* #PSA_HASH_LENGTH(\p alg).
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p hash_size is too small
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_hash_compute(
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *hash,
size_t hash_size,
size_t *hash_length);
/** Set up a multipart hash operation using Mbed TLS routines.
*
* \note The signature of this function is that of a PSA driver hash_setup
* entry point. This function behaves as a hash_setup entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* If an error occurs at any step after a call to mbedtls_psa_hash_setup(), the
* operation will need to be reset by a call to mbedtls_psa_hash_abort(). The
* core may call mbedtls_psa_hash_abort() at any time after the operation
* has been initialized.
*
* After a successful call to mbedtls_psa_hash_setup(), the core must
* eventually terminate the operation. The following events terminate an
* operation:
* - A successful call to mbedtls_psa_hash_finish() or mbedtls_psa_hash_verify().
* - A call to mbedtls_psa_hash_abort().
*
* \param[in,out] operation The operation object to set up. It must have
* been initialized to all-zero and not yet be in use.
* \param alg The hash algorithm to compute (\c PSA_ALG_XXX value
* such that #PSA_ALG_IS_HASH(\p alg) is true).
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported
* \retval #PSA_ERROR_BAD_STATE
* The operation state is not valid (it must be inactive).
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_hash_setup(
mbedtls_psa_hash_operation_t *operation,
psa_algorithm_t alg );
/** Clone an Mbed TLS hash operation.
*
* \note The signature of this function is that of a PSA driver hash_clone
* entry point. This function behaves as a hash_clone entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* This function copies the state of an ongoing hash operation to
* a new operation object. In other words, this function is equivalent
* to calling mbedtls_psa_hash_setup() on \p target_operation with the same
* algorithm that \p source_operation was set up for, then
* mbedtls_psa_hash_update() on \p target_operation with the same input that
* that was passed to \p source_operation. After this function returns, the
* two objects are independent, i.e. subsequent calls involving one of
* the objects do not affect the other object.
*
* \param[in] source_operation The active hash operation to clone.
* \param[in,out] target_operation The operation object to set up.
* It must be initialized but not active.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_BAD_STATE
* The \p source_operation state is not valid (it must be active).
* \retval #PSA_ERROR_BAD_STATE
* The \p target_operation state is not valid (it must be inactive).
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t mbedtls_psa_hash_clone(
const mbedtls_psa_hash_operation_t *source_operation,
mbedtls_psa_hash_operation_t *target_operation );
/** Add a message fragment to a multipart Mbed TLS hash operation.
*
* \note The signature of this function is that of a PSA driver hash_update
* entry point. This function behaves as a hash_update entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* The application must call mbedtls_psa_hash_setup() before calling this function.
*
* If this function returns an error status, the operation enters an error
* state and must be aborted by calling mbedtls_psa_hash_abort().
*
* \param[in,out] operation Active hash operation.
* \param[in] input Buffer containing the message fragment to hash.
* \param input_length Size of the \p input buffer in bytes.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_BAD_STATE
* The operation state is not valid (it must be active).
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_hash_update(
mbedtls_psa_hash_operation_t *operation,
const uint8_t *input,
size_t input_length );
/** Finish the calculation of the Mbed TLS-calculated hash of a message.
*
* \note The signature of this function is that of a PSA driver hash_finish
* entry point. This function behaves as a hash_finish entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* The application must call mbedtls_psa_hash_setup() before calling this function.
* This function calculates the hash of the message formed by concatenating
* the inputs passed to preceding calls to mbedtls_psa_hash_update().
*
* When this function returns successfuly, the operation becomes inactive.
* If this function returns an error status, the operation enters an error
* state and must be aborted by calling mbedtls_psa_hash_abort().
*
* \param[in,out] operation Active hash operation.
* \param[out] hash Buffer where the hash is to be written.
* \param hash_size Size of the \p hash buffer in bytes.
* \param[out] hash_length On success, the number of bytes
* that make up the hash value. This is always
* #PSA_HASH_LENGTH(\c alg) where \c alg is the
* hash algorithm that is calculated.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_BAD_STATE
* The operation state is not valid (it must be active).
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p hash buffer is too small. You can determine a
* sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg)
* where \c alg is the hash algorithm that is calculated.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_hash_finish(
mbedtls_psa_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length );
/** Abort an Mbed TLS hash operation.
*
* \note The signature of this function is that of a PSA driver hash_abort
* entry point. This function behaves as a hash_abort entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* Aborting an operation frees all associated resources except for the
* \p operation structure itself. Once aborted, the operation object
* can be reused for another operation by calling
* mbedtls_psa_hash_setup() again.
*
* You may call this function any time after the operation object has
* been initialized by one of the methods described in #psa_hash_operation_t.
*
* In particular, calling mbedtls_psa_hash_abort() after the operation has been
* terminated by a call to mbedtls_psa_hash_abort(), mbedtls_psa_hash_finish() or
* mbedtls_psa_hash_verify() is safe and has no effect.
*
* \param[in,out] operation Initialized hash operation.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_hash_abort(
mbedtls_psa_hash_operation_t *operation );
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
psa_status_t mbedtls_transparent_test_driver_hash_compute(
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *hash,
size_t hash_size,
size_t *hash_length);
psa_status_t mbedtls_transparent_test_driver_hash_setup(
mbedtls_transparent_test_driver_hash_operation_t *operation,
psa_algorithm_t alg );
psa_status_t mbedtls_transparent_test_driver_hash_clone(
const mbedtls_transparent_test_driver_hash_operation_t *source_operation,
mbedtls_transparent_test_driver_hash_operation_t *target_operation );
psa_status_t mbedtls_transparent_test_driver_hash_update(
mbedtls_transparent_test_driver_hash_operation_t *operation,
const uint8_t *input,
size_t input_length );
psa_status_t mbedtls_transparent_test_driver_hash_finish(
mbedtls_transparent_test_driver_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length );
psa_status_t mbedtls_transparent_test_driver_hash_abort(
mbedtls_transparent_test_driver_hash_operation_t *operation );
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_HASH_H */

View file

@ -35,6 +35,7 @@
#endif
#include "psa/crypto.h"
#include "common.h"
#include "mbedtls/entropy.h"
@ -76,4 +77,10 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
void (* entropy_free )( mbedtls_entropy_context *ctx ) );
#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)
psa_status_t psa_mac_key_can_do(
psa_algorithm_t algorithm,
psa_key_type_t key_type );
#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */
#endif /* PSA_CRYPTO_INVASIVE_H */

View file

@ -72,12 +72,12 @@ struct psa_storage_info_t
*
* \return A status indicating the success/failure of the operation
*
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG
* \retval #PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`)
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG
* \retval #PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`)
* is invalid, for example is `NULL` or references memory the caller cannot access
*/
psa_status_t psa_its_set(psa_storage_uid_t uid,
@ -97,11 +97,11 @@ psa_status_t psa_its_set(psa_storage_uid_t uid,
*
* \return A status indicating the success/failure of the operation
*
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage
* \retval #PSA_ERROR_INVALID_SIZE The operation failed because the data associated with provided uid is larger than `data_size`
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`)
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
* \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`)
* is invalid. For example is `NULL` or references memory the caller cannot access.
* In addition, this can also happen if an invalid offset was provided.
*/
@ -119,10 +119,10 @@ psa_status_t psa_its_get(psa_storage_uid_t uid,
*
* \return A status indicating the success/failure of the operation
*
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`)
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage
* \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`)
* is invalid, for example is `NULL` or references memory the caller cannot access
*/
psa_status_t psa_its_get_info(psa_storage_uid_t uid,
@ -135,10 +135,10 @@ psa_status_t psa_its_get_info(psa_storage_uid_t uid,
*
* \return A status indicating the success/failure of the operation
*
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage
* \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage
* \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
*/
psa_status_t psa_its_remove(psa_storage_uid_t uid);

View file

@ -1,6 +1,14 @@
/** \file psa_crypto_random_impl.h
*
* \brief PSA crypto random generator implementation abstraction.
*
* The definitions here need to be consistent with the declarations
* in include/mbedtls/psa_util.h. This file contains some redundant
* declarations to increase the chance that a compiler will detect
* inconsistencies if one file is changed without updating the other,
* but not all potential inconsistencies can be enforced, so make sure
* to check the public declarations and contracts in
* include/mbedtls/psa_util.h if you modify this file.
*/
/*
* Copyright The Mbed TLS Contributors
@ -22,6 +30,8 @@
#ifndef PSA_CRYPTO_RANDOM_IMPL_H
#define PSA_CRYPTO_RANDOM_IMPL_H
#include <mbedtls/psa_util.h>
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
#include <string.h>
@ -75,14 +85,6 @@ int mbedtls_psa_get_random( void *p_rng,
#include "mbedtls/entropy.h"
/** The type of the PSA DRBG context.
*/
#if defined(MBEDTLS_CTR_DRBG_C)
typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t;
#elif defined(MBEDTLS_HMAC_DRBG_C)
typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t;
#endif
/** Initialize the PSA DRBG.
*
* \param p_rng Pointer to the Mbed TLS DRBG state.
@ -122,33 +124,18 @@ typedef struct
mbedtls_psa_drbg_context_t drbg;
} mbedtls_psa_random_context_t;
/* The type of an Mbed TLS random generator function. This should be
* part of the public API instead of repeating the type everywhere.
* For the time being, declare it here. Declaring a type is necessary
* to define mbedtls_psa_get_random as a variable of a function pointer
* type without incurring the wrath of check-names.sh. */
typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_size );
/** Return random data.
*
* This function is suitable as the \p f_rng parameter to Mbed TLS functions
* that require a random generator. Use #MBEDTLS_PSA_RANDOM_STATE to
* obtain the \p p_rng parameter.
*
* \param p_rng The DRBG context. This must be
* #MBEDTLS_PSA_RANDOM_STATE.
* \param output The buffer to fill.
* \param output_len The length of the buffer in bytes.
* It must be at most #MBEDTLS_PSA_RANDOM_MAX_REQUEST.
*
* \retval \c 0 on success.
* \return \c MBEDTLS_ERR_xxx_DRBG_xxx or
* \c MBEDTLS_ERR_PLATFORM_xxx on failure.
/* Defined in include/mbedtls/psa_util.h so that it's visible to
* application code. The declaration here is redundant, but included
* as a safety net to make it more likely that a future change that
* accidentally causes the implementation to diverge from the interface
* will be noticed. */
/* Do not include the declaration under MSVC because it doesn't accept it
* ("error C2370: 'mbedtls_psa_get_random' : redefinition; different storage class").
* Observed with Visual Studio 2013. A known bug apparently:
* https://stackoverflow.com/questions/8146541/duplicate-external-static-declarations-not-allowed-in-visual-studio
*/
#if defined(MBEDTLS_CTR_DRBG_C)
static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random;
#elif defined(MBEDTLS_HMAC_DRBG_C)
static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random;
#if !defined(_MSC_VER)
static mbedtls_f_rng_t *const mbedtls_psa_get_random;
#endif
/** The maximum number of bytes that mbedtls_psa_get_random() is expected to
@ -167,6 +154,9 @@ static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random;
*/
/* psa_crypto.c sets this variable to a pointer to the DRBG state in the
* global PSA crypto state. */
/* The type `mbedtls_psa_drbg_context_t` is defined in
* include/mbedtls/psa_util.h so that `mbedtls_psa_random_state` can be
* declared there and be visible to application code. */
extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
/** A pointer to the PSA DRBG state.

709
library/psa_crypto_rsa.c Normal file
View file

@ -0,0 +1,709 @@
/*
* PSA RSA layer on top of Mbed TLS crypto
*/
/*
* 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.
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_random_impl.h"
#include "psa_crypto_rsa.h"
#include "psa_crypto_hash.h"
#include <stdlib.h>
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_PLATFORM_C)
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include <mbedtls/rsa.h>
#include <mbedtls/error.h>
#include <mbedtls/pk.h>
#include "pk_wrap.h"
#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) ) )
#define BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) ) )
#define BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) && \
defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V15) ) )
#define BUILTIN_ALG_RSA_PKCS1V15_SIGN 1
#endif
#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
( defined(PSA_CRYPTO_DRIVER_TEST) && \
defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) && \
defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) ) )
#define BUILTIN_ALG_RSA_PSS 1
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
defined(BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(BUILTIN_ALG_RSA_PSS) || \
defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes
* that are not a multiple of 8) well. For example, there is only
* mbedtls_rsa_get_len(), which returns a number of bytes, and no
* way to return the exact bit size of a key.
* To keep things simple, reject non-byte-aligned key sizes. */
static psa_status_t psa_check_rsa_key_byte_aligned(
const mbedtls_rsa_context *rsa )
{
mbedtls_mpi n;
psa_status_t status;
mbedtls_mpi_init( &n );
status = mbedtls_to_psa_error(
mbedtls_rsa_export( rsa, &n, NULL, NULL, NULL, NULL ) );
if( status == PSA_SUCCESS )
{
if( mbedtls_mpi_bitlen( &n ) % 8 != 0 )
status = PSA_ERROR_NOT_SUPPORTED;
}
mbedtls_mpi_free( &n );
return( status );
}
psa_status_t mbedtls_psa_rsa_load_representation(
psa_key_type_t type, const uint8_t *data, size_t data_length,
mbedtls_rsa_context **p_rsa )
{
psa_status_t status;
mbedtls_pk_context ctx;
size_t bits;
mbedtls_pk_init( &ctx );
/* Parse the data. */
if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
status = mbedtls_to_psa_error(
mbedtls_pk_parse_key( &ctx, data, data_length, NULL, 0 ) );
else
status = mbedtls_to_psa_error(
mbedtls_pk_parse_public_key( &ctx, data, data_length ) );
if( status != PSA_SUCCESS )
goto exit;
/* We have something that the pkparse module recognizes. If it is a
* valid RSA key, store it. */
if( mbedtls_pk_get_type( &ctx ) != MBEDTLS_PK_RSA )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
/* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS
* supports non-byte-aligned key sizes, but not well. For example,
* mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */
bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( mbedtls_pk_rsa( ctx ) ) );
if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
{
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = psa_check_rsa_key_byte_aligned( mbedtls_pk_rsa( ctx ) );
if( status != PSA_SUCCESS )
goto exit;
/* Copy out the pointer to the RSA context, and reset the PK context
* such that pk_free doesn't free the RSA context we just grabbed. */
*p_rsa = mbedtls_pk_rsa( ctx );
ctx.pk_info = NULL;
exit:
mbedtls_pk_free( &ctx );
return( status );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
* defined(BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
* defined(BUILTIN_ALG_RSA_PSS) ||
* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
* defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
#if defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
static psa_status_t rsa_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits )
{
psa_status_t status;
mbedtls_rsa_context *rsa = NULL;
/* Parse input */
status = mbedtls_psa_rsa_load_representation( attributes->core.type,
data,
data_length,
&rsa );
if( status != PSA_SUCCESS )
goto exit;
*bits = (psa_key_bits_t) PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( rsa ) );
/* Re-export the data to PSA export format, such that we can store export
* representation in the key slot. Export representation in case of RSA is
* the smallest representation that's allowed as input, so a straight-up
* allocation of the same size as the input buffer will be large enough. */
status = mbedtls_psa_rsa_export_key( attributes->core.type,
rsa,
key_buffer,
key_buffer_size,
key_buffer_length );
exit:
/* Always free the RSA object */
mbedtls_rsa_free( rsa );
mbedtls_free( rsa );
return( status );
}
psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type,
mbedtls_rsa_context *rsa,
uint8_t *data,
size_t data_size,
size_t *data_length )
{
#if defined(MBEDTLS_PK_WRITE_C)
int ret;
mbedtls_pk_context pk;
uint8_t *pos = data + data_size;
mbedtls_pk_init( &pk );
pk.pk_info = &mbedtls_rsa_info;
pk.pk_ctx = rsa;
/* PSA Crypto API defines the format of an RSA key as a DER-encoded
* representation of the non-encrypted PKCS#1 RSAPrivateKey for a
* private key and of the RFC3279 RSAPublicKey for a public key. */
if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
ret = mbedtls_pk_write_key_der( &pk, data, data_size );
else
ret = mbedtls_pk_write_pubkey( &pos, data, &pk );
if( ret < 0 )
{
/* Clean up in case pk_write failed halfway through. */
memset( data, 0, data_size );
return( mbedtls_to_psa_error( ret ) );
}
/* The mbedtls_pk_xxx functions write to the end of the buffer.
* Move the data to the beginning and erase remaining data
* at the original location. */
if( 2 * (size_t) ret <= data_size )
{
memcpy( data, data + data_size - ret, ret );
memset( data + data_size - ret, 0, ret );
}
else if( (size_t) ret < data_size )
{
memmove( data, data + data_size - ret, ret );
memset( data + ret, 0, data_size - ret );
}
*data_length = ret;
return( PSA_SUCCESS );
#else
(void) type;
(void) rsa;
(void) data;
(void) data_size;
(void) data_length;
return( PSA_ERROR_NOT_SUPPORTED );
#endif /* MBEDTLS_PK_WRITE_C */
}
static psa_status_t rsa_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
status = mbedtls_psa_rsa_load_representation(
attributes->core.type, key_buffer, key_buffer_size, &rsa );
if( status != PSA_SUCCESS )
return( status );
status = mbedtls_psa_rsa_export_key( PSA_KEY_TYPE_RSA_PUBLIC_KEY,
rsa,
data,
data_size,
data_length );
mbedtls_rsa_free( rsa );
mbedtls_free( rsa );
return( status );
}
#endif /* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
* defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
#if defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
static psa_status_t psa_rsa_read_exponent( const uint8_t *domain_parameters,
size_t domain_parameters_size,
int *exponent )
{
size_t i;
uint32_t acc = 0;
if( domain_parameters_size == 0 )
{
*exponent = 65537;
return( PSA_SUCCESS );
}
/* Mbed TLS encodes the public exponent as an int. For simplicity, only
* support values that fit in a 32-bit integer, which is larger than
* int on just about every platform anyway. */
if( domain_parameters_size > sizeof( acc ) )
return( PSA_ERROR_NOT_SUPPORTED );
for( i = 0; i < domain_parameters_size; i++ )
acc = ( acc << 8 ) | domain_parameters[i];
if( acc > INT_MAX )
return( PSA_ERROR_NOT_SUPPORTED );
*exponent = acc;
return( PSA_SUCCESS );
}
static psa_status_t rsa_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
psa_status_t status;
mbedtls_rsa_context rsa;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int exponent;
status = psa_rsa_read_exponent( attributes->domain_parameters,
attributes->domain_parameters_size,
&exponent );
if( status != PSA_SUCCESS )
return( status );
mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE );
ret = mbedtls_rsa_gen_key( &rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
(unsigned int)attributes->core.bits,
exponent );
if( ret != 0 )
return( mbedtls_to_psa_error( ret ) );
status = mbedtls_psa_rsa_export_key( attributes->core.type,
&rsa, key_buffer, key_buffer_size,
key_buffer_length );
mbedtls_rsa_free( &rsa );
return( status );
}
#endif /* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
/****************************************************************/
/* Sign/verify hashes */
/****************************************************************/
#if defined(BUILTIN_ALG_RSA_PKCS1V15_SIGN) || defined(BUILTIN_ALG_RSA_PSS)
/* Decode the hash algorithm from alg and store the mbedtls encoding in
* md_alg. Verify that the hash length is acceptable. */
static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg,
size_t hash_length,
mbedtls_md_type_t *md_alg )
{
psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
*md_alg = mbedtls_md_get_type( md_info );
/* The Mbed TLS RSA module uses an unsigned int for hash length
* parameters. Validate that it fits so that we don't risk an
* overflow later. */
#if SIZE_MAX > UINT_MAX
if( hash_length > UINT_MAX )
return( PSA_ERROR_INVALID_ARGUMENT );
#endif
#if defined(BUILTIN_ALG_RSA_PKCS1V15_SIGN)
/* For PKCS#1 v1.5 signature, if using a hash, the hash length
* must be correct. */
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) &&
alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW )
{
if( md_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
if( mbedtls_md_get_size( md_info ) != hash_length )
return( PSA_ERROR_INVALID_ARGUMENT );
}
#endif /* BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(BUILTIN_ALG_RSA_PSS)
/* PSS requires a hash internally. */
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
if( md_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
}
#endif /* BUILTIN_ALG_RSA_PSS */
return( PSA_SUCCESS );
}
static psa_status_t rsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = mbedtls_psa_rsa_load_representation( attributes->core.type,
key_buffer,
key_buffer_size,
&rsa );
if( status != PSA_SUCCESS )
return( status );
status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
if( status != PSA_SUCCESS )
goto exit;
if( signature_size < mbedtls_rsa_get_len( rsa ) )
{
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
#if defined(BUILTIN_ALG_RSA_PKCS1V15_SIGN)
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE );
ret = mbedtls_rsa_pkcs1_sign( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
md_alg,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(BUILTIN_ALG_RSA_PSS)
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
ret = mbedtls_rsa_rsassa_pss_sign( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* BUILTIN_ALG_RSA_PSS */
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
if( ret == 0 )
*signature_length = mbedtls_rsa_get_len( rsa );
status = mbedtls_to_psa_error( ret );
exit:
mbedtls_rsa_free( rsa );
mbedtls_free( rsa );
return( status );
}
static psa_status_t rsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = mbedtls_psa_rsa_load_representation( attributes->core.type,
key_buffer,
key_buffer_size,
&rsa );
if( status != PSA_SUCCESS )
goto exit;
status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
if( status != PSA_SUCCESS )
goto exit;
if( signature_length != mbedtls_rsa_get_len( rsa ) )
{
status = PSA_ERROR_INVALID_SIGNATURE;
goto exit;
}
#if defined(BUILTIN_ALG_RSA_PKCS1V15_SIGN)
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE );
ret = mbedtls_rsa_pkcs1_verify( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
md_alg,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(BUILTIN_ALG_RSA_PSS)
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
ret = mbedtls_rsa_rsassa_pss_verify( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* BUILTIN_ALG_RSA_PSS */
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
/* Mbed TLS distinguishes "invalid padding" from "valid padding but
* the rest of the signature is invalid". This has little use in
* practice and PSA doesn't report this distinction. */
status = ( ret == MBEDTLS_ERR_RSA_INVALID_PADDING ) ?
PSA_ERROR_INVALID_SIGNATURE :
mbedtls_to_psa_error( ret );
exit:
mbedtls_rsa_free( rsa );
mbedtls_free( rsa );
return( status );
}
#endif /* defined(BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
* defined(BUILTIN_ALG_RSA_PSS) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
psa_status_t mbedtls_psa_rsa_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits )
{
return( rsa_import_key( attributes, data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits ) );
}
psa_status_t mbedtls_psa_rsa_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length )
{
return( rsa_export_public_key( attributes, key_buffer, key_buffer_size,
data, data_size, data_length ) );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
return( rsa_generate_key( attributes, key_buffer, key_buffer_size,
key_buffer_length ) );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
psa_status_t mbedtls_psa_rsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length )
{
return( rsa_sign_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length ) );
}
psa_status_t mbedtls_psa_rsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length )
{
return( rsa_verify_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length ) );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY)
psa_status_t mbedtls_transparent_test_driver_rsa_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits )
{
return( rsa_import_key( attributes, data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits ) );
}
psa_status_t mbedtls_transparent_test_driver_rsa_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length )
{
return( rsa_export_public_key( attributes, key_buffer, key_buffer_size,
data, data_size, data_length ) );
}
#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) ||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR)
psa_status_t mbedtls_transparent_test_driver_rsa_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
return( rsa_generate_key( attributes, key_buffer, key_buffer_size,
key_buffer_length ) );
}
#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) */
#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
psa_status_t mbedtls_transparent_test_driver_rsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length )
{
#if defined(MBEDTLS_RSA_C) && \
(defined(MBEDTLS_PKCS1_V15) || defined(MBEDTLS_PKCS1_V21))
return( rsa_sign_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length ) );
#else
(void)attributes;
(void)key_buffer;
(void)key_buffer_size;
(void)alg;
(void)hash;
(void)hash_length;
(void)signature;
(void)signature_size;
(void)signature_length;
return( PSA_ERROR_NOT_SUPPORTED );
#endif
}
psa_status_t mbedtls_transparent_test_driver_rsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length )
{
#if defined(MBEDTLS_RSA_C) && \
(defined(MBEDTLS_PKCS1_V15) || defined(MBEDTLS_PKCS1_V21))
return( rsa_verify_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length ) );
#else
(void)attributes;
(void)key_buffer;
(void)key_buffer_size;
(void)alg;
(void)hash;
(void)hash_length;
(void)signature;
(void)signature_length;
return( PSA_ERROR_NOT_SUPPORTED );
#endif
}
#endif /* defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) ||
* defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* MBEDTLS_PSA_CRYPTO_C */

250
library/psa_crypto_rsa.h Normal file
View file

@ -0,0 +1,250 @@
/*
* PSA RSA layer on top of Mbed TLS crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PSA_CRYPTO_RSA_H
#define PSA_CRYPTO_RSA_H
#include <psa/crypto.h>
#include <mbedtls/rsa.h>
/** Load the contents of a key buffer into an internal RSA representation
*
* \param[in] type The type of key contained in \p data.
* \param[in] data The buffer from which to load the representation.
* \param[in] data_length The size in bytes of \p data.
* \param[out] p_rsa Returns a pointer to an RSA context on success.
* The caller is responsible for freeing both the
* contents of the context and the context itself
* when done.
*/
psa_status_t mbedtls_psa_rsa_load_representation( psa_key_type_t type,
const uint8_t *data,
size_t data_length,
mbedtls_rsa_context **p_rsa );
/** Import an RSA key in binary format.
*
* \note The signature of this function is that of a PSA driver
* import_key entry point. This function behaves as an import_key
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes for the key to import.
* \param[in] data The buffer containing the key data in import
* format.
* \param[in] data_length Size of the \p data buffer in bytes.
* \param[out] key_buffer The buffer containing the key data in output
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This
* size is greater or equal to \p data_length.
* \param[out] key_buffer_length The length of the data written in \p
* key_buffer in bytes.
* \param[out] bits The key size in number of bits.
*
* \retval #PSA_SUCCESS The RSA key was imported successfully.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key data is not correctly formatted.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_rsa_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits );
/** Export an RSA key to export representation
*
* \param[in] type The type of key (public/private) to export
* \param[in] rsa The internal RSA representation from which to export
* \param[out] data The buffer to export to
* \param[in] data_size The length of the buffer to export to
* \param[out] data_length The amount of bytes written to \p data
*/
psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type,
mbedtls_rsa_context *rsa,
uint8_t *data,
size_t data_size,
size_t *data_length );
/** Export a public RSA key or the public part of an RSA key pair in binary
* format.
*
* \note The signature of this function is that of a PSA driver
* export_public_key entry point. This function behaves as an
* export_public_key entry point as defined in the PSA driver interface
* specification.
*
* \param[in] attributes The attributes for the key to export.
* \param[in] key_buffer Material or context of the key to export.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[out] data Buffer where the key data is to be written.
* \param[in] data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes written in
* \p data.
*
* \retval #PSA_SUCCESS The RSA public key was exported successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t mbedtls_psa_rsa_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
/**
* \brief Generate an RSA key.
*
* \note The signature of the function is that of a PSA driver generate_key
* entry point.
*
* \param[in] attributes The attributes for the RSA key to generate.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
* \p key_buffer.
*
* \retval #PSA_SUCCESS
* The key was successfully generated.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Key length or type not supported.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
*/
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
/** Sign an already-calculated hash with an RSA private key.
*
* \note The signature of this function is that of a PSA driver
* sign_hash entry point. This function behaves as a sign_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the RSA key to use for the
* operation.
* \param[in] key_buffer The buffer containing the RSA key context.
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* an RSA key.
* \param[in] hash The hash or message to sign.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[out] signature Buffer where the signature is to be written.
* \param[in] signature_size Size of the \p signature buffer in bytes.
* \param[out] signature_length On success, the number of bytes
* that make up the returned signature value.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p signature buffer is too small. You can
* determine a sufficient buffer size by calling
* #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_RSA_KEY_PAIR, \c key_bits,
* \p alg) where \c key_bits is the bit-size of the RSA key.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
*/
psa_status_t mbedtls_psa_rsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length );
/**
* \brief Verify the signature a hash or short message using a public RSA key.
*
* \note The signature of this function is that of a PSA driver
* verify_hash entry point. This function behaves as a verify_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the RSA key to use for the
* operation.
* \param[in] key_buffer The buffer containing the RSA key context.
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* an RSA key.
* \param[in] hash The hash or message whose signature is to be
* verified.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[in] signature Buffer containing the signature to verify.
* \param[in] signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS
* The signature is valid.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The calculation was performed successfully, but the passed
* signature is not a valid signature.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
*/
psa_status_t mbedtls_psa_rsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length );
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
psa_status_t mbedtls_transparent_test_driver_rsa_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits );
psa_status_t mbedtls_transparent_test_driver_rsa_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
psa_status_t mbedtls_transparent_test_driver_rsa_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key, size_t key_size, size_t *key_length );
psa_status_t mbedtls_transparent_test_driver_rsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length );
psa_status_t mbedtls_transparent_test_driver_rsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length );
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_RSA_H */

View file

@ -155,6 +155,13 @@ psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver,
*
* \param driver The driver table entry containing the persistent
* data to load from storage.
*
* \return #PSA_SUCCESS
* \return #PSA_ERROR_NOT_SUPPORTED
* \return #PSA_ERROR_DOES_NOT_EXIST
* \return #PSA_ERROR_STORAGE_FAILURE
* \return #PSA_ERROR_DATA_CORRUPT
* \return #PSA_ERROR_INVALID_ARGUMENT
*/
psa_status_t psa_load_se_persistent_data(
const psa_se_drv_table_entry_t *driver );
@ -163,6 +170,14 @@ psa_status_t psa_load_se_persistent_data(
*
* \param[in] driver The driver table entry containing the persistent
* data to save to storage.
*
* \return #PSA_SUCCESS
* \return #PSA_ERROR_NOT_SUPPORTED
* \return #PSA_ERROR_NOT_PERMITTED
* \return #PSA_ERROR_NOT_SUPPORTED
* \return #PSA_ERROR_INSUFFICIENT_STORAGE
* \return #PSA_ERROR_STORAGE_FAILURE
* \return #PSA_ERROR_INVALID_ARGUMENT
*/
psa_status_t psa_save_se_persistent_data(
const psa_se_drv_table_entry_t *driver );

View file

@ -45,27 +45,26 @@
typedef struct
{
psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT];
psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];
unsigned key_slots_initialized : 1;
} psa_global_data_t;
static psa_global_data_t global_data;
psa_status_t psa_validate_key_id(
mbedtls_svc_key_id_t key, int vendor_ok )
int psa_is_valid_key_id( mbedtls_svc_key_id_t key, int vendor_ok )
{
psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key );
if( ( PSA_KEY_ID_USER_MIN <= key_id ) &&
( key_id <= PSA_KEY_ID_USER_MAX ) )
return( PSA_SUCCESS );
return( 1 );
if( vendor_ok &&
( PSA_KEY_ID_VENDOR_MIN <= key_id ) &&
( key_id <= PSA_KEY_ID_VENDOR_MAX ) )
return( PSA_SUCCESS );
return( 1 );
return( PSA_ERROR_INVALID_HANDLE );
return( 0 );
}
/** Get the description in memory of a key given its identifier and lock it.
@ -124,17 +123,16 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory(
}
else
{
status = psa_validate_key_id( key, 1 );
if( status != PSA_SUCCESS )
return( status );
if ( !psa_is_valid_key_id( key, 1 ) )
return( PSA_ERROR_INVALID_HANDLE );
for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
{
slot = &global_data.key_slots[ slot_idx ];
if( mbedtls_svc_key_id_equal( key, slot->attr.id ) )
break;
}
status = ( slot_idx < PSA_KEY_SLOT_COUNT ) ?
status = ( slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT ) ?
PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
}
@ -161,7 +159,7 @@ void psa_wipe_all_key_slots( void )
{
size_t slot_idx;
for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
{
psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
slot->lock_count = 1;
@ -184,7 +182,7 @@ psa_status_t psa_get_empty_key_slot( psa_key_id_t *volatile_key_id,
}
selected_slot = unlocked_persistent_key_slot = NULL;
for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
{
psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
if( ! psa_is_key_slot_occupied( slot ) )
@ -248,25 +246,27 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot )
goto exit;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( psa_key_lifetime_is_external( slot->attr.lifetime ) )
/* Special handling is required for loading keys associated with a
* dynamically registered SE interface. */
const psa_drv_se_t *drv;
psa_drv_se_context_t *drv_context;
if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
{
psa_se_key_data_storage_t *data;
if( key_data_length != sizeof( *data ) )
{
status = PSA_ERROR_STORAGE_FAILURE;
status = PSA_ERROR_DATA_INVALID;
goto exit;
}
data = (psa_se_key_data_storage_t *) key_data;
memcpy( &slot->data.se.slot_number, &data->slot_number,
sizeof( slot->data.se.slot_number ) );
status = psa_copy_key_material_into_slot(
slot, data->slot_number, sizeof( data->slot_number ) );
goto exit;
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
{
status = psa_copy_key_material_into_slot( slot, key_data, key_data_length );
if( status != PSA_SUCCESS )
goto exit;
}
status = psa_copy_key_material_into_slot( slot, key_data, key_data_length );
exit:
psa_free_persistent_key_data( key_data, key_data_length );
@ -303,13 +303,15 @@ psa_status_t psa_get_and_lock_key_slot( mbedtls_svc_key_id_t key,
status = psa_load_persistent_key_into_slot( *p_slot );
if( status != PSA_SUCCESS )
{
psa_wipe_key_slot( *p_slot );
if( status == PSA_ERROR_DOES_NOT_EXIST )
status = PSA_ERROR_INVALID_HANDLE;
}
return( status );
#else
return( PSA_ERROR_DOES_NOT_EXIST );
return( PSA_ERROR_INVALID_HANDLE );
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
}
psa_status_t psa_unlock_key_slot( psa_key_slot_t *slot )
@ -343,19 +345,26 @@ psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime,
if ( psa_key_lifetime_is_external( lifetime ) )
{
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* Check whether a driver is registered against this lifetime */
psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime );
if( driver == NULL )
return( PSA_ERROR_INVALID_ARGUMENT );
else
if( driver != NULL )
{
if (p_drv != NULL)
*p_drv = driver;
return( PSA_SUCCESS );
}
#else
#else /* MBEDTLS_PSA_CRYPTO_SE_C */
(void) p_drv;
return( PSA_ERROR_INVALID_ARGUMENT );
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
/* Key location for external keys gets checked by the wrapper */
return( PSA_SUCCESS );
#else /* MBEDTLS_PSA_CRYPTO_DRIVERS */
/* No support for external lifetimes at all, or dynamic interface
* did not find driver for requested lifetime. */
return( PSA_ERROR_INVALID_ARGUMENT );
#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
}
else
/* Local/internal keys are always valid */
@ -390,6 +399,9 @@ psa_status_t psa_open_key( mbedtls_svc_key_id_t key, psa_key_handle_t *handle )
if( status != PSA_SUCCESS )
{
*handle = PSA_KEY_HANDLE_INIT;
if( status == PSA_ERROR_INVALID_HANDLE )
status = PSA_ERROR_DOES_NOT_EXIST;
return( status );
}
@ -414,8 +426,12 @@ psa_status_t psa_close_key( psa_key_handle_t handle )
status = psa_get_and_lock_key_slot_in_memory( handle, &slot );
if( status != PSA_SUCCESS )
return( status );
{
if( status == PSA_ERROR_DOES_NOT_EXIST )
status = PSA_ERROR_INVALID_HANDLE;
return( status );
}
if( slot->lock_count <= 1 )
return( psa_wipe_key_slot( slot ) );
else
@ -444,7 +460,7 @@ void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats )
memset( stats, 0, sizeof( *stats ) );
for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
{
const psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
if( psa_is_key_slot_locked( slot ) )

View file

@ -25,14 +25,10 @@
#include "psa_crypto_core.h"
#include "psa_crypto_se.h"
/* Number of key slots (plus one because 0 is not used).
* The value is a compile-time constant for now, for simplicity. */
#define PSA_KEY_SLOT_COUNT 32
/** Range of volatile key identifiers.
*
* The last PSA_KEY_SLOT_COUNT identifiers of the implementation range
* of key identifiers are reserved for volatile key identifiers.
* The last #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation
* range of key identifiers are reserved for volatile key identifiers.
* A volatile key identifier is equal to #PSA_KEY_ID_VOLATILE_MIN plus the
* index of the key slot containing the volatile key definition.
*/
@ -40,7 +36,7 @@
/** The minimum value for a volatile key identifier.
*/
#define PSA_KEY_ID_VOLATILE_MIN ( PSA_KEY_ID_VENDOR_MAX - \
PSA_KEY_SLOT_COUNT + 1 )
MBEDTLS_PSA_KEY_SLOT_COUNT + 1 )
/** The maximum value for a volatile key identifier.
*/
@ -209,8 +205,8 @@ psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime,
* \param[in] lifetime The key lifetime attribute.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INVALID_ARGUMENT The key is persistent but persistent
* keys are not supported.
* \retval #PSA_ERROR_NOT_SUPPORTED The key is persistent but persistent keys
* are not supported.
*/
psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime );
@ -221,9 +217,8 @@ psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime );
* vendor range are allowed, volatile key identifiers
* excepted \c 0 otherwise.
*
* \retval #PSA_SUCCESS The identifier is valid.
* \retval #PSA_ERROR_INVALID_ARGUMENT The key identifier is not valid.
* \retval <> 0 if the key identifier is valid, 0 otherwise.
*/
psa_status_t psa_validate_key_id( mbedtls_svc_key_id_t key, int vendor_ok );
int psa_is_valid_key_id( mbedtls_svc_key_id_t key, int vendor_ok );
#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */

View file

@ -91,6 +91,8 @@ static psa_storage_uid_t psa_its_identifier_of_slot( mbedtls_svc_key_id_t key )
* \param data_size Size of the \c data buffer in bytes.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_DATA_INVALID
* \retval #PSA_ERROR_DATA_CORRUPT
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_DOES_NOT_EXIST
*/
@ -108,7 +110,7 @@ static psa_status_t psa_crypto_storage_load(
status = psa_its_get( data_identifier, 0, (uint32_t) data_size, data, &data_length );
if( data_size != data_length )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
return( status );
}
@ -139,8 +141,9 @@ int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key )
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_ALREADY_EXISTS
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_DATA_INVALID
*/
static psa_status_t psa_crypto_storage_store( const mbedtls_svc_key_id_t key,
const uint8_t *data,
@ -156,7 +159,7 @@ static psa_status_t psa_crypto_storage_store( const mbedtls_svc_key_id_t key,
status = psa_its_set( data_identifier, (uint32_t) data_length, data, 0 );
if( status != PSA_SUCCESS )
{
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
}
status = psa_its_get_info( data_identifier, &data_identifier_info );
@ -167,7 +170,7 @@ static psa_status_t psa_crypto_storage_store( const mbedtls_svc_key_id_t key,
if( data_identifier_info.size != data_length )
{
status = PSA_ERROR_STORAGE_FAILURE;
status = PSA_ERROR_DATA_INVALID;
goto exit;
}
@ -194,11 +197,11 @@ psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key )
return( PSA_SUCCESS );
if( psa_its_remove( data_identifier ) != PSA_SUCCESS )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
ret = psa_its_get_info( data_identifier, &data_identifier_info );
if( ret != PSA_ERROR_DOES_NOT_EXIST )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
return( PSA_SUCCESS );
}
@ -212,6 +215,8 @@ psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key )
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_DOES_NOT_EXIST
* \retval #PSA_ERROR_DATA_CORRUPT
*/
static psa_status_t psa_crypto_storage_get_data_length(
const mbedtls_svc_key_id_t key,
@ -313,7 +318,7 @@ static psa_status_t check_magic_header( const uint8_t *data )
{
if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER,
PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
return( PSA_SUCCESS );
}
@ -329,7 +334,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
uint32_t version;
if( storage_data_length < sizeof(*storage_format) )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
status = check_magic_header( storage_data );
if( status != PSA_SUCCESS )
@ -337,12 +342,12 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
GET_UINT32_LE( version, storage_format->version, 0 );
if( version != 0 )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
GET_UINT32_LE( *key_data_length, storage_format->data_len, 0 );
if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) ||
*key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
if( *key_data_length == 0 )
{
@ -374,8 +379,12 @@ psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
uint8_t *storage_data;
psa_status_t status;
/* All keys saved to persistent storage always have a key context */
if( data == NULL || data_length == 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
if( data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
return PSA_ERROR_INSUFFICIENT_STORAGE;
return( PSA_ERROR_INSUFFICIENT_STORAGE );
storage_data_length = data_length + sizeof( psa_persistent_key_storage_format );
storage_data = mbedtls_calloc( 1, storage_data_length );
@ -426,6 +435,11 @@ psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr,
status = psa_parse_key_data_from_storage( loaded_data, storage_data_length,
data, data_length, attr );
/* All keys saved to persistent storage always have a key context */
if( status == PSA_SUCCESS &&
( *data == NULL || *data_length == 0 ) )
status = PSA_ERROR_STORAGE_FAILURE;
exit:
mbedtls_free( loaded_data );
return( status );
@ -470,7 +484,7 @@ psa_status_t psa_crypto_load_transaction( void )
if( status != PSA_SUCCESS )
return( status );
if( length != sizeof( psa_crypto_transaction ) )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_ERROR_DATA_INVALID );
return( PSA_SUCCESS );
}

View file

@ -49,7 +49,7 @@ extern "C" {
* - Using the ITS backend, all key ids are ok except 0xFFFFFF52
* (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the
* device's random seed (if this feature is enabled).
* - Only key ids from 1 to #PSA_KEY_SLOT_COUNT are actually used.
* - Only key ids from 1 to #MBEDTLS_PSA_KEY_SLOT_COUNT are actually used.
*
* Since we need to preserve the random seed, avoid using that key slot.
* Reserve a whole range of key slots just in case something else comes up.
@ -86,6 +86,9 @@ int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key );
* already occupied non-persistent key, as well as ensuring the key data is
* validated.
*
* Note: This function will only succeed for key buffers which are not
* empty. If passed a NULL pointer or zero-length, the function will fail
* with #PSA_ERROR_INVALID_ARGUMENT.
*
* \param[in] attr The attributes of the key to save.
* The key identifier field in the attributes
@ -94,10 +97,13 @@ int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key );
* \param data_length The number of bytes that make up the key data.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_ALREADY_EXISTS
* \retval #PSA_ERROR_DATA_INVALID
* \retval #PSA_ERROR_DATA_CORRUPT
*/
psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
const uint8_t *data,
@ -111,9 +117,10 @@ psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
* metadata and writes them to the appropriate output parameters.
*
* Note: This function allocates a buffer and returns a pointer to it through
* the data parameter. psa_free_persistent_key_data() must be called after
* this function to zeroize and free this buffer, regardless of whether this
* function succeeds or fails.
* the data parameter. On successful return, the pointer is guaranteed to be
* valid and the buffer contains at least one byte of data.
* psa_free_persistent_key_data() must be called on the data buffer
* afterwards to zeroize and free this buffer.
*
* \param[in,out] attr On input, the key identifier field identifies
* the key to load. Other fields are ignored.
@ -124,7 +131,8 @@ psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_DATA_INVALID
* \retval #PSA_ERROR_DATA_CORRUPT
* \retval #PSA_ERROR_DOES_NOT_EXIST
*/
psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr,
@ -140,7 +148,7 @@ psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr,
* \retval #PSA_SUCCESS
* The key was successfully removed,
* or the key did not exist.
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_DATA_INVALID
*/
psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key );
@ -183,9 +191,8 @@ void psa_format_key_data_for_storage( const uint8_t *data,
* with the loaded key metadata.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_DATA_INVALID
*/
psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
size_t storage_data_length,
@ -319,6 +326,7 @@ static inline void psa_crypto_prepare_transaction(
* atomically update the transaction state.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_DATA_CORRUPT
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_STORAGE_FAILURE
*/
@ -335,6 +343,8 @@ psa_status_t psa_crypto_save_transaction( void );
* \retval #PSA_ERROR_DOES_NOT_EXIST
* There is no ongoing transaction.
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_DATA_INVALID
* \retval #PSA_ERROR_DATA_CORRUPT
*/
psa_status_t psa_crypto_load_transaction( void );

View file

@ -47,7 +47,7 @@
#define PSA_ITS_STORAGE_PREFIX ""
#endif
#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08lx%08lx"
#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08x%08x"
#define PSA_ITS_STORAGE_SUFFIX ".psa_its"
#define PSA_ITS_STORAGE_FILENAME_LENGTH \
( sizeof( PSA_ITS_STORAGE_PREFIX ) - 1 + /*prefix without terminating 0*/ \
@ -87,8 +87,8 @@ static void psa_its_fill_filename( psa_storage_uid_t uid, char *filename )
mbedtls_snprintf( filename, PSA_ITS_STORAGE_FILENAME_LENGTH,
"%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s",
PSA_ITS_STORAGE_PREFIX,
(unsigned long) ( uid >> 32 ),
(unsigned long) ( uid & 0xffffffff ),
(unsigned) ( uid >> 32 ),
(unsigned) ( uid & 0xffffffff ),
PSA_ITS_STORAGE_SUFFIX );
}

View file

@ -40,7 +40,7 @@
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#include "mbedtls/rsa_internal.h"
#include "rsa_alt_helpers.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
@ -490,6 +490,9 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
mbedtls_rsa_set_padding( ctx, padding, hash_id );
#if defined(MBEDTLS_THREADING_C)
/* Set ctx->ver to nonzero to indicate that the mutex has been
* initialized and will need to be freed. */
ctx->ver = 1;
mbedtls_mutex_init( &ctx->mutex );
#endif
}
@ -537,9 +540,6 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
RSA_VALIDATE_RET( ctx != NULL );
RSA_VALIDATE_RET( f_rng != NULL );
if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
/*
* If the modulus is 1024 bit long or shorter, then the security strength of
* the RSA algorithm is less than or equal to 80 bits and therefore an error
@ -552,6 +552,12 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
mbedtls_mpi_init( &G );
mbedtls_mpi_init( &L );
if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
/*
* find primes P and Q with Q < P so that:
* 1. |P-Q| > 2^( nbits / 2 - 100 )
@ -629,7 +635,9 @@ cleanup:
if( ret != 0 )
{
mbedtls_rsa_free( ctx );
return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret );
if( ( -ret & ~0x7f ) == 0 )
ret = MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret;
return( ret );
}
return( 0 );
@ -1787,21 +1795,19 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
}
#if defined(MBEDTLS_PKCS1_V21)
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
*/
int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
static int rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
mbedtls_md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
int saltlen,
unsigned char *sig )
{
size_t olen;
unsigned char *p = sig;
unsigned char salt[MBEDTLS_MD_MAX_SIZE];
unsigned char *salt = NULL;
size_t slen, min_slen, hlen, offset = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t msb;
@ -1839,31 +1845,44 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
hlen = mbedtls_md_get_size( md_info );
/* Calculate the largest possible salt length. Normally this is the hash
* length, which is the maximum length the salt can have. If there is not
* enough room, use the maximum salt length that fits. The constraint is
* that the hash length plus the salt length plus 2 bytes must be at most
* the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
* (PKCS#1 v2.2) §9.1.1 step 3. */
min_slen = hlen - 2;
if( olen < hlen + min_slen + 2 )
if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY)
{
/* Calculate the largest possible salt length, up to the hash size.
* Normally this is the hash length, which is the maximum salt length
* according to FIPS 185-4 §5.5 (e) and common practice. If there is not
* enough room, use the maximum salt length that fits. The constraint is
* that the hash length plus the salt length plus 2 bytes must be at most
* the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
* (PKCS#1 v2.2) §9.1.1 step 3. */
min_slen = hlen - 2;
if( olen < hlen + min_slen + 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
else if( olen >= hlen + hlen + 2 )
slen = hlen;
else
slen = olen - hlen - 2;
}
else if ( (saltlen < 0) || (saltlen + hlen + 2 > olen) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
else if( olen >= hlen + hlen + 2 )
slen = hlen;
}
else
slen = olen - hlen - 2;
{
slen = (size_t) saltlen;
}
memset( sig, 0, olen );
/* Generate salt of length slen */
if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
/* Note: EMSA-PSS encoding is over the length of N - 1 bits */
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
p += olen - hlen - slen - 2;
*p++ = 0x01;
memcpy( p, salt, slen );
/* Generate salt of length slen in place in the encoded message */
salt = p;
if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
p += slen;
mbedtls_md_init( &md_ctx );
@ -1897,8 +1916,6 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
p += hlen;
*p++ = 0xBC;
mbedtls_platform_zeroize( salt, sizeof( salt ) );
exit:
mbedtls_md_free( &md_ctx );
@ -1909,6 +1926,40 @@ exit:
? mbedtls_rsa_public( ctx, sig, sig )
: mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
}
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with
* the option to pass in the salt length.
*/
int mbedtls_rsa_rsassa_pss_sign_ext( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
int saltlen,
unsigned char *sig )
{
return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, md_alg,
hashlen, hash, saltlen, sig );
}
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
*/
int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
mbedtls_md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{
return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg,
hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig );
}
#endif /* MBEDTLS_PKCS1_V21 */
#if defined(MBEDTLS_PKCS1_V15)
@ -2481,7 +2532,6 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
RSA_VALIDATE_RET( dst != NULL );
RSA_VALIDATE_RET( src != NULL );
dst->ver = src->ver;
dst->len = src->len;
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
@ -2540,7 +2590,12 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
#endif /* MBEDTLS_RSA_NO_CRT */
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &ctx->mutex );
/* Free the mutex, but only if it hasn't been freed already. */
if( ctx->ver != 0 )
{
mbedtls_mutex_free( &ctx->mutex );
ctx->ver = 0;
}
#endif
}

View file

@ -24,7 +24,7 @@
#include "mbedtls/rsa.h"
#include "mbedtls/bignum.h"
#include "mbedtls/rsa_internal.h"
#include "rsa_alt_helpers.h"
/*
* Compute RSA prime factors from public and private exponents
@ -237,90 +237,36 @@ cleanup:
return( ret );
}
/*
* Check that RSA CRT parameters are in accordance with core parameters.
*/
int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *DP,
const mbedtls_mpi *DQ, const mbedtls_mpi *QP )
int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, mbedtls_mpi *DP,
mbedtls_mpi *DQ, mbedtls_mpi *QP )
{
int ret = 0;
mbedtls_mpi K, L;
mbedtls_mpi K;
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &L );
/* Check that DP - D == 0 mod P - 1 */
/* DP = D mod P-1 */
if( DP != NULL )
{
if( P == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) );
}
/* Check that DQ - D == 0 mod Q - 1 */
/* DQ = D mod Q-1 */
if( DQ != NULL )
{
if( Q == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) );
}
/* Check that QP * Q - 1 == 0 mod P */
/* QP = Q^{-1} mod P */
if( QP != NULL )
{
if( P == NULL || Q == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) );
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) );
}
cleanup:
/* Wrap MPI error codes by RSA check failure error code */
if( ret != 0 &&
ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
{
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
}
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &L );
return( ret );
}
@ -449,36 +395,90 @@ cleanup:
return( ret );
}
int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, mbedtls_mpi *DP,
mbedtls_mpi *DQ, mbedtls_mpi *QP )
/*
* Check that RSA CRT parameters are in accordance with core parameters.
*/
int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *DP,
const mbedtls_mpi *DQ, const mbedtls_mpi *QP )
{
int ret = 0;
mbedtls_mpi K;
mbedtls_mpi_init( &K );
/* DP = D mod P-1 */
mbedtls_mpi K, L;
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &L );
/* Check that DP - D == 0 mod P - 1 */
if( DP != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) );
if( P == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/* DQ = D mod Q-1 */
/* Check that DQ - D == 0 mod Q - 1 */
if( DQ != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) );
if( Q == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/* QP = Q^{-1} mod P */
/* Check that QP * Q - 1 == 0 mod P */
if( QP != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) );
if( P == NULL || Q == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) );
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
cleanup:
/* Wrap MPI error codes by RSA check failure error code */
if( ret != 0 &&
ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
{
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
}
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &L );
return( ret );
}

224
library/rsa_alt_helpers.h Normal file
View file

@ -0,0 +1,224 @@
/**
* \file rsa_alt_helpers.h
*
* \brief Context-independent RSA helper functions
*
* This module declares some RSA-related helper functions useful when
* implementing the RSA interface. These functions are provided in a separate
* compilation unit in order to make it easy for designers of alternative RSA
* implementations to use them in their own code, as it is conceived that the
* functionality they provide will be necessary for most complete
* implementations.
*
* End-users of Mbed TLS who are not providing their own alternative RSA
* implementations should not use these functions directly, and should instead
* use only the functions declared in rsa.h.
*
* The interface provided by this module will be maintained through LTS (Long
* Term Support) branches of Mbed TLS, but may otherwise be subject to change,
* and must be considered an internal interface of the library.
*
* There are two classes of helper functions:
*
* (1) Parameter-generating helpers. These are:
* - mbedtls_rsa_deduce_primes
* - mbedtls_rsa_deduce_private_exponent
* - mbedtls_rsa_deduce_crt
* Each of these functions takes a set of core RSA parameters and
* generates some other, or CRT related parameters.
*
* (2) Parameter-checking helpers. These are:
* - mbedtls_rsa_validate_params
* - mbedtls_rsa_validate_crt
* They take a set of core or CRT related RSA parameters and check their
* validity.
*
*/
/*
* 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_RSA_INTERNAL_H
#define MBEDTLS_RSA_INTERNAL_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/bignum.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Compute RSA prime moduli P, Q from public modulus N=PQ
* and a pair of private and public key.
*
* \note This is a 'static' helper function not operating on
* an RSA context. Alternative implementations need not
* overwrite it.
*
* \param N RSA modulus N = PQ, with P, Q to be found
* \param E RSA public exponent
* \param D RSA private exponent
* \param P Pointer to MPI holding first prime factor of N on success
* \param Q Pointer to MPI holding second prime factor of N on success
*
* \return
* - 0 if successful. In this case, P and Q constitute a
* factorization of N.
* - A non-zero error code otherwise.
*
* \note It is neither checked that P, Q are prime nor that
* D, E are modular inverses wrt. P-1 and Q-1. For that,
* use the helper function \c mbedtls_rsa_validate_params.
*
*/
int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E,
mbedtls_mpi const *D,
mbedtls_mpi *P, mbedtls_mpi *Q );
/**
* \brief Compute RSA private exponent from
* prime moduli and public key.
*
* \note This is a 'static' helper function not operating on
* an RSA context. Alternative implementations need not
* overwrite it.
*
* \param P First prime factor of RSA modulus
* \param Q Second prime factor of RSA modulus
* \param E RSA public exponent
* \param D Pointer to MPI holding the private exponent on success.
*
* \return
* - 0 if successful. In this case, D is set to a simultaneous
* modular inverse of E modulo both P-1 and Q-1.
* - A non-zero error code otherwise.
*
* \note This function does not check whether P and Q are primes.
*
*/
int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P,
mbedtls_mpi const *Q,
mbedtls_mpi const *E,
mbedtls_mpi *D );
/**
* \brief Generate RSA-CRT parameters
*
* \note This is a 'static' helper function not operating on
* an RSA context. Alternative implementations need not
* overwrite it.
*
* \param P First prime factor of N
* \param Q Second prime factor of N
* \param D RSA private exponent
* \param DP Output variable for D modulo P-1
* \param DQ Output variable for D modulo Q-1
* \param QP Output variable for the modular inverse of Q modulo P.
*
* \return 0 on success, non-zero error code otherwise.
*
* \note This function does not check whether P, Q are
* prime and whether D is a valid private exponent.
*
*/
int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, mbedtls_mpi *DP,
mbedtls_mpi *DQ, mbedtls_mpi *QP );
/**
* \brief Check validity of core RSA parameters
*
* \note This is a 'static' helper function not operating on
* an RSA context. Alternative implementations need not
* overwrite it.
*
* \param N RSA modulus N = PQ
* \param P First prime factor of N
* \param Q Second prime factor of N
* \param D RSA private exponent
* \param E RSA public exponent
* \param f_rng PRNG to be used for primality check, or NULL
* \param p_rng PRNG context for f_rng, or NULL
*
* \return
* - 0 if the following conditions are satisfied
* if all relevant parameters are provided:
* - P prime if f_rng != NULL (%)
* - Q prime if f_rng != NULL (%)
* - 1 < N = P * Q
* - 1 < D, E < N
* - D and E are modular inverses modulo P-1 and Q-1
* (%) This is only done if MBEDTLS_GENPRIME is defined.
* - A non-zero error code otherwise.
*
* \note The function can be used with a restricted set of arguments
* to perform specific checks only. E.g., calling it with
* (-,P,-,-,-) and a PRNG amounts to a primality check for P.
*/
int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P,
const mbedtls_mpi *Q, const mbedtls_mpi *D,
const mbedtls_mpi *E,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Check validity of RSA CRT parameters
*
* \note This is a 'static' helper function not operating on
* an RSA context. Alternative implementations need not
* overwrite it.
*
* \param P First prime factor of RSA modulus
* \param Q Second prime factor of RSA modulus
* \param D RSA private exponent
* \param DP MPI to check for D modulo P-1
* \param DQ MPI to check for D modulo P-1
* \param QP MPI to check for the modular inverse of Q modulo P.
*
* \return
* - 0 if the following conditions are satisfied:
* - D = DP mod P-1 if P, D, DP != NULL
* - Q = DQ mod P-1 if P, D, DQ != NULL
* - QP = Q^-1 mod P if P, Q, QP != NULL
* - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed,
* potentially including \c MBEDTLS_ERR_MPI_XXX if some
* MPI calculations failed.
* - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient
* data was provided to check DP, DQ or QP.
*
* \note The function can be used with a restricted set of arguments
* to perform specific checks only. E.g., calling it with the
* parameters (P, -, D, DP, -, -) will check DP = D mod P-1.
*/
int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *DP,
const mbedtls_mpi *DQ, const mbedtls_mpi *QP );
#ifdef __cplusplus
}
#endif
#endif /* rsa_alt_helpers.h */

View file

@ -34,7 +34,7 @@
#endif
#include "mbedtls/ssl_cache.h"
#include "mbedtls/ssl_internal.h"
#include "ssl_misc.h"
#include <string.h>

View file

@ -30,7 +30,7 @@
#endif
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
#include "ssl_misc.h"
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
@ -683,7 +683,7 @@ static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
return( 0 );
MBEDTLS_SSL_DEBUG_MSG( 3,
( "sending session ticket of length %d", tlen ) );
( "sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen ) );
memcpy( p, ssl->session_negotiate->ticket, tlen );
@ -903,7 +903,8 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl )
*p++ = (unsigned char)( t >> 8 );
*p++ = (unsigned char)( t );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
(long long) t ) );
#else
if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
return( ret );
@ -1105,7 +1106,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
for( i = 0; i < n; i++ )
*p++ = ssl->session_negotiate->id[i];
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n );
/*
@ -1174,7 +1175,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
continue;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %#04x (%s)",
ciphersuites[i], ciphersuite_info->name ) );
(unsigned int)ciphersuites[i], ciphersuite_info->name ) );
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@ -1189,7 +1190,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
}
MBEDTLS_SSL_DEBUG_MSG( 3,
( "client hello, got %d ciphersuites (excluding SCSVs)", n ) );
( "client hello, got %" MBEDTLS_PRINTF_SIZET " ciphersuites (excluding SCSVs)", n ) );
/*
* Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
@ -1380,7 +1381,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
/* olen unused if all extensions are disabled */
((void) olen);
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
ext_len ) );
if( ext_len > 0 )
@ -2122,10 +2123,10 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu",
( (uint32_t) buf[2] << 24 ) |
( (uint32_t) buf[3] << 16 ) |
( (uint32_t) buf[4] << 8 ) |
( (uint32_t) buf[5] ) ) );
( (unsigned long) buf[2] << 24 ) |
( (unsigned long) buf[3] << 16 ) |
( (unsigned long) buf[4] << 8 ) |
( (unsigned long) buf[5] ) ) );
memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 );
@ -2195,7 +2196,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
if( ssl->handshake->ciphersuite_info == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1,
( "ciphersuite info for %04x not found", i ) );
( "ciphersuite info for %04x not found", (unsigned int)i ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@ -2203,7 +2204,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n );
/*
@ -2246,7 +2247,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
ssl->handshake->resume ? "a" : "no" ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", (unsigned) i ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d",
buf[37 + n] ) );
@ -2312,7 +2313,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
ext = buf + 40 + n;
MBEDTLS_SSL_DEBUG_MSG( 2,
( "server hello, total extension length: %d", ext_len ) );
( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len ) );
while( ext_len )
{
@ -2476,7 +2477,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
default:
MBEDTLS_SSL_DEBUG_MSG( 3,
( "unknown extension found: %d (ignoring)", ext_id ) );
( "unknown extension found: %u (ignoring)", ext_id ) );
}
ext_len -= 4 + ext_size;
@ -2567,7 +2568,7 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u",
ssl->handshake->dhm_ctx.len * 8,
ssl->conf->dhm_min_bitlen ) );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
@ -4281,7 +4282,7 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len ) );
/* We're not waiting for a NewSessionTicket message any more */
ssl->handshake->new_session_ticket = 0;

View file

@ -33,7 +33,7 @@
#endif
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/ssl_internal.h"
#include "ssl_misc.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"

1265
library/ssl_misc.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -35,7 +35,7 @@
#endif
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
#include "ssl_misc.h"
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
@ -279,8 +279,8 @@ static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
}
ssl->handshake->retransmit_timeout = new_timeout;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
ssl->handshake->retransmit_timeout ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
(unsigned long) ssl->handshake->retransmit_timeout ) );
return( 0 );
}
@ -288,8 +288,8 @@ static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
{
ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
ssl->handshake->retransmit_timeout ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
(unsigned long) ssl->handshake->retransmit_timeout ) );
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
@ -557,9 +557,10 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
(unsigned) rec->data_len,
MBEDTLS_SSL_OUT_CONTENT_LEN ) );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %" MBEDTLS_PRINTF_SIZET
" too large, maximum %" MBEDTLS_PRINTF_SIZET,
rec->data_len,
(size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@ -687,7 +688,7 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
"including %d bytes of padding",
rec->data_len, 0 ) );
@ -765,7 +766,7 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
dynamic_iv_is_explicit ? dynamic_iv_len : 0 );
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
add_data, add_data_len );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
"including 0 bytes of padding",
rec->data_len ) );
@ -868,8 +869,9 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
"including %d bytes of IV and %d bytes of padding",
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
"including %" MBEDTLS_PRINTF_SIZET
" bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding",
rec->data_len, transform->ivlen,
padlen + 1 ) );
@ -1289,7 +1291,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
{
if( rec->data_len < dynamic_iv_len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) ",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
" ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ",
rec->data_len,
dynamic_iv_len ) );
return( MBEDTLS_ERR_SSL_INVALID_MAC );
@ -1308,7 +1311,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
/* Check that there's space for the authentication tag. */
if( rec->data_len < transform->taglen )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < taglen (%d) ",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
") < taglen (%" MBEDTLS_PRINTF_SIZET ") ",
rec->data_len,
transform->taglen ) );
return( MBEDTLS_ERR_SSL_INVALID_MAC );
@ -1411,7 +1415,9 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
if( rec->data_len < minlen + transform->ivlen ||
rec->data_len < minlen + transform->maclen + 1 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) "
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
") < max( ivlen(%" MBEDTLS_PRINTF_SIZET
"), maclen (%" MBEDTLS_PRINTF_SIZET ") "
"+ 1 ) ( + expl IV )", rec->data_len,
transform->ivlen,
transform->maclen ) );
@ -1477,7 +1483,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
* data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */
if( rec->data_len % transform->ivlen != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0",
rec->data_len, transform->ivlen ) );
return( MBEDTLS_ERR_SSL_INVALID_MAC );
}
@ -1547,7 +1554,9 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
#if defined(MBEDTLS_SSL_DEBUG_ALL)
if( rec->data_len < transform->maclen + padlen + 1 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
") < maclen (%" MBEDTLS_PRINTF_SIZET
") + padlen (%" MBEDTLS_PRINTF_SIZET ")",
rec->data_len,
transform->maclen,
padlen + 1 ) );
@ -1810,7 +1819,8 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
if( ssl->in_left != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d",
MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %"
MBEDTLS_PRINTF_SIZET,
ssl->next_record_offset ) );
memmove( ssl->in_hdr,
ssl->in_hdr + ssl->next_record_offset,
@ -1820,7 +1830,8 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
ssl->next_record_offset = 0;
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
", nb_want: %" MBEDTLS_PRINTF_SIZET,
ssl->in_left, nb_want ) );
/*
@ -1862,7 +1873,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
else
timeout = ssl->conf->read_timeout;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %lu ms", (unsigned long) timeout ) );
if( ssl->f_recv_timeout != NULL )
ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
@ -1921,7 +1932,8 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
else
#endif
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
", nb_want: %" MBEDTLS_PRINTF_SIZET,
ssl->in_left, nb_want ) );
while( ssl->in_left < nb_want )
@ -1945,7 +1957,8 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
}
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
", nb_want: %" MBEDTLS_PRINTF_SIZET,
ssl->in_left, nb_want ) );
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
@ -1958,8 +1971,8 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1,
( "f_recv returned %d bytes but only %lu were requested",
ret, (unsigned long)len ) );
( "f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested",
ret, len ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
@ -1998,7 +2011,8 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
while( ssl->out_left > 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %" MBEDTLS_PRINTF_SIZET
", out_left: %" MBEDTLS_PRINTF_SIZET,
mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
buf = ssl->out_hdr - ssl->out_left;
@ -2012,8 +2026,8 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1,
( "f_send returned %d bytes but only %lu bytes were sent",
ret, (unsigned long)ssl->out_left ) );
( "f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent",
ret, ssl->out_left ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
@ -2054,14 +2068,15 @@ static int ssl_flight_append( mbedtls_ssl_context *ssl )
/* Allocate space for current message */
if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
sizeof( mbedtls_ssl_flight_item ) ) );
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
}
if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
ssl->out_msglen ) );
mbedtls_free( msg );
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
}
@ -2447,9 +2462,10 @@ int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
"size %u, maximum %u",
(unsigned) ssl->out_msglen,
(unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
"size %" MBEDTLS_PRINTF_SIZET
", maximum %" MBEDTLS_PRINTF_SIZET,
ssl->out_msglen,
(size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
@ -2476,9 +2492,9 @@ int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
"size %u, maximum %u",
(unsigned) ( hs_len ),
(unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
"size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET,
hs_len,
(size_t) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@ -2640,8 +2656,8 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
/* Now write the potentially updated record content type. */
ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
"version = [%d:%d], msglen = %d",
MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %u, "
"version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET,
ssl->out_hdr[0], ssl->out_hdr[1],
ssl->out_hdr[2], len ) );
@ -2837,7 +2853,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
{
if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %" MBEDTLS_PRINTF_SIZET,
ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
@ -2845,7 +2861,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
" %d, type = %d, hslen = %d",
" %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET,
ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
@ -2881,7 +2897,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, "
"message_seq = %d, start_of_flight = %d",
"message_seq = %u, start_of_flight = %u",
recv_msg_seq,
ssl->handshake->in_flight_start_seq ) );
@ -2894,7 +2910,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
else
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: "
"message_seq = %d, expected = %d",
"message_seq = %u, expected = %u",
recv_msg_seq,
ssl->handshake->in_msg_seq ) );
}
@ -3464,8 +3480,8 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 );
MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
"version = [%d:%d], msglen = %d",
MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %u, "
"version = [%d:%d], msglen = %" MBEDTLS_PRINTF_SIZET,
rec->type,
major_ver, minor_ver, rec->data_len ) );
@ -3508,8 +3524,8 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
if( rec_epoch != ssl->in_epoch )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
"expected %d, received %d",
ssl->in_epoch, rec_epoch ) );
"expected %u, received %lu",
ssl->in_epoch, (unsigned long) rec_epoch ) );
/* Records from the next epoch are considered for buffering
* (concretely: early Finished messages). */
@ -4027,31 +4043,41 @@ static int ssl_buffer_message( mbedtls_ssl_context *ssl )
{
/* If we can't buffer a future message because
* of space limitations -- ignore. */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
(unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
(unsigned) hs->buffering.total_bytes_buffered ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
" would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
" (already %" MBEDTLS_PRINTF_SIZET
" bytes buffered) -- ignore\n",
msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
hs->buffering.total_bytes_buffered ) );
goto exit;
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n",
(unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
(unsigned) hs->buffering.total_bytes_buffered ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
" would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
" (already %" MBEDTLS_PRINTF_SIZET
" bytes buffered) -- attempt to make space by freeing buffered future messages\n",
msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
hs->buffering.total_bytes_buffered ) );
}
if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n",
(unsigned) msg_len,
(unsigned) reassembly_buf_sz,
MBEDTLS_SSL_DTLS_MAX_BUFFERING,
(unsigned) hs->buffering.total_bytes_buffered ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET
" (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed"
" the compile-time limit %" MBEDTLS_PRINTF_SIZET
" (already %" MBEDTLS_PRINTF_SIZET
" bytes buffered) -- fail\n",
msg_len,
reassembly_buf_sz,
(size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
hs->buffering.total_bytes_buffered ) );
ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
goto exit;
}
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET,
msg_len ) );
hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
@ -4097,7 +4123,8 @@ static int ssl_buffer_message( mbedtls_ssl_context *ssl )
frag_off = ssl_get_hs_frag_off( ssl );
frag_len = ssl_get_hs_frag_len( ssl );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %" MBEDTLS_PRINTF_SIZET
", length = %" MBEDTLS_PRINTF_SIZET,
frag_off, frag_len ) );
memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
@ -4324,15 +4351,18 @@ static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
hs->buffering.total_bytes_buffered ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
(unsigned) rec->buf_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
(unsigned) hs->buffering.total_bytes_buffered ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET
" would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
" (already %" MBEDTLS_PRINTF_SIZET
" bytes buffered) -- ignore\n",
rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
hs->buffering.total_bytes_buffered ) );
return( 0 );
}
/* Buffer record */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
ssl->in_epoch + 1 ) );
ssl->in_epoch + 1U ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len );
/* ssl_parse_record_header() only considers records
@ -4585,7 +4615,7 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
{
if( ssl->in_msglen != 1 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET,
ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
@ -4621,12 +4651,12 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
/* Note: Standard allows for more than one 2 byte alert
to be packed in a single message, but Mbed TLS doesn't
currently support this. */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %" MBEDTLS_PRINTF_SIZET,
ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%u:%u]",
ssl->in_msg[0], ssl->in_msg[1] ) );
/*
@ -5411,7 +5441,8 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) "
"maximum fragment length: %d > %d",
"maximum fragment length: %" MBEDTLS_PRINTF_SIZET
" > %" MBEDTLS_PRINTF_SIZET,
len, max_len ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}

View file

@ -30,7 +30,7 @@
#endif
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
#include "ssl_misc.h"
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
@ -298,13 +298,13 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
{
mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:"
" match sig %d and hash %d",
sig_cur, md_cur ) );
" match sig %u and hash %u",
(unsigned) sig_cur, (unsigned) md_cur ) );
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: "
"hash alg %d not supported", md_cur ) );
"hash alg %u not supported", (unsigned) md_cur ) );
}
}
@ -631,7 +631,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
/* Remember the client asked us to send a new ticket */
ssl->handshake->new_session_ticket = 1;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, len ) );
if( len == 0 )
return( 0 );
@ -1046,7 +1046,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %#04x (%s)",
suite_id, suite_info->name ) );
(unsigned int) suite_id, suite_info->name ) );
if( suite_info->min_minor_ver > ssl->minor_ver ||
suite_info->max_minor_ver < ssl->minor_ver )
@ -1105,7 +1105,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm "
"for signature algorithm %d", sig_type ) );
"for signature algorithm %u", (unsigned) sig_type ) );
return( 0 );
}
}
@ -1347,7 +1347,7 @@ read_record_header:
if( cli_msg_seq != ssl->handshake->in_msg_seq )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: "
"%d (expected %d)", cli_msg_seq,
"%u (expected %u)", cli_msg_seq,
ssl->handshake->in_msg_seq ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
@ -1588,8 +1588,7 @@ read_record_header:
ext_len = ( buf[ext_offset + 0] << 8 )
| ( buf[ext_offset + 1] );
if( ( ext_len > 0 && ext_len < 4 ) ||
msg_len != ext_offset + 2 + ext_len )
if( msg_len != ext_offset + 2 + ext_len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@ -1774,20 +1773,12 @@ read_record_header:
#endif /* MBEDTLS_SSL_DTLS_SRTP */
default:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %u (ignoring)",
ext_id ) );
}
ext_len -= 4 + ext_size;
ext += 4 + ext_size;
if( ext_len > 0 && ext_len < 4 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
}
#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
@ -1972,7 +1963,7 @@ have_ciphersuite:
else
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm "
"%d - should not happen", sig_alg ) );
"%u - should not happen", (unsigned) sig_alg ) );
}
}
#endif
@ -2522,7 +2513,8 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
*p++ = (unsigned char)( t >> 8 );
*p++ = (unsigned char)( t );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
(long long) t ) );
#else
if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
return( ret );
@ -2610,7 +2602,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len );
p += ssl->session_negotiate->id_len;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
ssl->handshake->resume ? "a" : "no" ) );
@ -2622,7 +2614,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s",
mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X",
ssl->session_negotiate->compression ) );
(unsigned int) ssl->session_negotiate->compression ) );
/*
* First write extensions, then the total length
@ -2685,7 +2677,8 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
ext_len += olen;
#endif
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
ext_len ) );
if( ext_len > 0 )
{
@ -3186,7 +3179,7 @@ curve_matching_done:
md_alg = MBEDTLS_MD_NONE;
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %u for signing", (unsigned) md_alg ) );
/*
* 2.2: Compute the hash to be signed

View file

@ -29,7 +29,7 @@
#define mbedtls_free free
#endif
#include "mbedtls/ssl_internal.h"
#include "ssl_misc.h"
#include "mbedtls/ssl_ticket.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"

View file

@ -34,7 +34,7 @@
#endif
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
#include "ssl_misc.h"
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
@ -279,7 +279,8 @@ static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing,
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %d", in_buf_new_len ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %" MBEDTLS_PRINTF_SIZET,
in_buf_new_len ) );
modified = 1;
}
}
@ -300,7 +301,8 @@ static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing,
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %d", out_buf_new_len ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %" MBEDTLS_PRINTF_SIZET,
out_buf_new_len ) );
modified = 1;
}
}
@ -867,7 +869,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
if( cipher_info == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %u not found",
ciphersuite_info->cipher ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@ -875,8 +877,8 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
if( md_info == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found",
ciphersuite_info->mac ) );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %u not found",
(unsigned) ciphersuite_info->mac ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@ -1959,8 +1961,9 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
n = crt->raw.len;
if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %" MBEDTLS_PRINTF_SIZET
" > %" MBEDTLS_PRINTF_SIZET,
i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE );
}
@ -2428,8 +2431,8 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_DEBUG_C)
if( ssl->session_negotiate->verify_result != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x",
ssl->session_negotiate->verify_result ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %08x",
(unsigned int) ssl->session_negotiate->verify_result ) );
}
else
{
@ -2552,7 +2555,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
if( chain == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed",
sizeof( mbedtls_x509_crt ) ) );
mbedtls_ssl_send_alert_message( ssl,
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@ -3468,7 +3471,7 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
ssl->in_buf = mbedtls_calloc( 1, in_buf_len );
if( ssl->in_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", in_buf_len ) );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len ) );
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
goto error;
}
@ -3479,7 +3482,7 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
ssl->out_buf = mbedtls_calloc( 1, out_buf_len );
if( ssl->out_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", out_buf_len ) );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len ) );
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
goto error;
}

View file

@ -22,7 +22,7 @@
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
#include "mbedtls/hkdf.h"
#include "mbedtls/ssl_internal.h"
#include "ssl_misc.h"
#include "ssl_tls13_keys.h"
#include <stdint.h>

View file

@ -67,6 +67,12 @@ static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
if( mutex == NULL )
return;
/* A nonzero value of is_valid indicates a successfully initialized
* mutex. This is a workaround for not being able to return an error
* code for this function. The lock/unlock functions return an error
* if is_valid is nonzero. The Mbed TLS unit test code uses this field
* to distinguish more states of the mutex; see
* tests/src/threading_helpers for details. */
mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0;
}

View file

@ -225,6 +225,9 @@ static const char * const features[] = {
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
"MBEDTLS_ECP_INTERNAL_ALT",
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
#if defined(MBEDTLS_ECP_NO_FALLBACK)
"MBEDTLS_ECP_NO_FALLBACK",
#endif /* MBEDTLS_ECP_NO_FALLBACK */
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
"MBEDTLS_ECP_RANDOMIZE_JAC_ALT",
#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
@ -432,6 +435,9 @@ static const char * const features[] = {
#if defined(MBEDTLS_PKCS1_V21)
"MBEDTLS_PKCS1_V21",
#endif /* MBEDTLS_PKCS1_V21 */
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
"MBEDTLS_PSA_CRYPTO_CLIENT",
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
"MBEDTLS_PSA_CRYPTO_DRIVERS",
#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
@ -624,9 +630,6 @@ static const char * const features[] = {
#if defined(MBEDTLS_CCM_C)
"MBEDTLS_CCM_C",
#endif /* MBEDTLS_CCM_C */
#if defined(MBEDTLS_CERTS_C)
"MBEDTLS_CERTS_C",
#endif /* MBEDTLS_CERTS_C */
#if defined(MBEDTLS_CHACHA20_C)
"MBEDTLS_CHACHA20_C",
#endif /* MBEDTLS_CHACHA20_C */

View file

@ -995,73 +995,4 @@ int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
return( 0 );
}
#endif /* MBEDTLS_HAVE_TIME_DATE */
#if defined(MBEDTLS_SELF_TEST)
#include "mbedtls/x509_crt.h"
#include "mbedtls/certs.h"
/*
* Checkup routine
*/
int mbedtls_x509_self_test( int verbose )
{
int ret = 0;
#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
uint32_t flags;
mbedtls_x509_crt cacert;
mbedtls_x509_crt clicert;
if( verbose != 0 )
mbedtls_printf( " X.509 certificate load: " );
mbedtls_x509_crt_init( &cacert );
mbedtls_x509_crt_init( &clicert );
ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
mbedtls_test_cli_crt_len );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
goto cleanup;
}
ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
mbedtls_test_ca_crt_len );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
goto cleanup;
}
if( verbose != 0 )
mbedtls_printf( "passed\n X.509 signature verify: ");
ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
goto cleanup;
}
if( verbose != 0 )
mbedtls_printf( "passed\n\n");
cleanup:
mbedtls_x509_crt_free( &cacert );
mbedtls_x509_crt_free( &clicert );
#else
((void) verbose);
#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */
return( ret );
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_X509_USE_C */

View file

@ -1629,6 +1629,8 @@ cleanup:
}
#endif /* MBEDTLS_THREADING_C */
memset( &sb, 0, sizeof( sb ) );
while( ( entry = readdir( dir ) ) != NULL )
{
snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,