Skip to content
317 changes: 316 additions & 1 deletion include/psa/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,9 @@ static size_t psa_get_key_bits(const psa_key_attributes_t *attributes);
* you must call psa_reset_key_attributes() to free these resources.
*
* \param[in] handle Handle to the key to query.
* \param[in,out] attributes On success, the attributes of the key.
* \param[in,out] attributes On entry, this structure must be in a
* valid state.
* On success, the attributes of the key.
* On failure, equivalent to a
* freshly-initialized structure.
*
Expand Down Expand Up @@ -852,7 +854,320 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle,
size_t data_size,
size_t *data_length);

/**
* \brief Export a key and its metadata in wrapped form.
*
* A wrapped form of the key object preserves the confidentiality and
* authenticity of the key material and the authenticity of the key
* policy. In practical terms, the key material is encrypted, and
* the key data and metadata are authenticated together.
*
* The format of the wrapped data is implementation-dependent. It may depend
* both on the choice of wrapping key and on the type of key to wrap.
*
* The policy on the key must have the usage flag
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to specify which key needs this policy?

* #PSA_KEY_USAGE_EXPORT_WRAPPED set.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#PSA_KEY_USAGE_BACKUP for this API

*
* \note This specification does not currently provide a way to
* create a wrapping key. Many implementations provide a
* predefined wrapping key #PSA_KEY_ID_WRAP_BOUND.
*
* \param wrapping_key Handle to the key to wrap with.
* \param handle Handle to the key to export in wrapped form.
* \param[out] data Buffer where the wrapped key data is to be written.
* \param data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes
* that make up the wrapped key data.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INVALID_HANDLE
* One or both of \p handle and \p wrapping_key is not a valid
* handle to a key.
* \retval #PSA_ERROR_NOT_PERMITTED
* The key \p handle does not have the #PSA_KEY_USAGE_BACKUP flag.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p wrapping_key does not support wrapping keys with metadata.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p wrapping_key does not support wrapping the key designated
* by \p handle.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p data buffer is too small. You can determine a
* sufficient buffer size by calling
* #PSA_WRAP_KEY_WITH_POLICY_OUTPUT_SIZE(\c type, \c bits)
* where \c type is the key type of \p handle
* and \c bits is the key size of \p handle in bits.
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \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_wrap_key_with_policy(psa_key_handle_t wrapping_key,
psa_key_handle_t handle,
uint8_t *data,
size_t data_size,
size_t *data_length);

/**
* \brief Import a wrapped key with its metadata.
*
* This function supports any output from psa_wrap_key_with_policy().
* For symmetric wrapping, you must unwrap with the same key that was
* used to wrap. For asymmetric wrapping where the wrapping operation uses
* a public key and the unwrapping operation uses the corresponding private
* key, you must unwrap with the corresponding unwrapping key.
*
* The resulting key object has the same attributes as the original key:
* same lifetime, same identifier if persistent, same usage policy.
* To restore a key to a different location or with a different policy,
* use psa_unwrap_key_to_alternate_lifetime().
*
* \param wrapping_key Handle to the key to unwrap with.
* \param[in] data Buffer containing the wrapped key material.
* The expected format of this buffer depends
* on the wrapping key.
* \param data_length Size of the \p data buffer in bytes.
* \param[out] handle On success, a handle to the newly created key.
* \c 0 on failure.
*
* \retval #PSA_SUCCESS
* Success.
* If the unwrapped 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_INVALID_ARGUMENT
* The key data is not correctly formatted.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p wrapping_key does not support unwrapping keys with metadata.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* \p data is not a valid wrapped key for \p wrapping_key.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Some of the metadata encoded in \p data is not supported.
* This can only happen when attempting to unwrap a key that
* was wrapped under a different implementation or a
* differently-configured implementation.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \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_unwrap_key_with_policy(psa_key_handle_t wrapping_key,
const uint8_t *data,
size_t data_length,
psa_key_handle_t *handle);

/**
* \brief Import a wrapped key with its metadata to volatile memory.
*
* This function supports any output from psa_wrap_key_with_policy()
* where the wrapped key has the usage flag #PSA_KEY_USAGE_COPY set.
* For symmetric wrapping, you must unwrap with the same key that was
* used to wrap. For asymmetric wrapping where the wrapping operation uses
* a public key and the unwrapping operation uses the corresponding private
* key, you must unwrap with the corresponding unwrapping key.
*
* The resulting key object has the same attributes as the original key
* apart from its lifetime, in particular it has the same usage policy.
* To unwrap a key and give it a more restrictive policy or place it
* in a different location:
* -# Call psa_unwrap_key_to_alternate_lifetime() to unwrap the key to a
* volatile location.
* -# If desired, call psa_get_key_attributes() to retrieve the
* attributes of the key, then modify them as desired for the
* subsequent copy.
* -# Call psa_copy_key() to copy the key to its desired location
* (volatile or persistent) and with the desired policy.
* -# Call psa_destroy_key() to destroy the intermediate volatile key.
*
* The resulting key does not have a persistent identifier, therefore
* the target lifetime must be volatile.
*
* \param wrapping_key Handle to the key to unwrap with.
* \param lifetime The lifetime to unwrap to.
* This must be a volatile lifetime.
* The wrapping key may constrain which lifetimes
* are permitted; such constraints are
* implementation-defined. As a guideline,
* implementations should allow unwrapping a key
* to a lifetime that is in the same location
* as the original key.
* \param[in] data Buffer containing the wrapped key material.
* The expected format of this buffer depends
* on the wrapping key.
* \param data_length Size of the \p data buffer in bytes.
* \param[out] handle On success, a handle to the newly created key.
* \c 0 on failure.
*
* \retval #PSA_SUCCESS
* Success.
* If the unwrapped key is persistent, the key material and the
* key's metadata have been saved to persistent storage.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p lifetime is not a volatile lifetime.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key data is not correctly formatted.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p wrapping_key does not support unwrapping keys with metadata.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* \p data is not a valid wrapped key for \p wrapping_key.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Some of the metadata encoded in \p data is not supported.
* This can only happen when attempting to unwrap a key that
* was wrapped under a different implementation or a
* differently-configured implementation.
* \retval #PSA_ERROR_NOT_PERMITTED
* The wrapped key does not have the #PSA_KEY_USAGE_COPY flag.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \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_unwrap_key_to_alternate_lifetime(
psa_key_handle_t wrapping_key,
psa_key_lifetime_t lifetime,
const uint8_t *data,
size_t data_length,
psa_key_handle_t *handle);

/**
* \brief Export key material in wrapped form.
*
* A wrapped form of the key material preserves the confidentiality
* and authenticity of the key material. In practical terms, the key
* material is encrypted and authenticated.
*
* The policy on the key to wrap must have the usage flag
* #PSA_KEY_USAGE_EXPORT_WRAPPED set.
* The policy on the wrapping key must have the usage flag
* #PSA_KEY_USAGE_WRAP_OTHER_KEY set.
*
* \param wrapping_key Handle to the key to wrap with.
* \param alg The key wrapping algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_KEY_WRAP(\p alg) is true).
* \param handle Handle to the key whose material is to be
* exported in wrapped form.
* \param[out] data Buffer where the wrapped key data is to be written.
* \param data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes
* that make up the wrapped key data.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INVALID_HANDLE
* One or both of \p handle and \p wrapping_key is not a valid
* handle to a key.
* \retval #PSA_ERROR_NOT_PERMITTED
* The key \p handle does not have the #PSA_KEY_USAGE_BACKUP flag.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy-pasta: presume PSA_KEY_USAGE_EXPORT_WRAPPED

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This issue is still present.

* \retval #PSA_ERROR_NOT_PERMITTED
* The key \p wrapping_key does not have the
* #PSA_KEY_USAGE_WRAP_OTHER_KEY flag.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p wrapping_key does not support wrapping key material.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p wrapping_key does not support wrapping the key designated
* by \p handle.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p data buffer is too small. You can determine a
* sufficient buffer size by calling
* #PSA_WRAP_KEY_MATERIAL_OUTPUT_SIZE(\p alg, \c type, \c bits)
* where \c type is the key type of \p handle
* and \c bits is the key size of \p handle in bits.
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \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_wrap_key_material(psa_key_handle_t wrapping_key,
psa_algorithm_t alg,
psa_key_handle_t handle,
uint8_t *data,
size_t data_size,
size_t *data_length);

/**
* \brief Import wrapped key material.
*
* The policy on the wrapping key must have the usage flag
* #PSA_KEY_USAGE_UNWRAP_OTHER_KEY set.
*
* \param wrapping_key Handle to the key to unwrap with.
* \param alg The key unwrapping algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_KEY_WRAP(\p alg) is true).
* \param[in] attributes The attributes for the new key.
* They are used in the same way as by
* psa_import_key().
* \param[in] data Buffer containing the key data. The expected
* format of this buffer depends on the wrapping
* key and on the type declared in \p attributes.
* \param data_length Size of the \p data buffer in bytes.
* \param[out] handle On success, a handle to the newly created key.
* \c 0 on failure.
*
* \retval #PSA_SUCCESS
* Success.
* If the unwrapped 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_PERMITTED
* The key \p wrapping_key does not have the
* #PSA_KEY_USAGE_UNWRAP_OTHER_KEY flag.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key attributes, as a whole, are invalid.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key data is not correctly formatted.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The size in \p attributes is nonzero and does not match the size
* of the key data.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p wrapping_key does not support unwrapping keys with metadata.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* \p data is not a valid wrapped key for \p wrapping_key.
* \retval #PSA_ERROR_NOT_SUPPORTED
* The key type or key size is not supported, either by the
* implementation in general or in this particular persistent location.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \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_unwrap_key_material(psa_key_handle_t wrapping_key,
psa_algorithm_t alg,
const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
psa_key_handle_t *handle);

/**@}*/

Expand Down
55 changes: 53 additions & 2 deletions include/psa/crypto_sizes.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,8 +641,8 @@
*
* \return If the parameters are valid and supported, return
* a buffer size in bytes that guarantees that
* psa_sign_hash() will not fail with
* #PSA_ERROR_BUFFER_TOO_SMALL.
* psa_export_key() (and psa_export_public_key() if applicable)
will not fail with #PSA_ERROR_BUFFER_TOO_SMALL.
* If the parameters are a valid combination that is not supported
* by the implementation, this macro shall return either a
* sensible size or 0.
Expand All @@ -659,4 +659,55 @@
PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \
0)

/** Sufficient output buffer size for psa_wrap_key_with_policy().
*
* This macro returns a compile-time constant if its arguments are
* compile-time constants.
*
* \warning This function may call its arguments multiple times or
* zero times, so you should not pass arguments that contain
* side effects.
*
* \param key_type A supported key type.
* \param key_bits The size of the key in bits.
*
* \return If the parameters are valid and supported, return
* a buffer size in bytes that guarantees that
* psa_wrap_key_with_policy() will not fail with
* #PSA_ERROR_BUFFER_TOO_SMALL.
* If the parameters are a valid combination that is not supported
* by the implementation, this macro shall return either a
* sensible size or 0.
* If the parameters are not valid, the
* return value is unspecified.
*/
#define PSA_WRAP_KEY_WITH_POLICY_OUTPUT_SIZE(key_type, key_bits) \
0u /*not implemented yet*/

/** Sufficient output buffer size for psa_wrap_key_material().
*
* This macro returns a compile-time constant if its arguments are
* compile-time constants.
*
* \warning This function may call its arguments multiple times or
* zero times, so you should not pass arguments that contain
* side effects.
*
* \param alg The key wrapping algorithm.
* \param key_type A supported key type.
* \param key_bits The size of the key in bits.
*
* \return If the parameters are valid and supported, return
* a buffer size in bytes that guarantees that
* psa_wrap_key_material() will not fail with
* #PSA_ERROR_BUFFER_TOO_SMALL.
* If the parameters are a valid combination that is not supported
* by the implementation, this macro shall return either a
* sensible size or 0.
* If the parameters are not valid, the
* return value is unspecified.
*/
#define PSA_WRAP_KEY_MATERIAL_OUTPUT_SIZE(alg, key_type, key_bits) \
0u /*not implemented yet*/

#endif /* PSA_CRYPTO_SIZES_H */
Loading