Merge pull request #4159 from d3zd3z/header-list
Add missing header to cpp_dummy_build.cpp test
diff --git a/ChangeLog.d/drbg-mutex.txt b/ChangeLog.d/drbg-mutex.txt
new file mode 100644
index 0000000..3ac5abf
--- /dev/null
+++ b/ChangeLog.d/drbg-mutex.txt
@@ -0,0 +1,5 @@
+Bugfix
+ * Fix a resource leak in CTR_DRBG and HMAC_DRBG when MBEDTLS_THREADING_C
+ is enabled, on platforms where initializing a mutex allocates resources.
+ This was a regression introduced in the previous release. Reported in
+ #4017, #4045 and #4071.
diff --git a/ChangeLog.d/mbedtls_psa_get_random.txt b/ChangeLog.d/mbedtls_psa_get_random.txt
new file mode 100644
index 0000000..f6e6b09
--- /dev/null
+++ b/ChangeLog.d/mbedtls_psa_get_random.txt
@@ -0,0 +1,9 @@
+Features
+ * Partial implementation of the PSA crypto driver interface: Mbed TLS can
+ now use an external random generator instead of the library's own
+ entropy collection and DRBG code. Enable MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+ and see the documentation of mbedtls_psa_external_get_random() for details.
+ * Applications using both mbedtls_xxx and psa_xxx functions (for example,
+ applications using TLS and MBEDTLS_USE_PSA_CRYPTO) can now use the PSA
+ random generator with mbedtls_xxx functions. See the documentation of
+ mbedtls_psa_get_random() for details.
diff --git a/ChangeLog.d/rsa-mutex.txt b/ChangeLog.d/rsa-mutex.txt
new file mode 100644
index 0000000..2a477a9
--- /dev/null
+++ b/ChangeLog.d/rsa-mutex.txt
@@ -0,0 +1,13 @@
+Bugfix
+ * Ensure that calling mbedtls_rsa_free() or mbedtls_entropy_free()
+ twice is safe. This happens for RSA when some Mbed TLS library functions
+ fail. Such a double-free was not safe when MBEDTLS_THREADING_C was
+ enabled on platforms where freeing a mutex twice is not safe.
+ * Fix a resource leak in a bad-arguments case of mbedtls_rsa_gen_key()
+ when MBEDTLS_THREADING_C is enabled on platforms where initializing
+ a mutex allocates resources.
+
+Default behavior changes
+ * In mbedtls_rsa_context objects, the ver field was formerly documented
+ as always 0. It is now reserved for internal purposes and may take
+ different values.
diff --git a/docs/proposed/psa-conditional-inclusion-c.md b/docs/proposed/psa-conditional-inclusion-c.md
index 52138b1..2ddba7f 100644
--- a/docs/proposed/psa-conditional-inclusion-c.md
+++ b/docs/proposed/psa-conditional-inclusion-c.md
@@ -5,8 +5,6 @@
This is currently a proposal for Mbed TLS. It is not currently on track for standardization in PSA.
-Time-stamp: "2020/11/26 09:30:50 GMT"
-
## Introduction
### Purpose of this specification
@@ -86,9 +84,17 @@
For asymmetric cryptography, `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR` determines whether private-key operations are desired, and `PSA_WANT_KEY_TYPE_xxx_PUBLIC_KEY` determines whether public-key operations are desired. `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR` implicitly enables `PSA_WANT_KEY_TYPE_xxx_PUBLIC_KEY`: there is no way to only include private-key operations (which typically saves little code).
-#### Configuration symbols for curves
+#### Configuration symbols for elliptic curves
-For elliptic curve key types, only the specified curves are included. To include a curve, include a symbol of the form **`PSA_WANT_ECC_family_size`**. For example: `PSA_WANT_ECC_SECP_R1_256` for secp256r1, `PSA_WANT_ECC_MONTGOMERY_CURVE25519`. It is an error to require an ECC key type but no curve, and Mbed TLS will reject this at compile time.
+For elliptic curve key types, only the specified curves are included. To include a curve, include a symbol of the form **`PSA_WANT_ECC_family_size`**. For example: `PSA_WANT_ECC_SECP_R1_256` for secp256r1, `PSA_WANT_ECC_MONTGOMERY_255` for Curve25519. It is an error to require an ECC key type but no curve, and Mbed TLS will reject this at compile time.
+
+Rationale: this is a deviation of the general principle that `PSA_ECC_FAMILY_xxx` would have a corresponding symbol `PSA_WANT_ECC_FAMILY_xxx`. This deviation is justified by the fact that it is very common to wish to include only certain curves in a family, and that can lead to a significant gain in code size.
+
+#### Configuration symbols for Diffie-Hellman groups
+
+There are no configuration symbols for Diffie-Hellman groups (`PSA_DH_GROUP_xxx`).
+
+Rationale: Finite-field Diffie-Hellman code is usually not specialized for any particular group, so reducing the number of available groups at compile time only saves a little code space. Constrained implementations tend to omit FFDH anyway, so the small code size gain is not important.
#### Configuration symbols for algorithms
@@ -195,7 +201,7 @@
#### Naming of symbols
-The names of [elliptic curve symbols](#configuration-symbols-for-curves) are a bit weird: `SECP_R1_256` instead of `SECP256R1`. Should we make them more classical, but less systematic?
+The names of [elliptic curve symbols](#configuration-symbols-for-elliptic-curves) are a bit weird: `SECP_R1_256` instead of `SECP256R1`, `MONTGOMERY_255` instead of `CURVE25519`. Should we make them more classical, but less systematic?
#### Impossible combinations
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index 7f1d232..653fd83 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -200,6 +200,13 @@
void *p_entropy; /*!< The context for the entropy function. */
#if defined(MBEDTLS_THREADING_C)
+ /* Invariant: the mutex is initialized if and only if f_entropy != NULL.
+ * This means that the mutex is initialized during the initial seeding
+ * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free().
+ *
+ * Note that this invariant may change without notice. Do not rely on it
+ * and do not access the mutex directly in application code.
+ */
mbedtls_threading_mutex_t mutex;
#endif
}
@@ -264,6 +271,15 @@
* make a second call to \p f_entropy.
*/
#endif
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * after this function returns successfully,
+ * it is safe to call mbedtls_ctr_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
/**
* - The \p custom string.
*
@@ -290,6 +306,8 @@
* the same context unless you call
* mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
* again first.
+ * After a failed call to mbedtls_ctr_drbg_seed(),
+ * you must call mbedtls_ctr_drbg_free().
* \param f_entropy The entropy callback, taking as arguments the
* \p p_entropy context, the buffer to fill, and the
* length of the buffer.
@@ -405,6 +423,11 @@
* \brief This function reseeds the CTR_DRBG context, that is
* extracts data from the entropy source.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param ctx The CTR_DRBG context.
* \param additional Additional data to add to the state. Can be \c NULL.
* \param len The length of the additional data.
@@ -422,6 +445,11 @@
/**
* \brief This function updates the state of the CTR_DRBG context.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with. This must not be
* \c NULL unless \p add_len is \c 0.
@@ -445,6 +473,11 @@
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
@@ -473,8 +506,16 @@
*
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
- *
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * it is safe to call mbedtls_ctr_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
diff --git a/include/mbedtls/entropy.h b/include/mbedtls/entropy.h
index 5a9c11c..fa0b24f 100644
--- a/include/mbedtls/entropy.h
+++ b/include/mbedtls/entropy.h
@@ -120,13 +120,15 @@
*/
typedef struct mbedtls_entropy_context
{
- int accumulator_started;
+ int accumulator_started; /* 0 after init.
+ * 1 after the first update.
+ * -1 after free. */
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_context accumulator;
#else
mbedtls_sha256_context accumulator;
#endif
- int source_count;
+ int source_count; /* Number of entries used in source. */
mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES];
#if defined(MBEDTLS_HAVEGE_C)
mbedtls_havege_state havege_data;
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index 9116541..fa33611 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -101,6 +101,14 @@
void *p_entropy; /*!< context for the entropy function */
#if defined(MBEDTLS_THREADING_C)
+ /* Invariant: the mutex is initialized if and only if
+ * md_ctx->md_info != NULL. This means that the mutex is initialized
+ * during the initial seeding in mbedtls_hmac_drbg_seed() or
+ * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free().
+ *
+ * Note that this invariant may change without notice. Do not rely on it
+ * and do not access the mutex directly in application code.
+ */
mbedtls_threading_mutex_t mutex;
#endif
} mbedtls_hmac_drbg_context;
@@ -150,7 +158,17 @@
* \note During the initial seeding, this function calls
* the entropy source to obtain a nonce
* whose length is half the entropy length.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * after this function returns successfully,
+ * it is safe to call mbedtls_hmac_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
* \param ctx HMAC_DRBG context to be seeded.
* \param md_info MD algorithm to use for HMAC_DRBG.
* \param f_entropy The entropy callback, taking as arguments the
@@ -189,7 +207,17 @@
*
* This function is meant for use in algorithms that need a pseudorandom
* input such as deterministic ECDSA.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * after this function returns successfully,
+ * it is safe to call mbedtls_hmac_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
* \param ctx HMAC_DRBG context to be initialised.
* \param md_info MD algorithm to use for HMAC_DRBG.
* \param data Concatenation of the initial entropy string and
@@ -252,6 +280,11 @@
/**
* \brief This function updates the state of the HMAC_DRBG context.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param ctx The HMAC_DRBG context.
* \param additional The data to update the state with.
* If this is \c NULL, there is no additional data.
@@ -268,6 +301,11 @@
* \brief This function reseeds the HMAC_DRBG context, that is
* extracts data from the entropy source.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param ctx The HMAC_DRBG context.
* \param additional Additional data to add to the state.
* If this is \c NULL, there is no additional data
@@ -293,6 +331,11 @@
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param p_rng The HMAC_DRBG context. This must be a pointer to a
* #mbedtls_hmac_drbg_context structure.
* \param output The buffer to fill.
@@ -322,7 +365,16 @@
*
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * it is safe to call mbedtls_ctr_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
* \param p_rng The HMAC_DRBG context. This must be a pointer to a
* #mbedtls_hmac_drbg_context structure.
* \param output The buffer to fill.
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index 0b8a216..f18857c 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -419,4 +419,90 @@
#endif /* MBEDTLS_USE_PSA_CRYPTO */
+/* Expose whatever RNG the PSA subsystem uses to applications using the
+ * mbedtls_xxx API. The declarations and definitions here need to be
+ * consistent with the implementation in library/psa_crypto_random_impl.h.
+ * See that file for implementation documentation. */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+/* The type of a `f_rng` random generator function that many library functions
+ * take.
+ *
+ * This type name is not part of the Mbed TLS stable API. It may be renamed
+ * or moved without warning.
+ */
+typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_size );
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+/** The random generator function for the PSA subsystem.
+ *
+ * This function is suitable as the `f_rng` random generator function
+ * parameter of many `mbedtls_xxx` functions. Use #MBEDTLS_PSA_RANDOM_STATE
+ * to obtain the \p p_rng parameter.
+ *
+ * The implementation of this function depends on the configuration of the
+ * library.
+ *
+ * \note Depending on the configuration, this may be a function or
+ * a pointer to a function.
+ *
+ * \note This function may only be used if the PSA crypto subsystem is active.
+ * This means that you must call psa_crypto_init() before any call to
+ * this function, and you must not call this function after calling
+ * mbedtls_psa_crypto_free().
+ *
+ * \param p_rng The random generator context. This must be
+ * #MBEDTLS_PSA_RANDOM_STATE. No other state is
+ * supported.
+ * \param output The buffer to fill. It must have room for
+ * \c output_size bytes.
+ * \param output_size The number of bytes to write to \p output.
+ * This function may fail if \p output_size is too
+ * large. It is guaranteed to accept any output size
+ * requested by Mbed TLS library functions. The
+ * maximum request size depends on the library
+ * configuration.
+ *
+ * \return \c 0 on success.
+ * \return An `MBEDTLS_ERR_ENTROPY_xxx`,
+ * `MBEDTLS_ERR_PLATFORM_xxx,
+ * `MBEDTLS_ERR_CTR_DRBG_xxx` or
+ * `MBEDTLS_ERR_HMAC_DRBG_xxx` on error.
+ */
+int mbedtls_psa_get_random( void *p_rng,
+ unsigned char *output,
+ size_t output_size );
+
+/** The random generator state for the PSA subsystem.
+ *
+ * This macro expands to an expression which is suitable as the `p_rng`
+ * random generator state parameter of many `mbedtls_xxx` functions.
+ * It must be used in combination with the random generator function
+ * mbedtls_psa_get_random().
+ *
+ * The implementation of this macro depends on the configuration of the
+ * library. Do not make any assumption on its nature.
+ */
+#define MBEDTLS_PSA_RANDOM_STATE NULL
+
+#else /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+#include "mbedtls/ctr_drbg.h"
+typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t;
+static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random;
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+#include "mbedtls/hmac_drbg.h"
+typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t;
+static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random;
+#endif
+extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
+
+#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state
+
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
#endif /* MBEDTLS_PSA_UTIL_H */
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index 6a31514..701fe8b 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -97,7 +97,10 @@
*/
typedef struct mbedtls_rsa_context
{
- int ver; /*!< Always 0.*/
+ int ver; /*!< Reserved for internal purposes.
+ * Do not set this field in application
+ * code. Its meaning might change without
+ * notice. */
size_t len; /*!< The size of \p N in Bytes. */
mbedtls_mpi N; /*!< The public modulus. */
@@ -127,6 +130,7 @@
mask generating function used in the
EME-OAEP and EMSA-PSS encodings. */
#if defined(MBEDTLS_THREADING_C)
+ /* Invariant: the mutex is initialized iff ver != 0. */
mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */
#endif
}
diff --git a/include/mbedtls/threading.h b/include/mbedtls/threading.h
index 8baf15a..05e27c5 100644
--- a/include/mbedtls/threading.h
+++ b/include/mbedtls/threading.h
@@ -46,6 +46,9 @@
typedef struct mbedtls_threading_mutex_t
{
pthread_mutex_t mutex;
+ /* is_valid is 0 after a failed init or a free, and nonzero after a
+ * successful init. This field is not considered part of the public
+ * API of Mbed TLS and may change without notice. */
char is_valid;
} mbedtls_threading_mutex_t;
#endif
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 3815dc7..ab52861 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -56,10 +56,6 @@
ctx->reseed_counter = -1;
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-
-#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_init( &ctx->mutex );
-#endif
}
/*
@@ -72,15 +68,14 @@
return;
#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_free( &ctx->mutex );
+ /* The mutex is initialized iff f_entropy is set. */
+ if( ctx->f_entropy != NULL )
+ mbedtls_mutex_free( &ctx->mutex );
#endif
mbedtls_aes_free( &ctx->aes_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
ctx->reseed_counter = -1;
-#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_init( &ctx->mutex );
-#endif
}
void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
@@ -464,6 +459,11 @@
memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
+ /* The mutex is initialized iff f_entropy is set. */
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_init( &ctx->mutex );
+#endif
+
mbedtls_aes_init( &ctx->aes_ctx );
ctx->f_entropy = f_entropy;
diff --git a/library/entropy.c b/library/entropy.c
index db61f16..b9aca86 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -116,6 +116,11 @@
void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
{
+ /* If the context was already free, don't call free() again.
+ * This is important for mutexes which don't allow double-free. */
+ if( ctx->accumulator_started == -1 )
+ return;
+
#if defined(MBEDTLS_HAVEGE_C)
mbedtls_havege_free( &ctx->havege_data );
#endif
@@ -132,7 +137,7 @@
#endif
ctx->source_count = 0;
mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
- ctx->accumulator_started = 0;
+ ctx->accumulator_started = -1;
}
int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 84b70fe..2c1e093 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -220,13 +220,13 @@
{
((void) data);
((void) output);
- *olen = 0;
+ *olen = 0;
if( len < sizeof(unsigned char) )
return( 0 );
+ output[0] = 0;
*olen = sizeof(unsigned char);
-
return( 0 );
}
#endif
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index 25a0225..de97068 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -54,10 +54,6 @@
memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-
-#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_init( &ctx->mutex );
-#endif
}
/*
@@ -129,6 +125,10 @@
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
return( ret );
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_init( &ctx->mutex );
+#endif
+
/*
* Set initial working state.
* Use the V memory location, which is currently all 0, to initialize the
@@ -254,6 +254,11 @@
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
return( ret );
+ /* The mutex is initialized iff the md context is set up. */
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_init( &ctx->mutex );
+#endif
+
md_size = mbedtls_md_get_size( md_info );
/*
@@ -421,14 +426,13 @@
return;
#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_free( &ctx->mutex );
+ /* The mutex is initialized iff the md context is set up. */
+ if( ctx->md_ctx.md_info != NULL )
+ mbedtls_mutex_free( &ctx->mutex );
#endif
mbedtls_md_free( &ctx->md_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_init( &ctx->mutex );
-#endif
}
#if defined(MBEDTLS_FS_IO)
diff --git a/library/md.c b/library/md.c
index de77b16..a10a835 100644
--- a/library/md.c
+++ b/library/md.c
@@ -1,5 +1,5 @@
/**
- * \file mbedtls_md.c
+ * \file md.c
*
* \brief Generic message digest wrapper for mbed TLS
*
diff --git a/library/psa_crypto_random_impl.h b/library/psa_crypto_random_impl.h
index 1232186..3c4c09a 100644
--- a/library/psa_crypto_random_impl.h
+++ b/library/psa_crypto_random_impl.h
@@ -1,6 +1,14 @@
/** \file psa_crypto_random_impl.h
*
* \brief PSA crypto random generator implementation abstraction.
+ *
+ * The definitions here need to be consistent with the declarations
+ * in include/mbedtls/psa_util.h. This file contains some redundant
+ * declarations to increase the chance that a compiler will detect
+ * inconsistencies if one file is changed without updating the other,
+ * but not all potential inconsistencies can be enforced, so make sure
+ * to check the public declarations and contracts in
+ * include/mbedtls/psa_util.h if you modify this file.
*/
/*
* Copyright The Mbed TLS Contributors
@@ -22,6 +30,8 @@
#ifndef PSA_CRYPTO_RANDOM_IMPL_H
#define PSA_CRYPTO_RANDOM_IMPL_H
+#include <mbedtls/psa_util.h>
+
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
#include <string.h>
@@ -75,14 +85,6 @@
#include "mbedtls/entropy.h"
-/** The type of the PSA DRBG context.
- */
-#if defined(MBEDTLS_CTR_DRBG_C)
-typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t;
-#elif defined(MBEDTLS_HMAC_DRBG_C)
-typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t;
-#endif
-
/** Initialize the PSA DRBG.
*
* \param p_rng Pointer to the Mbed TLS DRBG state.
@@ -122,33 +124,18 @@
mbedtls_psa_drbg_context_t drbg;
} mbedtls_psa_random_context_t;
-/* The type of an Mbed TLS random generator function. This should be
- * part of the public API instead of repeating the type everywhere.
- * For the time being, declare it here. Declaring a type is necessary
- * to define mbedtls_psa_get_random as a variable of a function pointer
- * type without incurring the wrath of check-names.sh. */
-typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_size );
-
-/** Return random data.
- *
- * This function is suitable as the \p f_rng parameter to Mbed TLS functions
- * that require a random generator. Use #MBEDTLS_PSA_RANDOM_STATE to
- * obtain the \p p_rng parameter.
- *
- * \param p_rng The DRBG context. This must be
- * #MBEDTLS_PSA_RANDOM_STATE.
- * \param output The buffer to fill.
- * \param output_len The length of the buffer in bytes.
- * It must be at most #MBEDTLS_PSA_RANDOM_MAX_REQUEST.
- *
- * \retval \c 0 on success.
- * \return \c MBEDTLS_ERR_xxx_DRBG_xxx or
- * \c MBEDTLS_ERR_PLATFORM_xxx on failure.
+/* Defined in include/mbedtls/psa_util.h so that it's visible to
+ * application code. The declaration here is redundant, but included
+ * as a safety net to make it more likely that a future change that
+ * accidentally causes the implementation to diverge from the interface
+ * will be noticed. */
+/* Do not include the declaration under MSVC because it doesn't accept it
+ * ("error C2370: 'mbedtls_psa_get_random' : redefinition; different storage class").
+ * Observed with Visual Studio 2013. A known bug apparently:
+ * https://stackoverflow.com/questions/8146541/duplicate-external-static-declarations-not-allowed-in-visual-studio
*/
-#if defined(MBEDTLS_CTR_DRBG_C)
-static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random;
-#elif defined(MBEDTLS_HMAC_DRBG_C)
-static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random;
+#if !defined(_MSC_VER)
+static mbedtls_f_rng_t *const mbedtls_psa_get_random;
#endif
/** The maximum number of bytes that mbedtls_psa_get_random() is expected to
@@ -167,6 +154,9 @@
*/
/* psa_crypto.c sets this variable to a pointer to the DRBG state in the
* global PSA crypto state. */
+/* The type `mbedtls_psa_drbg_context_t` is defined in
+ * include/mbedtls/psa_util.h so that `mbedtls_psa_random_state` can be
+ * declared there and be visible to application code. */
extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
/** A pointer to the PSA DRBG state.
diff --git a/library/rsa.c b/library/rsa.c
index 9fe551d..68a36f2 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -490,6 +490,9 @@
mbedtls_rsa_set_padding( ctx, padding, hash_id );
#if defined(MBEDTLS_THREADING_C)
+ /* Set ctx->ver to nonzero to indicate that the mutex has been
+ * initialized and will need to be freed. */
+ ctx->ver = 1;
mbedtls_mutex_init( &ctx->mutex );
#endif
}
@@ -537,9 +540,6 @@
RSA_VALIDATE_RET( ctx != NULL );
RSA_VALIDATE_RET( f_rng != NULL );
- if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
- return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
/*
* If the modulus is 1024 bit long or shorter, then the security strength of
* the RSA algorithm is less than or equal to 80 bits and therefore an error
@@ -552,6 +552,12 @@
mbedtls_mpi_init( &G );
mbedtls_mpi_init( &L );
+ if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
+ {
+ ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
/*
* find primes P and Q with Q < P so that:
* 1. |P-Q| > 2^( nbits / 2 - 100 )
@@ -629,7 +635,9 @@
if( ret != 0 )
{
mbedtls_rsa_free( ctx );
- return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret );
+ if( ( -ret & ~0x7f ) == 0 )
+ ret = MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret;
+ return( ret );
}
return( 0 );
@@ -2481,7 +2489,6 @@
RSA_VALIDATE_RET( dst != NULL );
RSA_VALIDATE_RET( src != NULL );
- dst->ver = src->ver;
dst->len = src->len;
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
@@ -2540,7 +2547,12 @@
#endif /* MBEDTLS_RSA_NO_CRT */
#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_free( &ctx->mutex );
+ /* Free the mutex, but only if it hasn't been freed already. */
+ if( ctx->ver != 0 )
+ {
+ mbedtls_mutex_free( &ctx->mutex );
+ ctx->ver = 0;
+ }
#endif
}
diff --git a/library/threading.c b/library/threading.c
index 2bb932d..2de117f 100644
--- a/library/threading.c
+++ b/library/threading.c
@@ -67,6 +67,12 @@
if( mutex == NULL )
return;
+ /* A nonzero value of is_valid indicates a successfully initialized
+ * mutex. This is a workaround for not being able to return an error
+ * code for this function. The lock/unlock functions return an error
+ * if is_valid is nonzero. The Mbed TLS unit test code uses this field
+ * to distinguish more states of the mutex; see
+ * tests/src/threading_helpers for details. */
mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0;
}
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 876555d..d0758bc 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -703,7 +703,7 @@
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_key_id_t key_slot = 0; /* invalid key slot */
#endif
-#endif
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
char *p, *q;
const int *list;
#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
@@ -734,6 +734,10 @@
mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
#endif
+#if defined(MBEDTLS_TEST_HOOKS)
+ test_hooks_init( );
+#endif /* MBEDTLS_TEST_HOOKS */
+
/*
* Make sure memory references are valid.
*/
@@ -760,10 +764,10 @@
ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
goto exit;
}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
mbedtls_test_enable_insecure_external_rng( );
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( argc == 0 )
{
@@ -1536,7 +1540,8 @@
mbedtls_printf( "\n . Seeding the random number generator..." );
fflush( stdout );
- if( rng_seed( &rng, opt.reproducible, pers ) != 0 )
+ ret = rng_seed( &rng, opt.reproducible, pers );
+ if( ret != 0 )
goto exit;
mbedtls_printf( " ok\n" );
@@ -1881,7 +1886,7 @@
#else
fprintf( stderr, "Warning: reproducible option used without constant time\n" );
#endif
-#endif
+#endif /* MBEDTLS_HAVE_TIME */
}
mbedtls_ssl_conf_rng( &conf, rng_get, &rng );
mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
@@ -1927,7 +1932,7 @@
goto exit;
}
}
-#endif
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_ECP_C)
if( opt.curves != NULL &&
@@ -2999,19 +3004,7 @@
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_destroy_key( key_slot );
#endif
-#endif
- mbedtls_ssl_session_free( &saved_session );
- mbedtls_ssl_free( &ssl );
- mbedtls_ssl_config_free( &conf );
- rng_free( &rng );
- if( session_data != NULL )
- mbedtls_platform_zeroize( session_data, session_data_len );
- mbedtls_free( session_data );
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
- if( context_buf != NULL )
- mbedtls_platform_zeroize( context_buf, context_buf_len );
- mbedtls_free( context_buf );
-#endif
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) && \
defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -3034,12 +3027,39 @@
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED &&
MBEDTLS_USE_PSA_CRYPTO */
+ mbedtls_ssl_session_free( &saved_session );
+ mbedtls_ssl_free( &ssl );
+ mbedtls_ssl_config_free( &conf );
+ rng_free( &rng );
+ if( session_data != NULL )
+ mbedtls_platform_zeroize( session_data, session_data_len );
+ mbedtls_free( session_data );
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+ if( context_buf != NULL )
+ mbedtls_platform_zeroize( context_buf, context_buf_len );
+ mbedtls_free( context_buf );
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ mbedtls_psa_crypto_free( );
+#endif
+
+#if defined(MBEDTLS_TEST_HOOKS)
+ if( test_hooks_failure_detected( ) )
+ {
+ if( ret == 0 )
+ ret = 1;
+ mbedtls_printf( "Test hooks detected errors.\n" );
+ }
+ test_hooks_free( );
+#endif /* MBEDTLS_TEST_HOOKS */
+
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_status();
#endif
mbedtls_memory_buffer_alloc_free();
-#endif
+#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
#if defined(_WIN32)
if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 57c053c..bd4dbb6 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -1369,6 +1369,10 @@
#endif /* MBEDTLS_MEMORY_DEBUG */
#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
+#if defined(MBEDTLS_TEST_HOOKS)
+ test_hooks_init( );
+#endif /* MBEDTLS_TEST_HOOKS */
+
/*
* Make sure memory references are valid in case we exit early.
*/
@@ -1412,10 +1416,10 @@
ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
goto exit;
}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
mbedtls_test_enable_insecure_external_rng( );
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if !defined(_WIN32)
/* Abort cleanly on SIGTERM and SIGINT */
@@ -2295,7 +2299,8 @@
mbedtls_printf( "\n . Seeding the random number generator..." );
fflush( stdout );
- if( rng_seed( &rng, opt.reproducible, pers ) != 0 )
+ ret = rng_seed( &rng, opt.reproducible, pers );
+ if( ret != 0 )
goto exit;
mbedtls_printf( " ok\n" );
@@ -2683,7 +2688,7 @@
#else
fprintf( stderr, "Warning: reproducible option used without constant time\n" );
#endif
-#endif
+#endif /* MBEDTLS_HAVE_TIME */
}
mbedtls_ssl_conf_rng( &conf, rng_get, &rng );
mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
@@ -3997,12 +4002,32 @@
mbedtls_free( context_buf );
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ mbedtls_psa_crypto_free( );
+#endif
+
+#if defined(MBEDTLS_TEST_HOOKS)
+ /* Let test hooks detect errors such as resource leaks.
+ * Don't do it in query_config mode, because some test code prints
+ * information to stdout and this gets mixed with the regular output. */
+ if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
+ {
+ if( test_hooks_failure_detected( ) )
+ {
+ if( ret == 0 )
+ ret = 1;
+ mbedtls_printf( "Test hooks detected errors.\n" );
+ }
+ }
+ test_hooks_free( );
+#endif /* MBEDTLS_TEST_HOOKS */
+
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_status();
#endif
mbedtls_memory_buffer_alloc_free();
-#endif
+#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
{
diff --git a/programs/ssl/ssl_test_lib.c b/programs/ssl/ssl_test_lib.c
index 46cea14..1bb9d61 100644
--- a/programs/ssl/ssl_test_lib.c
+++ b/programs/ssl/ssl_test_lib.c
@@ -22,6 +22,10 @@
#include "ssl_test_lib.h"
+#if defined(MBEDTLS_TEST_HOOKS)
+#include "test/helpers.h"
+#endif
+
#if !defined(MBEDTLS_SSL_TEST_IMPOSSIBLE)
void my_debug( void *ctx, int level,
@@ -46,6 +50,7 @@
return 0x5af2a056;
}
+#if !defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
static int dummy_entropy( void *data, unsigned char *output, size_t len )
{
size_t i;
@@ -60,9 +65,15 @@
}
return( ret );
}
+#endif
void rng_init( rng_context_t *rng )
{
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+ (void) rng;
+ psa_crypto_init( );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+
#if defined(MBEDTLS_CTR_DRBG_C)
mbedtls_ctr_drbg_init( &rng->drbg );
#elif defined(MBEDTLS_HMAC_DRBG_C)
@@ -72,10 +83,31 @@
#endif
mbedtls_entropy_init( &rng->entropy );
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
}
int rng_seed( rng_context_t *rng, int reproducible, const char *pers )
{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( reproducible )
+ {
+ mbedtls_fprintf( stderr,
+ "MBEDTLS_USE_PSA_CRYPTO does not support reproducible mode.\n" );
+ return( -1 );
+ }
+#endif
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+ /* The PSA crypto RNG does its own seeding. */
+ (void) rng;
+ (void) pers;
+ if( reproducible )
+ {
+ mbedtls_fprintf( stderr,
+ "The PSA RNG does not support reproducible mode.\n" );
+ return( -1 );
+ }
+ return( 0 );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
int ( *f_entropy )( void *, unsigned char *, size_t ) =
( reproducible ? dummy_entropy : mbedtls_entropy_func );
@@ -100,9 +132,9 @@
f_entropy, &rng->entropy,
(const unsigned char *) pers,
strlen( pers ) );
-#else
+#else /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) */
#error "No DRBG available"
-#endif
+#endif /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) */
if( ret != 0 )
{
@@ -110,12 +142,21 @@
(unsigned int) -ret );
return( ret );
}
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
return( 0 );
}
void rng_free( rng_context_t *rng )
{
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+ (void) rng;
+ /* Deinitialize the PSA crypto subsystem. This deactivates all PSA APIs.
+ * This is ok because none of our applications try to do any crypto after
+ * deinitializing the RNG. */
+ mbedtls_psa_crypto_free( );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+
#if defined(MBEDTLS_CTR_DRBG_C)
mbedtls_ctr_drbg_free( &rng->drbg );
#elif defined(MBEDTLS_HMAC_DRBG_C)
@@ -125,11 +166,18 @@
#endif
mbedtls_entropy_free( &rng->entropy );
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
}
int rng_get( void *p_rng, unsigned char *output, size_t output_len )
{
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+ (void) p_rng;
+ return( mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+ output, output_len ) );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
rng_context_t *rng = p_rng;
+
#if defined(MBEDTLS_CTR_DRBG_C)
return( mbedtls_ctr_drbg_random( &rng->drbg, output, output_len ) );
#elif defined(MBEDTLS_HMAC_DRBG_C)
@@ -137,6 +185,8 @@
#else
#error "No DRBG available"
#endif
+
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
}
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
@@ -275,4 +325,33 @@
return( 0 );
}
+#if defined(MBEDTLS_TEST_HOOKS)
+
+void test_hooks_init( void )
+{
+ mbedtls_test_info_reset( );
+
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+ mbedtls_test_mutex_usage_init( );
+#endif
+}
+
+int test_hooks_failure_detected( void )
+{
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+ /* Errors are reported via mbedtls_test_info. */
+ mbedtls_test_mutex_usage_check( );
+#endif
+
+ if( mbedtls_test_info.result != MBEDTLS_TEST_RESULT_SUCCESS )
+ return( 1 );
+ return( 0 );
+}
+
+void test_hooks_free( void )
+{
+}
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
#endif /* !defined(MBEDTLS_SSL_TEST_IMPOSSIBLE) */
diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h
index 861e82a..98751a0 100644
--- a/programs/ssl/ssl_test_lib.h
+++ b/programs/ssl/ssl_test_lib.h
@@ -43,23 +43,33 @@
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
-#if !defined(MBEDTLS_ENTROPY_C) || \
- !defined(MBEDTLS_NET_C) || \
+#undef HAVE_RNG
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \
+ ( defined(MBEDTLS_USE_PSA_CRYPTO) || \
+ defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) )
+#define HAVE_RNG
+#elif defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
+#define HAVE_RNG
+#elif defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_HMAC_DRBG_C) && \
+ ( defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) )
+#define HAVE_RNG
+#endif
+
+#if !defined(MBEDTLS_NET_C) || \
!defined(MBEDTLS_SSL_TLS_C) || \
defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
#define MBEDTLS_SSL_TEST_IMPOSSIBLE \
- "MBEDTLS_ENTROPY_C and/or " \
"MBEDTLS_NET_C and/or " \
"MBEDTLS_SSL_TLS_C not defined, " \
"and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined.\n"
-#elif !( defined(MBEDTLS_CTR_DRBG_C) || \
- defined(MBEDTLS_HMAC_DRBG_C) && ( defined(MBEDTLS_SHA256_C) || \
- defined(MBEDTLS_SHA512_C) ) )
-#define MBEDTLS_SSL_TEST_IMPOSSIBLE \
- "Neither MBEDTLS_CTR_DRBG_C, nor MBEDTLS_HMAC_DRBG_C and a supported hash defined.\n"
+#elif !defined(HAVE_RNG)
+#define MBEDTLS_SSL_TEST_IMPOSSIBLE \
+ "No random generator is available.\n"
#else
#undef MBEDTLS_SSL_TEST_IMPOSSIBLE
+#undef HAVE_RNG
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -76,7 +86,7 @@
#include "mbedtls/timing.h"
#include "mbedtls/base64.h"
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
#endif
@@ -130,10 +140,38 @@
mbedtls_time_t dummy_constant_time( mbedtls_time_t* time );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/* If MBEDTLS_TEST_USE_PSA_CRYPTO_RNG is defined, the SSL test programs will use
+ * mbedtls_psa_get_random() rather than entropy+DRBG as a random generator.
+ *
+ * The constraints are:
+ * - Without the entropy module, the PSA RNG is the only option.
+ * - Without at least one of the DRBG modules, the PSA RNG is the only option.
+ * - The PSA RNG does not support explicit seeding, so it is incompatible with
+ * the reproducible mode used by test programs.
+ * - For good overall test coverage, there should be at least one configuration
+ * where the test programs use the PSA RNG while the PSA RNG is itself based
+ * on entropy+DRBG, and at least one configuration where the test programs
+ * do not use the PSA RNG even though it's there.
+ *
+ * A simple choice that meets the constraints is to use the PSA RNG whenever
+ * MBEDTLS_USE_PSA_CRYPTO is enabled. There's no real technical reason the
+ * choice to use the PSA RNG in the test programs and the choice to use
+ * PSA crypto when TLS code needs crypto have to be tied together, but it
+ * happens to be a good match. It's also a good match from an application
+ * perspective: either PSA is preferred for TLS (both for crypto and for
+ * random generation) or it isn't.
+ */
+#define MBEDTLS_TEST_USE_PSA_CRYPTO_RNG
+#endif
+
/** A context for random number generation (RNG).
*/
typedef struct
{
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+ unsigned char dummy;
+#else /* MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
mbedtls_entropy_context entropy;
#if defined(MBEDTLS_CTR_DRBG_C)
mbedtls_ctr_drbg_context drbg;
@@ -142,6 +180,7 @@
#else
#error "No DRBG available"
#endif
+#endif /* MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
} rng_context_t;
/** Initialize the RNG.
@@ -219,5 +258,37 @@
#endif
int idle_reason );
+#if defined(MBEDTLS_TEST_HOOKS)
+/** Initialize whatever test hooks are enabled by the compile-time
+ * configuration and make sense for the TLS test programs. */
+void test_hooks_init( void );
+
+/** Check if any test hooks detected a problem.
+ *
+ * If a problem was detected, it's ok for the calling program to keep going,
+ * but it should ultimately exit with an error status.
+ *
+ * \note When implementing a test hook that detects errors on its own
+ * (as opposed to e.g. leaving the error for a memory sanitizer to
+ * report), make sure to print a message to standard error either at
+ * the time the problem is detected or during the execution of this
+ * function. This function does not indicate what problem was detected,
+ * so printing a message is the only way to provide feedback in the
+ * logs of the calling program.
+ *
+ * \return Nonzero if a problem was detected.
+ * \c 0 if no problem was detected.
+ */
+int test_hooks_failure_detected( void );
+
+/** Free any resources allocated for the sake of test hooks.
+ *
+ * Call this at the end of the program so that resource leak analyzers
+ * don't complain.
+ */
+void test_hooks_free( void );
+
+#endif /* !MBEDTLS_TEST_HOOKS */
+
#endif /* MBEDTLS_SSL_TEST_IMPOSSIBLE conditions: else */
#endif /* MBEDTLS_PROGRAMS_SSL_SSL_TEST_LIB_H */
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 13f0593..e2bc420 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -67,6 +67,10 @@
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+if(CMAKE_COMPILER_IS_CLANG)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code")
+endif(CMAKE_COMPILER_IS_CLANG)
+
if(MSVC)
# If a warning level has been defined, suppress all warnings for test code
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W0")
@@ -153,6 +157,7 @@
add_test_suite(psa_crypto_se_driver_hal_mocks)
add_test_suite(psa_crypto_slot_management)
add_test_suite(psa_its)
+add_test_suite(random)
add_test_suite(rsa)
add_test_suite(shax)
add_test_suite(ssl)
diff --git a/tests/include/test/asn1_helpers.h b/tests/include/test/asn1_helpers.h
new file mode 100644
index 0000000..91ae260
--- /dev/null
+++ b/tests/include/test/asn1_helpers.h
@@ -0,0 +1,50 @@
+/** Helper functions for tests that manipulate ASN.1 data.
+ */
+/*
+ * 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 ASN1_HELPERS_H
+#define ASN1_HELPERS_H
+
+#include "test/helpers.h"
+
+/** Skip past an INTEGER in an ASN.1 buffer.
+ *
+ * Mark the current test case as failed in any of the following conditions:
+ * - The buffer does not start with an ASN.1 INTEGER.
+ * - The integer's size or parity does not match the constraints expressed
+ * through \p min_bits, \p max_bits and \p must_be_odd.
+ *
+ * \param p Upon entry, `*p` points to the first byte of the
+ * buffer to parse.
+ * On successful return, `*p` points to the first byte
+ * after the parsed INTEGER.
+ * On failure, `*p` is unspecified.
+ * \param end The end of the ASN.1 buffer.
+ * \param min_bits Fail the test case if the integer does not have at
+ * least this many significant bits.
+ * \param max_bits Fail the test case if the integer has more than
+ * this many significant bits.
+ * \param must_be_odd Fail the test case if the integer is even.
+ *
+ * \return \c 0 if the test failed, otherwise 1.
+ */
+int mbedtls_test_asn1_skip_integer( unsigned char **p, const unsigned char *end,
+ size_t min_bits, size_t max_bits,
+ int must_be_odd );
+
+#endif /* ASN1_HELPERS_H */
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index 8b56d3a..c3a844b 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -31,6 +31,11 @@
#include MBEDTLS_CONFIG_FILE
#endif
+#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_PTHREAD) && \
+ defined(MBEDTLS_TEST_HOOKS)
+#define MBEDTLS_TEST_MUTEX_USAGE
+#endif
+
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@@ -63,6 +68,9 @@
const char *filename;
int line_no;
unsigned long step;
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+ const char *mutex_usage_error;
+#endif
}
mbedtls_test_info_t;
extern mbedtls_test_info_t mbedtls_test_info;
@@ -256,8 +264,18 @@
void mbedtls_test_param_failed_reset_state( void );
#endif /* MBEDTLS_CHECK_PARAMS */
-#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
#include "test/fake_external_rng_for_test.h"
#endif
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+/** Permanently activate the mutex usage verification framework. See
+ * threading_helpers.c for information. */
+void mbedtls_test_mutex_usage_init( void );
+
+/** Call this function after executing a test case to check for mutex usage
+ * errors. */
+void mbedtls_test_mutex_usage_check( void );
+#endif /* MBEDTLS_TEST_MUTEX_USAGE */
+
#endif /* TEST_HELPERS_H */
diff --git a/tests/include/test/macros.h b/tests/include/test/macros.h
index 6930a5d..450bc2c 100644
--- a/tests/include/test/macros.h
+++ b/tests/include/test/macros.h
@@ -321,40 +321,45 @@
mbedtls_exit( 1 ); \
}
+/** \def ARRAY_LENGTH
+ * Return the number of elements of a static or stack array.
+ *
+ * \param array A value of array (not pointer) type.
+ *
+ * \return The number of elements of the array.
+ */
+/* A correct implementation of ARRAY_LENGTH, but which silently gives
+ * a nonsensical result if called with a pointer rather than an array. */
+#define ARRAY_LENGTH_UNSAFE( array ) \
+ ( sizeof( array ) / sizeof( *( array ) ) )
+
#if defined(__GNUC__)
/* Test if arg and &(arg)[0] have the same type. This is true if arg is
* an array but not if it's a pointer. */
#define IS_ARRAY_NOT_POINTER( arg ) \
( ! __builtin_types_compatible_p( __typeof__( arg ), \
__typeof__( &( arg )[0] ) ) )
-#else
-/* On platforms where we don't know how to implement this check,
- * omit it. Oh well, a non-portable check is better than nothing. */
-#define IS_ARRAY_NOT_POINTER( arg ) 1
-#endif
-
/* A compile-time constant with the value 0. If `const_expr` is not a
* compile-time constant with a nonzero value, cause a compile-time error. */
#define STATIC_ASSERT_EXPR( const_expr ) \
( 0 && sizeof( struct { unsigned int STATIC_ASSERT : 1 - 2 * ! ( const_expr ); } ) )
+
/* Return the scalar value `value` (possibly promoted). This is a compile-time
* constant if `value` is. `condition` must be a compile-time constant.
* If `condition` is false, arrange to cause a compile-time error. */
#define STATIC_ASSERT_THEN_RETURN( condition, value ) \
( STATIC_ASSERT_EXPR( condition ) ? 0 : ( value ) )
-#define ARRAY_LENGTH_UNSAFE( array ) \
- ( sizeof( array ) / sizeof( *( array ) ) )
-/** Return the number of elements of a static or stack array.
- *
- * \param array A value of array (not pointer) type.
- *
- * \return The number of elements of the array.
- */
#define ARRAY_LENGTH( array ) \
( STATIC_ASSERT_THEN_RETURN( IS_ARRAY_NOT_POINTER( array ), \
ARRAY_LENGTH_UNSAFE( array ) ) )
+#else
+/* If we aren't sure the compiler supports our non-standard tricks,
+ * fall back to the unsafe implementation. */
+#define ARRAY_LENGTH( array ) ARRAY_LENGTH_UNSAFE( array )
+#endif
+
/** Return the smaller of two values.
*
* \param x An integer-valued expression without side effects.
diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h
index b7dc4b5..9881eae 100644
--- a/tests/include/test/psa_crypto_helpers.h
+++ b/tests/include/test/psa_crypto_helpers.h
@@ -22,11 +22,73 @@
#define PSA_CRYPTO_HELPERS_H
#include "test/helpers.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
#include "test/psa_helpers.h"
#include <psa/crypto.h>
#include <psa_crypto_slot_management.h>
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+
+/* Internal function for #TEST_USES_KEY_ID. Return 1 on success, 0 on failure. */
+int mbedtls_test_uses_key_id( mbedtls_svc_key_id_t key_id );
+
+/** Destroy persistent keys recorded with #TEST_USES_KEY_ID.
+ */
+void mbedtls_test_psa_purge_key_storage( void );
+
+/** Purge the in-memory cache of persistent keys recorded with
+ * #TEST_USES_KEY_ID.
+ *
+ * Call this function before calling PSA_DONE() if it's ok for
+ * persistent keys to still exist at this point.
+ */
+void mbedtls_test_psa_purge_key_cache( void );
+
+/** \def TEST_USES_KEY_ID
+ *
+ * Call this macro in a test function before potentially creating a
+ * persistent key. Test functions that use this mechanism must call
+ * mbedtls_test_psa_purge_key_storage() in their cleanup code.
+ *
+ * This macro records a persistent key identifier as potentially used in the
+ * current test case. Recorded key identifiers will be cleaned up at the end
+ * of the test case, even on failure.
+ *
+ * This macro has no effect on volatile keys. Therefore, it is safe to call
+ * this macro in a test function that creates either volatile or persistent
+ * keys depending on the test data.
+ *
+ * This macro currently has no effect on special identifiers
+ * used to store implementation-specific files.
+ *
+ * Calling this macro multiple times on the same key identifier in the same
+ * test case has no effect.
+ *
+ * This macro can fail the test case if there isn't enough memory to
+ * record the key id.
+ *
+ * \param key_id The PSA key identifier to record.
+ */
+#define TEST_USES_KEY_ID( key_id ) \
+ TEST_ASSERT( mbedtls_test_uses_key_id( key_id ) )
+
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+
+#define TEST_USES_KEY_ID( key_id ) ( (void) ( key_id ) )
+#define mbedtls_test_psa_purge_key_storage( ) ( (void) 0 )
+#define mbedtls_test_psa_purge_key_cache( ) ( (void) 0 )
+
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+
+#define PSA_INIT( ) PSA_ASSERT( psa_crypto_init( ) )
+
/** Check for things that have not been cleaned up properly in the
* PSA subsystem.
*
@@ -51,13 +113,36 @@
} \
while( 0 )
-/** Shut down the PSA Crypto subsystem. Expect a clean shutdown, with no slots
- * in use.
+/** Shut down the PSA Crypto subsystem and destroy persistent keys.
+ * Expect a clean shutdown, with no slots in use.
+ *
+ * If some key slots are still in use, record the test case as failed,
+ * but continue executing. This macro is suitable (and primarily intended)
+ * for use in the cleanup section of test functions.
+ *
+ * \note Persistent keys must be recorded with #TEST_USES_KEY_ID before
+ * creating them.
*/
#define PSA_DONE( ) \
do \
{ \
test_fail_if_psa_leaking( __LINE__, __FILE__ ); \
+ mbedtls_test_psa_purge_key_storage( ); \
+ mbedtls_psa_crypto_free( ); \
+ } \
+ while( 0 )
+
+/** Shut down the PSA Crypto subsystem, allowing persistent keys to survive.
+ * Expect a clean shutdown, with no slots in use.
+ *
+ * If some key slots are still in use, record the test case as failed and
+ * jump to the `exit` label.
+ */
+#define PSA_SESSION_DONE( ) \
+ do \
+ { \
+ mbedtls_test_psa_purge_key_cache( ); \
+ ASSERT_PSA_PRISTINE( ); \
mbedtls_psa_crypto_free( ); \
} \
while( 0 )
@@ -185,4 +270,29 @@
} \
while( 0 )
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+/** \def USE_PSA_INIT
+ *
+ * Call this macro to initialize the PSA subsystem if #MBEDTLS_USE_PSA_CRYPTO
+ * is enabled and do nothing otherwise. If the initialization fails, mark
+ * the test case as failed and jump to the \p exit label.
+ */
+/** \def USE_PSA_DONE
+ *
+ * Call this macro at the end of a test case if you called #USE_PSA_INIT.
+ * This is like #PSA_DONE, except that it does nothing if
+ * #MBEDTLS_USE_PSA_CRYPTO is disabled.
+ */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define USE_PSA_INIT( ) PSA_INIT( )
+#define USE_PSA_DONE( ) PSA_DONE( )
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+/* 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 USE_PSA_INIT( ) ( (void) 0 )
+#define USE_PSA_DONE( ) ( (void) 0 )
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+
#endif /* PSA_CRYPTO_HELPERS_H */
diff --git a/tests/include/test/psa_exercise_key.h b/tests/include/test/psa_exercise_key.h
new file mode 100644
index 0000000..57eae58
--- /dev/null
+++ b/tests/include/test/psa_exercise_key.h
@@ -0,0 +1,241 @@
+/** Code to exercise a PSA key object, i.e. validate that it seems well-formed
+ * and can do what it is supposed to do.
+ */
+/*
+ * 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_EXERCISE_KEY_H
+#define PSA_EXERCISE_KEY_H
+
+#include "test/helpers.h"
+#include "test/psa_crypto_helpers.h"
+
+#include <psa/crypto.h>
+
+/** \def KNOWN_SUPPORTED_HASH_ALG
+ *
+ * A hash algorithm that is known to be supported.
+ *
+ * This is used in some smoke tests.
+ */
+#if defined(PSA_WANT_ALG_MD2)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD2
+#elif defined(PSA_WANT_ALG_MD4)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD4
+#elif defined(PSA_WANT_ALG_MD5)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD5
+/* MBEDTLS_RIPEMD160_C omitted. This is necessary for the sake of
+ * exercise_signature_key() because Mbed TLS doesn't support RIPEMD160
+ * in RSA PKCS#1v1.5 signatures. A RIPEMD160-only configuration would be
+ * implausible anyway. */
+#elif defined(PSA_WANT_ALG_SHA_1)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_1
+#elif defined(PSA_WANT_ALG_SHA_256)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_256
+#elif defined(PSA_WANT_ALG_SHA_384)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_384
+#elif defined(PSA_WANT_ALG_SHA_512)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_512
+#elif defined(PSA_WANT_ALG_SHA3_256)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA3_256
+#else
+#undef KNOWN_SUPPORTED_HASH_ALG
+#endif
+
+/** \def KNOWN_SUPPORTED_BLOCK_CIPHER
+ *
+ * A block cipher that is known to be supported.
+ *
+ * For simplicity's sake, stick to block ciphers with 16-byte blocks.
+ */
+#if defined(MBEDTLS_AES_C)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_AES
+#elif defined(MBEDTLS_ARIA_C)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_ARIA
+#elif defined(MBEDTLS_CAMELLIA_C)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_CAMELLIA
+#undef KNOWN_SUPPORTED_BLOCK_CIPHER
+#endif
+
+/** \def KNOWN_SUPPORTED_MAC_ALG
+ *
+ * A MAC mode that is known to be supported.
+ *
+ * It must either be HMAC with #KNOWN_SUPPORTED_HASH_ALG or
+ * a block cipher-based MAC with #KNOWN_SUPPORTED_BLOCK_CIPHER.
+ *
+ * This is used in some smoke tests.
+ */
+#if defined(KNOWN_SUPPORTED_HASH_ALG) && defined(PSA_WANT_ALG_HMAC)
+#define KNOWN_SUPPORTED_MAC_ALG ( PSA_ALG_HMAC( KNOWN_SUPPORTED_HASH_ALG ) )
+#define KNOWN_SUPPORTED_MAC_KEY_TYPE PSA_KEY_TYPE_HMAC
+#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CMAC_C)
+#define KNOWN_SUPPORTED_MAC_ALG PSA_ALG_CMAC
+#define KNOWN_SUPPORTED_MAC_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
+#else
+#undef KNOWN_SUPPORTED_MAC_ALG
+#undef KNOWN_SUPPORTED_MAC_KEY_TYPE
+#endif
+
+/** \def KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
+ *
+ * A cipher algorithm and key type that are known to be supported.
+ *
+ * This is used in some smoke tests.
+ */
+#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CTR)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CTR
+#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CBC)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CBC_NO_PADDING
+#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CFB)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CFB
+#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_OFB)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_OFB
+#else
+#undef KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
+#endif
+#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER_ALG)
+#define KNOWN_SUPPORTED_CIPHER_ALG KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
+#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
+#elif defined(MBEDTLS_RC4_C)
+#define KNOWN_SUPPORTED_CIPHER_ALG PSA_ALG_RC4
+#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE PSA_KEY_TYPE_RC4
+#else
+#undef KNOWN_SUPPORTED_CIPHER_ALG
+#undef KNOWN_SUPPORTED_CIPHER_KEY_TYPE
+#endif
+
+/** Convenience function to set up a key derivation.
+ *
+ * In case of failure, mark the current test case as failed.
+ *
+ * The inputs \p input1 and \p input2 are, in order:
+ * - HKDF: salt, info.
+ * - TKS 1.2 PRF, TLS 1.2 PSK-to-MS: seed, label.
+ *
+ * \param operation The operation object to use.
+ * It must be in the initialized state.
+ * \param key The key to use.
+ * \param alg The algorithm to use.
+ * \param input1 The first input to pass.
+ * \param input1_length The length of \p input1 in bytes.
+ * \param input2 The first input to pass.
+ * \param input2_length The length of \p input2 in bytes.
+ * \param capacity The capacity to set.
+ *
+ * \return \c 1 on success, \c 0 on failure.
+ */
+int mbedtls_test_psa_setup_key_derivation_wrap(
+ psa_key_derivation_operation_t* operation,
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg,
+ const unsigned char* input1, size_t input1_length,
+ const unsigned char* input2, size_t input2_length,
+ size_t capacity );
+
+/** Perform a key agreement using the given key pair against its public key
+ * using psa_raw_key_agreement().
+ *
+ * The result is discarded. The purpose of this function is to smoke-test a key.
+ *
+ * In case of failure, mark the current test case as failed.
+ *
+ * \param alg A key agreement algorithm compatible with \p key.
+ * \param key A key that allows key agreement with \p alg.
+ *
+ * \return \c 1 on success, \c 0 on failure.
+ */
+psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
+ psa_algorithm_t alg,
+ mbedtls_svc_key_id_t key );
+
+/** Perform a key agreement using the given key pair against its public key
+ * using psa_key_derivation_raw_key().
+ *
+ * The result is discarded. The purpose of this function is to smoke-test a key.
+ *
+ * In case of failure, mark the current test case as failed.
+ *
+ * \param operation An operation that has been set up for a key
+ * agreement algorithm that is compatible with
+ * \p key.
+ * \param key A key pair object that is suitable for a key
+ * agreement with \p operation.
+ *
+ * \return \c 1 on success, \c 0 on failure.
+ */
+psa_status_t mbedtls_test_psa_key_agreement_with_self(
+ psa_key_derivation_operation_t *operation,
+ mbedtls_svc_key_id_t key );
+
+/** Perform sanity checks on the given key representation.
+ *
+ * If any of the checks fail, mark the current test case as failed.
+ *
+ * The checks depend on the key type.
+ * - All types: check the export size against maximum-size macros.
+ * - DES: parity bits.
+ * - RSA: check the ASN.1 structure and the size and parity of the integers.
+ * - ECC private or public key: exact representation length.
+ * - Montgomery public key: first byte.
+ *
+ * \param type The key type.
+ * \param bits The key size in bits.
+ * \param exported A buffer containing the key representation.
+ * \param exported_length The length of \p exported in bytes.
+ *
+ * \return \c 1 if all checks passed, \c 0 on failure.
+ */
+int mbedtls_test_psa_exported_key_sanity_check(
+ psa_key_type_t type, size_t bits,
+ const uint8_t *exported, size_t exported_length );
+
+/** Do smoke tests on a key.
+ *
+ * Perform one of each operation indicated by \p alg (decrypt/encrypt,
+ * sign/verify, or derivation) that is permitted according to \p usage.
+ * \p usage and \p alg should correspond to the expected policy on the
+ * key.
+ *
+ * Export the key if permitted by \p usage, and check that the output
+ * looks sensible. If \p usage forbids export, check that
+ * \p psa_export_key correctly rejects the attempt. If the key is
+ * asymmetric, also check \p psa_export_public_key.
+ *
+ * If the key fails the tests, this function calls the test framework's
+ * `mbedtls_test_fail` function and returns false. Otherwise this function
+ * returns true. Therefore it should be used as follows:
+ * ```
+ * if( ! exercise_key( ... ) ) goto exit;
+ * ```
+ *
+ * \param key The key to exercise. It should be capable of performing
+ * \p alg.
+ * \param usage The usage flags to assume.
+ * \param alg The algorithm to exercise.
+ *
+ * \retval 0 The key failed the smoke tests.
+ * \retval 1 The key passed the smoke tests.
+ */
+int mbedtls_test_psa_exercise_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg );
+
+psa_key_usage_t mbedtls_test_psa_usage_to_exercise( psa_key_type_t type,
+ psa_algorithm_t alg );
+
+#endif /* PSA_EXERCISE_KEY_H */
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 1036a7c..43742fd 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -922,37 +922,61 @@
if_build_succeeded tests/context-info.sh
}
-component_test_no_ctr_drbg () {
- msg "build: Full minus CTR_DRBG"
+component_test_no_ctr_drbg_classic () {
+ msg "build: Full minus CTR_DRBG, classic crypto in TLS"
scripts/config.py full
scripts/config.py unset MBEDTLS_CTR_DRBG_C
+ scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
- msg "test: Full minus CTR_DRBG - main suites"
+ msg "test: Full minus CTR_DRBG, classic crypto - main suites"
make test
# In this configuration, the TLS test programs use HMAC_DRBG.
# The SSL tests are slow, so run a small subset, just enough to get
# confidence that the SSL code copes with HMAC_DRBG.
- msg "test: Full minus CTR_DRBG - ssl-opt.sh (subset)"
+ msg "test: Full minus CTR_DRBG, classic crypto - ssl-opt.sh (subset)"
if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private.*delay=\|tickets enabled on server'
- msg "test: Full minus CTR_DRBG - compat.sh (subset)"
+ msg "test: Full minus CTR_DRBG, classic crypto - compat.sh (subset)"
if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA PSK' -V NO -p OpenSSL
}
-component_test_no_hmac_drbg () {
- msg "build: Full minus HMAC_DRBG"
+component_test_no_ctr_drbg_use_psa () {
+ msg "build: Full minus CTR_DRBG, PSA crypto in TLS"
scripts/config.py full
- scripts/config.py unset MBEDTLS_HMAC_DRBG_C
- scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
+ scripts/config.py unset MBEDTLS_CTR_DRBG_C
+ scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
- msg "test: Full minus HMAC_DRBG - main suites"
+ msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - main suites"
+ make test
+
+ # In this configuration, the TLS test programs use HMAC_DRBG.
+ # The SSL tests are slow, so run a small subset, just enough to get
+ # confidence that the SSL code copes with HMAC_DRBG.
+ msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - ssl-opt.sh (subset)"
+ if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private.*delay=\|tickets enabled on server'
+
+ msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - compat.sh (subset)"
+ if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA PSK' -V NO -p OpenSSL
+}
+
+component_test_no_hmac_drbg_classic () {
+ msg "build: Full minus HMAC_DRBG, classic crypto in TLS"
+ scripts/config.py full
+ scripts/config.py unset MBEDTLS_HMAC_DRBG_C
+ scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
+ scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+
+ CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+ make
+
+ msg "test: Full minus HMAC_DRBG, classic crypto - main suites"
make test
# Normally our ECDSA implementation uses deterministic ECDSA. But since
@@ -960,29 +984,84 @@
# instead.
# Test SSL with non-deterministic ECDSA. Only test features that
# might be affected by how ECDSA signature is performed.
- msg "test: Full minus HMAC_DRBG - ssl-opt.sh (subset)"
+ msg "test: Full minus HMAC_DRBG, classic crypto - ssl-opt.sh (subset)"
if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private: sign'
# To save time, only test one protocol version, since this part of
# the protocol is identical in (D)TLS up to 1.2.
- msg "test: Full minus HMAC_DRBG - compat.sh (ECDSA)"
+ msg "test: Full minus HMAC_DRBG, classic crypto - compat.sh (ECDSA)"
if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA'
}
-component_test_psa_external_rng_no_drbg () {
- msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG"
+component_test_no_hmac_drbg_use_psa () {
+ msg "build: Full minus HMAC_DRBG, PSA crypto in TLS"
+ scripts/config.py full
+ scripts/config.py unset MBEDTLS_HMAC_DRBG_C
+ scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
+ scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
+
+ CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+ make
+
+ msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - main suites"
+ make test
+
+ # Normally our ECDSA implementation uses deterministic ECDSA. But since
+ # HMAC_DRBG is disabled in this configuration, randomized ECDSA is used
+ # instead.
+ # Test SSL with non-deterministic ECDSA. Only test features that
+ # might be affected by how ECDSA signature is performed.
+ msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - ssl-opt.sh (subset)"
+ if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private: sign'
+
+ # To save time, only test one protocol version, since this part of
+ # the protocol is identical in (D)TLS up to 1.2.
+ msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - compat.sh (ECDSA)"
+ if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA'
+}
+
+component_test_psa_external_rng_no_drbg_classic () {
+ msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto in TLS"
+ scripts/config.py full
+ scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+ scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+ scripts/config.py unset MBEDTLS_ENTROPY_C
+ scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
+ scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
+ 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
+ # When MBEDTLS_USE_PSA_CRYPTO is disabled and there is no DRBG,
+ # the SSL test programs don't have an RNG and can't work. Explicitly
+ # make them use the PSA RNG with -DMBEDTLS_TEST_USE_PSA_CRYPTO_RNG.
+ make CFLAGS="$ASAN_CFLAGS -O2 -DMBEDTLS_TEST_USE_PSA_CRYPTO_RNG" LDFLAGS="$ASAN_CFLAGS"
+
+ msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto - main suites"
+ make test
+
+ msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto - ssl-opt.sh (subset)"
+ if_build_succeeded tests/ssl-opt.sh -f 'Default'
+}
+
+component_test_psa_external_rng_no_drbg_use_psa () {
+ msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto in TLS"
scripts/config.py full
scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+ scripts/config.py unset MBEDTLS_ENTROPY_C
+ scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
+ scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
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"
+ msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto - main suites"
make test
- # no SSL tests as they all depend on having a DRBG
+ msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto - ssl-opt.sh (subset)"
+ if_build_succeeded tests/ssl-opt.sh -f 'Default\|opaque'
}
component_test_psa_external_rng_use_psa_crypto () {
diff --git a/tests/src/asn1_helpers.c b/tests/src/asn1_helpers.c
new file mode 100644
index 0000000..79aa166
--- /dev/null
+++ b/tests/src/asn1_helpers.c
@@ -0,0 +1,74 @@
+/** \file asn1_helpers.c
+ *
+ * \brief Helper functions for tests that manipulate ASN.1 data.
+ */
+
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <test/helpers.h>
+#include <test/macros.h>
+
+#if defined(MBEDTLS_ASN1_PARSE_C)
+
+#include <mbedtls/asn1.h>
+
+int mbedtls_test_asn1_skip_integer( unsigned char **p, const unsigned char *end,
+ size_t min_bits, size_t max_bits,
+ int must_be_odd )
+{
+ size_t len;
+ size_t actual_bits;
+ unsigned char msb;
+ TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len,
+ MBEDTLS_ASN1_INTEGER ),
+ 0 );
+
+ /* Check if the retrieved length doesn't extend the actual buffer's size.
+ * It is assumed here, that end >= p, which validates casting to size_t. */
+ TEST_ASSERT( len <= (size_t)( end - *p) );
+
+ /* Tolerate a slight departure from DER encoding:
+ * - 0 may be represented by an empty string or a 1-byte string.
+ * - The sign bit may be used as a value bit. */
+ if( ( len == 1 && ( *p )[0] == 0 ) ||
+ ( len > 1 && ( *p )[0] == 0 && ( ( *p )[1] & 0x80 ) != 0 ) )
+ {
+ ++( *p );
+ --len;
+ }
+ if( min_bits == 0 && len == 0 )
+ return( 1 );
+ msb = ( *p )[0];
+ TEST_ASSERT( msb != 0 );
+ actual_bits = 8 * ( len - 1 );
+ while( msb != 0 )
+ {
+ msb >>= 1;
+ ++actual_bits;
+ }
+ TEST_ASSERT( actual_bits >= min_bits );
+ TEST_ASSERT( actual_bits <= max_bits );
+ if( must_be_odd )
+ TEST_ASSERT( ( ( *p )[len-1] & 1 ) != 0 );
+ *p += len;
+ return( 1 );
+exit:
+ return( 0 );
+}
+
+#endif /* MBEDTLS_ASN1_PARSE_C */
diff --git a/tests/src/fake_external_rng_for_test.c b/tests/src/fake_external_rng_for_test.c
index 98b3fe0..9c2195b 100644
--- a/tests/src/fake_external_rng_for_test.c
+++ b/tests/src/fake_external_rng_for_test.c
@@ -1,4 +1,4 @@
-/** \file psa_crypto_helpers.c
+/** \file fake_external_rng_for_test.c
*
* \brief Helper functions to test PSA crypto functionality.
*/
diff --git a/tests/src/psa_crypto_helpers.c b/tests/src/psa_crypto_helpers.c
index cb79a22..f2222cb 100644
--- a/tests/src/psa_crypto_helpers.c
+++ b/tests/src/psa_crypto_helpers.c
@@ -28,6 +28,51 @@
#include <psa/crypto.h>
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+
+#include <psa_crypto_storage.h>
+
+static mbedtls_svc_key_id_t key_ids_used_in_test[9];
+static size_t num_key_ids_used;
+
+int mbedtls_test_uses_key_id( mbedtls_svc_key_id_t key_id )
+{
+ size_t i;
+ if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key_id ) >
+ PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
+ {
+ /* Don't touch key id values that designate non-key files. */
+ return( 1 );
+ }
+ for( i = 0; i < num_key_ids_used ; i++ )
+ {
+ if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
+ return( 1 );
+ }
+ if( num_key_ids_used == ARRAY_LENGTH( key_ids_used_in_test ) )
+ return( 0 );
+ key_ids_used_in_test[num_key_ids_used] = key_id;
+ ++num_key_ids_used;
+ return( 1 );
+}
+
+void mbedtls_test_psa_purge_key_storage( void )
+{
+ size_t i;
+ for( i = 0; i < num_key_ids_used; i++ )
+ psa_destroy_persistent_key( key_ids_used_in_test[i] );
+ num_key_ids_used = 0;
+}
+
+void mbedtls_test_psa_purge_key_cache( void )
+{
+ size_t i;
+ for( i = 0; i < num_key_ids_used; i++ )
+ psa_purge_key( key_ids_used_in_test[i] );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+
const char *mbedtls_test_helper_is_psa_leaking( void )
{
mbedtls_psa_stats_t stats;
diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c
new file mode 100644
index 0000000..9f80d7b
--- /dev/null
+++ b/tests/src/psa_exercise_key.c
@@ -0,0 +1,875 @@
+/** Code to exercise a PSA key object, i.e. validate that it seems well-formed
+ * and can do what it is supposed to do.
+ */
+
+/*
+ * 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_exercise_key.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <mbedtls/asn1.h>
+#include <psa/crypto.h>
+
+#include <test/asn1_helpers.h>
+#include <test/psa_crypto_helpers.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+static int lifetime_is_dynamic_secure_element( psa_key_lifetime_t lifetime )
+{
+ return( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) !=
+ PSA_KEY_LOCATION_LOCAL_STORAGE );
+}
+#endif
+
+static int check_key_attributes_sanity( mbedtls_svc_key_id_t key )
+{
+ int ok = 0;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_lifetime_t lifetime;
+ mbedtls_svc_key_id_t id;
+ psa_key_type_t type;
+ size_t bits;
+
+ PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+ lifetime = psa_get_key_lifetime( &attributes );
+ id = psa_get_key_id( &attributes );
+ type = psa_get_key_type( &attributes );
+ bits = psa_get_key_bits( &attributes );
+
+ /* Persistence */
+ if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
+ {
+ TEST_ASSERT(
+ ( PSA_KEY_ID_VOLATILE_MIN <=
+ MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
+ ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <=
+ PSA_KEY_ID_VOLATILE_MAX ) );
+ }
+ else
+ {
+ TEST_ASSERT(
+ ( PSA_KEY_ID_USER_MIN <= MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
+ ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <= PSA_KEY_ID_USER_MAX ) );
+ }
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+ /* randomly-generated 64-bit constant, should never appear in test data */
+ psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
+ psa_status_t status = psa_get_key_slot_number( &attributes, &slot_number );
+ if( lifetime_is_dynamic_secure_element( lifetime ) )
+ {
+ /* Mbed Crypto currently always exposes the slot number to
+ * applications. This is not mandated by the PSA specification
+ * and may change in future versions. */
+ TEST_EQUAL( status, 0 );
+ TEST_ASSERT( slot_number != 0xec94d4a5058a1a21 );
+ }
+ else
+ {
+ TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
+ }
+#endif
+
+ /* Type and size */
+ TEST_ASSERT( type != 0 );
+ TEST_ASSERT( bits != 0 );
+ TEST_ASSERT( bits <= PSA_MAX_KEY_BITS );
+ if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
+ TEST_ASSERT( bits % 8 == 0 );
+
+ /* MAX macros concerning specific key types */
+ if( PSA_KEY_TYPE_IS_ECC( type ) )
+ TEST_ASSERT( bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS );
+ else if( PSA_KEY_TYPE_IS_RSA( type ) )
+ TEST_ASSERT( bits <= PSA_VENDOR_RSA_MAX_KEY_BITS );
+ TEST_ASSERT( PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ) <= PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE );
+
+ ok = 1;
+
+exit:
+ /*
+ * Key attributes may have been returned by psa_get_key_attributes()
+ * thus reset them as required.
+ */
+ psa_reset_key_attributes( &attributes );
+
+ return( ok );
+}
+
+static int exercise_mac_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+ const unsigned char input[] = "foo";
+ unsigned char mac[PSA_MAC_MAX_SIZE] = {0};
+ size_t mac_length = sizeof( mac );
+
+ if( usage & PSA_KEY_USAGE_SIGN_HASH )
+ {
+ PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
+ PSA_ASSERT( psa_mac_update( &operation,
+ input, sizeof( input ) ) );
+ PSA_ASSERT( psa_mac_sign_finish( &operation,
+ mac, sizeof( mac ),
+ &mac_length ) );
+ }
+
+ if( usage & PSA_KEY_USAGE_VERIFY_HASH )
+ {
+ psa_status_t verify_status =
+ ( usage & PSA_KEY_USAGE_SIGN_HASH ?
+ PSA_SUCCESS :
+ PSA_ERROR_INVALID_SIGNATURE );
+ PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
+ PSA_ASSERT( psa_mac_update( &operation,
+ input, sizeof( input ) ) );
+ TEST_EQUAL( psa_mac_verify_finish( &operation, mac, mac_length ),
+ verify_status );
+ }
+
+ return( 1 );
+
+exit:
+ psa_mac_abort( &operation );
+ return( 0 );
+}
+
+static int exercise_cipher_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+ unsigned char iv[16] = {0};
+ size_t iv_length = sizeof( iv );
+ const unsigned char plaintext[16] = "Hello, world...";
+ unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
+ size_t ciphertext_length = sizeof( ciphertext );
+ unsigned char decrypted[sizeof( ciphertext )];
+ size_t part_length;
+
+ if( usage & PSA_KEY_USAGE_ENCRYPT )
+ {
+ PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
+ PSA_ASSERT( psa_cipher_generate_iv( &operation,
+ iv, sizeof( iv ),
+ &iv_length ) );
+ PSA_ASSERT( psa_cipher_update( &operation,
+ plaintext, sizeof( plaintext ),
+ ciphertext, sizeof( ciphertext ),
+ &ciphertext_length ) );
+ PSA_ASSERT( psa_cipher_finish( &operation,
+ ciphertext + ciphertext_length,
+ sizeof( ciphertext ) - ciphertext_length,
+ &part_length ) );
+ ciphertext_length += part_length;
+ }
+
+ if( usage & PSA_KEY_USAGE_DECRYPT )
+ {
+ psa_status_t status;
+ int maybe_invalid_padding = 0;
+ if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
+ {
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+ /* This should be PSA_CIPHER_GET_IV_SIZE but the API doesn't
+ * have this macro yet. */
+ iv_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(
+ psa_get_key_type( &attributes ) );
+ maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
+ psa_reset_key_attributes( &attributes );
+ }
+ PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
+ PSA_ASSERT( psa_cipher_set_iv( &operation,
+ iv, iv_length ) );
+ PSA_ASSERT( psa_cipher_update( &operation,
+ ciphertext, ciphertext_length,
+ decrypted, sizeof( decrypted ),
+ &part_length ) );
+ status = psa_cipher_finish( &operation,
+ decrypted + part_length,
+ sizeof( decrypted ) - part_length,
+ &part_length );
+ /* For a stream cipher, all inputs are valid. For a block cipher,
+ * if the input is some aribtrary data rather than an actual
+ ciphertext, a padding error is likely. */
+ if( maybe_invalid_padding )
+ TEST_ASSERT( status == PSA_SUCCESS ||
+ status == PSA_ERROR_INVALID_PADDING );
+ else
+ PSA_ASSERT( status );
+ }
+
+ return( 1 );
+
+exit:
+ psa_cipher_abort( &operation );
+ return( 0 );
+}
+
+static int exercise_aead_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ unsigned char nonce[16] = {0};
+ size_t nonce_length = sizeof( nonce );
+ unsigned char plaintext[16] = "Hello, world...";
+ unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
+ size_t ciphertext_length = sizeof( ciphertext );
+ size_t plaintext_length = sizeof( ciphertext );
+
+ /* Default IV length for AES-GCM is 12 bytes */
+ if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
+ PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ) )
+ {
+ nonce_length = 12;
+ }
+
+ if( usage & PSA_KEY_USAGE_ENCRYPT )
+ {
+ PSA_ASSERT( psa_aead_encrypt( key, alg,
+ nonce, nonce_length,
+ NULL, 0,
+ plaintext, sizeof( plaintext ),
+ ciphertext, sizeof( ciphertext ),
+ &ciphertext_length ) );
+ }
+
+ if( usage & PSA_KEY_USAGE_DECRYPT )
+ {
+ psa_status_t verify_status =
+ ( usage & PSA_KEY_USAGE_ENCRYPT ?
+ PSA_SUCCESS :
+ PSA_ERROR_INVALID_SIGNATURE );
+ TEST_EQUAL( psa_aead_decrypt( key, alg,
+ nonce, nonce_length,
+ NULL, 0,
+ ciphertext, ciphertext_length,
+ plaintext, sizeof( plaintext ),
+ &plaintext_length ),
+ verify_status );
+ }
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+static int exercise_signature_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
+ size_t payload_length = 16;
+ unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
+ size_t signature_length = sizeof( signature );
+ psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
+
+ /* If the policy allows signing with any hash, just pick one. */
+ if( PSA_ALG_IS_HASH_AND_SIGN( alg ) && hash_alg == PSA_ALG_ANY_HASH )
+ {
+#if defined(KNOWN_SUPPORTED_HASH_ALG)
+ hash_alg = KNOWN_SUPPORTED_HASH_ALG;
+ alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
+#else
+ TEST_ASSERT( ! "No hash algorithm for hash-and-sign testing" );
+#endif
+ }
+
+ if( usage & PSA_KEY_USAGE_SIGN_HASH )
+ {
+ /* Some algorithms require the payload to have the size of
+ * the hash encoded in the algorithm. Use this input size
+ * even for algorithms that allow other input sizes. */
+ if( hash_alg != 0 )
+ payload_length = PSA_HASH_LENGTH( hash_alg );
+ PSA_ASSERT( psa_sign_hash( key, alg,
+ payload, payload_length,
+ signature, sizeof( signature ),
+ &signature_length ) );
+ }
+
+ if( usage & PSA_KEY_USAGE_VERIFY_HASH )
+ {
+ psa_status_t verify_status =
+ ( usage & PSA_KEY_USAGE_SIGN_HASH ?
+ PSA_SUCCESS :
+ PSA_ERROR_INVALID_SIGNATURE );
+ TEST_EQUAL( psa_verify_hash( key, alg,
+ payload, payload_length,
+ signature, signature_length ),
+ verify_status );
+ }
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+static int exercise_asymmetric_encryption_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ unsigned char plaintext[256] = "Hello, world...";
+ unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
+ size_t ciphertext_length = sizeof( ciphertext );
+ size_t plaintext_length = 16;
+
+ if( usage & PSA_KEY_USAGE_ENCRYPT )
+ {
+ PSA_ASSERT( psa_asymmetric_encrypt( key, alg,
+ plaintext, plaintext_length,
+ NULL, 0,
+ ciphertext, sizeof( ciphertext ),
+ &ciphertext_length ) );
+ }
+
+ if( usage & PSA_KEY_USAGE_DECRYPT )
+ {
+ psa_status_t status =
+ psa_asymmetric_decrypt( key, alg,
+ ciphertext, ciphertext_length,
+ NULL, 0,
+ plaintext, sizeof( plaintext ),
+ &plaintext_length );
+ TEST_ASSERT( status == PSA_SUCCESS ||
+ ( ( usage & PSA_KEY_USAGE_ENCRYPT ) == 0 &&
+ ( status == PSA_ERROR_INVALID_ARGUMENT ||
+ status == PSA_ERROR_INVALID_PADDING ) ) );
+ }
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+int mbedtls_test_psa_setup_key_derivation_wrap(
+ psa_key_derivation_operation_t* operation,
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg,
+ const unsigned char* input1, size_t input1_length,
+ const unsigned char* input2, size_t input2_length,
+ size_t capacity )
+{
+ PSA_ASSERT( psa_key_derivation_setup( operation, alg ) );
+ if( PSA_ALG_IS_HKDF( alg ) )
+ {
+ PSA_ASSERT( psa_key_derivation_input_bytes( operation,
+ PSA_KEY_DERIVATION_INPUT_SALT,
+ input1, input1_length ) );
+ PSA_ASSERT( psa_key_derivation_input_key( operation,
+ PSA_KEY_DERIVATION_INPUT_SECRET,
+ key ) );
+ PSA_ASSERT( psa_key_derivation_input_bytes( operation,
+ PSA_KEY_DERIVATION_INPUT_INFO,
+ input2,
+ input2_length ) );
+ }
+ else if( PSA_ALG_IS_TLS12_PRF( alg ) ||
+ PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
+ {
+ PSA_ASSERT( psa_key_derivation_input_bytes( operation,
+ PSA_KEY_DERIVATION_INPUT_SEED,
+ input1, input1_length ) );
+ PSA_ASSERT( psa_key_derivation_input_key( operation,
+ PSA_KEY_DERIVATION_INPUT_SECRET,
+ key ) );
+ PSA_ASSERT( psa_key_derivation_input_bytes( operation,
+ PSA_KEY_DERIVATION_INPUT_LABEL,
+ input2, input2_length ) );
+ }
+ else
+ {
+ TEST_ASSERT( ! "Key derivation algorithm not supported" );
+ }
+
+ if( capacity != SIZE_MAX )
+ PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+
+static int exercise_key_derivation_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+ unsigned char input1[] = "Input 1";
+ size_t input1_length = sizeof( input1 );
+ unsigned char input2[] = "Input 2";
+ size_t input2_length = sizeof( input2 );
+ unsigned char output[1];
+ size_t capacity = sizeof( output );
+
+ if( usage & PSA_KEY_USAGE_DERIVE )
+ {
+ if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
+ input1, input1_length,
+ input2, input2_length,
+ capacity ) )
+ goto exit;
+
+ PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
+ output,
+ capacity ) );
+ PSA_ASSERT( psa_key_derivation_abort( &operation ) );
+ }
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+/* We need two keys to exercise key agreement. Exercise the
+ * private key against its own public key. */
+psa_status_t mbedtls_test_psa_key_agreement_with_self(
+ psa_key_derivation_operation_t *operation,
+ mbedtls_svc_key_id_t key )
+{
+ psa_key_type_t private_key_type;
+ psa_key_type_t public_key_type;
+ size_t key_bits;
+ uint8_t *public_key = NULL;
+ size_t public_key_length;
+ /* Return GENERIC_ERROR if something other than the final call to
+ * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
+ * but it's good enough: callers will report it as a failed test anyway. */
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+ private_key_type = psa_get_key_type( &attributes );
+ key_bits = psa_get_key_bits( &attributes );
+ public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
+ public_key_length = PSA_EXPORT_KEY_OUTPUT_SIZE( public_key_type, key_bits );
+ ASSERT_ALLOC( public_key, public_key_length );
+ PSA_ASSERT( psa_export_public_key( key, public_key, public_key_length,
+ &public_key_length ) );
+
+ status = psa_key_derivation_key_agreement(
+ operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
+ public_key, public_key_length );
+exit:
+ /*
+ * Key attributes may have been returned by psa_get_key_attributes()
+ * thus reset them as required.
+ */
+ psa_reset_key_attributes( &attributes );
+
+ mbedtls_free( public_key );
+ return( status );
+}
+
+/* We need two keys to exercise key agreement. Exercise the
+ * private key against its own public key. */
+psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
+ psa_algorithm_t alg,
+ mbedtls_svc_key_id_t key )
+{
+ psa_key_type_t private_key_type;
+ psa_key_type_t public_key_type;
+ size_t key_bits;
+ uint8_t *public_key = NULL;
+ size_t public_key_length;
+ uint8_t output[1024];
+ size_t output_length;
+ /* Return GENERIC_ERROR if something other than the final call to
+ * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
+ * but it's good enough: callers will report it as a failed test anyway. */
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+ private_key_type = psa_get_key_type( &attributes );
+ key_bits = psa_get_key_bits( &attributes );
+ public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
+ public_key_length = PSA_EXPORT_KEY_OUTPUT_SIZE( public_key_type, key_bits );
+ ASSERT_ALLOC( public_key, public_key_length );
+ PSA_ASSERT( psa_export_public_key( key,
+ public_key, public_key_length,
+ &public_key_length ) );
+
+ status = psa_raw_key_agreement( alg, key,
+ public_key, public_key_length,
+ output, sizeof( output ), &output_length );
+exit:
+ /*
+ * Key attributes may have been returned by psa_get_key_attributes()
+ * thus reset them as required.
+ */
+ psa_reset_key_attributes( &attributes );
+
+ mbedtls_free( public_key );
+ return( status );
+}
+
+static int exercise_raw_key_agreement_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ int ok = 0;
+
+ if( usage & PSA_KEY_USAGE_DERIVE )
+ {
+ /* We need two keys to exercise key agreement. Exercise the
+ * private key against its own public key. */
+ PSA_ASSERT( mbedtls_test_psa_raw_key_agreement_with_self( alg, key ) );
+ }
+ ok = 1;
+
+exit:
+ return( ok );
+}
+
+static int exercise_key_agreement_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+ unsigned char output[1];
+ int ok = 0;
+
+ if( usage & PSA_KEY_USAGE_DERIVE )
+ {
+ /* We need two keys to exercise key agreement. Exercise the
+ * private key against its own public key. */
+ PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
+ PSA_ASSERT( mbedtls_test_psa_key_agreement_with_self( &operation, key ) );
+ PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
+ output,
+ sizeof( output ) ) );
+ PSA_ASSERT( psa_key_derivation_abort( &operation ) );
+ }
+ ok = 1;
+
+exit:
+ return( ok );
+}
+
+int mbedtls_test_psa_exported_key_sanity_check(
+ psa_key_type_t type, size_t bits,
+ const uint8_t *exported, size_t exported_length )
+{
+ TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_OUTPUT_SIZE( type, bits ) );
+
+ if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
+ TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
+ else
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
+ if( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
+ {
+ uint8_t *p = (uint8_t*) exported;
+ const uint8_t *end = exported + exported_length;
+ size_t len;
+ /* RSAPrivateKey ::= SEQUENCE {
+ * version INTEGER, -- must be 0
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * }
+ */
+ TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_SEQUENCE |
+ MBEDTLS_ASN1_CONSTRUCTED ), 0 );
+ TEST_EQUAL( p + len, end );
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, 0, 0, 0 ) )
+ goto exit;
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
+ goto exit;
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
+ goto exit;
+ /* Require d to be at least half the size of n. */
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits, 1 ) )
+ goto exit;
+ /* Require p and q to be at most half the size of n, rounded up. */
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
+ goto exit;
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
+ goto exit;
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
+ goto exit;
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
+ goto exit;
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
+ goto exit;
+ TEST_EQUAL( p, end );
+ }
+ else
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_ECP_C)
+ if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
+ {
+ /* Just the secret value */
+ TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
+ }
+ else
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_RSA_C)
+ if( type == PSA_KEY_TYPE_RSA_PUBLIC_KEY )
+ {
+ uint8_t *p = (uint8_t*) exported;
+ const uint8_t *end = exported + exported_length;
+ size_t len;
+ /* RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER } -- e
+ */
+ TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_SEQUENCE |
+ MBEDTLS_ASN1_CONSTRUCTED ),
+ 0 );
+ TEST_EQUAL( p + len, end );
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
+ goto exit;
+ if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
+ goto exit;
+ TEST_EQUAL( p, end );
+ }
+ else
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_ECP_C)
+ if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) )
+ {
+ if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY )
+ {
+ /* The representation of an ECC Montgomery public key is
+ * the raw compressed point */
+ TEST_EQUAL( PSA_BITS_TO_BYTES( bits ), exported_length );
+ }
+ else
+ {
+ /* The representation of an ECC Weierstrass public key is:
+ * - The byte 0x04;
+ * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
+ * - `y_P` as a `ceiling(m/8)`-byte string, big-endian;
+ * - where m is the bit size associated with the curve.
+ */
+ TEST_EQUAL( 1 + 2 * PSA_BITS_TO_BYTES( bits ), exported_length );
+ TEST_EQUAL( exported[0], 4 );
+ }
+ }
+ else
+#endif /* MBEDTLS_ECP_C */
+
+ {
+ TEST_ASSERT( ! "Sanity check not implemented for this key type" );
+ }
+
+#if defined(MBEDTLS_DES_C)
+ if( type == PSA_KEY_TYPE_DES )
+ {
+ /* Check the parity bits. */
+ unsigned i;
+ for( i = 0; i < bits / 8; i++ )
+ {
+ unsigned bit_count = 0;
+ unsigned m;
+ for( m = 1; m <= 0x100; m <<= 1 )
+ {
+ if( exported[i] & m )
+ ++bit_count;
+ }
+ TEST_ASSERT( bit_count % 2 != 0 );
+ }
+ }
+#endif
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+static int exercise_export_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage )
+{
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ uint8_t *exported = NULL;
+ size_t exported_size = 0;
+ size_t exported_length = 0;
+ int ok = 0;
+
+ PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+
+ exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
+ psa_get_key_type( &attributes ),
+ psa_get_key_bits( &attributes ) );
+ ASSERT_ALLOC( exported, exported_size );
+
+ if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
+ ! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) )
+ {
+ TEST_EQUAL( psa_export_key( key, exported,
+ exported_size, &exported_length ),
+ PSA_ERROR_NOT_PERMITTED );
+ ok = 1;
+ goto exit;
+ }
+
+ PSA_ASSERT( psa_export_key( key,
+ exported, exported_size,
+ &exported_length ) );
+ ok = mbedtls_test_psa_exported_key_sanity_check(
+ psa_get_key_type( &attributes ), psa_get_key_bits( &attributes ),
+ exported, exported_length );
+
+exit:
+ /*
+ * Key attributes may have been returned by psa_get_key_attributes()
+ * thus reset them as required.
+ */
+ psa_reset_key_attributes( &attributes );
+
+ mbedtls_free( exported );
+ return( ok );
+}
+
+static int exercise_export_public_key( mbedtls_svc_key_id_t key )
+{
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_type_t public_type;
+ uint8_t *exported = NULL;
+ size_t exported_size = 0;
+ size_t exported_length = 0;
+ int ok = 0;
+
+ PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+ if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) )
+ {
+ exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
+ psa_get_key_type( &attributes ),
+ psa_get_key_bits( &attributes ) );
+ ASSERT_ALLOC( exported, exported_size );
+
+ TEST_EQUAL( psa_export_public_key( key, exported,
+ exported_size, &exported_length ),
+ PSA_ERROR_INVALID_ARGUMENT );
+ ok = 1;
+ goto exit;
+ }
+
+ public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
+ psa_get_key_type( &attributes ) );
+ exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE( public_type,
+ psa_get_key_bits( &attributes ) );
+ ASSERT_ALLOC( exported, exported_size );
+
+ PSA_ASSERT( psa_export_public_key( key,
+ exported, exported_size,
+ &exported_length ) );
+ ok = mbedtls_test_psa_exported_key_sanity_check(
+ public_type, psa_get_key_bits( &attributes ),
+ exported, exported_length );
+
+exit:
+ /*
+ * Key attributes may have been returned by psa_get_key_attributes()
+ * thus reset them as required.
+ */
+ psa_reset_key_attributes( &attributes );
+
+ mbedtls_free( exported );
+ return( ok );
+}
+
+int mbedtls_test_psa_exercise_key( mbedtls_svc_key_id_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ int ok = 0;
+
+ if( ! check_key_attributes_sanity( key ) )
+ return( 0 );
+
+ if( alg == 0 )
+ ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
+ else if( PSA_ALG_IS_MAC( alg ) )
+ ok = exercise_mac_key( key, usage, alg );
+ else if( PSA_ALG_IS_CIPHER( alg ) )
+ ok = exercise_cipher_key( key, usage, alg );
+ else if( PSA_ALG_IS_AEAD( alg ) )
+ ok = exercise_aead_key( key, usage, alg );
+ else if( PSA_ALG_IS_SIGN( alg ) )
+ ok = exercise_signature_key( key, usage, alg );
+ else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
+ ok = exercise_asymmetric_encryption_key( key, usage, alg );
+ else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
+ ok = exercise_key_derivation_key( key, usage, alg );
+ else if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
+ ok = exercise_raw_key_agreement_key( key, usage, alg );
+ else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
+ ok = exercise_key_agreement_key( key, usage, alg );
+ else
+ TEST_ASSERT( ! "No code to exercise this category of algorithm" );
+
+ ok = ok && exercise_export_key( key, usage );
+ ok = ok && exercise_export_public_key( key );
+
+exit:
+ return( ok );
+}
+
+psa_key_usage_t mbedtls_test_psa_usage_to_exercise( psa_key_type_t type,
+ psa_algorithm_t alg )
+{
+ if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) )
+ {
+ return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
+ PSA_KEY_USAGE_VERIFY_HASH :
+ PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH );
+ }
+ else if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ||
+ PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
+ {
+ return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
+ PSA_KEY_USAGE_ENCRYPT :
+ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+ }
+ else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ||
+ PSA_ALG_IS_KEY_AGREEMENT( alg ) )
+ {
+ return( PSA_KEY_USAGE_DERIVE );
+ }
+ else
+ {
+ return( 0 );
+ }
+
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/tests/src/threading_helpers.c b/tests/src/threading_helpers.c
new file mode 100644
index 0000000..ca91b79
--- /dev/null
+++ b/tests/src/threading_helpers.c
@@ -0,0 +1,223 @@
+/** Mutex usage verification framework. */
+
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <test/helpers.h>
+#include <test/macros.h>
+
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+
+#include "mbedtls/threading.h"
+
+/** Mutex usage verification framework.
+ *
+ * The mutex usage verification code below aims to detect bad usage of
+ * Mbed TLS's mutex abstraction layer at runtime. Note that this is solely
+ * about the use of the mutex itself, not about checking whether the mutex
+ * correctly protects whatever it is supposed to protect.
+ *
+ * The normal usage of a mutex is:
+ * ```
+ * digraph mutex_states {
+ * "UNINITIALIZED"; // the initial state
+ * "IDLE";
+ * "FREED";
+ * "LOCKED";
+ * "UNINITIALIZED" -> "IDLE" [label="init"];
+ * "FREED" -> "IDLE" [label="init"];
+ * "IDLE" -> "LOCKED" [label="lock"];
+ * "LOCKED" -> "IDLE" [label="unlock"];
+ * "IDLE" -> "FREED" [label="free"];
+ * }
+ * ```
+ *
+ * All bad transitions that can be unambiguously detected are reported.
+ * An attempt to use an uninitialized mutex cannot be detected in general
+ * since the memory content may happen to denote a valid state. For the same
+ * reason, a double init cannot be detected.
+ * All-bits-zero is the state of a freed mutex, which is distinct from an
+ * initialized mutex, so attempting to use zero-initialized memory as a mutex
+ * without calling the init function is detected.
+ *
+ * The framework attempts to detect missing calls to init and free by counting
+ * calls to init and free. If there are more calls to init than free, this
+ * means that a mutex is not being freed somewhere, which is a memory leak
+ * on platforms where a mutex consumes resources other than the
+ * mbedtls_threading_mutex_t object itself. If there are more calls to free
+ * than init, this indicates a missing init, which is likely to be detected
+ * by an attempt to lock the mutex as well. A limitation of this framework is
+ * that it cannot detect scenarios where there is exactly the same number of
+ * calls to init and free but the calls don't match. A bug like this is
+ * unlikely to happen uniformly throughout the whole test suite though.
+ *
+ * If an error is detected, this framework will report what happened and the
+ * test case will be marked as failed. Unfortunately, the error report cannot
+ * indicate the exact location of the problematic call. To locate the error,
+ * use a debugger and set a breakpoint on mbedtls_test_mutex_usage_error().
+ */
+enum value_of_mutex_is_valid_field
+{
+ /* Potential values for the is_valid field of mbedtls_threading_mutex_t.
+ * Note that MUTEX_FREED must be 0 and MUTEX_IDLE must be 1 for
+ * compatibility with threading_mutex_init_pthread() and
+ * threading_mutex_free_pthread(). MUTEX_LOCKED could be any nonzero
+ * value. */
+ MUTEX_FREED = 0, //!< Set by threading_mutex_free_pthread
+ MUTEX_IDLE = 1, //!< Set by threading_mutex_init_pthread and by our unlock
+ MUTEX_LOCKED = 2, //!< Set by our lock
+};
+
+typedef struct
+{
+ void (*init)( mbedtls_threading_mutex_t * );
+ void (*free)( mbedtls_threading_mutex_t * );
+ int (*lock)( mbedtls_threading_mutex_t * );
+ int (*unlock)( mbedtls_threading_mutex_t * );
+} mutex_functions_t;
+static mutex_functions_t mutex_functions;
+
+/** The total number of calls to mbedtls_mutex_init(), minus the total number
+ * of calls to mbedtls_mutex_free().
+ *
+ * Reset to 0 after each test case.
+ */
+static int live_mutexes;
+
+static void mbedtls_test_mutex_usage_error( mbedtls_threading_mutex_t *mutex,
+ const char *msg )
+{
+ (void) mutex;
+ if( mbedtls_test_info.mutex_usage_error == NULL )
+ mbedtls_test_info.mutex_usage_error = msg;
+ mbedtls_fprintf( stdout, "[mutex: %s] ", msg );
+ /* Don't mark the test as failed yet. This way, if the test fails later
+ * for a functional reason, the test framework will report the message
+ * and location for this functional reason. If the test passes,
+ * mbedtls_test_mutex_usage_check() will mark it as failed. */
+}
+
+static void mbedtls_test_wrap_mutex_init( mbedtls_threading_mutex_t *mutex )
+{
+ mutex_functions.init( mutex );
+ if( mutex->is_valid )
+ ++live_mutexes;
+}
+
+static void mbedtls_test_wrap_mutex_free( mbedtls_threading_mutex_t *mutex )
+{
+ switch( mutex->is_valid )
+ {
+ case MUTEX_FREED:
+ mbedtls_test_mutex_usage_error( mutex, "free without init or double free" );
+ break;
+ case MUTEX_IDLE:
+ /* Do nothing. The underlying free function will reset is_valid
+ * to 0. */
+ break;
+ case MUTEX_LOCKED:
+ mbedtls_test_mutex_usage_error( mutex, "free without unlock" );
+ break;
+ default:
+ mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
+ break;
+ }
+ if( mutex->is_valid )
+ --live_mutexes;
+ mutex_functions.free( mutex );
+}
+
+static int mbedtls_test_wrap_mutex_lock( mbedtls_threading_mutex_t *mutex )
+{
+ int ret = mutex_functions.lock( mutex );
+ switch( mutex->is_valid )
+ {
+ case MUTEX_FREED:
+ mbedtls_test_mutex_usage_error( mutex, "lock without init" );
+ break;
+ case MUTEX_IDLE:
+ if( ret == 0 )
+ mutex->is_valid = 2;
+ break;
+ case MUTEX_LOCKED:
+ mbedtls_test_mutex_usage_error( mutex, "double lock" );
+ break;
+ default:
+ mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
+ break;
+ }
+ return( ret );
+}
+
+static int mbedtls_test_wrap_mutex_unlock( mbedtls_threading_mutex_t *mutex )
+{
+ int ret = mutex_functions.unlock( mutex );
+ switch( mutex->is_valid )
+ {
+ case MUTEX_FREED:
+ mbedtls_test_mutex_usage_error( mutex, "unlock without init" );
+ break;
+ case MUTEX_IDLE:
+ mbedtls_test_mutex_usage_error( mutex, "unlock without lock" );
+ break;
+ case MUTEX_LOCKED:
+ if( ret == 0 )
+ mutex->is_valid = MUTEX_IDLE;
+ break;
+ default:
+ mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
+ break;
+ }
+ return( ret );
+}
+
+void mbedtls_test_mutex_usage_init( void )
+{
+ mutex_functions.init = mbedtls_mutex_init;
+ mutex_functions.free = mbedtls_mutex_free;
+ mutex_functions.lock = mbedtls_mutex_lock;
+ mutex_functions.unlock = mbedtls_mutex_unlock;
+ mbedtls_mutex_init = &mbedtls_test_wrap_mutex_init;
+ mbedtls_mutex_free = &mbedtls_test_wrap_mutex_free;
+ mbedtls_mutex_lock = &mbedtls_test_wrap_mutex_lock;
+ mbedtls_mutex_unlock = &mbedtls_test_wrap_mutex_unlock;
+}
+
+void mbedtls_test_mutex_usage_check( void )
+{
+ if( live_mutexes != 0 )
+ {
+ /* A positive number (more init than free) means that a mutex resource
+ * is leaking (on platforms where a mutex consumes more than the
+ * mbedtls_threading_mutex_t object itself). The rare case of a
+ * negative number means a missing init somewhere. */
+ mbedtls_fprintf( stdout, "[mutex: %d leaked] ", live_mutexes );
+ live_mutexes = 0;
+ if( mbedtls_test_info.mutex_usage_error == NULL )
+ mbedtls_test_info.mutex_usage_error = "missing free";
+ }
+ if( mbedtls_test_info.mutex_usage_error != NULL &&
+ mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED )
+ {
+ /* Functionally, the test passed. But there was a mutex usage error,
+ * so mark the test as failed after all. */
+ mbedtls_test_fail( "Mutex usage error", __LINE__, __FILE__ );
+ }
+ mbedtls_test_info.mutex_usage_error = NULL;
+}
+
+#endif /* MBEDTLS_TEST_MUTEX_USAGE */
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index ebe2f06..91ad925 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -5,9 +5,7 @@
#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>
diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function
index 3138c33..d83d751 100644
--- a/tests/suites/host_test.function
+++ b/tests/suites/host_test.function
@@ -360,8 +360,6 @@
/**
* \brief Tests snprintf implementation.
*
- * \param none
- *
* \return 0 for success else 1
*/
static int run_test_snprintf( void )
@@ -428,8 +426,8 @@
* \param unmet_dependencies The array of unmet dependencies.
* \param missing_unmet_dependencies Non-zero if there was a problem tracking
* all unmet dependencies, 0 otherwise.
- * \param ret The test dispatch status (DISPATCH_xxx).
- * \param mbedtls_test_info A pointer to the test info structure.
+ * \param ret The test dispatch status (DISPATCH_xxx).
+ * \param info A pointer to the test info structure.
*/
static void write_outcome_result( FILE *outcome_file,
size_t unmet_dep_count,
@@ -536,6 +534,10 @@
mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof( alloc_buf ) );
#endif
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+ mbedtls_test_mutex_usage_init( );
+#endif
+
/*
* The C standard doesn't guarantee that all-bits-0 is the representation
* of a NULL pointer. We do however use that in our code for initializing
diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function
index 57395ae..36a7d23 100644
--- a/tests/suites/main_test.function
+++ b/tests/suites/main_test.function
@@ -105,7 +105,7 @@
* Identifiers and check code is generated by script:
* $generator_script
*
- * \param exp_id Dependency identifier.
+ * \param dep_id Dependency identifier.
*
* \return DEPENDENCY_SUPPORTED if set else DEPENDENCY_NOT_SUPPORTED
*/
@@ -129,13 +129,17 @@
/**
* \brief Function pointer type for test function wrappers.
*
+ * A test function wrapper decodes the parameters and passes them to the
+ * underlying test function. Both the wrapper and the underlying function
+ * return void. Test wrappers assume that they are passed a suitable
+ * parameter array and do not perform any error detection.
*
- * \param void ** Pointer to void pointers. Represents an array of test
- * function parameters.
- *
- * \return void
+ * \param param_array The array of parameters. Each element is a `void *`
+ * which the wrapper casts to the correct type and
+ * dereferences. Each wrapper function hard-codes the
+ * number and types of the parameters.
*/
-typedef void (*TestWrapper_t)( void ** );
+typedef void (*TestWrapper_t)( void **param_array );
/**
@@ -158,8 +162,8 @@
* parameter failure callback, to be used. Calls to setjmp()
* can invalidate the state of any local auto variables.
*
- * \param fp Function pointer to the test function
- * \param params Parameters to pass
+ * \param fp Function pointer to the test function.
+ * \param params Parameters to pass to the #TestWrapper_t wrapper function.
*
*/
void execute_function_ptr(TestWrapper_t fp, void **params)
@@ -188,12 +192,18 @@
#else
fp( params );
#endif
+
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+ mbedtls_test_mutex_usage_check( );
+#endif /* MBEDTLS_TEST_MUTEX_USAGE */
}
/**
* \brief Dispatches test functions based on function index.
*
- * \param exp_id Test function index.
+ * \param func_idx Test function index.
+ * \param params The array of parameters to pass to the test function.
+ * It will be decoded by the #TestWrapper_t wrapper function.
*
* \return DISPATCH_TEST_SUCCESS if found
* DISPATCH_TEST_FN_NOT_FOUND if not found
@@ -222,9 +232,10 @@
/**
- * \brief Checks if test function is supported
+ * \brief Checks if test function is supported in this build-time
+ * configuration.
*
- * \param exp_id Test function index.
+ * \param func_idx Test function index.
*
* \return DISPATCH_TEST_SUCCESS if found
* DISPATCH_TEST_FN_NOT_FOUND if not found
diff --git a/tests/suites/test_suite_ccm.function b/tests/suites/test_suite_ccm.function
index faa7e13..5a3726e 100644
--- a/tests/suites/test_suite_ccm.function
+++ b/tests/suites/test_suite_ccm.function
@@ -201,12 +201,11 @@
unsigned char iv[13];
unsigned char result[50];
mbedtls_ccm_context ctx;
- size_t i, iv_len, tag_len;
+ size_t iv_len, tag_len;
int ret;
mbedtls_ccm_init( &ctx );
- memset( iv, 0x00, sizeof( iv ) );
memset( result, 0x00, sizeof( result ) );
if( sec_level % 4 == 0)
@@ -214,12 +213,10 @@
else
tag_len = 1 << ( sec_level % 4 + 1);
- for( i = 0; i < source_address->len; i++ )
- iv[i] = source_address->x[i];
-
- for( i = 0; i < frame_counter->len; i++ )
- iv[source_address->len + i] = frame_counter->x[i];
-
+ TEST_ASSERT( source_address->len == 8 );
+ TEST_ASSERT( frame_counter->len == 4 );
+ memcpy( iv, source_address->x, source_address->len );
+ memcpy( iv + source_address->len, frame_counter->x, frame_counter->len );
iv[source_address->len + frame_counter->len] = sec_level;
iv_len = sizeof( iv );
@@ -254,7 +251,7 @@
unsigned char iv[13];
unsigned char result[50];
mbedtls_ccm_context ctx;
- size_t i, iv_len, tag_len;
+ size_t iv_len, tag_len;
int ret;
mbedtls_ccm_init( &ctx );
@@ -267,12 +264,10 @@
else
tag_len = 1 << ( sec_level % 4 + 1);
- for( i = 0; i < source_address->len; i++ )
- iv[i] = source_address->x[i];
-
- for( i = 0; i < frame_counter->len; i++ )
- iv[source_address->len + i] = frame_counter->x[i];
-
+ TEST_ASSERT( source_address->len == 8 );
+ TEST_ASSERT( frame_counter->len == 4 );
+ memcpy( iv, source_address->x, source_address->len );
+ memcpy( iv + source_address->len, frame_counter->x, frame_counter->len );
iv[source_address->len + frame_counter->len] = sec_level;
iv_len = sizeof( iv );
diff --git a/tests/suites/test_suite_entropy.data b/tests/suites/test_suite_entropy.data
index b2d20b4..2ce01fa 100644
--- a/tests/suites/test_suite_entropy.data
+++ b/tests/suites/test_suite_entropy.data
@@ -1,3 +1,9 @@
+Entropy init-free-free
+entropy_init_free:0
+
+Entropy init-free-init-free
+entropy_init_free:1
+
Create NV seed_file
nv_seed_file_create:
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index d9ea441..ad9b5a4 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -134,6 +134,28 @@
* END_DEPENDENCIES
*/
+/* BEGIN_CASE */
+void entropy_init_free( int reinit )
+{
+ mbedtls_entropy_context ctx;
+
+ /* Double free is not explicitly documented to work, but it is convenient
+ * to call mbedtls_entropy_free() unconditionally on an error path without
+ * checking whether it has already been called in the success path. */
+
+ mbedtls_entropy_init( &ctx );
+ mbedtls_entropy_free( &ctx );
+
+ if( reinit )
+ mbedtls_entropy_init( &ctx );
+ mbedtls_entropy_free( &ctx );
+
+ /* This test case always succeeds, functionally speaking. A plausible
+ * bug might trigger an invalid pointer dereference or a memory leak. */
+ goto exit;
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
void entropy_seed_file( char * path, int ret )
{
@@ -217,6 +239,9 @@
for( j = len; j < sizeof( buf ); j++ )
TEST_ASSERT( acc[j] == 0 );
+
+exit:
+ mbedtls_entropy_free( &ctx );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 577fb47..bc469b6 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -15,18 +15,6 @@
* unconditionally (https://github.com/ARMmbed/mbedtls/issues/2023). */
#include "psa/crypto.h"
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "mbedtls/psa_util.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
-
#define RSA_KEY_SIZE 512
#define RSA_KEY_LEN 64
@@ -208,7 +196,7 @@
mbedtls_pk_free( &pk ); /* redundant except upon error */
mbedtls_pk_free( &pk2 );
- PSA_DONE( );
+ USE_PSA_DONE( );
}
/* END_CASE */
@@ -770,7 +758,7 @@
mbedtls_ecp_keypair *eckey;
mbedtls_pk_init( &pk );
- PSA_INIT( );
+ USE_PSA_INIT( );
TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( type ) ) == 0 );
@@ -787,7 +775,7 @@
exit:
mbedtls_pk_free( &pk );
- PSA_DONE( );
+ USE_PSA_DONE( );
}
/* END_CASE */
@@ -911,7 +899,7 @@
#endif
mbedtls_pk_init( &pk );
- PSA_INIT( );
+ USE_PSA_INIT( );
memset( hash, 0x2a, sizeof hash );
memset( sig, 0, sizeof sig );
@@ -973,7 +961,7 @@
mbedtls_pk_restart_free( rs_ctx );
#endif
mbedtls_pk_free( &pk );
- PSA_DONE( );
+ USE_PSA_DONE( );
}
/* END_CASE */
@@ -1302,6 +1290,6 @@
psa_reset_key_attributes( &attributes );
mbedtls_pk_free( &pk );
- PSA_DONE( );
+ USE_PSA_DONE( );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 93f41b5..7ae6725 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -12,110 +12,13 @@
#include "psa/crypto.h"
#include "psa_crypto_slot_management.h"
+#include "test/asn1_helpers.h"
#include "test/psa_crypto_helpers.h"
+#include "test/psa_exercise_key.h"
/** An invalid export length that will never be set by psa_export_key(). */
static const size_t INVALID_EXPORT_LENGTH = ~0U;
-/* A hash algorithm that is known to be supported.
- *
- * This is used in some smoke tests.
- */
-#if defined(PSA_WANT_ALG_MD2)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD2
-#elif defined(PSA_WANT_ALG_MD4)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD4
-#elif defined(PSA_WANT_ALG_MD5)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD5
-/* MBEDTLS_RIPEMD160_C omitted. This is necessary for the sake of
- * exercise_signature_key() because Mbed TLS doesn't support RIPEMD160
- * in RSA PKCS#1v1.5 signatures. A RIPEMD160-only configuration would be
- * implausible anyway. */
-#elif defined(PSA_WANT_ALG_SHA_1)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_1
-#elif defined(PSA_WANT_ALG_SHA_256)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_256
-#elif defined(PSA_WANT_ALG_SHA_384)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_384
-#elif defined(PSA_WANT_ALG_SHA_512)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_512
-#elif defined(PSA_WANT_ALG_SHA3_256)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA3_256
-#else
-#undef KNOWN_SUPPORTED_HASH_ALG
-#endif
-
-/* A block cipher that is known to be supported.
- *
- * For simplicity's sake, stick to block ciphers with 16-byte blocks.
- */
-#if defined(MBEDTLS_AES_C)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_AES
-#elif defined(MBEDTLS_ARIA_C)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_ARIA
-#elif defined(MBEDTLS_CAMELLIA_C)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_CAMELLIA
-#undef KNOWN_SUPPORTED_BLOCK_CIPHER
-#endif
-
-/* A MAC mode that is known to be supported.
- *
- * It must either be HMAC with #KNOWN_SUPPORTED_HASH_ALG or
- * a block cipher-based MAC with #KNOWN_SUPPORTED_BLOCK_CIPHER.
- *
- * This is used in some smoke tests.
- */
-#if defined(KNOWN_SUPPORTED_HASH_ALG) && defined(PSA_WANT_ALG_HMAC)
-#define KNOWN_SUPPORTED_MAC_ALG ( PSA_ALG_HMAC( KNOWN_SUPPORTED_HASH_ALG ) )
-#define KNOWN_SUPPORTED_MAC_KEY_TYPE PSA_KEY_TYPE_HMAC
-#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CMAC_C)
-#define KNOWN_SUPPORTED_MAC_ALG PSA_ALG_CMAC
-#define KNOWN_SUPPORTED_MAC_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
-#else
-#undef KNOWN_SUPPORTED_MAC_ALG
-#undef KNOWN_SUPPORTED_MAC_KEY_TYPE
-#endif
-
-/* A cipher algorithm and key type that are known to be supported.
- *
- * This is used in some smoke tests.
- */
-#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CTR)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CTR
-#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CBC)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CBC_NO_PADDING
-#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CFB)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CFB
-#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_OFB)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_OFB
-#else
-#undef KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
-#endif
-#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER_ALG)
-#define KNOWN_SUPPORTED_CIPHER_ALG KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
-#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
-#elif defined(MBEDTLS_RC4_C)
-#define KNOWN_SUPPORTED_CIPHER_ALG PSA_ALG_RC4
-#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE PSA_KEY_TYPE_RC4
-#else
-#undef KNOWN_SUPPORTED_CIPHER_ALG
-#undef KNOWN_SUPPORTED_CIPHER_KEY_TYPE
-#endif
-
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-int lifetime_is_dynamic_secure_element( psa_key_lifetime_t lifetime )
-{
- return( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) !=
- PSA_KEY_LOCATION_LOCAL_STORAGE );
-}
-#else
-int lifetime_is_secure_element( psa_key_lifetime_t lifetime )
-{
- (void) lifetime;
- return( 0 );
-}
-#endif
-
/** Test if a buffer contains a constant byte value.
*
* `mem_is_char(buffer, c, size)` is true after `memset(buffer, c, size)`.
@@ -222,80 +125,6 @@
return( len );
}
-int check_key_attributes_sanity( mbedtls_svc_key_id_t key )
-{
- int ok = 0;
- psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- psa_key_lifetime_t lifetime;
- mbedtls_svc_key_id_t id;
- psa_key_type_t type;
- psa_key_type_t bits;
-
- PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
- lifetime = psa_get_key_lifetime( &attributes );
- id = psa_get_key_id( &attributes );
- type = psa_get_key_type( &attributes );
- bits = psa_get_key_bits( &attributes );
-
- /* Persistence */
- if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
- {
- TEST_ASSERT(
- ( PSA_KEY_ID_VOLATILE_MIN <=
- MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
- ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <=
- PSA_KEY_ID_VOLATILE_MAX ) );
- }
- else
- {
- TEST_ASSERT(
- ( PSA_KEY_ID_USER_MIN <= MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
- ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <= PSA_KEY_ID_USER_MAX ) );
- }
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
- /* randomly-generated 64-bit constant, should never appear in test data */
- psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
- psa_status_t status = psa_get_key_slot_number( &attributes, &slot_number );
- if( lifetime_is_dynamic_secure_element( lifetime ) )
- {
- /* Mbed Crypto currently always exposes the slot number to
- * applications. This is not mandated by the PSA specification
- * and may change in future versions. */
- TEST_EQUAL( status, 0 );
- TEST_ASSERT( slot_number != 0xec94d4a5058a1a21 );
- }
- else
- {
- TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
- }
-#endif
-
- /* Type and size */
- TEST_ASSERT( type != 0 );
- TEST_ASSERT( bits != 0 );
- TEST_ASSERT( bits <= PSA_MAX_KEY_BITS );
- if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
- TEST_ASSERT( bits % 8 == 0 );
-
- /* MAX macros concerning specific key types */
- if( PSA_KEY_TYPE_IS_ECC( type ) )
- TEST_ASSERT( bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS );
- else if( PSA_KEY_TYPE_IS_RSA( type ) )
- TEST_ASSERT( bits <= PSA_VENDOR_RSA_MAX_KEY_BITS );
- TEST_ASSERT( PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ) <= PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE );
-
- ok = 1;
-
-exit:
- /*
- * Key attributes may have been returned by psa_get_key_attributes()
- * thus reset them as required.
- */
- psa_reset_key_attributes( &attributes );
-
- return( ok );
-}
-
int exercise_mac_setup( psa_key_type_t key_type,
const unsigned char *key_bytes,
size_t key_length,
@@ -363,853 +192,6 @@
return( 0 );
}
-static int exercise_mac_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
- const unsigned char input[] = "foo";
- unsigned char mac[PSA_MAC_MAX_SIZE] = {0};
- size_t mac_length = sizeof( mac );
-
- if( usage & PSA_KEY_USAGE_SIGN_HASH )
- {
- PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
- PSA_ASSERT( psa_mac_update( &operation,
- input, sizeof( input ) ) );
- PSA_ASSERT( psa_mac_sign_finish( &operation,
- mac, sizeof( mac ),
- &mac_length ) );
- }
-
- if( usage & PSA_KEY_USAGE_VERIFY_HASH )
- {
- psa_status_t verify_status =
- ( usage & PSA_KEY_USAGE_SIGN_HASH ?
- PSA_SUCCESS :
- PSA_ERROR_INVALID_SIGNATURE );
- PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
- PSA_ASSERT( psa_mac_update( &operation,
- input, sizeof( input ) ) );
- TEST_EQUAL( psa_mac_verify_finish( &operation, mac, mac_length ),
- verify_status );
- }
-
- return( 1 );
-
-exit:
- psa_mac_abort( &operation );
- return( 0 );
-}
-
-static int exercise_cipher_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
- unsigned char iv[16] = {0};
- size_t iv_length = sizeof( iv );
- const unsigned char plaintext[16] = "Hello, world...";
- unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
- size_t ciphertext_length = sizeof( ciphertext );
- unsigned char decrypted[sizeof( ciphertext )];
- size_t part_length;
-
- if( usage & PSA_KEY_USAGE_ENCRYPT )
- {
- PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
- PSA_ASSERT( psa_cipher_generate_iv( &operation,
- iv, sizeof( iv ),
- &iv_length ) );
- PSA_ASSERT( psa_cipher_update( &operation,
- plaintext, sizeof( plaintext ),
- ciphertext, sizeof( ciphertext ),
- &ciphertext_length ) );
- PSA_ASSERT( psa_cipher_finish( &operation,
- ciphertext + ciphertext_length,
- sizeof( ciphertext ) - ciphertext_length,
- &part_length ) );
- ciphertext_length += part_length;
- }
-
- if( usage & PSA_KEY_USAGE_DECRYPT )
- {
- psa_status_t status;
- int maybe_invalid_padding = 0;
- if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
- {
- psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
- /* This should be PSA_CIPHER_GET_IV_SIZE but the API doesn't
- * have this macro yet. */
- iv_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(
- psa_get_key_type( &attributes ) );
- maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
- psa_reset_key_attributes( &attributes );
- }
- PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
- PSA_ASSERT( psa_cipher_set_iv( &operation,
- iv, iv_length ) );
- PSA_ASSERT( psa_cipher_update( &operation,
- ciphertext, ciphertext_length,
- decrypted, sizeof( decrypted ),
- &part_length ) );
- status = psa_cipher_finish( &operation,
- decrypted + part_length,
- sizeof( decrypted ) - part_length,
- &part_length );
- /* For a stream cipher, all inputs are valid. For a block cipher,
- * if the input is some aribtrary data rather than an actual
- ciphertext, a padding error is likely. */
- if( maybe_invalid_padding )
- TEST_ASSERT( status == PSA_SUCCESS ||
- status == PSA_ERROR_INVALID_PADDING );
- else
- PSA_ASSERT( status );
- }
-
- return( 1 );
-
-exit:
- psa_cipher_abort( &operation );
- return( 0 );
-}
-
-static int exercise_aead_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- unsigned char nonce[16] = {0};
- size_t nonce_length = sizeof( nonce );
- unsigned char plaintext[16] = "Hello, world...";
- unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
- size_t ciphertext_length = sizeof( ciphertext );
- size_t plaintext_length = sizeof( ciphertext );
-
- /* Default IV length for AES-GCM is 12 bytes */
- if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
- PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ) )
- {
- nonce_length = 12;
- }
-
- if( usage & PSA_KEY_USAGE_ENCRYPT )
- {
- PSA_ASSERT( psa_aead_encrypt( key, alg,
- nonce, nonce_length,
- NULL, 0,
- plaintext, sizeof( plaintext ),
- ciphertext, sizeof( ciphertext ),
- &ciphertext_length ) );
- }
-
- if( usage & PSA_KEY_USAGE_DECRYPT )
- {
- psa_status_t verify_status =
- ( usage & PSA_KEY_USAGE_ENCRYPT ?
- PSA_SUCCESS :
- PSA_ERROR_INVALID_SIGNATURE );
- TEST_EQUAL( psa_aead_decrypt( key, alg,
- nonce, nonce_length,
- NULL, 0,
- ciphertext, ciphertext_length,
- plaintext, sizeof( plaintext ),
- &plaintext_length ),
- verify_status );
- }
-
- return( 1 );
-
-exit:
- return( 0 );
-}
-
-static int exercise_signature_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
- size_t payload_length = 16;
- unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
- size_t signature_length = sizeof( signature );
- psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
-
- /* If the policy allows signing with any hash, just pick one. */
- if( PSA_ALG_IS_HASH_AND_SIGN( alg ) && hash_alg == PSA_ALG_ANY_HASH )
- {
-#if defined(KNOWN_SUPPORTED_HASH_ALG)
- hash_alg = KNOWN_SUPPORTED_HASH_ALG;
- alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
-#else
- mbedtls_test_fail( "No hash algorithm for hash-and-sign testing",
- __LINE__, __FILE__ );
- return( 1 );
-#endif
- }
-
- if( usage & PSA_KEY_USAGE_SIGN_HASH )
- {
- /* Some algorithms require the payload to have the size of
- * the hash encoded in the algorithm. Use this input size
- * even for algorithms that allow other input sizes. */
- if( hash_alg != 0 )
- payload_length = PSA_HASH_LENGTH( hash_alg );
- PSA_ASSERT( psa_sign_hash( key, alg,
- payload, payload_length,
- signature, sizeof( signature ),
- &signature_length ) );
- }
-
- if( usage & PSA_KEY_USAGE_VERIFY_HASH )
- {
- psa_status_t verify_status =
- ( usage & PSA_KEY_USAGE_SIGN_HASH ?
- PSA_SUCCESS :
- PSA_ERROR_INVALID_SIGNATURE );
- TEST_EQUAL( psa_verify_hash( key, alg,
- payload, payload_length,
- signature, signature_length ),
- verify_status );
- }
-
- return( 1 );
-
-exit:
- return( 0 );
-}
-
-static int exercise_asymmetric_encryption_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- unsigned char plaintext[256] = "Hello, world...";
- unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
- size_t ciphertext_length = sizeof( ciphertext );
- size_t plaintext_length = 16;
-
- if( usage & PSA_KEY_USAGE_ENCRYPT )
- {
- PSA_ASSERT( psa_asymmetric_encrypt( key, alg,
- plaintext, plaintext_length,
- NULL, 0,
- ciphertext, sizeof( ciphertext ),
- &ciphertext_length ) );
- }
-
- if( usage & PSA_KEY_USAGE_DECRYPT )
- {
- psa_status_t status =
- psa_asymmetric_decrypt( key, alg,
- ciphertext, ciphertext_length,
- NULL, 0,
- plaintext, sizeof( plaintext ),
- &plaintext_length );
- TEST_ASSERT( status == PSA_SUCCESS ||
- ( ( usage & PSA_KEY_USAGE_ENCRYPT ) == 0 &&
- ( status == PSA_ERROR_INVALID_ARGUMENT ||
- status == PSA_ERROR_INVALID_PADDING ) ) );
- }
-
- return( 1 );
-
-exit:
- return( 0 );
-}
-
-static int setup_key_derivation_wrap( psa_key_derivation_operation_t* operation,
- mbedtls_svc_key_id_t key,
- psa_algorithm_t alg,
- unsigned char* input1, size_t input1_length,
- unsigned char* input2, size_t input2_length,
- size_t capacity )
-{
- PSA_ASSERT( psa_key_derivation_setup( operation, alg ) );
- if( PSA_ALG_IS_HKDF( alg ) )
- {
- PSA_ASSERT( psa_key_derivation_input_bytes( operation,
- PSA_KEY_DERIVATION_INPUT_SALT,
- input1, input1_length ) );
- PSA_ASSERT( psa_key_derivation_input_key( operation,
- PSA_KEY_DERIVATION_INPUT_SECRET,
- key ) );
- PSA_ASSERT( psa_key_derivation_input_bytes( operation,
- PSA_KEY_DERIVATION_INPUT_INFO,
- input2,
- input2_length ) );
- }
- else if( PSA_ALG_IS_TLS12_PRF( alg ) ||
- PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
- {
- PSA_ASSERT( psa_key_derivation_input_bytes( operation,
- PSA_KEY_DERIVATION_INPUT_SEED,
- input1, input1_length ) );
- PSA_ASSERT( psa_key_derivation_input_key( operation,
- PSA_KEY_DERIVATION_INPUT_SECRET,
- key ) );
- PSA_ASSERT( psa_key_derivation_input_bytes( operation,
- PSA_KEY_DERIVATION_INPUT_LABEL,
- input2, input2_length ) );
- }
- else
- {
- TEST_ASSERT( ! "Key derivation algorithm not supported" );
- }
-
- if( capacity != SIZE_MAX )
- PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
-
- return( 1 );
-
-exit:
- return( 0 );
-}
-
-
-static int exercise_key_derivation_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
- unsigned char input1[] = "Input 1";
- size_t input1_length = sizeof( input1 );
- unsigned char input2[] = "Input 2";
- size_t input2_length = sizeof( input2 );
- unsigned char output[1];
- size_t capacity = sizeof( output );
-
- if( usage & PSA_KEY_USAGE_DERIVE )
- {
- if( !setup_key_derivation_wrap( &operation, key, alg,
- input1, input1_length,
- input2, input2_length, capacity ) )
- goto exit;
-
- PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
- output,
- capacity ) );
- PSA_ASSERT( psa_key_derivation_abort( &operation ) );
- }
-
- return( 1 );
-
-exit:
- return( 0 );
-}
-
-/* We need two keys to exercise key agreement. Exercise the
- * private key against its own public key. */
-static psa_status_t key_agreement_with_self(
- psa_key_derivation_operation_t *operation,
- mbedtls_svc_key_id_t key )
-{
- psa_key_type_t private_key_type;
- psa_key_type_t public_key_type;
- size_t key_bits;
- uint8_t *public_key = NULL;
- size_t public_key_length;
- /* Return GENERIC_ERROR if something other than the final call to
- * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
- * but it's good enough: callers will report it as a failed test anyway. */
- psa_status_t status = PSA_ERROR_GENERIC_ERROR;
- psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
- PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
- private_key_type = psa_get_key_type( &attributes );
- key_bits = psa_get_key_bits( &attributes );
- public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
- public_key_length = PSA_EXPORT_KEY_OUTPUT_SIZE( public_key_type, key_bits );
- ASSERT_ALLOC( public_key, public_key_length );
- PSA_ASSERT( psa_export_public_key( key, public_key, public_key_length,
- &public_key_length ) );
-
- status = psa_key_derivation_key_agreement(
- operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
- public_key, public_key_length );
-exit:
- /*
- * Key attributes may have been returned by psa_get_key_attributes()
- * thus reset them as required.
- */
- psa_reset_key_attributes( &attributes );
-
- mbedtls_free( public_key );
- return( status );
-}
-
-/* We need two keys to exercise key agreement. Exercise the
- * private key against its own public key. */
-static psa_status_t raw_key_agreement_with_self( psa_algorithm_t alg,
- mbedtls_svc_key_id_t key )
-{
- psa_key_type_t private_key_type;
- psa_key_type_t public_key_type;
- size_t key_bits;
- uint8_t *public_key = NULL;
- size_t public_key_length;
- uint8_t output[1024];
- size_t output_length;
- /* Return GENERIC_ERROR if something other than the final call to
- * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
- * but it's good enough: callers will report it as a failed test anyway. */
- psa_status_t status = PSA_ERROR_GENERIC_ERROR;
- psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
- PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
- private_key_type = psa_get_key_type( &attributes );
- key_bits = psa_get_key_bits( &attributes );
- public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
- public_key_length = PSA_EXPORT_KEY_OUTPUT_SIZE( public_key_type, key_bits );
- ASSERT_ALLOC( public_key, public_key_length );
- PSA_ASSERT( psa_export_public_key( key,
- public_key, public_key_length,
- &public_key_length ) );
-
- status = psa_raw_key_agreement( alg, key,
- public_key, public_key_length,
- output, sizeof( output ), &output_length );
-exit:
- /*
- * Key attributes may have been returned by psa_get_key_attributes()
- * thus reset them as required.
- */
- psa_reset_key_attributes( &attributes );
-
- mbedtls_free( public_key );
- return( status );
-}
-
-static int exercise_raw_key_agreement_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- int ok = 0;
-
- if( usage & PSA_KEY_USAGE_DERIVE )
- {
- /* We need two keys to exercise key agreement. Exercise the
- * private key against its own public key. */
- PSA_ASSERT( raw_key_agreement_with_self( alg, key ) );
- }
- ok = 1;
-
-exit:
- return( ok );
-}
-
-static int exercise_key_agreement_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
- unsigned char output[1];
- int ok = 0;
-
- if( usage & PSA_KEY_USAGE_DERIVE )
- {
- /* We need two keys to exercise key agreement. Exercise the
- * private key against its own public key. */
- PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
- PSA_ASSERT( key_agreement_with_self( &operation, key ) );
- PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
- output,
- sizeof( output ) ) );
- PSA_ASSERT( psa_key_derivation_abort( &operation ) );
- }
- ok = 1;
-
-exit:
- return( ok );
-}
-
-int asn1_skip_integer( unsigned char **p, const unsigned char *end,
- size_t min_bits, size_t max_bits,
- int must_be_odd )
-{
- size_t len;
- size_t actual_bits;
- unsigned char msb;
- TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len,
- MBEDTLS_ASN1_INTEGER ),
- 0 );
-
- /* Check if the retrieved length doesn't extend the actual buffer's size.
- * It is assumed here, that end >= p, which validates casting to size_t. */
- TEST_ASSERT( len <= (size_t)( end - *p) );
-
- /* Tolerate a slight departure from DER encoding:
- * - 0 may be represented by an empty string or a 1-byte string.
- * - The sign bit may be used as a value bit. */
- if( ( len == 1 && ( *p )[0] == 0 ) ||
- ( len > 1 && ( *p )[0] == 0 && ( ( *p )[1] & 0x80 ) != 0 ) )
- {
- ++( *p );
- --len;
- }
- if( min_bits == 0 && len == 0 )
- return( 1 );
- msb = ( *p )[0];
- TEST_ASSERT( msb != 0 );
- actual_bits = 8 * ( len - 1 );
- while( msb != 0 )
- {
- msb >>= 1;
- ++actual_bits;
- }
- TEST_ASSERT( actual_bits >= min_bits );
- TEST_ASSERT( actual_bits <= max_bits );
- if( must_be_odd )
- TEST_ASSERT( ( ( *p )[len-1] & 1 ) != 0 );
- *p += len;
- return( 1 );
-exit:
- return( 0 );
-}
-
-static int exported_key_sanity_check( psa_key_type_t type, size_t bits,
- uint8_t *exported, size_t exported_length )
-{
- if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
- TEST_EQUAL( exported_length, ( bits + 7 ) / 8 );
- else
- TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_OUTPUT_SIZE( type, bits ) );
-
-#if defined(MBEDTLS_DES_C)
- if( type == PSA_KEY_TYPE_DES )
- {
- /* Check the parity bits. */
- unsigned i;
- for( i = 0; i < bits / 8; i++ )
- {
- unsigned bit_count = 0;
- unsigned m;
- for( m = 1; m <= 0x100; m <<= 1 )
- {
- if( exported[i] & m )
- ++bit_count;
- }
- TEST_ASSERT( bit_count % 2 != 0 );
- }
- }
- else
-#endif
-
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
- if( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
- {
- uint8_t *p = exported;
- uint8_t *end = exported + exported_length;
- size_t len;
- /* RSAPrivateKey ::= SEQUENCE {
- * version INTEGER, -- must be 0
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * }
- */
- TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_SEQUENCE |
- MBEDTLS_ASN1_CONSTRUCTED ), 0 );
- TEST_EQUAL( p + len, end );
- if( ! asn1_skip_integer( &p, end, 0, 0, 0 ) )
- goto exit;
- if( ! asn1_skip_integer( &p, end, bits, bits, 1 ) )
- goto exit;
- if( ! asn1_skip_integer( &p, end, 2, bits, 1 ) )
- goto exit;
- /* Require d to be at least half the size of n. */
- if( ! asn1_skip_integer( &p, end, bits / 2, bits, 1 ) )
- goto exit;
- /* Require p and q to be at most half the size of n, rounded up. */
- if( ! asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
- goto exit;
- if( ! asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
- goto exit;
- if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
- goto exit;
- if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
- goto exit;
- if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
- goto exit;
- TEST_EQUAL( p, end );
- }
- else
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
- if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
- {
- /* Just the secret value */
- TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
- }
- else
-#endif /* MBEDTLS_ECP_C */
-
- if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
- {
- uint8_t *p = exported;
- uint8_t *end = exported + exported_length;
-#if defined(MBEDTLS_RSA_C)
- if( type == PSA_KEY_TYPE_RSA_PUBLIC_KEY )
- {
- size_t len;
- /* RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER } -- e
- */
- TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_SEQUENCE |
- MBEDTLS_ASN1_CONSTRUCTED ),
- 0 );
- TEST_EQUAL( p + len, end );
- if( ! asn1_skip_integer( &p, end, bits, bits, 1 ) )
- goto exit;
- if( ! asn1_skip_integer( &p, end, 2, bits, 1 ) )
- goto exit;
- TEST_EQUAL( p, end );
- }
- else
-#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
- if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) )
- {
- if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY )
- {
- /* The representation of an ECC Montgomery public key is
- * the raw compressed point */
- TEST_EQUAL( p + PSA_BITS_TO_BYTES( bits ), end );
- }
- else
- {
- /* The representation of an ECC Weierstrass public key is:
- * - The byte 0x04;
- * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
- * - `y_P` as a `ceiling(m/8)`-byte string, big-endian;
- * - where m is the bit size associated with the curve.
- */
- TEST_EQUAL( p + 1 + 2 * PSA_BITS_TO_BYTES( bits ), end );
- TEST_EQUAL( p[0], 4 );
- }
- }
- else
-#endif /* MBEDTLS_ECP_C */
- {
- char message[47];
- mbedtls_snprintf( message, sizeof( message ),
- "No sanity check for public key type=0x%08lx",
- (unsigned long) type );
- mbedtls_test_fail( message, __LINE__, __FILE__ );
- (void) p;
- (void) end;
- return( 0 );
- }
- }
- else
-
- {
- /* No sanity checks for other types */
- }
-
- return( 1 );
-
-exit:
- return( 0 );
-}
-
-static int exercise_export_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage )
-{
- psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- uint8_t *exported = NULL;
- size_t exported_size = 0;
- size_t exported_length = 0;
- int ok = 0;
-
- PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
-
- exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
- psa_get_key_type( &attributes ),
- psa_get_key_bits( &attributes ) );
- ASSERT_ALLOC( exported, exported_size );
-
- if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
- ! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) )
- {
- TEST_EQUAL( psa_export_key( key, exported,
- exported_size, &exported_length ),
- PSA_ERROR_NOT_PERMITTED );
- ok = 1;
- goto exit;
- }
-
- PSA_ASSERT( psa_export_key( key,
- exported, exported_size,
- &exported_length ) );
- ok = exported_key_sanity_check( psa_get_key_type( &attributes ),
- psa_get_key_bits( &attributes ),
- exported, exported_length );
-
-exit:
- /*
- * Key attributes may have been returned by psa_get_key_attributes()
- * thus reset them as required.
- */
- psa_reset_key_attributes( &attributes );
-
- mbedtls_free( exported );
- return( ok );
-}
-
-static int exercise_export_public_key( mbedtls_svc_key_id_t key )
-{
- psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- psa_key_type_t public_type;
- uint8_t *exported = NULL;
- size_t exported_size = 0;
- size_t exported_length = 0;
- int ok = 0;
-
- PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
- if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) )
- {
- exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
- psa_get_key_type( &attributes ),
- psa_get_key_bits( &attributes ) );
- ASSERT_ALLOC( exported, exported_size );
-
- TEST_EQUAL( psa_export_public_key( key, exported,
- exported_size, &exported_length ),
- PSA_ERROR_INVALID_ARGUMENT );
- ok = 1;
- goto exit;
- }
-
- public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
- psa_get_key_type( &attributes ) );
- exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE( public_type,
- psa_get_key_bits( &attributes ) );
- ASSERT_ALLOC( exported, exported_size );
-
- PSA_ASSERT( psa_export_public_key( key,
- exported, exported_size,
- &exported_length ) );
- ok = exported_key_sanity_check( public_type,
- psa_get_key_bits( &attributes ),
- exported, exported_length );
-
-exit:
- /*
- * Key attributes may have been returned by psa_get_key_attributes()
- * thus reset them as required.
- */
- psa_reset_key_attributes( &attributes );
-
- mbedtls_free( exported );
- return( ok );
-}
-
-/** Do smoke tests on a key.
- *
- * Perform one of each operation indicated by \p alg (decrypt/encrypt,
- * sign/verify, or derivation) that is permitted according to \p usage.
- * \p usage and \p alg should correspond to the expected policy on the
- * key.
- *
- * Export the key if permitted by \p usage, and check that the output
- * looks sensible. If \p usage forbids export, check that
- * \p psa_export_key correctly rejects the attempt. If the key is
- * asymmetric, also check \p psa_export_public_key.
- *
- * If the key fails the tests, this function calls the test framework's
- * `mbedtls_test_fail` function and returns false. Otherwise this function
- * returns true. Therefore it should be used as follows:
- * ```
- * if( ! exercise_key( ... ) ) goto exit;
- * ```
- *
- * \param key The key to exercise. It should be capable of performing
- * \p alg.
- * \param usage The usage flags to assume.
- * \param alg The algorithm to exercise.
- *
- * \retval 0 The key failed the smoke tests.
- * \retval 1 The key passed the smoke tests.
- */
-static int exercise_key( mbedtls_svc_key_id_t key,
- psa_key_usage_t usage,
- psa_algorithm_t alg )
-{
- int ok;
-
- if( ! check_key_attributes_sanity( key ) )
- return( 0 );
-
- if( alg == 0 )
- ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
- else if( PSA_ALG_IS_MAC( alg ) )
- ok = exercise_mac_key( key, usage, alg );
- else if( PSA_ALG_IS_CIPHER( alg ) )
- ok = exercise_cipher_key( key, usage, alg );
- else if( PSA_ALG_IS_AEAD( alg ) )
- ok = exercise_aead_key( key, usage, alg );
- else if( PSA_ALG_IS_SIGN( alg ) )
- ok = exercise_signature_key( key, usage, alg );
- else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
- ok = exercise_asymmetric_encryption_key( key, usage, alg );
- else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
- ok = exercise_key_derivation_key( key, usage, alg );
- else if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
- ok = exercise_raw_key_agreement_key( key, usage, alg );
- else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
- ok = exercise_key_agreement_key( key, usage, alg );
- else
- {
- char message[40];
- mbedtls_snprintf( message, sizeof( message ),
- "No code to exercise alg=0x%08lx",
- (unsigned long) alg );
- mbedtls_test_fail( message, __LINE__, __FILE__ );
- ok = 0;
- }
-
- ok = ok && exercise_export_key( key, usage );
- ok = ok && exercise_export_public_key( key );
-
- return( ok );
-}
-
-static psa_key_usage_t usage_to_exercise( psa_key_type_t type,
- psa_algorithm_t alg )
-{
- if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) )
- {
- return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
- PSA_KEY_USAGE_VERIFY_HASH :
- PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH );
- }
- else if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ||
- PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
- {
- return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
- PSA_KEY_USAGE_ENCRYPT :
- PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
- }
- else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ||
- PSA_ALG_IS_KEY_AGREEMENT( alg ) )
- {
- return( PSA_KEY_USAGE_DERIVE );
- }
- else
- {
- return( 0 );
- }
-
-}
-
static int test_operations_on_invalid_key( mbedtls_svc_key_id_t key )
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1609,7 +591,11 @@
goto destroy;
}
- if( ! exercise_export_key( key, usage_arg ) )
+ /* Run sanity checks on the exported key. For non-canonical inputs,
+ * this validates the canonical representations. For canonical inputs,
+ * this doesn't directly validate the implementation, but it still helps
+ * by cross-validating the test data with the sanity check code. */
+ if( ! mbedtls_test_psa_exercise_key( key, usage_arg, 0 ) )
goto exit;
if( canonical_input )
@@ -1715,7 +701,7 @@
psa_key_type_t type = type_arg;
size_t bits = bits_arg;
psa_algorithm_t alg = alg_arg;
- psa_key_usage_t usage = usage_to_exercise( type, alg );
+ psa_key_usage_t usage = mbedtls_test_psa_usage_to_exercise( type, alg );
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1734,7 +720,7 @@
TEST_EQUAL( psa_get_key_bits( &got_attributes ), bits );
/* Do something with the key according to its type and permitted usage. */
- if( ! exercise_key( key, usage, alg ) )
+ if( ! mbedtls_test_psa_exercise_key( key, usage, alg ) )
goto exit;
PSA_ASSERT( psa_destroy_key( key ) );
@@ -2187,7 +1173,7 @@
&key ) );
PSA_ASSERT( psa_key_derivation_setup( &operation, exercise_alg ) );
- status = key_agreement_with_self( &operation, key );
+ status = mbedtls_test_psa_key_agreement_with_self( &operation, key );
TEST_EQUAL( status, expected_status );
@@ -2224,9 +1210,9 @@
TEST_EQUAL( psa_get_key_algorithm( &got_attributes ), alg );
TEST_EQUAL( psa_get_key_enrollment_algorithm( &got_attributes ), alg2 );
- if( ! exercise_key( key, usage, alg ) )
+ if( ! mbedtls_test_psa_exercise_key( key, usage, alg ) )
goto exit;
- if( ! exercise_key( key, usage, alg2 ) )
+ if( ! mbedtls_test_psa_exercise_key( key, usage, alg2 ) )
goto exit;
exit:
@@ -2265,7 +1251,7 @@
PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
&key ) );
- status = raw_key_agreement_with_self( exercise_alg, key );
+ status = mbedtls_test_psa_raw_key_agreement_with_self( exercise_alg, key );
TEST_EQUAL( status, expected_status );
@@ -2348,9 +1334,9 @@
ASSERT_COMPARE( material->x, material->len,
export_buffer, length );
}
- if( ! exercise_key( target_key, expected_usage, expected_alg ) )
+ if( ! mbedtls_test_psa_exercise_key( target_key, expected_usage, expected_alg ) )
goto exit;
- if( ! exercise_key( target_key, expected_usage, expected_alg2 ) )
+ if( ! mbedtls_test_psa_exercise_key( target_key, expected_usage, expected_alg2 ) )
goto exit;
PSA_ASSERT( psa_destroy_key( target_key ) );
@@ -4740,7 +3726,8 @@
{
// When taking a private key as secret input, use key agreement
// to add the shared secret to the derivation
- TEST_EQUAL( key_agreement_with_self( &operation, keys[i] ),
+ TEST_EQUAL( mbedtls_test_psa_key_agreement_with_self(
+ &operation, keys[i] ),
expected_statuses[i] );
}
else
@@ -4815,10 +3802,10 @@
&key ) );
/* valid key derivation */
- if( !setup_key_derivation_wrap( &operation, key, alg,
- input1, input1_length,
- input2, input2_length,
- capacity ) )
+ if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
+ input1, input1_length,
+ input2, input2_length,
+ capacity ) )
goto exit;
/* state of operation shouldn't allow additional generation */
@@ -5007,10 +3994,10 @@
PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
&key ) );
- if( !setup_key_derivation_wrap( &operation, key, alg,
- input1->x, input1->len,
- input2->x, input2->len,
- requested_capacity ) )
+ if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
+ input1->x, input1->len,
+ input2->x, input2->len,
+ requested_capacity ) )
goto exit;
PSA_ASSERT( psa_key_derivation_get_capacity( &operation,
@@ -5076,9 +4063,10 @@
&base_key ) );
/* Derive a key. */
- if ( setup_key_derivation_wrap( &operation, base_key, alg,
- input1->x, input1->len,
- input2->x, input2->len, capacity ) )
+ if ( mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+ input1->x, input1->len,
+ input2->x, input2->len,
+ capacity ) )
goto exit;
psa_set_key_usage_flags( &attributes, derived_usage );
@@ -5094,7 +4082,7 @@
TEST_EQUAL( psa_get_key_bits( &got_attributes ), derived_bits );
/* Exercise the derived key. */
- if( ! exercise_key( derived_key, derived_usage, derived_alg ) )
+ if( ! mbedtls_test_psa_exercise_key( derived_key, derived_usage, derived_alg ) )
goto exit;
exit:
@@ -5143,9 +4131,10 @@
&base_key ) );
/* Derive some material and output it. */
- if( !setup_key_derivation_wrap( &operation, base_key, alg,
- input1->x, input1->len,
- input2->x, input2->len, capacity ) )
+ if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+ input1->x, input1->len,
+ input2->x, input2->len,
+ capacity ) )
goto exit;
PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
@@ -5154,9 +4143,10 @@
PSA_ASSERT( psa_key_derivation_abort( &operation ) );
/* Derive the same output again, but this time store it in key objects. */
- if( !setup_key_derivation_wrap( &operation, base_key, alg,
- input1->x, input1->len,
- input2->x, input2->len, capacity ) )
+ if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+ input1->x, input1->len,
+ input2->x, input2->len,
+ capacity ) )
goto exit;
psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT );
@@ -5217,9 +4207,10 @@
PSA_ASSERT( psa_import_key( &base_attributes, key_data->x, key_data->len,
&base_key ) );
- if( !setup_key_derivation_wrap( &operation, base_key, alg,
- input1->x, input1->len,
- input2->x, input2->len, SIZE_MAX ) )
+ if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+ input1->x, input1->len,
+ input2->x, input2->len,
+ SIZE_MAX ) )
goto exit;
psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT );
@@ -5535,7 +4526,7 @@
TEST_EQUAL( psa_get_key_bits( &got_attributes ), bits );
/* Do something with the key according to its type and permitted usage. */
- if( ! exercise_key( key, usage, alg ) )
+ if( ! mbedtls_test_psa_exercise_key( key, usage, alg ) )
goto exit;
exit:
@@ -5607,7 +4598,7 @@
ASSERT_COMPARE( e_read_buffer, e_read_length, e_arg->x, e_arg->len );
/* Do something with the key according to its type and permitted usage. */
- if( ! exercise_key( key, usage, alg ) )
+ if( ! mbedtls_test_psa_exercise_key( key, usage, alg ) )
goto exit;
/* Export the key and check the public exponent. */
@@ -5625,7 +4616,7 @@
TEST_EQUAL( 0, mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_SEQUENCE |
MBEDTLS_ASN1_CONSTRUCTED ) );
- TEST_ASSERT( asn1_skip_integer( &p, end, bits, bits, 1 ) );
+ TEST_ASSERT( mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) );
TEST_EQUAL( 0, mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) );
if( len >= 1 && p[0] == 0 )
@@ -5783,7 +4774,7 @@
}
/* Do something with the key according to its type and permitted usage. */
- if( ! exercise_key( key, usage_flags, alg ) )
+ if( ! mbedtls_test_psa_exercise_key( key, usage_flags, alg ) )
goto exit;
exit:
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 fa516c5..79d658f 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -767,41 +767,12 @@
return( ok );
}
-static mbedtls_svc_key_id_t key_ids_used_in_test[10];
-static size_t num_key_ids_used;
-
-/* Record a key id as potentially used in a test case. */
-static int test_uses_key_id( mbedtls_svc_key_id_t key_id )
-{
- size_t i;
-
- for( i = 0; i < num_key_ids_used ; i++ )
- {
- if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
- return( 1 );
- }
-
- if( num_key_ids_used >= ARRAY_LENGTH( key_ids_used_in_test ) )
- return( 0 );
-
- key_ids_used_in_test[num_key_ids_used] = key_id;
- ++num_key_ids_used;
-
- return( 1 );
-}
-
-#define TEST_USES_KEY_ID( key_id ) \
- TEST_ASSERT( test_uses_key_id( key_id ) )
-
static void psa_purge_storage( void )
{
- size_t i;
+ /* The generic code in mbedtls_test_psa_purge_key_storage()
+ * (which is called by PSA_DONE()) doesn't take care of things that are
+ * specific to dynamic secure elements. */
psa_key_location_t location;
-
- for( i = 0; i < num_key_ids_used; i++ )
- psa_destroy_persistent_key( key_ids_used_in_test[i] );
- num_key_ids_used = 0;
-
/* Purge the transaction file. */
psa_crypto_stop_transaction( );
/* Purge driver persistent data. */
@@ -1496,6 +1467,7 @@
( validate > 0 ? PSA_SUCCESS : PSA_ERROR_NOT_PERMITTED );
}
+ mbedtls_test_set_step( 1 );
PSA_ASSERT( psa_register_se_driver( MIN_DRIVER_LOCATION, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
@@ -1525,7 +1497,8 @@
PSA_ASSERT( psa_purge_key( id ) );
/* Restart and try again. */
- PSA_DONE( );
+ mbedtls_test_set_step( 2 );
+ PSA_SESSION_DONE( );
PSA_ASSERT( psa_register_se_driver( location, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
if( ! check_key_attributes( id, &attributes ) )
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function
index dbf05d2..bafb7d8 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.function
+++ b/tests/suites/test_suite_psa_crypto_slot_management.function
@@ -43,51 +43,6 @@
INVALID_HANDLE_HUGE,
} invalid_handle_construction_t;
-/* All test functions that create persistent keys must call
- * `TEST_USES_KEY_ID( key_id )` before creating a persistent key with this
- * identifier, and must call psa_purge_key_storage() in their cleanup
- * code. */
-
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-static mbedtls_svc_key_id_t key_ids_used_in_test[9];
-static size_t num_key_ids_used;
-
-/* Record a key id as potentially used in a test case. */
-static int test_uses_key_id( mbedtls_svc_key_id_t key_id )
-{
- size_t i;
- if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key_id ) >
- PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
- {
- /* Don't touch key id values that designate non-key files. */
- return( 1 );
- }
- for( i = 0; i < num_key_ids_used ; i++ )
- {
- if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
- return( 1 );
- }
- if( num_key_ids_used == ARRAY_LENGTH( key_ids_used_in_test ) )
- return( 0 );
- key_ids_used_in_test[num_key_ids_used] = key_id;
- ++num_key_ids_used;
- return( 1 );
-}
-#define TEST_USES_KEY_ID( key_id ) \
- TEST_ASSERT( test_uses_key_id( key_id ) )
-
-/* Destroy all key ids that may have been created by the current test case. */
-static void psa_purge_key_storage( void )
-{
- size_t i;
- for( i = 0; i < num_key_ids_used; i++ )
- psa_destroy_persistent_key( key_ids_used_in_test[i] );
- num_key_ids_used = 0;
-}
-#else
-#define TEST_USES_KEY_ID( key_id ) ( (void) ( key_id ) )
-#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
-
/** Apply \p invalidate_method to invalidate the specified key:
* close it, destroy it, or do nothing;
*/
@@ -131,7 +86,7 @@
case INVALIDATE_BY_DESTROYING_WITH_SHUTDOWN:
case INVALIDATE_BY_PURGING_WITH_SHUTDOWN:
/* All keys must have been closed. */
- PSA_DONE( );
+ PSA_SESSION_DONE( );
break;
case INVALIDATE_BY_SHUTDOWN:
/* Some keys may remain behind, and we're testing that this
@@ -168,6 +123,7 @@
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ mbedtls_test_set_step( 1 );
PSA_ASSERT( psa_crypto_init( ) );
/* Import a key. */
@@ -214,6 +170,7 @@
psa_reset_key_attributes( &attributes );
/* Do something that invalidates the key. */
+ mbedtls_test_set_step( 2 );
if( ! invalidate_key( invalidate_method, key ) )
goto exit;
if( ! invalidate_psa( invalidate_method ) )
@@ -263,6 +220,7 @@
TEST_USES_KEY_ID( id );
+ mbedtls_test_set_step( 1 );
PSA_ASSERT( psa_crypto_init( ) );
psa_set_key_id( &attributes, id );
@@ -312,6 +270,7 @@
* Do something that wipes key data in volatile memory or destroy the
* key.
*/
+ mbedtls_test_set_step( 2 );
if( ! invalidate_key( invalidate_method, id ) )
goto exit;
if( ! invalidate_psa( invalidate_method ) )
@@ -383,7 +342,6 @@
psa_reset_key_attributes( &read_attributes );
PSA_DONE( );
- psa_purge_key_storage( );
mbedtls_free( reexported );
}
/* END_CASE */
@@ -457,7 +415,6 @@
psa_reset_key_attributes( &attributes );
PSA_DONE( );
- psa_purge_key_storage( );
}
/* END_CASE */
@@ -516,9 +473,6 @@
exit:
PSA_DONE( );
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
- psa_purge_key_storage( );
-#endif
}
/* END_CASE */
@@ -654,9 +608,6 @@
PSA_DONE( );
mbedtls_free( export_buffer );
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
- psa_purge_key_storage( );
-#endif
}
/* END_CASE */
@@ -772,9 +723,6 @@
PSA_DONE( );
mbedtls_free( export_buffer );
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
- psa_purge_key_storage( );
-#endif
}
/* END_CASE */
diff --git a/tests/suites/test_suite_random.data b/tests/suites/test_suite_random.data
new file mode 100644
index 0000000..c23d922
--- /dev/null
+++ b/tests/suites/test_suite_random.data
@@ -0,0 +1,55 @@
+Generate random twice with CTR_DRBG
+random_twice_with_ctr_drbg:
+
+Generate random twice with HMAC_DRBG(SHA-1)
+depends_on:MBEDTLS_SHA1_C
+random_twice_with_hmac_drbg:MBEDTLS_MD_SHA1
+
+Generate random twice with HMAC_DRBG(SHA-256)
+depends_on:MBEDTLS_SHA256_C
+random_twice_with_hmac_drbg:MBEDTLS_MD_SHA256
+
+Generate random twice with HMAC_DRBG(SHA-512)
+depends_on:MBEDTLS_SHA512_C
+random_twice_with_hmac_drbg:MBEDTLS_MD_SHA512
+
+Generate random twice with PSA classic wrapper
+random_twice_with_psa_from_classic:
+
+Generate random twice with PSA API
+random_twice_with_psa_from_psa:
+
+# This bad-usage test case currently crashes in the default configuration
+# because CTR_DRBG crashes when given an unseeded context. This is arguably
+# a good thing because it prevents misuse of mbedtls_psa_get_random().
+#PSA classic wrapper: PSA not active
+#mbedtls_psa_get_random_no_init:
+
+PSA classic wrapper: 0 bytes
+mbedtls_psa_get_random_length:0
+
+PSA classic wrapper: 1 byte
+mbedtls_psa_get_random_length:1
+
+PSA classic wrapper: 256 bytes
+mbedtls_psa_get_random_length:256
+
+# An external RNG is supposed to handle arbitrary request lengths. Test it
+# with something larger than any RNG call made by Mbed TLS itself expects.
+# CTR_DRBG and HMAC_DRBG have their own maximum request lengths which may
+# be lower than the value chosen here and are tested separately.
+PSA classic wrapper: external RNG large
+depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+mbedtls_psa_get_random_length:1024
+
+PSA classic wrapper: CTR_DRBG max
+depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG:MBEDTLS_CTR_DRBG_C
+mbedtls_psa_get_random_length:MBEDTLS_CTR_DRBG_MAX_REQUEST
+
+PSA classic wrapper: HMAC_DRBG max
+depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG:!MBEDTLS_CTR_DRBG_C:MBEDTLS_HMAC_DRBG_C
+mbedtls_psa_get_random_length:MBEDTLS_HMAC_DRBG_MAX_REQUEST
+
+PSA classic wrapper: ECDSA signature (SECP256R1)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+mbedtls_psa_get_random_ecdsa_sign:MBEDTLS_ECP_DP_SECP256R1
diff --git a/tests/suites/test_suite_random.function b/tests/suites/test_suite_random.function
new file mode 100644
index 0000000..37fa36e
--- /dev/null
+++ b/tests/suites/test_suite_random.function
@@ -0,0 +1,202 @@
+/* BEGIN_HEADER */
+
+/* Test random generation as a whole. */
+
+#include "mbedtls/bignum.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/ecdsa.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/hmac_drbg.h"
+#include "mbedtls/psa_util.h"
+#include "psa/crypto.h"
+
+/* How many bytes to generate in each test case for repeated generation.
+ * This must be high enough that the probability of generating the same
+ * output twice is infinitesimal, but low enough that random generators
+ * are willing to deliver that much. */
+#define OUTPUT_SIZE 32
+
+/* END_HEADER */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:MBEDTLS_CTR_DRBG_C */
+void random_twice_with_ctr_drbg( )
+{
+ mbedtls_entropy_context entropy;
+ mbedtls_ctr_drbg_context drbg;
+ unsigned char output1[OUTPUT_SIZE];
+ unsigned char output2[OUTPUT_SIZE];
+
+ /* First round */
+ mbedtls_entropy_init( &entropy );
+ mbedtls_ctr_drbg_init( &drbg );
+ TEST_EQUAL( 0, mbedtls_ctr_drbg_seed( &drbg,
+ mbedtls_entropy_func, &entropy,
+ NULL, 0 ) );
+ TEST_EQUAL( 0, mbedtls_ctr_drbg_random( &drbg,
+ output1, sizeof( output1 ) ) );
+ mbedtls_ctr_drbg_free( &drbg );
+ mbedtls_entropy_free( &entropy );
+
+ /* Second round */
+ mbedtls_entropy_init( &entropy );
+ mbedtls_ctr_drbg_init( &drbg );
+ TEST_EQUAL( 0, mbedtls_ctr_drbg_seed( &drbg,
+ mbedtls_entropy_func, &entropy,
+ NULL, 0 ) );
+ TEST_EQUAL( 0, mbedtls_ctr_drbg_random( &drbg,
+ output2, sizeof( output2 ) ) );
+ mbedtls_ctr_drbg_free( &drbg );
+ mbedtls_entropy_free( &entropy );
+
+ /* The two rounds must generate different random data. */
+ TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
+
+exit:
+ mbedtls_ctr_drbg_free( &drbg );
+ mbedtls_entropy_free( &entropy );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:MBEDTLS_HMAC_DRBG_C */
+void random_twice_with_hmac_drbg( int md_type )
+{
+ mbedtls_entropy_context entropy;
+ mbedtls_hmac_drbg_context drbg;
+ unsigned char output1[OUTPUT_SIZE];
+ unsigned char output2[OUTPUT_SIZE];
+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
+
+ /* First round */
+ mbedtls_entropy_init( &entropy );
+ mbedtls_hmac_drbg_init( &drbg );
+ TEST_EQUAL( 0, mbedtls_hmac_drbg_seed( &drbg, md_info,
+ mbedtls_entropy_func, &entropy,
+ NULL, 0 ) );
+ TEST_EQUAL( 0, mbedtls_hmac_drbg_random( &drbg,
+ output1, sizeof( output1 ) ) );
+ mbedtls_hmac_drbg_free( &drbg );
+ mbedtls_entropy_free( &entropy );
+
+ /* Second round */
+ mbedtls_entropy_init( &entropy );
+ mbedtls_hmac_drbg_init( &drbg );
+ TEST_EQUAL( 0, mbedtls_hmac_drbg_seed( &drbg, md_info,
+ mbedtls_entropy_func, &entropy,
+ NULL, 0 ) );
+ TEST_EQUAL( 0, mbedtls_hmac_drbg_random( &drbg,
+ output2, sizeof( output2 ) ) );
+ mbedtls_hmac_drbg_free( &drbg );
+ mbedtls_entropy_free( &entropy );
+
+ /* The two rounds must generate different random data. */
+ TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
+
+exit:
+ mbedtls_hmac_drbg_free( &drbg );
+ mbedtls_entropy_free( &entropy );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+void random_twice_with_psa_from_classic( )
+{
+ unsigned char output1[OUTPUT_SIZE];
+ unsigned char output2[OUTPUT_SIZE];
+
+ /* First round */
+ PSA_ASSERT( psa_crypto_init( ) );
+ TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+ output1, sizeof( output1 ) ) );
+ PSA_DONE( );
+
+ /* Second round */
+ PSA_ASSERT( psa_crypto_init( ) );
+ TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+ output2, sizeof( output2 ) ) );
+ PSA_DONE( );
+
+ /* The two rounds must generate different random data. */
+ TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
+
+exit:
+ PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+void random_twice_with_psa_from_psa( )
+{
+ unsigned char output1[OUTPUT_SIZE];
+ unsigned char output2[OUTPUT_SIZE];
+
+ /* First round */
+ PSA_ASSERT( psa_crypto_init( ) );
+ PSA_ASSERT( psa_generate_random( output1, sizeof( output1 ) ) );
+ PSA_DONE( );
+
+ /* Second round */
+ PSA_ASSERT( psa_crypto_init( ) );
+ PSA_ASSERT( psa_generate_random( output2, sizeof( output2 ) ) );
+ PSA_DONE( );
+
+ /* The two rounds must generate different random data. */
+ TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
+
+exit:
+ PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */
+void mbedtls_psa_get_random_no_init( )
+{
+ unsigned char output[1];
+
+ TEST_ASSERT( mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+ output, sizeof( output ) ) != 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */
+void mbedtls_psa_get_random_length( int n )
+{
+ unsigned char *output = NULL;
+
+ PSA_ASSERT( psa_crypto_init( ) );
+ ASSERT_ALLOC( output, n );
+
+ TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+ output, n ) );
+exit:
+ mbedtls_free( output );
+ PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_ECDSA_C */
+void mbedtls_psa_get_random_ecdsa_sign( int curve )
+{
+ mbedtls_ecp_group grp;
+ mbedtls_mpi d, r, s;
+ unsigned char buf[] = "This is not a hash.";
+
+ mbedtls_ecp_group_init( &grp );
+ mbedtls_mpi_init( &d );
+ mbedtls_mpi_init( &r );
+ mbedtls_mpi_init( &s );
+
+ TEST_EQUAL( 0, mbedtls_mpi_lset( &d, 123456789 ) );
+ TEST_EQUAL( 0, mbedtls_ecp_group_load( &grp, curve ) );
+ PSA_ASSERT( psa_crypto_init( ) );
+ TEST_EQUAL( 0, mbedtls_ecdsa_sign( &grp, &r, &s, &d,
+ buf, sizeof( buf ),
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE ) );
+exit:
+ mbedtls_mpi_free( &d );
+ mbedtls_mpi_free( &r );
+ mbedtls_mpi_free( &s );
+ mbedtls_ecp_group_free( &grp );
+ PSA_DONE( );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_rsa.data b/tests/suites/test_suite_rsa.data
index 30919f3..6f9406c 100644
--- a/tests/suites/test_suite_rsa.data
+++ b/tests/suites/test_suite_rsa.data
@@ -1,6 +1,12 @@
RSA parameter validation
rsa_invalid_param:
+RSA init-free-free
+rsa_init_free:0
+
+RSA init-free-init-free
+rsa_init_free:1
+
RSA PKCS1 Verify v1.5 CAVS #1
depends_on:MBEDTLS_SHA1_C:MBEDTLS_PKCS1_V15
# Good padding but wrong hash
diff --git a/tests/suites/test_suite_rsa.function b/tests/suites/test_suite_rsa.function
index 6c73e39..cdbaa13 100644
--- a/tests/suites/test_suite_rsa.function
+++ b/tests/suites/test_suite_rsa.function
@@ -467,6 +467,29 @@
/* END_CASE */
/* BEGIN_CASE */
+void rsa_init_free( int reinit )
+{
+ mbedtls_rsa_context ctx;
+
+ /* Double free is not explicitly documented to work, but we rely on it
+ * even inside the library so that you can call mbedtls_rsa_free()
+ * unconditionally on an error path without checking whether it has
+ * already been called in the success path. */
+
+ mbedtls_rsa_init( &ctx, 0, 0 );
+ mbedtls_rsa_free( &ctx );
+
+ if( reinit )
+ mbedtls_rsa_init( &ctx, 0, 0 );
+ mbedtls_rsa_free( &ctx );
+
+ /* This test case always succeeds, functionally speaking. A plausible
+ * bug might trigger an invalid pointer dereference or a memory leak. */
+ goto exit;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void mbedtls_rsa_pkcs1_sign( data_t * message_str, int padding_mode,
int digest, int mod, int radix_P, char * input_P,
int radix_Q, char * input_Q, int radix_N,
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 5c97d90..b1ebf5b 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -3836,9 +3836,7 @@
if( output == NULL )
goto exit;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
- TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
+ USE_PSA_INIT( );
TEST_ASSERT( mbedtls_ssl_tls_prf( type, secret->x, secret->len,
label, random->x, random->len,
@@ -3852,6 +3850,7 @@
exit:
mbedtls_free( output );
+ USE_PSA_DONE( );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index 2bba4e2..66f0376 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -610,14 +610,12 @@
char * cn_name = NULL;
const mbedtls_x509_crt_profile *profile;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
- TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
-
mbedtls_x509_crt_init( &crt );
mbedtls_x509_crt_init( &ca );
mbedtls_x509_crl_init( &crl );
+ USE_PSA_INIT( );
+
if( strcmp( cn_name_str, "NULL" ) != 0 )
cn_name = cn_name_str;
@@ -669,6 +667,7 @@
mbedtls_x509_crt_free( &crt );
mbedtls_x509_crt_free( &ca );
mbedtls_x509_crl_free( &crl );
+ USE_PSA_DONE( );
}
/* END_CASE */
@@ -712,14 +711,12 @@
uint32_t flags = 0;
verify_print_context vrfy_ctx;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
- TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
-
mbedtls_x509_crt_init( &crt );
mbedtls_x509_crt_init( &ca );
verify_print_init( &vrfy_ctx );
+ USE_PSA_INIT( );
+
TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
TEST_ASSERT( mbedtls_x509_crt_parse_file( &ca, ca_file ) == 0 );
@@ -737,6 +734,7 @@
exit:
mbedtls_x509_crt_free( &crt );
mbedtls_x509_crt_free( &ca );
+ USE_PSA_DONE( );
}
/* END_CASE */
@@ -1024,10 +1022,6 @@
uint32_t flags;
mbedtls_x509_crt trusted, chain;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
- TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
-
/*
* We expect chain_dir to contain certificates 00.crt, 01.crt, etc.
* with NN.crt signed by NN-1.crt
@@ -1036,6 +1030,8 @@
mbedtls_x509_crt_init( &trusted );
mbedtls_x509_crt_init( &chain );
+ USE_PSA_INIT( );
+
/* Load trusted root */
TEST_ASSERT( mbedtls_x509_crt_parse_file( &trusted, ca_file ) == 0 );
@@ -1055,6 +1051,7 @@
exit:
mbedtls_x509_crt_free( &chain );
mbedtls_x509_crt_free( &trusted );
+ USE_PSA_DONE( );
}
/* END_CASE */
@@ -1069,13 +1066,11 @@
mbedtls_x509_crt trusted, chain;
const mbedtls_x509_crt_profile *profile = NULL;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
- TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
-
mbedtls_x509_crt_init( &chain );
mbedtls_x509_crt_init( &trusted );
+ USE_PSA_INIT( );
+
while( ( act = mystrsep( &chain_paths, " " ) ) != NULL )
TEST_ASSERT( mbedtls_x509_crt_parse_file( &chain, act ) == 0 );
TEST_ASSERT( mbedtls_x509_crt_parse_file( &trusted, trusted_ca ) == 0 );
@@ -1100,6 +1095,7 @@
exit:
mbedtls_x509_crt_free( &trusted );
mbedtls_x509_crt_free( &chain );
+ USE_PSA_DONE( );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index 9960989..59ea17b 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -6,12 +6,6 @@
#include "mbedtls/oid.h"
#include "mbedtls/rsa.h"
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
-#define PSA_INIT( ) PSA_ASSERT( psa_crypto_init( ) )
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
#if defined(MBEDTLS_RSA_C)
int mbedtls_rsa_decrypt_func( void *ctx, int mode, size_t *olen,
const unsigned char *input, unsigned char *output,
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index e6d6532..c2051e6 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -232,11 +232,13 @@
<ClInclude Include="..\..\include\psa\crypto_struct.h" />
<ClInclude Include="..\..\include\psa\crypto_types.h" />
<ClInclude Include="..\..\include\psa\crypto_values.h" />
+ <ClInclude Include="..\..\tests\include\test\asn1_helpers.h" />
<ClInclude Include="..\..\tests\include\test\constant_flow.h" />
<ClInclude Include="..\..\tests\include\test\fake_external_rng_for_test.h" />
<ClInclude Include="..\..\tests\include\test\helpers.h" />
<ClInclude Include="..\..\tests\include\test\macros.h" />
<ClInclude Include="..\..\tests\include\test\psa_crypto_helpers.h" />
+ <ClInclude Include="..\..\tests\include\test\psa_exercise_key.h" />
<ClInclude Include="..\..\tests\include\test\psa_helpers.h" />
<ClInclude Include="..\..\tests\include\test\random.h" />
<ClInclude Include="..\..\tests\include\test\drivers\cipher.h" />
@@ -354,10 +356,13 @@
<ClCompile Include="..\..\library\x509write_crt.c" />
<ClCompile Include="..\..\library\x509write_csr.c" />
<ClCompile Include="..\..\library\xtea.c" />
+ <ClCompile Include="..\..\tests\src\asn1_helpers.c" />
<ClCompile Include="..\..\tests\src\fake_external_rng_for_test.c" />
<ClCompile Include="..\..\tests\src\helpers.c" />
<ClCompile Include="..\..\tests\src\psa_crypto_helpers.c" />
+ <ClCompile Include="..\..\tests\src\psa_exercise_key.c" />
<ClCompile Include="..\..\tests\src\random.c" />
+ <ClCompile Include="..\..\tests\src\threading_helpers.c" />
<ClCompile Include="..\..\3rdparty\everest\library\everest.c" />
<ClCompile Include="..\..\3rdparty\everest\library\Hacl_Curve25519_joined.c" />
<ClCompile Include="..\..\3rdparty\everest\library\x25519.c" />