Merge pull request #3895 from gilles-peskine-arm/psa-external-random
Alternative random generator support for PSA
diff --git a/ChangeLog.d/psa-crypto-hmac-drbg.txt b/ChangeLog.d/psa-crypto-hmac-drbg.txt
new file mode 100644
index 0000000..18a0d1b
--- /dev/null
+++ b/ChangeLog.d/psa-crypto-hmac-drbg.txt
@@ -0,0 +1,5 @@
+Features
+ * The PSA crypto subsystem can now use HMAC_DRBG instead of CTR_DRBG.
+ CTR_DRBG is used by default if it is available, but you can override
+ this choice by setting MBEDTLS_PSA_HMAC_DRBG_MD_TYPE at compile time.
+ Fix #3354.
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 1ebb706..accf51e 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -572,10 +572,11 @@
#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
#endif
-#if defined(MBEDTLS_PSA_CRYPTO_C) && \
- !( defined(MBEDTLS_CTR_DRBG_C) && \
- defined(MBEDTLS_ENTROPY_C) )
-#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites"
+#if defined(MBEDTLS_PSA_CRYPTO_C) && \
+ !( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \
+ defined(MBEDTLS_ENTROPY_C) ) || \
+ defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) )
+#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C)
@@ -604,6 +605,11 @@
#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources"
#endif
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
+ defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG"
+#endif
+
#if defined(MBEDTLS_PSA_ITS_FILE_C) && \
!defined(MBEDTLS_FS_IO)
#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites"
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 464b61e..c5f65e1 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1337,6 +1337,44 @@
*/
//#define MBEDTLS_PSA_CRYPTO_DRIVERS
+/** \def MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+ *
+ * Make the PSA Crypto module use an external random generator provided
+ * by a driver, instead of Mbed TLS's entropy and DRBG modules.
+ *
+ * \note This random generator must deliver random numbers with cryptographic
+ * quality and high performance. It must supply unpredictable numbers
+ * with a uniform distribution. The implementation of this function
+ * is responsible for ensuring that the random generator is seeded
+ * with sufficient entropy. If you have a hardware TRNG which is slow
+ * or delivers non-uniform output, declare it as an entropy source
+ * with mbedtls_entropy_add_source() instead of enabling this option.
+ *
+ * If you enable this option, you must configure the type
+ * ::mbedtls_psa_external_random_context_t in psa/crypto_platform.h
+ * and define a function called mbedtls_psa_external_get_random()
+ * with the following prototype:
+ * ```
+ * psa_status_t mbedtls_psa_external_get_random(
+ * mbedtls_psa_external_random_context_t *context,
+ * uint8_t *output, size_t output_size, size_t *output_length);
+ * );
+ * ```
+ * The \c context value is initialized to 0 before the first call.
+ * The function must fill the \c output buffer with \p output_size bytes
+ * of random data and set \c *output_length to \p output_size.
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C
+ *
+ * \warning If you enable this option, code that uses the PSA cryptography
+ * interface will not use any of the entropy sources set up for
+ * the entropy module, nor the NV seed that MBEDTLS_ENTROPY_NV_SEED
+ * enables.
+ *
+ * \note This option is experimental and may be removed without notice.
+ */
+//#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+
/**
* \def MBEDTLS_PSA_CRYPTO_SPM
*
@@ -3115,7 +3153,9 @@
*
* Module: library/psa_crypto.c
*
- * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C
+ * Requires: either MBEDTLS_CTR_DRBG_C and MBEDTLS_ENTROPY_C,
+ * or MBEDTLS_HMAC_DRBG_C and MBEDTLS_ENTROPY_C,
+ * or MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG.
*
*/
#define MBEDTLS_PSA_CRYPTO_C
@@ -3603,6 +3643,19 @@
*/
//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond )
+/* PSA options */
+/**
+ * Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the
+ * PSA crypto subsystem.
+ *
+ * If this option is unset:
+ * - If CTR_DRBG is available, the PSA subsystem uses it rather than HMAC_DRBG.
+ * - Otherwise, the PSA subsystem uses HMAC_DRBG with either
+ * #MBEDTLS_MD_SHA512 or #MBEDTLS_MD_SHA256 based on availability and
+ * on unspecified heuristics.
+ */
+//#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
+
/* SSL Cache options */
//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */
//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index f793a6c..9abce33 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -649,6 +649,57 @@
/**@}*/
+/** \defgroup psa_external_rng External random generator
+ * @{
+ */
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+/** External random generator function, implemented by the platform.
+ *
+ * When the compile-time option #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled,
+ * this function replaces Mbed TLS's entropy and DRBG modules for all
+ * random generation triggered via PSA crypto interfaces.
+ *
+ * \note This random generator must deliver random numbers with cryptographic
+ * quality and high performance. It must supply unpredictable numbers
+ * with a uniform distribution. The implementation of this function
+ * is responsible for ensuring that the random generator is seeded
+ * with sufficient entropy. If you have a hardware TRNG which is slow
+ * or delivers non-uniform output, declare it as an entropy source
+ * with mbedtls_entropy_add_source() instead of enabling this option.
+ *
+ * \param[in,out] context Pointer to the random generator context.
+ * This is all-bits-zero on the first call
+ * and preserved between successive calls.
+ * \param[out] output Output buffer. On success, this buffer
+ * contains random data with a uniform
+ * distribution.
+ * \param output_size The size of the \p output buffer in bytes.
+ * \param[out] output_length On success, set this value to \p output_size.
+ *
+ * \retval #PSA_SUCCESS
+ * Success. The output buffer contains \p output_size bytes of
+ * cryptographic-quality random data, and \c *output_length is
+ * set to \p output_size.
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * The random generator requires extra entropy and there is no
+ * way to obtain entropy under current environment conditions.
+ * This error should not happen under normal circumstances since
+ * this function is responsible for obtaining as much entropy as
+ * it needs. However implementations of this function may return
+ * #PSA_ERROR_INSUFFICIENT_ENTROPY if there is no way to obtain
+ * entropy without blocking indefinitely.
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * A failure of the random generator hardware that isn't covered
+ * by #PSA_ERROR_INSUFFICIENT_ENTROPY.
+ */
+psa_status_t mbedtls_psa_external_get_random(
+ mbedtls_psa_external_random_context_t *context,
+ uint8_t *output, size_t output_size, size_t *output_length );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+/**@}*/
+
#ifdef __cplusplus
}
#endif
diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h
index 567398d..8acf22c 100644
--- a/include/psa/crypto_platform.h
+++ b/include/psa/crypto_platform.h
@@ -81,4 +81,19 @@
#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+/** The type of the context passed to mbedtls_psa_external_get_random().
+ *
+ * Mbed TLS initializes the context to all-bits-zero before calling
+ * mbedtls_psa_external_get_random() for the first time.
+ *
+ * The definition of this type in the Mbed TLS source code is for
+ * demonstration purposes. Implementers of mbedtls_psa_external_get_random()
+ * are expected to replace it with a custom definition.
+ */
+typedef struct {
+ uintptr_t opaque[2];
+} mbedtls_psa_external_random_context_t;
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
#endif /* PSA_CRYPTO_PLATFORM_H */
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index f7b9129..7ea2a1a 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -40,6 +40,8 @@
* stored keys. */
#include "psa_crypto_storage.h"
+#include "psa_crypto_random_impl.h"
+
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -49,6 +51,7 @@
#define mbedtls_free free
#endif
+#include "mbedtls/aes.h"
#include "mbedtls/arc4.h"
#include "mbedtls/asn1.h"
#include "mbedtls/asn1write.h"
@@ -60,7 +63,6 @@
#include "mbedtls/cipher.h"
#include "mbedtls/ccm.h"
#include "mbedtls/cmac.h"
-#include "mbedtls/ctr_drbg.h"
#include "mbedtls/des.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/ecp.h"
@@ -115,16 +117,18 @@
typedef struct
{
- void (* entropy_init )( mbedtls_entropy_context *ctx );
- void (* entropy_free )( mbedtls_entropy_context *ctx );
- mbedtls_entropy_context entropy;
- mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_psa_random_context_t rng;
unsigned initialized : 1;
unsigned rng_state : 2;
} psa_global_data_t;
static psa_global_data_t global_data;
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state =
+ &global_data.rng.drbg;
+#endif
+
#define GUARD_MODULE_INITIALIZED \
if( global_data.initialized == 0 ) \
return( PSA_ERROR_BAD_STATE );
@@ -214,6 +218,10 @@
case MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED:
return( PSA_ERROR_HARDWARE_FAILURE );
+#if !( defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) || \
+ defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) )
+ /* Only check CTR_DRBG error codes if underlying mbedtls_xxx
+ * functions are passed a CTR_DRBG instance. */
case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
return( PSA_ERROR_INSUFFICIENT_ENTROPY );
case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG:
@@ -221,6 +229,7 @@
return( PSA_ERROR_NOT_SUPPORTED );
case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR:
return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+#endif
case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH:
return( PSA_ERROR_NOT_SUPPORTED );
@@ -239,6 +248,19 @@
case MBEDTLS_ERR_GCM_HW_ACCEL_FAILED:
return( PSA_ERROR_HARDWARE_FAILURE );
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \
+ defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
+ /* Only check HMAC_DRBG error codes if underlying mbedtls_xxx
+ * functions are passed a HMAC_DRBG instance. */
+ case MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+ case MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG:
+ case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR:
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+#endif
+
case MBEDTLS_ERR_MD2_HW_ACCEL_FAILED:
case MBEDTLS_ERR_MD4_HW_ACCEL_FAILED:
case MBEDTLS_ERR_MD5_HW_ACCEL_FAILED:
@@ -867,7 +889,7 @@
/* Calculate the public key */
status = mbedtls_to_psa_error(
mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
- mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) );
+ mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) );
if( status != PSA_SUCCESS )
return( status );
}
@@ -3682,8 +3704,8 @@
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE );
ret = mbedtls_rsa_pkcs1_sign( rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
md_alg,
(unsigned int) hash_length,
@@ -3697,8 +3719,8 @@
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
ret = mbedtls_rsa_rsassa_pss_sign( rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
@@ -3740,8 +3762,8 @@
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE );
ret = mbedtls_rsa_pkcs1_verify( rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
md_alg,
(unsigned int) hash_length,
@@ -3755,8 +3777,8 @@
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
ret = mbedtls_rsa_rsassa_pss_verify( rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
@@ -3813,8 +3835,8 @@
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s,
&ecp->d, hash,
hash_length, md_alg,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg ) );
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE ) );
}
else
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
@@ -3822,8 +3844,8 @@
(void) alg;
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d,
hash, hash_length,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg ) );
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE ) );
}
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r,
@@ -3868,7 +3890,7 @@
{
MBEDTLS_MPI_CHK(
mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
- mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) );
+ mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) );
}
ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length,
@@ -4168,8 +4190,8 @@
{
status = mbedtls_to_psa_error(
mbedtls_rsa_pkcs1_encrypt( rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
input_length,
input,
@@ -4183,8 +4205,8 @@
psa_rsa_oaep_set_padding_mode( alg, rsa );
status = mbedtls_to_psa_error(
mbedtls_rsa_rsaes_oaep_encrypt( rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
salt, salt_length,
input_length,
@@ -4275,8 +4297,8 @@
{
status = mbedtls_to_psa_error(
mbedtls_rsa_pkcs1_decrypt( rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
output_length,
input,
@@ -4291,8 +4313,8 @@
psa_rsa_oaep_set_padding_mode( alg, rsa );
status = mbedtls_to_psa_error(
mbedtls_rsa_rsaes_oaep_decrypt( rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
salt, salt_length,
output_length,
@@ -4526,8 +4548,8 @@
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
- ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg,
- iv, operation->iv_size );
+ ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+ iv, operation->iv_size );
if( ret != 0 )
{
status = mbedtls_to_psa_error( ret );
@@ -6142,8 +6164,8 @@
mbedtls_ecdh_calc_secret( &ecdh,
shared_secret_length,
shared_secret, shared_secret_size,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg ) );
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE ) );
if( status != PSA_SUCCESS )
goto exit;
if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length )
@@ -6321,31 +6343,139 @@
}
+
/****************************************************************/
/* Random generation */
/****************************************************************/
+/** Initialize the PSA random generator.
+ */
+static void mbedtls_psa_random_init( mbedtls_psa_random_context_t *rng )
+{
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+ memset( rng, 0, sizeof( *rng ) );
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+ /* Set default configuration if
+ * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */
+ if( rng->entropy_init == NULL )
+ rng->entropy_init = mbedtls_entropy_init;
+ if( rng->entropy_free == NULL )
+ rng->entropy_free = mbedtls_entropy_free;
+
+ rng->entropy_init( &rng->entropy );
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
+ defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
+ /* The PSA entropy injection feature depends on using NV seed as an entropy
+ * source. Add NV seed as an entropy source for PSA entropy injection. */
+ mbedtls_entropy_add_source( &rng->entropy,
+ mbedtls_nv_seed_poll, NULL,
+ MBEDTLS_ENTROPY_BLOCK_SIZE,
+ MBEDTLS_ENTROPY_SOURCE_STRONG );
+#endif
+
+ mbedtls_psa_drbg_init( MBEDTLS_PSA_RANDOM_STATE );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
+/** Deinitialize the PSA random generator.
+ */
+static void mbedtls_psa_random_free( mbedtls_psa_random_context_t *rng )
+{
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+ memset( rng, 0, sizeof( *rng ) );
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+ mbedtls_psa_drbg_free( MBEDTLS_PSA_RANDOM_STATE );
+ rng->entropy_free( &rng->entropy );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
+/** Seed the PSA random generator.
+ */
+static psa_status_t mbedtls_psa_random_seed( mbedtls_psa_random_context_t *rng )
+{
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+ /* Do nothing: the external RNG seeds itself. */
+ (void) rng;
+ return( PSA_SUCCESS );
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+ const unsigned char drbg_seed[] = "PSA";
+ int ret = mbedtls_psa_drbg_seed( &rng->entropy,
+ drbg_seed, sizeof( drbg_seed ) - 1 );
+ return mbedtls_to_psa_error( ret );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
psa_status_t psa_generate_random( uint8_t *output,
size_t output_size )
{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
GUARD_MODULE_INITIALIZED;
- while( output_size > MBEDTLS_CTR_DRBG_MAX_REQUEST )
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+ size_t output_length = 0;
+ psa_status_t status = mbedtls_psa_external_get_random( &global_data.rng,
+ output, output_size,
+ &output_length );
+ if( status != PSA_SUCCESS )
+ return( status );
+ /* Breaking up a request into smaller chunks is currently not supported
+ * for the extrernal RNG interface. */
+ if( output_length != output_size )
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+ return( PSA_SUCCESS );
+
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+ while( output_size > 0 )
{
- ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg,
- output,
- MBEDTLS_CTR_DRBG_MAX_REQUEST );
+ size_t request_size =
+ ( output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?
+ MBEDTLS_PSA_RANDOM_MAX_REQUEST :
+ output_size );
+ int ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+ output, request_size );
if( ret != 0 )
return( mbedtls_to_psa_error( ret ) );
- output += MBEDTLS_CTR_DRBG_MAX_REQUEST;
- output_size -= MBEDTLS_CTR_DRBG_MAX_REQUEST;
+ output_size -= request_size;
+ output += request_size;
}
-
- ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, output, output_size );
- return( mbedtls_to_psa_error( ret ) );
+ return( PSA_SUCCESS );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
}
+/* Wrapper function allowing the classic API to use the PSA RNG.
+ *
+ * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls
+ * `psa_generate_random(...)`. The state parameter is ignored since the
+ * PSA API doesn't support passing an explicit state.
+ *
+ * In the non-external case, psa_generate_random() calls an
+ * `mbedtls_xxx_drbg_random` function which has exactly the same signature
+ * and semantics as mbedtls_psa_get_random(). As an optimization,
+ * instead of doing this back-and-forth between the PSA API and the
+ * classic API, psa_crypto_random_impl.h defines `mbedtls_psa_get_random`
+ * as a constant function pointer to `mbedtls_xxx_drbg_random`.
+ */
+#if defined (MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+int mbedtls_psa_get_random( void *p_rng,
+ unsigned char *output,
+ size_t output_size )
+{
+ /* This function takes a pointer to the RNG state because that's what
+ * classic mbedtls functions using an RNG expect. The PSA RNG manages
+ * its own state internally and doesn't let the caller access that state.
+ * So we just ignore the state parameter, and in practice we'll pass
+ * NULL. */
+ (void) p_rng;
+ psa_status_t status = psa_generate_random( output, output_size );
+ if( status == PSA_SUCCESS )
+ return( 0 );
+ else
+ return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+}
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
#include "mbedtls/entropy_poll.h"
@@ -6448,8 +6578,8 @@
return( status );
mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE );
ret = mbedtls_rsa_gen_key( &rsa,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
(unsigned int) bits,
exponent );
if( ret != 0 )
@@ -6494,8 +6624,8 @@
return( PSA_ERROR_NOT_SUPPORTED );
mbedtls_ecp_keypair_init( &ecp );
ret = mbedtls_ecp_gen_key( grp_id, &ecp,
- mbedtls_ctr_drbg_random,
- &global_data.ctr_drbg );
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE );
if( ret != 0 )
{
mbedtls_ecp_keypair_free( &ecp );
@@ -6575,24 +6705,25 @@
/* Module setup */
/****************************************************************/
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
void (* entropy_init )( mbedtls_entropy_context *ctx ),
void (* entropy_free )( mbedtls_entropy_context *ctx ) )
{
if( global_data.rng_state != RNG_NOT_INITIALIZED )
return( PSA_ERROR_BAD_STATE );
- global_data.entropy_init = entropy_init;
- global_data.entropy_free = entropy_free;
+ global_data.rng.entropy_init = entropy_init;
+ global_data.rng.entropy_free = entropy_free;
return( PSA_SUCCESS );
}
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
void mbedtls_psa_crypto_free( void )
{
psa_wipe_all_key_slots( );
if( global_data.rng_state != RNG_NOT_INITIALIZED )
{
- mbedtls_ctr_drbg_free( &global_data.ctr_drbg );
- global_data.entropy_free( &global_data.entropy );
+ mbedtls_psa_random_free( &global_data.rng );
}
/* Wipe all remaining data, including configuration.
* In particular, this sets all state indicator to the value
@@ -6634,37 +6765,15 @@
psa_status_t psa_crypto_init( void )
{
psa_status_t status;
- const unsigned char drbg_seed[] = "PSA";
/* Double initialization is explicitly allowed. */
if( global_data.initialized != 0 )
return( PSA_SUCCESS );
- /* Set default configuration if
- * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */
- if( global_data.entropy_init == NULL )
- global_data.entropy_init = mbedtls_entropy_init;
- if( global_data.entropy_free == NULL )
- global_data.entropy_free = mbedtls_entropy_free;
-
- /* Initialize the random generator. */
- global_data.entropy_init( &global_data.entropy );
-#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
- defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
- /* The PSA entropy injection feature depends on using NV seed as an entropy
- * source. Add NV seed as an entropy source for PSA entropy injection. */
- mbedtls_entropy_add_source( &global_data.entropy,
- mbedtls_nv_seed_poll, NULL,
- MBEDTLS_ENTROPY_BLOCK_SIZE,
- MBEDTLS_ENTROPY_SOURCE_STRONG );
-#endif
- mbedtls_ctr_drbg_init( &global_data.ctr_drbg );
+ /* Initialize and seed the random generator. */
+ mbedtls_psa_random_init( &global_data.rng );
global_data.rng_state = RNG_INITIALIZED;
- status = mbedtls_to_psa_error(
- mbedtls_ctr_drbg_seed( &global_data.ctr_drbg,
- mbedtls_entropy_func,
- &global_data.entropy,
- drbg_seed, sizeof( drbg_seed ) - 1 ) );
+ status = mbedtls_psa_random_seed( &global_data.rng );
if( status != PSA_SUCCESS )
goto exit;
global_data.rng_state = RNG_SEEDED;
diff --git a/library/psa_crypto_invasive.h b/library/psa_crypto_invasive.h
index 2b4ee1f..be127d9 100644
--- a/library/psa_crypto_invasive.h
+++ b/library/psa_crypto_invasive.h
@@ -38,6 +38,7 @@
#include "mbedtls/entropy.h"
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
/** \brief Configure entropy sources.
*
* This function may only be called before a call to psa_crypto_init(),
@@ -73,5 +74,6 @@
psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
void (* entropy_init )( mbedtls_entropy_context *ctx ),
void (* entropy_free )( mbedtls_entropy_context *ctx ) );
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
#endif /* PSA_CRYPTO_INVASIVE_H */
diff --git a/library/psa_crypto_random_impl.h b/library/psa_crypto_random_impl.h
new file mode 100644
index 0000000..1232186
--- /dev/null
+++ b/library/psa_crypto_random_impl.h
@@ -0,0 +1,215 @@
+/** \file psa_crypto_random_impl.h
+ *
+ * \brief PSA crypto random generator implementation abstraction.
+ */
+/*
+ * 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_RANDOM_IMPL_H
+#define PSA_CRYPTO_RANDOM_IMPL_H
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+#include <string.h>
+#include <mbedtls/entropy.h> // only for error codes
+#include <psa/crypto.h>
+
+typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t;
+
+/* Trivial wrapper around psa_generate_random(). */
+int mbedtls_psa_get_random( void *p_rng,
+ unsigned char *output,
+ size_t output_size );
+
+/* The PSA RNG API doesn't need any externally maintained state. */
+#define MBEDTLS_PSA_RANDOM_STATE NULL
+
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+/* Choose a DRBG based on configuration and availability */
+#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
+
+#include "mbedtls/hmac_drbg.h"
+
+#elif defined(MBEDTLS_CTR_DRBG_C)
+
+#include "mbedtls/ctr_drbg.h"
+
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+
+#include "mbedtls/hmac_drbg.h"
+#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA256_C)
+#include <limits.h>
+#if SIZE_MAX > 0xffffffff
+/* Looks like a 64-bit system, so prefer SHA-512. */
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512
+#else
+/* Looks like a 32-bit system, so prefer SHA-256. */
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
+#endif
+#elif defined(MBEDTLS_SHA512_C)
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512
+#elif defined(MBEDTLS_SHA256_C)
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
+#else
+#error "No hash algorithm available for HMAC_DBRG."
+#endif
+
+#else
+#error "No DRBG module available for the psa_crypto module."
+#endif
+
+#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.
+ */
+static inline void mbedtls_psa_drbg_init( mbedtls_psa_drbg_context_t *p_rng )
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+ mbedtls_ctr_drbg_init( p_rng );
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+ mbedtls_hmac_drbg_init( p_rng );
+#endif
+}
+
+/** Deinitialize the PSA DRBG.
+ *
+ * \param p_rng Pointer to the Mbed TLS DRBG state.
+ */
+static inline void mbedtls_psa_drbg_free( mbedtls_psa_drbg_context_t *p_rng )
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+ mbedtls_ctr_drbg_free( p_rng );
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+ mbedtls_hmac_drbg_free( p_rng );
+#endif
+}
+
+/** The type of the PSA random generator context.
+ *
+ * The random generator context is composed of an entropy context and
+ * a DRBG context.
+ */
+typedef struct
+{
+ void (* entropy_init )( mbedtls_entropy_context *ctx );
+ void (* entropy_free )( mbedtls_entropy_context *ctx );
+ mbedtls_entropy_context entropy;
+ 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.
+ */
+#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;
+#endif
+
+/** The maximum number of bytes that mbedtls_psa_get_random() is expected to
+ * return.
+ */
+#if defined(MBEDTLS_CTR_DRBG_C)
+#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST
+#endif
+
+/** A pointer to the PSA DRBG state.
+ *
+ * This variable is only intended to be used through the macro
+ * #MBEDTLS_PSA_RANDOM_STATE.
+ */
+/* psa_crypto.c sets this variable to a pointer to the DRBG state in the
+ * global PSA crypto state. */
+extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
+
+/** A pointer to the PSA DRBG state.
+ *
+ * This macro expands to an expression that is suitable as the \c p_rng
+ * parameter to pass to mbedtls_psa_get_random().
+ *
+ * This macro exists in all configurations where the psa_crypto module is
+ * enabled. Its expansion depends on the configuration.
+ */
+#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state
+
+/** Seed the PSA DRBG.
+ *
+ * \param entropy An entropy context to read the seed from.
+ * \param custom The personalization string.
+ * This can be \c NULL, in which case the personalization
+ * string is empty regardless of the value of \p len.
+ * \param len The length of the personalization string.
+ *
+ * \return \c 0 on success.
+ * \return An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure.
+ */
+static inline int mbedtls_psa_drbg_seed(
+ mbedtls_entropy_context *entropy,
+ const unsigned char *custom, size_t len )
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+ return( mbedtls_ctr_drbg_seed( MBEDTLS_PSA_RANDOM_STATE,
+ mbedtls_entropy_func,
+ entropy,
+ custom, len ) );
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type( MBEDTLS_PSA_HMAC_DRBG_MD_TYPE );
+ return( mbedtls_hmac_drbg_seed( MBEDTLS_PSA_RANDOM_STATE,
+ md_info,
+ mbedtls_entropy_func,
+ entropy,
+ custom, len ) );
+#endif
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+#endif /* PSA_CRYPTO_RANDOM_IMPL_H */
diff --git a/library/version_features.c b/library/version_features.c
index 42ccaf9..80f121a 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -438,6 +438,9 @@
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
"MBEDTLS_PSA_CRYPTO_DRIVERS",
#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+ "MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG",
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
#if defined(MBEDTLS_PSA_CRYPTO_SPM)
"MBEDTLS_PSA_CRYPTO_SPM",
#endif /* MBEDTLS_PSA_CRYPTO_SPM */
diff --git a/programs/test/query_config.c b/programs/test/query_config.c
index 1345b11..1fb7384 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -1224,6 +1224,14 @@
}
#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+ if( strcmp( "MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG", config ) == 0 )
+ {
+ MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG );
+ return( 0 );
+ }
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
#if defined(MBEDTLS_PSA_CRYPTO_SPM)
if( strcmp( "MBEDTLS_PSA_CRYPTO_SPM", config ) == 0 )
{
@@ -2608,6 +2616,14 @@
}
#endif /* MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO */
+#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
+ if( strcmp( "MBEDTLS_PSA_HMAC_DRBG_MD_TYPE", config ) == 0 )
+ {
+ MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_HMAC_DRBG_MD_TYPE );
+ return( 0 );
+ }
+#endif /* MBEDTLS_PSA_HMAC_DRBG_MD_TYPE */
+
#if defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT)
if( strcmp( "MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT", config ) == 0 )
{
diff --git a/scripts/config.py b/scripts/config.py
index ae0614a..b60f93d 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -185,6 +185,7 @@
'MBEDTLS_PKCS11_C', # build dependency (libpkcs11-helper)
'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', # removes a feature
'MBEDTLS_PSA_CRYPTO_CONFIG', # toggles old/new style PSA config
+ 'MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG', # behavior change + build dependency
'MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER', # incompatible with USE_PSA_CRYPTO
'MBEDTLS_PSA_CRYPTO_SPM', # platform dependency (PSA SPM)
'MBEDTLS_PSA_INJECT_ENTROPY', # build dependency (hook functions)
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index af59c62..a016732 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -915,10 +915,6 @@
msg "build: Full minus CTR_DRBG"
scripts/config.py full
scripts/config.py unset MBEDTLS_CTR_DRBG_C
- scripts/config.py unset MBEDTLS_PSA_CRYPTO_C # requires CTR_DRBG
- scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA Crypto
- scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C # requires PSA Crypto
- scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO # requires PSA Crypto
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
@@ -945,6 +941,36 @@
# so there's little value in running those lengthy tests here.
}
+component_test_psa_external_rng_no_drbg () {
+ msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG"
+ scripts/config.py full
+ scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+ scripts/config.py unset MBEDTLS_CTR_DRBG_C
+ scripts/config.py unset MBEDTLS_HMAC_DRBG_C
+ scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
+ scripts/config.py set MBEDTLS_ECP_NO_INTERNAL_RNG
+ make CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+
+ msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG"
+ make test
+
+ # No ssl-opt.sh/compat.sh because they require CTR_DRBG.
+}
+
+component_test_psa_external_rng_use_psa_crypto () {
+ msg "build: full + PSA_CRYPTO_EXTERNAL_RNG + USE_PSA_CRYPTO minus CTR_DRBG"
+ scripts/config.py full
+ scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+ scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
+ scripts/config.py unset MBEDTLS_CTR_DRBG_C
+ make CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+
+ msg "test: full + PSA_CRYPTO_EXTERNAL_RNG + USE_PSA_CRYPTO minus CTR_DRBG"
+ make test
+
+ # No ssl-opt.sh/compat.sh because they require CTR_DRBG.
+}
+
component_test_ecp_no_internal_rng () {
msg "build: Default plus ECP_NO_INTERNAL_RNG minus DRBG modules"
scripts/config.py set MBEDTLS_ECP_NO_INTERNAL_RNG
diff --git a/tests/src/psa_crypto_helpers.c b/tests/src/psa_crypto_helpers.c
new file mode 100644
index 0000000..dacda68
--- /dev/null
+++ b/tests/src/psa_crypto_helpers.c
@@ -0,0 +1,46 @@
+/** \file psa_crypto_helpers.c
+ *
+ * \brief Helper functions to test PSA crypto functionality.
+ */
+
+/*
+ * 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 <test/helpers.h>
+#include <test/macros.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#include <test/random.h>
+
+psa_status_t mbedtls_psa_external_get_random(
+ mbedtls_psa_external_random_context_t *context,
+ uint8_t *output, size_t output_size, size_t *output_length )
+{
+ /* This implementation is for test purposes only!
+ * Use the libc non-cryptographic random generator. */
+ (void) context;
+ mbedtls_test_rnd_std_rand( NULL, output, output_size );
+ *output_length = output_size;
+ return( PSA_SUCCESS );
+}
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/tests/suites/test_suite_psa_crypto_init.function b/tests/suites/test_suite_psa_crypto_init.function
index 62ef6e2..e6097bb 100644
--- a/tests/suites/test_suite_psa_crypto_init.function
+++ b/tests/suites/test_suite_psa_crypto_init.function
@@ -11,11 +11,23 @@
#define ENTROPY_MIN_NV_SEED_SIZE \
MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
+#include "psa_crypto_random_impl.h"
+#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
+/* PSA crypto uses the HMAC_DRBG module. It reads from the entropy source twice:
+ * once for the initial entropy and once for a nonce. The nonce length is
+ * half the entropy length. For SHA-256, SHA-384 or SHA-512, the
+ * entropy length is 256 per the documentation of mbedtls_hmac_drbg_seed(),
+ * and PSA crypto doesn't support other hashes for HMAC_DRBG. */
+#define ENTROPY_NONCE_LEN ( 256 / 2 )
+#else
/* PSA crypto uses the CTR_DRBG module. In some configurations, it needs
* to read from the entropy source twice: once for the initial entropy
* and once for a nonce. */
#include "mbedtls/ctr_drbg.h"
#define ENTROPY_NONCE_LEN MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN
+#endif
+
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
typedef struct
{
@@ -118,6 +130,8 @@
MBEDTLS_ENTROPY_SOURCE_STRONG );
}
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -125,7 +139,7 @@
* END_DEPENDENCIES
*/
-/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED */
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
void create_nv_seed( )
{
static unsigned char seed[ENTROPY_MIN_NV_SEED_SIZE];
@@ -201,7 +215,7 @@
}
/* END_CASE */
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
void custom_entropy_sources( int sources_arg, int expected_init_status_arg )
{
psa_status_t expected_init_status = expected_init_status_arg;
@@ -222,7 +236,7 @@
}
/* END_CASE */
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
void fake_entropy_source( int threshold,
int amount1,
int amount2,
@@ -262,7 +276,7 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED */
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
void entropy_from_nv_seed( int seed_size_arg,
int expected_init_status_arg )
{
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 440cc11..100c313 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -249,6 +249,7 @@
<ClInclude Include="..\..\library\psa_crypto_driver_wrappers.h" />
<ClInclude Include="..\..\library\psa_crypto_invasive.h" />
<ClInclude Include="..\..\library\psa_crypto_its.h" />
+ <ClInclude Include="..\..\library\psa_crypto_random_impl.h" />
<ClInclude Include="..\..\library\psa_crypto_se.h" />
<ClInclude Include="..\..\library\psa_crypto_service_integration.h" />
<ClInclude Include="..\..\library\psa_crypto_slot_management.h" />
@@ -348,6 +349,7 @@
<ClCompile Include="..\..\library\x509write_csr.c" />
<ClCompile Include="..\..\library\xtea.c" />
<ClCompile Include="..\..\tests\src\helpers.c" />
+ <ClCompile Include="..\..\tests\src\psa_crypto_helpers.c" />
<ClCompile Include="..\..\tests\src\random.c" />
<ClCompile Include="..\..\3rdparty\everest\library\everest.c" />
<ClCompile Include="..\..\3rdparty\everest\library\Hacl_Curve25519_joined.c" />