Key derivation by small input steps: proof-of-concept
Document the new API. Keep the old one.
Implement for HKDF. Use it in a few test cases.
Key agreement is still unchanged.
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 683feb8..6005269 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -1963,6 +1963,22 @@
psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator,
size_t *capacity);
+/** Set the maximum capacity of a generator.
+ *
+ * \param[in,out] generator The generator object to modify.
+ * \param capacity The new capacity of the generator.
+ * It must be less or equal to the generator's
+ * current capacity.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \p capacity is larger than the generator's current capacity.
+ * \retval #PSA_ERROR_BAD_STATE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ */
+psa_status_t psa_set_generator_capacity(psa_crypto_generator_t *generator,
+ size_t capacity);
+
/** Read some data from a generator.
*
* This function reads and returns a sequence of bytes from a generator.
@@ -2090,6 +2106,131 @@
/** Set up a key derivation operation.
*
+ * A key derivation algorithm takes some inputs and uses them to create
+ * a byte generator which can be used to produce keys and other
+ * cryptographic material.
+ *
+ * To use a generator for key derivation:
+ * - Start with an initialized object of type #psa_crypto_generator_t.
+ * - Call psa_key_derivation_setup() to select the algorithm.
+ * - Provide the inputs for the key derivation by calling
+ * psa_key_derivation_input_bytes() or psa_key_derivation_input_key()
+ * as appropriate. Which inputs are needed, in what order, and whether
+ * they may be keys and if so of what type depends on the algorithm.
+ * - Optionally set the generator's maximum capacity with
+ * psa_set_generator_capacity(). You may do this before, in the middle of
+ * or after providing inputs. For some algorithms, this step is mandatory
+ * because the output depends on the maximum capacity.
+ * - Generate output with psa_generator_read() or
+ * psa_generator_import_key(). Successive calls to these functions
+ * use successive output bytes from the generator.
+ * - Clean up the generator object with psa_generator_abort().
+ *
+ * \param[in,out] generator The generator object to set up. It must
+ * have been initialized but not set up yet.
+ * \param alg The key derivation algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c alg is not a key derivation algorithm.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \c alg is not supported or is not a key derivation algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ */
+psa_status_t psa_key_derivation_setup(psa_crypto_generator_t *generator,
+ psa_algorithm_t alg);
+
+/** Provide an input for key derivation.
+ *
+ * Which inputs are required and in what order depends on the type of
+ * key derivation algorithm.
+ *
+ * - For HKDF (#PSA_ALG_HKDF), the following inputs are supported:
+ * - #PSA_KDF_STEP_SALT is the salt used in the "extract" step.
+ * It is optional; if omitted, the derivation uses an empty salt.
+ * - #PSA_KDF_STEP_SECRET is the secret key used in the "extract" step.
+ * It may be a key of type #PSA_KEY_TYPE_DERIVE with the
+ * usage flag #PSA_KEY_USAGE_DERIVE.
+ * - #PSA_KDF_STEP_INFO is the info string used in the "expand" step.
+ * You must pass #PSA_KDF_STEP_SALT before #PSA_KDF_STEP_SECRET.
+ * #PSA_KDF_STEP_INFO may be passed at any time before starting to
+ * generate output.
+ *
+ * \param[in,out] generator The generator object to use. It must
+ * have been set up with
+ * psa_key_derivation_setup() and must not
+ * have produced any output yet.
+ * \param step Which step the input data is for.
+ * See above for the permitted values
+ * depending on the algorithm.
+ * \param[in] data Input data to use.
+ * \param data_length Size of the \p data buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c step is not compatible with the generator's algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ * The value of \p step is not valid given the state of \p generator.
+ * \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_key_derivation_input_bytes(psa_crypto_generator_t *generator,
+ psa_key_derivation_step_t step,
+ const uint8_t *data,
+ size_t data_length);
+
+/** Provide an input for key derivation in the form of a key.
+ *
+ * See the descrition of psa_key_derivation_input_bytes() regarding
+ * what inputs are supported and in what order. An input step may only be
+ * a key if the descrition of psa_key_derivation_input_bytes() explicitly
+ * allows it.
+ *
+ * \param[in,out] generator The generator object to use. It must
+ * have been set up with
+ * psa_key_derivation_setup() and must not
+ * have produced any output yet.
+ * \param step Which step the input data is for.
+ * \param handle Handle to the secret key.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c step is not compatible with the generator's algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ * The value of \p step is not valid given the state of \p generator.
+ * \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_key_derivation_input_key(psa_crypto_generator_t *generator,
+ psa_key_derivation_step_t step,
+ psa_key_handle_t handle);
+
+/** Set up a key derivation operation.
+ *
* A key derivation algorithm takes three inputs: a secret input \p key and
* two non-secret inputs \p label and p salt.
* The result of this function is a byte generator which can
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index ee3ecd7..bebc5c4 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -165,6 +165,8 @@
#endif
uint8_t offset_in_block;
uint8_t block_number;
+ uint8_t state : 2;
+ uint8_t info_set : 1;
} psa_hkdf_generator_t;
#endif /* MBEDTLS_MD_C */
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 9b44d6a..637e07c 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -98,4 +98,13 @@
/**@}*/
+/** \defgroup derivation Key derivation
+ * @{
+ */
+
+/** \brief Encoding of the step of a key derivation. */
+typedef uint16_t psa_key_derivation_step_t;
+
+/**@}*/
+
#endif /* PSA_CRYPTO_TYPES_H */
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 4d25835..5c81acd 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -1417,4 +1417,16 @@
/**@}*/
+/** \defgroup derivation Key derivation
+ * @{
+ */
+
+#define PSA_KDF_STEP_SECRET ((psa_key_derivation_step_t)0x0101)
+#define PSA_KDF_STEP_LABEL ((psa_key_derivation_step_t)0x0201)
+#define PSA_KDF_STEP_SALT ((psa_key_derivation_step_t)0x0202)
+#define PSA_KDF_STEP_INFO ((psa_key_derivation_step_t)0x0203)
+#define PSA_KDF_STEP_PEER_KEY ((psa_key_derivation_step_t)0x0301)
+
+/**@}*/
+
#endif /* PSA_CRYPTO_VALUES_H */