diff --git a/ChangeLog.d/psa-crypto-hmac-drbg.txt b/ChangeLog.d/psa-crypto-hmac-drbg.txt new file mode 100644 index 000000000..18a0d1b56 --- /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 1ebb7066a..accf51e32 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 464b61ee2..c5f65e178 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 f793a6cac..9abce33d5 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -649,6 +649,57 @@ mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_family_t curve, /**@}*/ +/** \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 567398dbf..8acf22c7f 100644 --- a/include/psa/crypto_platform.h +++ b/include/psa/crypto_platform.h @@ -81,4 +81,19 @@ static inline int mbedtls_key_owner_id_equal( mbedtls_key_owner_id_t id1, #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 f7b9129de..7ea2a1a9a 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 #include #include @@ -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 @@ static int key_type_is_raw_bytes( psa_key_type_t type ) 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 @@ psa_status_t mbedtls_to_psa_error( int ret ) 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 @@ psa_status_t mbedtls_to_psa_error( int ret ) 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 @@ psa_status_t mbedtls_to_psa_error( int ret ) 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 @@ static psa_status_t psa_export_ecp_key( psa_key_type_t type, /* 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 @@ static psa_status_t psa_rsa_sign( mbedtls_rsa_context *rsa, 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 @@ static psa_status_t psa_rsa_sign( mbedtls_rsa_context *rsa, { 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 @@ static psa_status_t psa_rsa_verify( mbedtls_rsa_context *rsa, 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 @@ static psa_status_t psa_rsa_verify( mbedtls_rsa_context *rsa, { 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 @@ static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, 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 @@ static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, (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 @@ static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp, { 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 @@ psa_status_t psa_asymmetric_encrypt( mbedtls_svc_key_id_t key, { 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_status_t psa_asymmetric_encrypt( mbedtls_svc_key_id_t key, 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 @@ psa_status_t psa_asymmetric_decrypt( mbedtls_svc_key_id_t key, { 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_status_t psa_asymmetric_decrypt( mbedtls_svc_key_id_t key, 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 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, 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 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, 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 @@ exit: } + /****************************************************************/ /* 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 @@ static psa_status_t psa_generate_key_internal( 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 @@ static psa_status_t psa_generate_key_internal( 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 @@ exit: /* 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 @@ static psa_status_t psa_crypto_recover_transaction( 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 2b4ee1f34..be127d9f8 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 000000000..1232186c9 --- /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 +#include // only for error codes +#include + +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 +#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 42ccaf954..80f121a0d 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -438,6 +438,9 @@ static const char * const features[] = { #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 1345b11fe..1fb7384fd 100644 --- a/programs/test/query_config.c +++ b/programs/test/query_config.c @@ -1224,6 +1224,14 @@ int query_config( const char *config ) } #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 @@ int query_config( const char *config ) } #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 ae0614ae0..b60f93d7d 100755 --- a/scripts/config.py +++ b/scripts/config.py @@ -185,6 +185,7 @@ EXCLUDE_FROM_FULL = frozenset([ '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 af59c62d6..a016732f4 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -915,10 +915,6 @@ component_test_no_ctr_drbg () { 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 @@ component_test_no_hmac_drbg () { # 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 000000000..dacda683a --- /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 +#include + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#include + +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 62ef6e2d7..e6097bb27 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 @@ static void custom_entropy_init( mbedtls_entropy_context *ctx ) MBEDTLS_ENTROPY_SOURCE_STRONG ); } +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -125,7 +139,7 @@ static void custom_entropy_init( mbedtls_entropy_context *ctx ) * 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 @@ void validate_module_init_key_based( int count ) } /* 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 @@ exit: } /* 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 @@ exit: } /* 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 440cc1159..100c3138a 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -249,6 +249,7 @@ + @@ -348,6 +349,7 @@ +