Expose mbedtls_psa_get_random()

Expose whatever RNG the PSA subsystem uses to applications using the
mbedtls_xxx API.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2021-02-03 20:04:08 +01:00
parent 077599ad85
commit e3ed802138
5 changed files with 212 additions and 0 deletions

View file

@ -0,0 +1,8 @@
Features
* Partial implementation of the PSA crypto driver interface: Mbed TLS can
now use an external random generator instead of the library's own
entropy collection and DRBG code. Enable MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
and See the documentatio of mbedtls_psa_external_get_random() for details.
* Applications using PSA crypto can now use its random generator in the
mbedtls_xxx API. See the documentation of mbedtls_psa_get_random() for
details.

View file

@ -419,4 +419,88 @@ static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src,
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* Expose whatever RNG the PSA subsystem uses to applications using the
* mbedtls_xxx API. The declarations here need to be consistent with the
* implementation in library/psa_crypto_random_impl.h. */
#if defined(MBEDTLS_PSA_CRYPTO_C)
/* The type of a `f_rng` random generator function that many library functions
* take.
*
* This type name is not part of the Mbed TLS stable API. It may be renamed
* or moved without warning.
*/
typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_size );
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
/** The random generator function for the PSA subsystem.
*
* This function is suitable as the `f_rng` random generator function
* parameter of many `mbedtls_xxx` functions. It must be used in combination
* with the random generator state #MBEDTLS_PSA_RANDOM_STATE.
*
* The implementation of this function depends on the configuration of the
* library.
* \note Depending on the configuration, this may be a function or
* a pointer to a function.
*
* \note This function may only be used if the PSA crypto subsystem is active.
* This means that you must call psa_crypto_init() before any call to
* this function, and you must not call this function after calling
* mbedtls_psa_crypto_free().
*
* \param p_rng The random generator context. This must be
* #MBEDTLS_PSA_RANDOM_STATE. No other state is
* supported.
* \param output The buffer to fill. It must have room for
* \c output_size bytes.
* \param output_size The number of bytes to write to \p output.
* This function may fail if \p output_size is too
* large. It is guaranteed to accept any output size
* requested by Mbed TLS library functions. The
* maximum request size depends on the library
* configuration.
*
* \return \c 0 on success.
* \return An `MBEDTLS_ERR_ENTROPY_xxx`,
* `MBEDTLS_ERR_CTR_DRBG_xxx` or
* `MBEDTLS_ERR_HMAC_DRBG_xxx` on error.
*/
int mbedtls_psa_get_random( void *p_rng,
unsigned char *output,
size_t output_size );
/** The random generator state for the PSA subsystem.
*
* This macro expands to an expression which is suitable as the `p_rng`
* random generator state parameter of many `mbedtls_xxx` functions.
* It must be used in combination with the random generator function
* mbedtls_psa_get_random().
*
* The implementation of this macro depends on the configuration of the
* library. Do not make any assumption on its nature.
*/
#define MBEDTLS_PSA_RANDOM_STATE NULL
#else /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
#if defined(MBEDTLS_CTR_DRBG_C)
#include "mbedtls/ctr_drbg.h"
typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t;
static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random;
#elif defined(MBEDTLS_HMAC_DRBG_C)
#include "mbedtls/hmac_drbg.h"
typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t;
static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random;
#endif
extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state
#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
#endif /* MBEDTLS_PSA_CRYPTO_C */
#endif /* MBEDTLS_PSA_UTIL_H */

View file

@ -1,6 +1,9 @@
/** \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.
*/
/*
* Copyright The Mbed TLS Contributors

View file

@ -13,5 +13,39 @@ Generate random twice with HMAC_DRBG(SHA-512)
depends_on:MBEDTLS_SHA512_C
random_twice_with_hmac_drbg:MBEDTLS_MD_SHA512
Generate random twice with PSA classic wrapper
random_twice_with_psa_from_classic:
Generate random twice with PSA API
random_twice_with_psa_from_psa:
# This bad-usage test case currently crashes in the default configuration
# because CTR_DRBG crashes when given an unseeded context. This is arguably
# a good thing because it prevents misuse of mbedtls_psa_get_random().
#PSA classic wrapper: PSA not active
#mbedtls_psa_get_random_no_init:
PSA classic wrapper: 0 bytes
mbedtls_psa_get_random_length:0
PSA classic wrapper: 1 byte
mbedtls_psa_get_random_length:1
PSA classic wrapper: 256 bytes
mbedtls_psa_get_random_length:256
PSA classic wrapper: external RNG large
depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
mbedtls_psa_get_random_length:1024
PSA classic wrapper: CTR_DRBG max
depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG:MBEDTLS_CTR_DRBG_C
mbedtls_psa_get_random_length:MBEDTLS_CTR_DRBG_MAX_REQUEST
PSA classic wrapper: HMAC_DRBG max
depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG:!MBEDTLS_CTR_DRBG_C:MBEDTLS_HMAC_DRBG_C
mbedtls_psa_get_random_length:MBEDTLS_HMAC_DRBG_MAX_REQUEST
PSA classic wrapper: ECDSA signature (SECP256R1)
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
mbedtls_psa_get_random_ecdsa_sign:MBEDTLS_ECP_DP_SECP256R1

View file

@ -2,9 +2,12 @@
/* Test random generation as a whole. */
#include "mbedtls/bignum.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/entropy.h"
#include "mbedtls/hmac_drbg.h"
#include "mbedtls/psa_util.h"
#include "psa/crypto.h"
/* How many bytes to generate in each test case for repeated generation.
@ -94,6 +97,32 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
void random_twice_with_psa_from_classic( )
{
unsigned char output1[OUTPUT_SIZE];
unsigned char output2[OUTPUT_SIZE];
/* First round */
PSA_ASSERT( psa_crypto_init( ) );
TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
output1, sizeof( output1 ) ) );
PSA_DONE( );
/* Second round */
PSA_ASSERT( psa_crypto_init( ) );
TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
output2, sizeof( output2 ) ) );
PSA_DONE( );
/* The two rounds must generate different random data. */
TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
exit:
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
void random_twice_with_psa_from_psa( )
{
@ -117,3 +146,57 @@ exit:
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */
void mbedtls_psa_get_random_no_init( )
{
unsigned char output[1];
TEST_ASSERT( mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
output, sizeof( output ) ) != 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */
void mbedtls_psa_get_random_length( int n )
{
unsigned char *output = NULL;
PSA_ASSERT( psa_crypto_init( ) );
ASSERT_ALLOC( output, n );
TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
output, n ) );
exit:
mbedtls_free( output );
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_ECDSA_C */
void mbedtls_psa_get_random_ecdsa_sign( int curve )
{
mbedtls_ecp_group grp;
mbedtls_mpi d, r, s;
unsigned char buf[] = "This is not a hash.";
mbedtls_ecp_group_init( &grp );
mbedtls_mpi_init( &d );
mbedtls_mpi_init( &r );
mbedtls_mpi_init( &s );
TEST_EQUAL( 0, mbedtls_mpi_lset( &d, 123456789 ) );
TEST_EQUAL( 0, mbedtls_ecp_group_load( &grp, curve ) );
PSA_ASSERT( psa_crypto_init( ) );
TEST_EQUAL( 0, mbedtls_ecdsa_sign( &grp, &r, &s, &d,
buf, sizeof( buf ),
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE ) );
exit:
mbedtls_mpi_free( &d );
mbedtls_mpi_free( &r );
mbedtls_mpi_free( &s );
mbedtls_ecp_group_free( &grp );
PSA_DONE( );
}
/* END_CASE */