Implement psa_generate_key_custom
Implement `psa_generate_key_custom()` and
`psa_key_derivation_output_key_custom()`. These functions replace
`psa_generate_key_ext()` and `psa_key_derivation_output_key_ext()`.
They have the same functionality, but a slightly different interface:
the `ext` functions use a structure with a flexible array member to pass
variable-length data, while the `custom` functions use a separate parameter.
Keep the `ext` functions for backward compatibility with Mbed TLS 3.6.0.
But make them a thin wrapper around the new `custom` functions.
Duplicate the test code and data. The test cases have to be duplicated
anyway, and the test functions are individually more readable this way.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 3525da2..9dbd014 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -3781,6 +3781,81 @@
* the policy must be the same as in the current
* operation.
* \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] custom Customization parameters for the key generation.
+ * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ * with \p custom_data_length = 0,
+ * this function is equivalent to
+ * psa_key_derivation_output_key().
+ * \param[in] custom_data Variable-length data associated with \c custom.
+ * \param custom_data_length
+ * Length of `custom_data` in bytes.
+ * \param[out] key On success, an identifier for the newly created
+ * key. For persistent keys, this is the key
+ * identifier defined in \p attributes.
+ * \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * If the key is persistent, the key material and the key's metadata
+ * have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ * This is an attempt to create a persistent key, and there is
+ * already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ * There was not enough data to create the desired key.
+ * Note that in this case, no output is written to the output buffer.
+ * The operation's capacity is set to 0, thus subsequent calls to
+ * this function will not succeed, even with a smaller output buffer.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * The key type or key size is not supported, either by the
+ * implementation in general or in this particular location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The provided key attributes are not valid for the operation.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The #PSA_KEY_DERIVATION_INPUT_SECRET or
+ * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
+ * key; or one of the inputs was a key whose policy didn't allow
+ * #PSA_KEY_USAGE_DERIVE.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (it must be active and completed
+ * all required input steps), or the library has not been previously
+ * initialized by psa_crypto_init().
+ * It is implementation-dependent whether a failure to initialize
+ * results in this error code.
+ */
+psa_status_t psa_key_derivation_output_key_custom(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ const psa_custom_key_parameters_t *custom,
+ const uint8_t *custom_data,
+ size_t custom_data_length,
+ mbedtls_svc_key_id_t *key);
+
+/** Derive a key from an ongoing key derivation operation with custom
+ * production parameters.
+ *
+ * See the description of psa_key_derivation_out_key() for the operation of
+ * this function with the default production parameters.
+ * Mbed TLS currently does not currently support any non-default production
+ * parameters.
+ *
+ * \note This function is experimental and may change in future minor
+ * versions of Mbed TLS.
+ *
+ * \param[in] attributes The attributes for the new key.
+ * If the key type to be created is
+ * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
+ * the policy must be the same as in the current
+ * operation.
+ * \param[in,out] operation The key derivation operation object to read from.
* \param[in] params Customization parameters for the key derivation.
* When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
* with \p params_data_length = 0,
@@ -4137,6 +4212,62 @@
* See the description of psa_generate_key() for the operation of this
* function with the default production parameters. In addition, this function
* supports the following production customizations, described in more detail
+ * in the documentation of ::psa_custom_key_parameters_t:
+ *
+ * - RSA keys: generation with a custom public exponent.
+ *
+ * \note This function is experimental and may change in future minor
+ * versions of Mbed TLS.
+ *
+ * \param[in] attributes The attributes for the new key.
+ * \param[in] custom Customization parameters for the key generation.
+ * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ * with \p custom_data_length = 0,
+ * this function is equivalent to
+ * psa_generate_key().
+ * \param[in] custom_data Variable-length data associated with \c custom.
+ * \param custom_data_length
+ * Length of `custom_data` in bytes.
+ * \param[out] key On success, an identifier for the newly created
+ * key. For persistent keys, this is the key
+ * identifier defined in \p attributes.
+ * \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * If the key is persistent, the key material and the key's metadata
+ * have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ * This is an attempt to create a persistent key, and there is
+ * already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The library has not been previously initialized by psa_crypto_init().
+ * It is implementation-dependent whether a failure to initialize
+ * results in this error code.
+ */
+psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes,
+ const psa_custom_key_parameters_t *custom,
+ const uint8_t *custom_data,
+ size_t custom_data_length,
+ mbedtls_svc_key_id_t *key);
+
+/**
+ * \brief Generate a key or key pair using custom production parameters.
+ *
+ * See the description of psa_generate_key() for the operation of this
+ * function with the default production parameters. In addition, this function
+ * supports the following production customizations, described in more detail
* in the documentation of ::psa_key_production_parameters_t:
*
* - RSA keys: generation with a custom public exponent.
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 3913551..dcc2a83 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -223,9 +223,28 @@
return v;
}
-struct psa_key_production_parameters_s {
+struct psa_custom_key_parameters_s {
/* Future versions may add other fields in this structure. */
uint32_t flags;
+};
+
+/** The default production parameters for key generation or key derivation.
+ *
+ * Calling psa_generate_key_custom() or psa_key_derivation_output_key_custom()
+ * with `custom=PSA_CUSTOM_KEY_PARAMETERS_INIT` and `custom_data_length=0` is
+ * equivalent to calling psa_generate_key() or psa_key_derivation_output_key()
+ * respectively.
+ */
+#define PSA_CUSTOM_KEY_PARAMETERS_INIT { 0 }
+
+/* This is a deprecated variant of `struct psa_custom_key_parameters_s`.
+ * It has exactly the same layout, plus an extra field which is a flexible
+ * array members. Thus a `const struct psa_key_production_parameters_s*`
+ * can be passed to any function that reads a
+ * `const struct psa_custom_key_parameters_s*`.
+ */
+struct psa_key_production_parameters_s {
+ uint32_t flags;
uint8_t data[];
};
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index c21bad8..f831486 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -457,6 +457,30 @@
/** \brief Custom parameters for key generation or key derivation.
*
+ * This is a structure type with at least the following field:
+ *
+ * - \c flags: an unsigned integer type. 0 for the default production parameters.
+ *
+ * Functions that take such a structure as input also take an associated
+ * input buffer \c custom_data of length \c custom_data_length.
+ *
+ * The interpretation of this structure and the associated \c custom_data
+ * parameter depend on the type of the created key.
+ *
+ * - #PSA_KEY_TYPE_RSA_KEY_PAIR:
+ * - \c flags: must be 0.
+ * - \c custom_data: the public exponent, in little-endian order.
+ * This must be an odd integer and must not be 1.
+ * Implementations must support 65537, should support 3 and may
+ * support other values.
+ * When not using a driver, Mbed TLS supports values up to \c INT_MAX.
+ * If this is empty, the default value 65537 is used.
+ * - Other key types: reserved for future use. \c flags must be 0.
+ */
+typedef struct psa_custom_key_parameters_s psa_custom_key_parameters_t;
+
+/** \brief Custom parameters for key generation or key derivation.
+ *
* This is a structure type with at least the following fields:
*
* - \c flags: an unsigned integer type. 0 for the default production parameters.