Merge pull request #3986 from gilles-peskine-arm/ssl_test_lib-create
Unify common code of ssl_client2.c and ssl_server2.c
diff --git a/ChangeLog.d/issue3819.txt b/ChangeLog.d/issue3819.txt
new file mode 100644
index 0000000..e41520f
--- /dev/null
+++ b/ChangeLog.d/issue3819.txt
@@ -0,0 +1,10 @@
+Security
+ * Fix a security reduction in CTR_DRBG when the initial seeding obtained a
+ nonce from entropy. Applications were affected if they called
+ mbedtls_ctr_drbg_set_nonce_len(), if they called
+ mbedtls_ctr_drbg_set_entropy_len() with a size that was 3/2 times the key
+ length, or when the entropy module uses SHA-256 and CTR_DRBG uses AES-256.
+ In such cases, a random nonce was necessary to achieve the advertised
+ security strength, but the code incorrectly used a constant instead of
+ entropy from the nonce.
+ Found by John Stroebel in #3819 and fixed in #3973.
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/ChangeLog.d/psa_close_key_memory_leak_fix.txt b/ChangeLog.d/psa_close_key_memory_leak_fix.txt
new file mode 100644
index 0000000..91ce174
--- /dev/null
+++ b/ChangeLog.d/psa_close_key_memory_leak_fix.txt
@@ -0,0 +1,3 @@
+Bugfix
+ * Fix memory leak that occured when calling psa_close_key() on a
+ wrapped key with MBEDTLS_PSA_CRYPTO_SE_C defined.
diff --git a/ChangeLog.d/rsa_private-ret.txt b/ChangeLog.d/rsa_private-ret.txt
new file mode 100644
index 0000000..b965cea
--- /dev/null
+++ b/ChangeLog.d/rsa_private-ret.txt
@@ -0,0 +1,2 @@
+Bugfix
+ * Fix an incorrect error code if an RSA private operation glitched.
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/ctr_drbg.c b/library/ctr_drbg.c
index 023aac5..3815dc7 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -394,7 +394,7 @@
/* Gather entropy for a nonce if requested. */
if( nonce_len != 0 )
{
- if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
+ if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
{
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
}
@@ -684,54 +684,134 @@
#if defined(MBEDTLS_SELF_TEST)
-static const unsigned char entropy_source_pr[96] =
- { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
- 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
- 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
- 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
- 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
- 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
- 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
- 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
- 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
- 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
- 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
- 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
-
-static const unsigned char entropy_source_nopr[64] =
- { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
- 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
- 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
- 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
- 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
- 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
- 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
- 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
-
-static const unsigned char nonce_pers_pr[16] =
- { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
- 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
-
-static const unsigned char nonce_pers_nopr[16] =
- { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
- 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+/* The CTR_DRBG NIST test vectors used here are available at
+ * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
+ *
+ * The parameters used to derive the test data are:
+ *
+ * [AES-128 use df]
+ * [PredictionResistance = True/False]
+ * [EntropyInputLen = 128]
+ * [NonceLen = 64]
+ * [PersonalizationStringLen = 128]
+ * [AdditionalInputLen = 0]
+ * [ReturnedBitsLen = 512]
+ *
+ * [AES-256 use df]
+ * [PredictionResistance = True/False]
+ * [EntropyInputLen = 256]
+ * [NonceLen = 128]
+ * [PersonalizationStringLen = 256]
+ * [AdditionalInputLen = 0]
+ * [ReturnedBitsLen = 512]
+ *
+ */
#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
-static const unsigned char result_pr[16] =
- { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
- 0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
+static const unsigned char entropy_source_pr[] =
+ { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
+ 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
+ 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
+ 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
+ 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
+ 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
+ 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
-static const unsigned char result_nopr[16] =
- { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
- 0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
+static const unsigned char entropy_source_nopr[] =
+ { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
+ 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
+ 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
+ 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
+ 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
+
+static const unsigned char pers_pr[] =
+ { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
+ 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
+
+static const unsigned char pers_nopr[] =
+ { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
+ 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
+
+static const unsigned char result_pr[] =
+ { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
+ 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
+ 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
+ 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
+ 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
+ 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
+ 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
+ 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
+
+static const unsigned char result_nopr[] =
+ { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
+ 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
+ 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
+ 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
+ 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
+ 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
+ 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
+ 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
-static const unsigned char result_pr[16] =
- { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
- 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
-static const unsigned char result_nopr[16] =
- { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
- 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+static const unsigned char entropy_source_pr[] =
+ { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
+ 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
+ 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
+ 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
+ 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
+ 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
+ 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
+ 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
+ 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
+ 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
+ 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
+ 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
+ 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
+ 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
+
+static const unsigned char entropy_source_nopr[] =
+ { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
+ 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
+ 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
+ 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
+ 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
+ 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
+ 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
+ 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
+ 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
+ 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
+
+static const unsigned char pers_pr[] =
+ { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
+ 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
+ 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
+ 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
+
+static const unsigned char pers_nopr[] =
+ { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
+ 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
+ 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
+ 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
+
+static const unsigned char result_pr[] =
+ { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
+ 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
+ 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
+ 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
+ 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
+ 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
+ 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
+ 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
+
+static const unsigned char result_nopr[] =
+ { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
+ 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
+ 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
+ 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
+ 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
+ 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
+ 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
+ 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
static size_t test_offset;
@@ -751,13 +831,15 @@
return( 1 ); \
}
+#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
+
/*
* Checkup routine
*/
int mbedtls_ctr_drbg_self_test( int verbose )
{
mbedtls_ctr_drbg_context ctx;
- unsigned char buf[16];
+ unsigned char buf[ sizeof( result_pr ) ];
mbedtls_ctr_drbg_init( &ctx );
@@ -768,16 +850,16 @@
mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
test_offset = 0;
- mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
- mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+ mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
+ mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
CHK( mbedtls_ctr_drbg_seed( &ctx,
ctr_drbg_self_test_entropy,
(void *) entropy_source_pr,
- nonce_pers_pr, 16 ) );
+ pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
- CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
- CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
- CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
+ CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
+ CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
+ CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
mbedtls_ctr_drbg_free( &ctx );
@@ -793,16 +875,16 @@
mbedtls_ctr_drbg_init( &ctx );
test_offset = 0;
- mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
- mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+ mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
+ mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
CHK( mbedtls_ctr_drbg_seed( &ctx,
ctr_drbg_self_test_entropy,
(void *) entropy_source_nopr,
- nonce_pers_nopr, 16 ) );
- CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
+ pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
- CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
- CHK( memcmp( buf, result_nopr, 16 ) );
+ CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
+ CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
+ CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
mbedtls_ctr_drbg_free( &ctx );
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 82b95dc..b7c4591 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,25 +117,29 @@
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 );
psa_status_t mbedtls_to_psa_error( int ret )
{
- /* If there's both a high-level code and low-level code, dispatch on
- * the high-level code. */
- switch( ret < -0x7f ? - ( -ret & 0x7f80 ) : ret )
+ /* Mbed TLS error codes can combine a high-level error code and a
+ * low-level error code. The low-level error usually reflects the
+ * root cause better, so dispatch on that preferably. */
+ int low_level_ret = - ( -ret & 0x007f );
+ switch( low_level_ret != 0 ? low_level_ret : ret )
{
case 0:
return( PSA_SUCCESS );
@@ -214,6 +220,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 +231,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 +250,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:
@@ -322,7 +346,7 @@
case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
return( PSA_ERROR_BUFFER_TOO_SMALL );
case MBEDTLS_ERR_RSA_RNG_FAILED:
- return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
case MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
return( PSA_ERROR_NOT_SUPPORTED );
case MBEDTLS_ERR_RSA_HW_ACCEL_FAILED:
@@ -350,8 +374,11 @@
return( PSA_ERROR_INVALID_SIGNATURE );
case MBEDTLS_ERR_ECP_ALLOC_FAILED:
return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ case MBEDTLS_ERR_ECP_RANDOM_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
case MBEDTLS_ERR_ECP_HW_ACCEL_FAILED:
return( PSA_ERROR_HARDWARE_FAILURE );
+
case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
return( PSA_ERROR_CORRUPTION_DETECTED );
@@ -867,7 +894,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 );
}
@@ -1316,7 +1343,8 @@
static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot )
{
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
- if( psa_key_slot_is_external( slot ) )
+ if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) &&
+ psa_key_slot_is_external( slot ) )
{
/* No key material to clean. */
}
@@ -3681,8 +3709,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,
@@ -3696,8 +3724,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,
@@ -3739,8 +3767,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,
@@ -3754,8 +3782,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,
@@ -3812,8 +3840,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) */
@@ -3821,8 +3849,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,
@@ -3867,7 +3895,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,
@@ -4167,8 +4195,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,
@@ -4182,8 +4210,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,
@@ -4274,8 +4302,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,
@@ -4290,8 +4318,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,
@@ -4525,8 +4553,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 );
@@ -6141,8 +6169,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 )
@@ -6320,31 +6348,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"
@@ -6447,8 +6583,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 )
@@ -6493,8 +6629,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 );
@@ -6574,24 +6710,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
@@ -6633,37 +6770,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/rsa.c b/library/rsa.c
index d6abd65..9fe551d 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -1076,10 +1076,10 @@
mbedtls_mpi_free( &C );
mbedtls_mpi_free( &I );
- if( ret != 0 )
+ if( ret != 0 && ret >= -0x007f )
return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
- return( 0 );
+ return( ret );
}
#if defined(MBEDTLS_PKCS1_V21)
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 d15c7e9..aae8e2e 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -1226,6 +1226,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 )
{
@@ -2610,6 +2618,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/Makefile b/tests/Makefile
index 511db9d..b9c5525 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -84,8 +84,13 @@
mbedtls_test: $(MBEDTLS_TEST_OBJS)
+TEST_OBJS_DEPS =
+ifdef RECORD_PSA_STATUS_COVERAGE_LOG
+TEST_OBJS_DEPS += include/test/instrument_record_status.h
+endif
+
# Rule to compile common test C files in src folder
-src/%.o : src/%.c
+src/%.o : src/%.c $(TEST_OBJS_DEPS)
echo " CC $<"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
@@ -121,7 +126,7 @@
-o .
-$(BINARIES): %$(EXEXT): %.c $(MBEDLIBS) $(MBEDTLS_TEST_OBJS)
+$(BINARIES): %$(EXEXT): %.c $(MBEDLIBS) $(TEST_OBJS_DEPS) $(MBEDTLS_TEST_OBJS)
echo " CC $<"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(MBEDTLS_TEST_OBJS) $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -135,6 +140,7 @@
ifndef WINDOWS
rm -rf $(BINARIES) *.c *.datax TESTS
rm -f src/*.o src/drivers/*.o src/libmbed*
+ rm -f include/test/instrument_record_status.h
else
if exist *.c del /Q /F *.c
if exist *.exe del /Q /F *.exe
@@ -142,6 +148,7 @@
if exist src/*.o del /Q /F src/*.o
if exist src/drivers/*.o del /Q /F src/drivers/*.o
if exist src/libmbed* del /Q /F src/libmed*
+ if exist include/test/instrument_record_status.h del /Q /F include/test/instrument_record_status.h
ifneq ($(wildcard TESTS/.*),)
rmdir /Q /S TESTS
endif
@@ -187,7 +194,7 @@
$(eval $(call copy_header_to_target,$(app),$(file)))))
ifdef RECORD_PSA_STATUS_COVERAGE_LOG
-$(BINARIES): include/test/instrument_record_status.h
include/test/instrument_record_status.h: ../include/psa/crypto.h Makefile
+ echo " Gen $@"
sed <../include/psa/crypto.h >$@ -n 's/^psa_status_t \([A-Za-z0-9_]*\)(.*/#define \1(...) RECORD_STATUS("\1", \1(__VA_ARGS__))/p'
endif
diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h
index 01b0547..b8eb4aa 100644
--- a/tests/include/test/psa_crypto_helpers.h
+++ b/tests/include/test/psa_crypto_helpers.h
@@ -26,79 +26,74 @@
#include <psa/crypto.h>
#include <psa_crypto_slot_management.h>
-static int test_helper_is_psa_pristine( int line, const char *file )
-{
- mbedtls_psa_stats_t stats;
- const char *msg = NULL;
-
- mbedtls_psa_get_stats( &stats );
-
- if( stats.volatile_slots != 0 )
- msg = "A volatile slot has not been closed properly.";
- else if( stats.persistent_slots != 0 )
- msg = "A persistent slot has not been closed properly.";
- else if( stats.external_slots != 0 )
- msg = "An external slot has not been closed properly.";
- else if( stats.half_filled_slots != 0 )
- msg = "A half-filled slot has not been cleared properly.";
- else if( stats.locked_slots != 0 )
- {
- msg = "Some slots are still marked as locked.";
- }
-
- /* If the test has already failed, don't overwrite the failure
- * information. Do keep the stats lookup above, because it can be
- * convenient to break on it when debugging a failure. */
- if( msg != NULL && test_info.result == TEST_RESULT_SUCCESS )
- test_fail( msg, line, file );
-
- return( msg == NULL );
-}
+/** Check for things that have not been cleaned up properly in the
+ * PSA subsystem.
+ *
+ * \return NULL if nothing has leaked.
+ * \return A string literal explaining what has not been cleaned up
+ * if applicable.
+ */
+const char *mbedtls_test_helper_is_psa_leaking( void );
/** Check that no PSA Crypto key slots are in use.
+ *
+ * If any slots are in use, mark the current test as failed and jump to
+ * the exit label. This is equivalent to
+ * `TEST_ASSERT( ! mbedtls_test_helper_is_psa_leaking( ) )`
+ * but with a more informative message.
*/
-#define ASSERT_PSA_PRISTINE( ) \
- do \
- { \
- if( ! test_helper_is_psa_pristine( __LINE__, __FILE__ ) ) \
- goto exit; \
- } \
+#define ASSERT_PSA_PRISTINE( ) \
+ do \
+ { \
+ if( test_fail_if_psa_leaking( __LINE__, __FILE__ ) ) \
+ goto exit; \
+ } \
while( 0 )
-static void test_helper_psa_done( int line, const char *file )
-{
- (void) test_helper_is_psa_pristine( line, file );
- mbedtls_psa_crypto_free( );
-}
-
/** Shut down the PSA Crypto subsystem. Expect a clean shutdown, with no slots
* in use.
*/
-#define PSA_DONE( ) test_helper_psa_done( __LINE__, __FILE__ )
+#define PSA_DONE( ) \
+ do \
+ { \
+ test_fail_if_psa_leaking( __LINE__, __FILE__ ); \
+ mbedtls_psa_crypto_free( ); \
+ } \
+ while( 0 )
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+/** Enable the insecure implementation of mbedtls_psa_external_get_random().
+ *
+ * The insecure implementation of mbedtls_psa_external_get_random() is
+ * disabled by default.
+ *
+ * When MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled and the test
+ * helpers are linked into a program, you must enable this before running any
+ * code that uses the PSA subsystem to generate random data (including internal
+ * random generation for purposes such as blinding when the random generation
+ * is routed through PSA).
+ *
+ * You can enable and disable it at any time, regardless of the state
+ * of the PSA subsystem. You may disable it temporarily to simulate a
+ * depleted entropy source.
+ */
+void mbedtls_test_enable_insecure_external_rng( void );
+
+/** Disable the insecure implementation of mbedtls_psa_external_get_random().
+ *
+ * See mbedtls_test_enable_insecure_external_rng().
+ */
+void mbedtls_test_disable_insecure_external_rng( void );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+
#if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
-#include <psa/crypto.h>
-
-/** Name of the file where return statuses are logged by #RECORD_STATUS. */
-#define STATUS_LOG_FILE_NAME "statuses.log"
-
-static psa_status_t record_status( psa_status_t status,
- const char *func,
- const char *file, int line,
- const char *expr )
-{
- /* We open the log file on first use.
- * We never close the log file, so the record_status feature is not
- * compatible with resource leak detectors such as Asan.
- */
- static FILE *log;
- if( log == NULL )
- log = fopen( STATUS_LOG_FILE_NAME, "a" );
- fprintf( log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr );
- return( status );
-}
+psa_status_t mbedtls_test_record_status( psa_status_t status,
+ const char *func,
+ const char *file, int line,
+ const char *expr );
/** Return value logging wrapper macro.
*
@@ -125,7 +120,7 @@
* \return The value of \p expr.
*/
#define RECORD_STATUS( string, expr ) \
- record_status( ( expr ), string, __FILE__, __LINE__, #expr )
+ mbedtls_test_record_status( ( expr ), string, __FILE__, __LINE__, #expr )
#include "instrument_record_status.h"
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..0009857
--- /dev/null
+++ b/tests/src/psa_crypto_helpers.c
@@ -0,0 +1,104 @@
+/** \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>
+#include <test/psa_crypto_helpers.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+
+const char *mbedtls_test_helper_is_psa_leaking( void )
+{
+ mbedtls_psa_stats_t stats;
+
+ mbedtls_psa_get_stats( &stats );
+
+ if( stats.volatile_slots != 0 )
+ return( "A volatile slot has not been closed properly." );
+ if( stats.persistent_slots != 0 )
+ return( "A persistent slot has not been closed properly." );
+ if( stats.external_slots != 0 )
+ return( "An external slot has not been closed properly." );
+ if( stats.half_filled_slots != 0 )
+ return( "A half-filled slot has not been cleared properly." );
+ if( stats.locked_slots != 0 )
+ return( "Some slots are still marked as locked." );
+
+ return( NULL );
+}
+
+#if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
+/** Name of the file where return statuses are logged by #RECORD_STATUS. */
+#define STATUS_LOG_FILE_NAME "statuses.log"
+
+psa_status_t mbedtls_test_record_status( psa_status_t status,
+ const char *func,
+ const char *file, int line,
+ const char *expr )
+{
+ /* We open the log file on first use.
+ * We never close the log file, so the record_status feature is not
+ * compatible with resource leak detectors such as Asan.
+ */
+ static FILE *log;
+ if( log == NULL )
+ log = fopen( STATUS_LOG_FILE_NAME, "a" );
+ fprintf( log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr );
+ return( status );
+}
+#endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#include <test/random.h>
+
+static int test_insecure_external_rng_enabled = 0;
+
+void mbedtls_test_enable_insecure_external_rng( void )
+{
+ test_insecure_external_rng_enabled = 1;
+}
+
+void mbedtls_test_disable_insecure_external_rng( void )
+{
+ test_insecure_external_rng_enabled = 0;
+}
+
+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 )
+{
+ (void) context;
+
+ if( !test_insecure_external_rng_enabled )
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+
+ /* This implementation is for test purposes only!
+ * Use the libc non-cryptographic random generator. */
+ 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/helpers.function b/tests/suites/helpers.function
index aafcf5c..1dc6721 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -5,6 +5,9 @@
#include <test/macros.h>
#include <test/helpers.h>
#include <test/random.h>
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#include <test/psa_crypto_helpers.h>
+#endif
#include <stdlib.h>
@@ -418,6 +421,26 @@
test_info.filename = filename;
}
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+/** Check that no PSA Crypto key slots are in use.
+ *
+ * If any slots are in use, mark the current test as failed.
+ *
+ * \return 0 if the key store is empty, 1 otherwise.
+ */
+int test_fail_if_psa_leaking( int line_no, const char *filename )
+{
+ const char *msg = mbedtls_test_helper_is_psa_leaking( );
+ if( msg == NULL )
+ return 0;
+ else
+ {
+ test_fail( msg, line_no, filename );
+ return 1;
+ }
+}
+#endif /* defined(MBEDTLS_PSA_CRYPTO_C) */
+
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
static int redirect_output( FILE* out_stream, const char* path )
{
diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function
index 256224e..98dab3e 100644
--- a/tests/suites/main_test.function
+++ b/tests/suites/main_test.function
@@ -164,6 +164,10 @@
*/
void execute_function_ptr(TestWrapper_t fp, void **params)
{
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+ mbedtls_test_enable_insecure_external_rng( );
+#endif
+
#if defined(MBEDTLS_CHECK_PARAMS)
mbedtls_test_param_failed_location_record_t location_record;
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index 1d98f3d..76e474f 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -9,10 +9,6 @@
#include "mbedtls/gcm.h"
#endif
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "test/psa_crypto_helpers.h"
-#endif
-
#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C)
#define MBEDTLS_CIPHER_AUTH_CRYPT
#endif
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 98016c6..577fb47 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -17,13 +17,13 @@
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "mbedtls/psa_util.h"
-#include "test/psa_crypto_helpers.h"
#define PSA_INIT( ) PSA_ASSERT( psa_crypto_init( ) )
#else
/* Define empty macros so that we can use them in the preamble and teardown
* of every test function that uses PSA conditionally based on
* MBEDTLS_USE_PSA_CRYPTO. */
#define PSA_INIT( ) ( (void) 0 )
+#undef PSA_DONE
#define PSA_DONE( ) ( (void) 0 )
#endif
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 8e71610..d486dd1 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -9,8 +9,6 @@
* uses mbedtls_ctr_drbg internally. */
#include "mbedtls/ctr_drbg.h"
-#include "test/psa_crypto_helpers.h"
-
/* Tests that require more than 128kB of RAM plus change have this symbol
* as a dependency. Currently we always define this symbol, so the tests
* are always executed. In the future we should make this conditional
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
index 6d20eff..23da0c3 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -1,6 +1,4 @@
/* BEGIN_HEADER */
-#include "test/psa_crypto_helpers.h"
-
#include "test/drivers/test_driver.h"
/* END_HEADER */
diff --git a/tests/suites/test_suite_psa_crypto_entropy.data b/tests/suites/test_suite_psa_crypto_entropy.data
index 61593e9..0e53b60 100644
--- a/tests/suites/test_suite_psa_crypto_entropy.data
+++ b/tests/suites/test_suite_psa_crypto_entropy.data
@@ -1,3 +1,30 @@
+PSA external RNG failure: generate random and key
+external_rng_failure_generate:
+
+# When verifying the impact of a forced RNG failure, depend on the built-in
+# implementation of the algorithm that uses randomization, whether it's
+# because the algorithm is randomized or because our implementation uses
+# randomization for (e.g.) blinding. An external implementation could use
+# its own randomness source which is not affected by the forced failure of
+# the RNG driver.
+# Key types and non-randomized auxilary algorithms (in practice, hashes) can
+# use an external implementation.
+PSA external RNG failure: randomized ECDSA
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PSA_BUILTIN_ALG_ECDSA:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+external_rng_failure_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA_ANY:32
+
+PSA external RNG failure: deterministic ECDSA (software implementation)
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:PSA_WANT_ALG_SHA_256
+external_rng_failure_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):32
+
+PSA external RNG failure: RSA-PSS
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256
+external_rng_failure_sign:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):32
+
+PSA external RNG failure: RSA PKCS#1v1.5 (software implementation)
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN
+external_rng_failure_sign:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:32
+
PSA validate entropy injection: good, minimum size
validate_entropy_seed_injection:MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE:PSA_SUCCESS:MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE:PSA_ERROR_NOT_PERMITTED
diff --git a/tests/suites/test_suite_psa_crypto_entropy.function b/tests/suites/test_suite_psa_crypto_entropy.function
index 66c241e..8c1fdab 100644
--- a/tests/suites/test_suite_psa_crypto_entropy.function
+++ b/tests/suites/test_suite_psa_crypto_entropy.function
@@ -1,19 +1,23 @@
/* BEGIN_HEADER */
#include <stdint.h>
+#include <string.h>
+
+#include <psa/crypto.h>
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
-#include "test/psa_crypto_helpers.h"
+/* Calculating the minimum allowed entropy size in bytes */
+#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+
#if defined(MBEDTLS_PSA_ITS_FILE_C)
#include <stdio.h>
#else
#include <psa/internal_trusted_storage.h>
#endif
-/* Calculating the minimum allowed entropy size in bytes */
-#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
-
/* Remove the entropy seed file. Since the library does not expose a way
* to do this (it would be a security risk if such a function was ever
* accessible in production), implement this functionality in a white-box
@@ -30,14 +34,89 @@
#endif
}
+#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
+
/* END_HEADER */
-/* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_PSA_INJECT_ENTROPY
- * END_DEPENDENCIES
- */
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+void external_rng_failure_generate( )
+{
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
+ psa_set_key_bits( &attributes, 128 );
+ mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+ uint8_t output[1];
-/* BEGIN_CASE */
+ PSA_ASSERT( psa_crypto_init( ) );
+
+ PSA_ASSERT( psa_generate_random( output, sizeof( output ) ) );
+ PSA_ASSERT( psa_generate_key( &attributes, &key ) );
+ PSA_ASSERT( psa_destroy_key( key ) );
+
+ mbedtls_test_disable_insecure_external_rng( );
+ TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
+ psa_generate_random( output, sizeof( output ) ) );
+ TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
+ psa_generate_key( &attributes, &key ) );
+
+exit:
+ psa_destroy_key( key );
+ PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+void external_rng_failure_sign( int key_type, data_t *key_data, int alg,
+ int input_size_arg )
+{
+ /* This test case is only expected to pass if the signature mechanism
+ * requires randomness, either because it is a randomized signature
+ * or because the implementation uses blinding. */
+
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_set_key_type( &attributes, key_type );
+ psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN );
+ psa_set_key_algorithm( &attributes, alg );
+ mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+ size_t input_size = input_size_arg;
+ uint8_t *input = NULL;
+ uint8_t *signature = NULL;
+ size_t signature_size = PSA_SIGNATURE_MAX_SIZE;
+ size_t signature_length;
+
+ ASSERT_ALLOC( input, input_size );
+ ASSERT_ALLOC( signature, signature_size );
+
+ PSA_ASSERT( psa_crypto_init( ) );
+ PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+ &key ) );
+ PSA_ASSERT( psa_sign_hash( key, alg,
+ input, input_size,
+ signature, signature_size,
+ &signature_length ) );
+ PSA_ASSERT( psa_destroy_key( key ) );
+
+ mbedtls_test_disable_insecure_external_rng( );
+ /* Import the key again, because for RSA Mbed TLS caches blinding values
+ * in the key object and this could perturb the test. */
+ PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+ &key ) );
+ TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
+ psa_sign_hash( key, alg,
+ input, input_size,
+ signature, signature_size,
+ &signature_length ) );
+ PSA_ASSERT( psa_destroy_key( key ) );
+
+exit:
+ psa_destroy_key( key );
+ PSA_DONE( );
+ mbedtls_free( input );
+ mbedtls_free( signature );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_INJECT_ENTROPY */
void validate_entropy_seed_injection( int seed_length_a,
int expected_status_a,
int seed_length_b,
@@ -81,7 +160,7 @@
}
/* END_CASE */
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_INJECT_ENTROPY */
void run_entropy_inject_with_crypto_init( )
{
psa_status_t status;
diff --git a/tests/suites/test_suite_psa_crypto_hash.function b/tests/suites/test_suite_psa_crypto_hash.function
index 1bc9331..b0da2bf 100644
--- a/tests/suites/test_suite_psa_crypto_hash.function
+++ b/tests/suites/test_suite_psa_crypto_hash.function
@@ -2,8 +2,6 @@
#include <stdint.h>
-#include "test/psa_crypto_helpers.h"
-
/* END_HEADER */
/* BEGIN_DEPENDENCIES
diff --git a/tests/suites/test_suite_psa_crypto_init.function b/tests/suites/test_suite_psa_crypto_init.function
index 62ef6e2..40efb87 100644
--- a/tests/suites/test_suite_psa_crypto_init.function
+++ b/tests/suites/test_suite_psa_crypto_init.function
@@ -1,7 +1,6 @@
/* BEGIN_HEADER */
#include <stdint.h>
-#include "test/psa_crypto_helpers.h"
/* Some tests in this module configure entropy sources. */
#include "psa_crypto_invasive.h"
@@ -11,11 +10,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 +129,8 @@
MBEDTLS_ENTROPY_SOURCE_STRONG );
}
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -125,7 +138,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 +214,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 +235,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 +275,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/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function
index 8e10158..9759077 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.function
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.function
@@ -9,7 +9,6 @@
#include <stdint.h>
-#include "test/psa_crypto_helpers.h"
#include "psa_crypto_slot_management.h"
#include "psa_crypto_storage.h"
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
index 1add9b4..d623221 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -1,5 +1,4 @@
/* BEGIN_HEADER */
-#include "test/psa_crypto_helpers.h"
#include "psa/crypto_se_driver.h"
#include "psa_crypto_se.h"
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
index 629c924..12c58eb 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
@@ -1,5 +1,4 @@
/* BEGIN_HEADER */
-#include "test/psa_crypto_helpers.h"
#include "psa/crypto_se_driver.h"
#include "psa_crypto_se.h"
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function
index 57d4789..b0c660b 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.function
+++ b/tests/suites/test_suite_psa_crypto_slot_management.function
@@ -1,7 +1,6 @@
/* BEGIN_HEADER */
#include <stdint.h>
-#include "test/psa_crypto_helpers.h"
#include "psa_crypto_slot_management.h"
#include "psa_crypto_storage.h"
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index 3803377..9b32cba 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -6,24 +6,11 @@
#include "mbedtls/oid.h"
#include "mbedtls/rsa.h"
-/* These are the same depends as the test function x509_crs_check_opaque(),
- * the only function using PSA here. Using a weaker condition would result in
- * warnings about the static functions defined in psa_crypto_helpers.h being
- * unused. */
-#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
- defined(MBEDTLS_PEM_WRITE_C) && \
- defined(MBEDTLS_X509_CSR_WRITE_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
-#include "test/psa_crypto_helpers.h"
#define PSA_INIT( ) PSA_ASSERT( psa_crypto_init( ) )
-#else
-/* Define empty macros so that we can use them in the preamble and teardown
- * of every test function that uses PSA conditionally based on
- * MBEDTLS_USE_PSA_CRYPTO. */
-#define PSA_INIT( ) ( (void) 0 )
-#define PSA_DONE( ) ( (void) 0 )
-#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C && MBEDTLS_X509_CSR_WRITE_C */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_RSA_C)
int mbedtls_rsa_decrypt_func( void *ctx, int mode, size_t *olen,
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" />