diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index 8cc8cf5c..c4cbc118 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -10,6 +10,8 @@ typedef /* implementation-defined type */ psa_hash_operation_t; typedef /* implementation-defined type */ psa_key_attributes_t; typedef /* implementation-defined type */ psa_key_derivation_operation_t; typedef uint16_t psa_key_derivation_step_t; +typedef uint32_t psa_key_format_option_t; +typedef uint32_t psa_key_format_t; typedef uint32_t psa_key_id_t; typedef uint32_t psa_key_lifetime_t; typedef uint32_t psa_key_location_t; @@ -224,6 +226,16 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) #define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) #define PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE /* implementation-defined value */ +#define PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE \ + /* implementation-defined value */ +#define PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE(format, options, key_type, key_bits) \ + /* implementation-defined value */ +#define PSA_EXPORT_FORMATTED_KEY_PAIR_MAX_SIZE \ + /* implementation-defined value */ +#define PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE \ + /* implementation-defined value */ +#define PSA_EXPORT_FORMATTED_PUBLIC_KEY_OUTPUT_SIZE(format, options, key_type, key_bits) \ + /* implementation-defined value */ #define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits) \ /* implementation-defined value */ #define PSA_EXPORT_KEY_PAIR_MAX_SIZE /* implementation-defined value */ @@ -255,6 +267,19 @@ typedef struct psa_custom_key_parameters_t { #define PSA_KEY_DERIVATION_OPERATION_INIT /* implementation-defined value */ #define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY \ /* implementation-defined value */ +#define PSA_KEY_FORMAT_DEFAULT ((psa_key_format_t) 0) +#define PSA_KEY_FORMAT_EC_PRIVATE_KEY /* implementation-defined value */ +#define PSA_KEY_FORMAT_ONE_ASYMMETRIC_KEY /* implementation-defined value */ +#define PSA_KEY_FORMAT_OPTION_DEFAULT ((psa_key_format_option_t) 0) +#define PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED \ + /* implementation-defined value */ +#define PSA_KEY_FORMAT_OPTION_PEM /* implementation-defined value */ +#define PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN \ + /* implementation-defined value */ +#define PSA_KEY_FORMAT_RSA_PRIVATE_KEY /* implementation-defined value */ +#define PSA_KEY_FORMAT_RSA_PUBLIC_KEY /* implementation-defined value */ +#define PSA_KEY_FORMAT_SUBJECT_PUBLIC_KEY_INFO \ + /* implementation-defined value */ #define PSA_KEY_ID_NULL ((psa_key_id_t)0) #define PSA_KEY_ID_USER_MAX ((psa_key_id_t)0x3fffffff) #define PSA_KEY_ID_USER_MIN ((psa_key_id_t)0x00000001) @@ -499,6 +524,18 @@ psa_status_t psa_copy_key(psa_key_id_t source_key, psa_key_id_t * target_key); psa_status_t psa_crypto_init(void); psa_status_t psa_destroy_key(psa_key_id_t key); +psa_status_t psa_export_formatted_key(psa_key_format_t format, + psa_key_format_option_t options, + psa_key_id_t key, + uint8_t * data, + size_t data_size, + size_t * data_length); +psa_status_t psa_export_formatted_public_key(psa_key_format_t format, + psa_key_format_option_t options, + psa_key_id_t key, + uint8_t * data, + size_t data_size, + size_t * data_length); psa_status_t psa_export_key(psa_key_id_t key, uint8_t * data, size_t data_size, @@ -558,6 +595,11 @@ psa_status_t psa_hash_update(psa_hash_operation_t * operation, psa_status_t psa_hash_verify(psa_hash_operation_t * operation, const uint8_t * hash, size_t hash_length); +psa_status_t psa_import_formatted_key(const psa_key_attributes_t * attributes, + psa_key_format_t format, + const uint8_t * data, + size_t data_length, + psa_key_id_t * key); psa_status_t psa_import_key(const psa_key_attributes_t * attributes, const uint8_t * data, size_t data_length, diff --git a/doc/crypto/api/keys/management.rst b/doc/crypto/api/keys/management.rst index b6a7391c..ec23af30 100644 --- a/doc/crypto/api/keys/management.rst +++ b/doc/crypto/api/keys/management.rst @@ -14,14 +14,21 @@ Key creation New keys can be created in the following ways: -* `psa_import_key()` creates a key from a data buffer provided by the application. +* `psa_import_key()` and `psa_import_formatted_key()` create a key from a data buffer provided by the application. + See :secref:`key-import`. * `psa_generate_key()` and `psa_generate_key_custom()` create a key from randomly generated data. -* `psa_key_derivation_output_key()` and `psa_key_derivation_output_key_custom()` create a key from data generated by a pseudorandom derivation process. See :secref:`kdf`. -* `psa_key_agreement()` creates a key from the shared secret result of a key agreement process. See :secref:`key-agreement`. -* `psa_pake_get_shared_key()` creates a key from the shared secret result of a password-authenticated key exchange. See :secref:`pake`. + See :secref:`key-generation`. +* `psa_key_derivation_output_key()` and `psa_key_derivation_output_key_custom()` create a key from data generated by a pseudorandom derivation process. + See :secref:`kdf`. +* `psa_key_agreement()` creates a key from the shared secret result of a key agreement process. + See :secref:`key-agreement`. +* `psa_pake_get_shared_key()` creates a key from the shared secret result of a password-authenticated key exchange. + See :secref:`pake`. * `psa_copy_key()` duplicates an existing key with a different lifetime or with a more restrictive usage policy. + See :secref:`key-duplication`. -When creating a key, the attributes for the new key are specified in a `psa_key_attributes_t` object. Each key creation function defines how it uses the attributes. +When creating a key, the attributes for the new key are specified in a `psa_key_attributes_t` object. +Each key creation function defines how it uses the attributes. .. note:: @@ -29,17 +36,23 @@ When creating a key, the attributes for the new key are specified in a `psa_key_ The application must set the key algorithm policy and the appropriate key usage flags in the attributes in order for the key to be used in any cryptographic operations. -.. function:: psa_import_key +.. _key-generation: + +Key generation +-------------- + +.. function:: psa_generate_key .. summary:: - Import a key in binary format. + Generate a key or key pair. .. param:: const psa_key_attributes_t * attributes The attributes for the new key. The following attributes are required for all keys: - * The key type determines how the ``data`` buffer is interpreted. + * The key type. It must not be an asymmetric public key. + * The key size. It must be a valid size for the key type. The following attributes must be set for keys used in cryptographic operations: @@ -51,24 +64,14 @@ When creating a key, the attributes for the new key are specified in a `psa_key_ * The key lifetime, see :secref:`key-lifetimes`. * The key identifier is required for a key with a persistent lifetime, see :secref:`key-identifiers`. - The following attributes are optional: - - * If the key size is nonzero, it must be equal to the key size determined from ``data``. - .. note:: This is an input parameter: it is not updated with the final key attributes. The final attributes of the new key can be queried by calling `psa_get_key_attributes()` with the key's identifier. - .. param:: const uint8_t * data - Buffer containing the key data. - The content of this buffer is interpreted according to the type declared in ``attributes``. - - All implementations must support at least the format described in the *Key format* section of the chosen key type. - Implementations can support other formats, but be conservative in interpreting the key data: it is recommended that implementations reject content if it might be erroneous, for example, if it is the wrong type or is truncated. - .. param:: size_t data_length - Size of the ``data`` buffer in bytes. .. param:: psa_key_id_t * key - On success, an identifier for the newly created key. `PSA_KEY_ID_NULL` on failure. + On success, an identifier for the newly created key. + For persistent keys, this is the key identifier defined in ``attributes``. + `PSA_KEY_ID_NULL` on failure. .. return:: psa_status_t .. retval:: PSA_SUCCESS @@ -81,38 +84,35 @@ When creating a key, the attributes for the new key are specified in a `psa_key_ .. retval:: PSA_ERROR_INVALID_ARGUMENT The following conditions can result in this error: - * The key type is invalid. - * The key size is nonzero, and is incompatible with the key data in ``data``. + * The key type is invalid, or is an asymmetric public key type. + * The key size is not valid for the key type. * The key lifetime is invalid. * The key identifier is not valid for the key lifetime. * The key usage flags include invalid values. * The key's permitted-usage algorithm is invalid. * The key attributes, as a whole, are invalid. - * The key data is not correctly formatted for the key type. .. retval:: PSA_ERROR_NOT_PERMITTED The implementation does not permit creating a key with the specified attributes due to some implementation-specific policy. .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY - .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE + .. retval:: PSA_ERROR_INSUFFICIENT_ENTROPY .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE .. retval:: PSA_ERROR_STORAGE_FAILURE .. retval:: PSA_ERROR_DATA_CORRUPT .. retval:: PSA_ERROR_DATA_INVALID - .. retval:: PSA_ERROR_CORRUPTION_DETECTED .. retval:: PSA_ERROR_BAD_STATE The library requires initializing by a call to `psa_crypto_init()`. - The key is extracted from the provided ``data`` buffer. Its location, policy, and type are taken from ``attributes``. - - The provided key data determines the key size. The attributes can optionally specify a key size; in this case it must match the size determined from the key data. A key size of ``0`` in ``attributes`` --- the default value --- indicates that the key size is solely determined by the key data. - - Implementations must reject an attempt to import a key of size ``0``. + The key is generated randomly. Its location, policy, type and size are taken from ``attributes``. - This function supports any output from `psa_export_key()`. Each key type in :secref:`key-types` describes the expected format of keys. + Implementations must reject an attempt to generate a key of size ``0``. - This specification defines a single format for each key type. Implementations can optionally support other formats in addition to the standard format. It is recommended that implementations that support other formats ensure that the formats are clearly unambiguous, to minimize the risk that an invalid input is accidentally interpreted according to a different format. + The key type definitions in :secref:`key-types` provide specific details relating to generation of the key. .. note:: - The |API| does not support asymmetric private key objects outside of a key pair. To import a private key, the ``attributes`` must specify the corresponding key pair type. Depending on the key type, either the import format contains the public key data or the implementation will reconstruct the public key from the private key as needed. + + This function is equivalent to calling `psa_generate_key_custom()` with the production parameters `PSA_CUSTOM_KEY_PARAMETERS_INIT` and ``custom_data_length == 0`` (``custom_data`` is ignored). .. struct:: psa_custom_key_parameters_t :type: @@ -158,79 +158,6 @@ When creating a key, the attributes for the new key are specified in a `psa_key_ Calling `psa_generate_key_custom()` or `psa_key_derivation_output_key_custom()` with :code:`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. -.. function:: psa_generate_key - - .. summary:: - Generate a key or key pair. - - .. param:: const psa_key_attributes_t * attributes - The attributes for the new key. - - The following attributes are required for all keys: - - * The key type. It must not be an asymmetric public key. - * The key size. It must be a valid size for the key type. - - The following attributes must be set for keys used in cryptographic operations: - - * The key permitted-algorithm policy, see :secref:`permitted-algorithms`. - * The key usage flags, see :secref:`key-usage-flags`. - - The following attributes must be set for keys that do not use the default volatile lifetime: - - * The key lifetime, see :secref:`key-lifetimes`. - * The key identifier is required for a key with a persistent lifetime, see :secref:`key-identifiers`. - - .. note:: - This is an input parameter: it is not updated with the final key attributes. - The final attributes of the new key can be queried by calling `psa_get_key_attributes()` with the key's identifier. - - .. param:: psa_key_id_t * key - On success, an identifier for the newly created key. - For persistent keys, this is the key identifier defined in ``attributes``. - `PSA_KEY_ID_NULL` on failure. - - .. return:: psa_status_t - .. 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 - The key attributes, as a whole, are not supported, either by the implementation in general or in the specified storage location. - .. retval:: PSA_ERROR_INVALID_ARGUMENT - The following conditions can result in this error: - - * The key type is invalid, or is an asymmetric public key type. - * The key size is not valid for the key type. - * The key lifetime is invalid. - * The key identifier is not valid for the key lifetime. - * The key usage flags include invalid values. - * The key's permitted-usage algorithm is invalid. - * The key attributes, as a whole, are invalid. - .. retval:: PSA_ERROR_NOT_PERMITTED - The implementation does not permit creating a key with the specified attributes due to some implementation-specific policy. - .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY - .. retval:: PSA_ERROR_INSUFFICIENT_ENTROPY - .. retval:: PSA_ERROR_COMMUNICATION_FAILURE - .. retval:: PSA_ERROR_CORRUPTION_DETECTED - .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE - .. retval:: PSA_ERROR_STORAGE_FAILURE - .. retval:: PSA_ERROR_DATA_CORRUPT - .. retval:: PSA_ERROR_DATA_INVALID - .. retval:: PSA_ERROR_BAD_STATE - The library requires initializing by a call to `psa_crypto_init()`. - - The key is generated randomly. Its location, policy, type and size are taken from ``attributes``. - - Implementations must reject an attempt to generate a key of size ``0``. - - The key type definitions in :secref:`key-types` provide specific details relating to generation of the key. - - .. note:: - - This function is equivalent to calling `psa_generate_key_custom()` with the production parameters `PSA_CUSTOM_KEY_PARAMETERS_INIT` and ``custom_data_length == 0`` (``custom_data`` is ignored). - .. function:: psa_generate_key_custom .. summary:: @@ -315,6 +242,11 @@ When creating a key, the attributes for the new key are specified in a `psa_key_ See the documentation of `psa_custom_key_parameters_t` for a list of non-default production parameters. See the key type definitions in :secref:`key-types` for details of the custom production parameters used for key generation. +.. _key-duplication: + +Key duplication +--------------- + .. function:: psa_copy_key .. summary:: @@ -481,182 +413,873 @@ Key destruction See also :secref:`key-material`. +.. _key-formats: -.. _key-export: +Key formats +----------- -Key export ----------- +Outside of the key store, keys are exchanged using defined formats. +These formats are used to import and export keys, or to input public asymmetric keys to key agreement or PAKE operations. -.. function:: psa_export_key +The |API| defines the default format for each standard key type, to be used for these operations. +The default formats are defined in the *Key format* section of each key type in :secref:`key-types`. - .. summary:: - Export a key in binary format. +Some application use cases require key data to be in other standard formats. +:code:`psa_import_formatted_key()`, :code:`psa_export_formatted_key()`, and :code:`psa_export_formatted_public_key()` allow data in these formats to be used directly with the |API|. - .. param:: psa_key_id_t key - Identifier of the key to export. - It must permit the usage `PSA_KEY_USAGE_EXPORT`, unless it is a public key. - .. param:: uint8_t * data - Buffer where the key data is to be written. - .. param:: size_t data_size - Size of the ``data`` buffer in bytes. - This must be appropriate for the key: +Some key formats have options for how the key data is represented. +For example, - * The required output size is :code:`PSA_EXPORT_KEY_OUTPUT_SIZE(type, bits)` where ``type`` is the key type and ``bits`` is the key size in bits. - * `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or key pair. - * `PSA_EXPORT_KEY_PAIR_MAX_SIZE` evaluates to the maximum output size of any supported key pair. - * `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key. - * This API defines no maximum size for symmetric keys. Arbitrarily large data items can be stored in the key store, for example certificates that correspond to a stored private key or input material for key derivation. +* Data layouts used in X.509 certificates, such as RSAPublicKey, can be encoded using :term:`DER` or :term:`PEM`. +* Elliptic curve keys can be specified using a curve identifier and the key value, or by providing for full set of curve parameters and the key value. +* Elliptic curve public keys can use a compressed or uncompressed representation for the point on the curve. - .. param:: size_t * data_length - On success, the number of bytes that make up the key data. +These options need to be specified by the application, or a default used, when formatting key data for export. +When importing a key, the formatted data includes information that indicates the formatting options, so the options do not need to be provided by the application. - .. return:: psa_status_t - .. retval:: PSA_SUCCESS - Success. - The first ``(*data_length)`` bytes of ``data`` contain the exported key. - .. retval:: PSA_ERROR_INVALID_HANDLE - ``key`` is not a valid key identifier. - .. retval:: PSA_ERROR_NOT_PERMITTED - The key does not have the `PSA_KEY_USAGE_EXPORT` flag. - .. retval:: PSA_ERROR_NOT_SUPPORTED - The following conditions can result in this error: +The |API| defines elements for some common key formats and format options. +Implementations are permitted to define additional key formats and options. - * The key's storage location does not support export of the key. - * The implementation does not support export of keys with this key type. - .. retval:: PSA_ERROR_BUFFER_TOO_SMALL - The size of the ``data`` buffer is too small. - `PSA_EXPORT_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`, or `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE` can be used to determine a sufficient buffer size. - .. retval:: PSA_ERROR_COMMUNICATION_FAILURE - .. retval:: PSA_ERROR_CORRUPTION_DETECTED - .. retval:: PSA_ERROR_STORAGE_FAILURE - .. retval:: PSA_ERROR_DATA_CORRUPT - .. retval:: PSA_ERROR_DATA_INVALID - .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY - .. retval:: PSA_ERROR_BAD_STATE - The library requires initializing by a call to `psa_crypto_init()`. +.. typedef:: uint32_t psa_key_format_t - The output of this function can be passed to `psa_import_key()` to create an equivalent object. + .. summary:: + Encoding of a key format. - If the implementation of `psa_import_key()` supports other formats beyond the format specified here, the output from `psa_export_key()` must use the representation specified in :secref:`key-types`, not the originally imported representation. + Key formats are specified in the |API| using values of this type. - For standard key types, the output format is defined in the relevant *Key format* section in :secref:`key-types`. - The policy on the key must have the usage flag `PSA_KEY_USAGE_EXPORT` set. + `PSA_KEY_FORMAT_DEFAULT` (value ``0``) indicates the default format for the key type. -.. function:: psa_export_public_key +.. macro:: PSA_KEY_FORMAT_DEFAULT + :definition: ((psa_key_format_t) 0) .. summary:: - Export a public key or the public part of a key pair in binary format. + Key format value indicating the default format. - .. param:: psa_key_id_t key - Identifier of the key to export. - .. param:: uint8_t * data - Buffer where the key data is to be written. - .. param:: size_t data_size - Size of the ``data`` buffer in bytes. - This must be appropriate for the key: + The default formats are specified for each key type in the :secref:`key-types` chapter. - * The required output size is :code:`PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(type, bits)` where ``type`` is the key type and ``bits`` is the key size in bits. - * `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or public part of a key pair. - * `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or key pair. + Some options can be specified with the default format, when appropriate for the key type. + See the description of each format option for details. - .. param:: size_t * data_length - On success, the number of bytes that make up the key data. + .. subsection:: Compatible key types - .. return:: psa_status_t - .. retval:: PSA_SUCCESS - Success. - The first ``(*data_length)`` bytes of ``data`` contain the exported public key. - .. retval:: PSA_ERROR_INVALID_HANDLE - ``key`` is not a valid key identifier. - .. retval:: PSA_ERROR_INVALID_ARGUMENT - The key is neither a public key nor a key pair. - .. retval:: PSA_ERROR_NOT_SUPPORTED - The following conditions can result in this error: + All key types can be used with the default format. - * The key's storage location does not support export of the key. - * The implementation does not support export of keys with this key type. - .. retval:: PSA_ERROR_BUFFER_TOO_SMALL - The size of the ``data`` buffer is too small. - `PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`, or `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE` can be used to determine a sufficient buffer size. - .. retval:: PSA_ERROR_COMMUNICATION_FAILURE - .. retval:: PSA_ERROR_CORRUPTION_DETECTED - .. retval:: PSA_ERROR_STORAGE_FAILURE - .. retval:: PSA_ERROR_DATA_CORRUPT - .. retval:: PSA_ERROR_DATA_INVALID - .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY - .. retval:: PSA_ERROR_BAD_STATE - The library requires initializing by a call to `psa_crypto_init()`. + .. subsection:: Key format options - The output of this function can be passed to `psa_import_key()` to create an object that is equivalent to the public key. + * `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` (for Weierstrass elliptic curve keys) - If the implementation of `psa_import_key()` supports other formats beyond the format specified here, the output from `psa_export_public_key()` must use the representation specified in :secref:`key-types`, not the originally imported representation. +.. macro:: PSA_KEY_FORMAT_RSA_PUBLIC_KEY + :definition: /* implementation-defined value */ - For standard key types, the output format is defined in the relevant *Key format* section in :secref:`key-types`. + .. summary:: + The *RSAPublicKey* key format for RSA public keys. - Exporting a public key object or the public part of a key pair is always permitted, regardless of the key's usage flags. + RSAPublicKey is defined by :RFC-title:`8017#A.1.1`. -.. macro:: PSA_EXPORT_KEY_OUTPUT_SIZE + This is the default key format for RSA public keys. + + When exporting a key in this format, the output is :term:`DER` encoded by default. + For output that is :term:`PEM` encoded, use the `PSA_KEY_FORMAT_OPTION_PEM` option. + + .. subsection:: Compatible key types + + * `PSA_KEY_TYPE_RSA_PUBLIC_KEY` + * `PSA_KEY_TYPE_RSA_KEY_PAIR` (when used with :code:`psa_export_formatted_public_key()`) + + .. subsection:: Key format options + + * `PSA_KEY_FORMAT_OPTION_PEM` + +.. macro:: PSA_KEY_FORMAT_SUBJECT_PUBLIC_KEY_INFO :definition: /* implementation-defined value */ .. summary:: - Sufficient output buffer size for `psa_export_key()`. + The *SubjectPublicKeyInfo* key format for RSA and elliptic curve public keys. - .. param:: key_type - A supported key type. - .. param:: key_bits - The size of the key in bits. + SubjectPublicKeyInfo is defined by :RFC-title:`5280#4.1`. + The following documents define the encoding of SubjectPublicKeyInfo elements, depending on the type of key: - .. return:: - If the parameters are valid and supported, return a buffer size in bytes that guarantees that `psa_export_key()` or `psa_export_public_key()` will not fail with :code:`PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified. + * :RFC-title:`8017` defines the details for RSA keys. + * :RFC-title:`5480` defines the details for Weierstrass elliptic curve keys. + * :RFC-title:`8410` defines the details for Montgomery and Edwards elliptic curve keys. - The following code illustrates how to allocate enough memory to export a key by querying the key type and size at runtime. + When exporting a key in this format, the output is :term:`DER` encoded by default. + For output that is :term:`PEM` encoded, use the `PSA_KEY_FORMAT_OPTION_PEM` option. - .. code-block:: xref + When exporting a Weierstrass elliptic curve key in this format: - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_status_t status; - status = psa_get_key_attributes(key, &attributes); - if (status != PSA_SUCCESS) - handle_error(...); - psa_key_type_t key_type = psa_get_key_type(&attributes); - size_t key_bits = psa_get_key_bits(&attributes); - size_t buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits); - psa_reset_key_attributes(&attributes); - uint8_t *buffer = malloc(buffer_size); - if (buffer == NULL) - handle_error(...); - size_t buffer_length; - status = psa_export_key(key, buffer, buffer_size, &buffer_length); - if (status != PSA_SUCCESS) - handle_error(...); + * The *ECPoint* containing the key value is uncompressed by default. + For the compressed encoding, use the `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` option. + * The *ECParameters* element uses a *namedCurve* by default. + To output specified domain parameters instead, use the `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` option. - See also `PSA_EXPORT_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`, and `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE`. + .. subsection:: Compatible key types -.. macro:: PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE + * `PSA_KEY_TYPE_ECC_PUBLIC_KEY` + * `PSA_KEY_TYPE_ECC_KEY_PAIR` (when used with :code:`psa_export_formatted_public_key()`) + * `PSA_KEY_TYPE_RSA_PUBLIC_KEY` + * `PSA_KEY_TYPE_RSA_KEY_PAIR` (when used with :code:`psa_export_formatted_public_key()`) + + .. subsection:: Key format options + + * `PSA_KEY_FORMAT_OPTION_PEM` + * `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` (for Weierstrass elliptic curve keys) + * `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` (for Weierstrass elliptic curve keys) + +.. macro:: PSA_KEY_FORMAT_RSA_PRIVATE_KEY :definition: /* implementation-defined value */ .. summary:: - Sufficient output buffer size for `psa_export_public_key()`. + The *RSAPrivateKey* key format for RSA key-pairs. - .. param:: key_type - A public key or key pair key type. - .. param:: key_bits - The size of the key in bits. + RSAPrivateKey is defined by :RFC-title:`8017#A.1.2`. - .. return:: - If the parameters are valid and supported, return a buffer size in bytes that guarantees that `psa_export_public_key()` will not fail with :code:`PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified. + This is the default key format for RSA key-pairs. - If the parameters are valid and supported, it is recommended that this macro returns the same result as :code:`PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type), key_bits)`. + When exporting a key in this format, the output is :term:`DER` encoded by default. + For output that is :term:`PEM` encoded, use the `PSA_KEY_FORMAT_OPTION_PEM` option. - The following code illustrates how to allocate enough memory to export a public key by querying the key type and size at runtime. + .. subsection:: Compatible key types - .. code-block:: xref + * `PSA_KEY_TYPE_RSA_KEY_PAIR` - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_status_t status; - status = psa_get_key_attributes(key, &attributes); - if (status != PSA_SUCCESS) - handle_error(...); + .. subsection:: Key format options + + * `PSA_KEY_FORMAT_OPTION_PEM` + +.. macro:: PSA_KEY_FORMAT_EC_PRIVATE_KEY + :definition: /* implementation-defined value */ + + .. summary:: + The *ECPrivateKey* key format for elliptic curve key-pairs. + + ECPrivateKey is defined by :RFC-title:`5915#3`. + :RFC:`5915` includes the encoding of Weierstrass elliptic curve key-pairs. + See :RFC-title:`8410` for the encoding of Montgomery and Edwards elliptic curve key-pairs. + + When exporting a key in this format: + + * The public key is always included in the output. + * The output is :term:`DER` encoded by default. + For output that is :term:`PEM` encoded, use the `PSA_KEY_FORMAT_OPTION_PEM` option. + + When exporting a Weierstrass elliptic curve key in this format: + + * The *ECPoint* containing the key value is uncompressed by default. + For the compressed encoding, use the `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` option. + * The *ECParameters* element uses a *namedCurve* by default. + To output specified domain parameters instead, use the `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` option. + + .. subsection:: Compatible key types + + * `PSA_KEY_TYPE_ECC_KEY_PAIR` + + .. subsection:: Key format options + + * `PSA_KEY_FORMAT_OPTION_PEM` + * `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` (for Weierstrass elliptic curve keys) + * `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` (for Weierstrass elliptic curve keys) + +.. macro:: PSA_KEY_FORMAT_ONE_ASYMMETRIC_KEY + :definition: /* implementation-defined value */ + + .. summary:: + The *OneAsymmetricKey* key format for RSA and elliptic curve key-pairs. + + .. todo:: Should this be named ``PSA_KEY_FORMAT_PKCS8`` instead? + + Technically I think not: PKCS#8 defines both *PrivateKeyInfo* and *EncryptedPrivateKeyInfo*, OneAsymmetricKey (version 1) is synonymous with PrivateKeyInfo. + + Perhaps ``PSA_KEY_FORMAT_PRIVATE_KEY_INFO`` could be a synonym of OneAsymmetricKey? + + OneAsymmetricKey is defined by :RFC-title:`5958#2`. + OneAsymmetricKey is an update to the PKCS#8 *PrivateKeyInfo* format defined by :RFC-title:`5208`. + Encoding of specific key types is defined in other documents: + + * :RFC-title:`8017` defines the encoding of RSA keys. + * :RFC-title:`5915` defines the encoding of Weierstrass elliptic curve keys. + * :RFC-title:`8410` defines the encoding of Montgomery and Edwards elliptic curve keys. + + When exporting a key in this format: + + * The public key is always included in the output. + * The output is :term:`DER` encoded by default. + For output that is :term:`PEM` encoded, use the `PSA_KEY_FORMAT_OPTION_PEM` option. + + When exporting a Weierstrass elliptic curve key in this format: + + * The *ECPoint* containing the key value is uncompressed by default. + For the compressed encoding, use the `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` option. + * The *ECParameters* element uses a *namedCurve* by default. + To output specified domain parameters instead, use the `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` option. + + .. subsection:: Compatible key types + + * `PSA_KEY_TYPE_ECC_KEY_PAIR` + * `PSA_KEY_TYPE_RSA_KEY_PAIR` + + .. subsection:: Key format options + + * `PSA_KEY_FORMAT_OPTION_PEM` + * `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` (for Weierstrass elliptic curve keys) + * `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` (for Weierstrass elliptic curve keys) + +.. todo:: RFC 5958/PKCS#8 also supports encryption and authentication of the key data. + + This would either be a *EncryptedPrivateKeyInfo* structure (PKCS#8) or one of the CMS content types. + This requires one or more additional format specifiers. + +.. typedef:: uint32_t psa_key_format_option_t + + .. summary:: + Encoding of formatting options for a key format. + + Key format options are specified in the |API| using values of this type. + When multiple format options are required, the options are combined using bitwise-OR. + + `PSA_KEY_FORMAT_OPTION_DEFAULT` (value ``0``) indicates the default format options for the key format. + +.. macro:: PSA_KEY_FORMAT_OPTION_DEFAULT + :definition: ((psa_key_format_option_t) 0) + + .. summary:: + Key format option value indicating the default options. + + The default format options are specified by each key format. + +.. macro:: PSA_KEY_FORMAT_OPTION_PEM + :definition: /* implementation-defined value */ + + .. summary:: + Key format option to encode the key data using :term:`PEM` encoding. + + By default, key formats that are defined using :term:`ASN.1` use the binary :term:`DER` encoding for key export. + The `PSA_KEY_FORMAT_OPTION_PEM` option results in using the ASCII :term:`PEM` encoding instead. + + PEM encoding is defined by :RFC-title:`7468`. + + .. note:: + Some key formats use PEM labels that are not described in :RFC:`7468`, but are used in other tools that produce and consume PEM-encoded data. + + This option is not applicable to the default key format. + To export a PEM-encoded key, use the appropriate format specifier. + + .. subsection:: Related key formats + + * `PSA_KEY_FORMAT_EC_PRIVATE_KEY` + * `PSA_KEY_FORMAT_ONE_ASYMMETRIC_KEY` + * `PSA_KEY_FORMAT_RSA_PRIVATE_KEY` + * `PSA_KEY_FORMAT_RSA_PUBLIC_KEY` + * `PSA_KEY_FORMAT_SUBJECT_PUBLIC_KEY_INFO` + +.. macro:: PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED + :definition: /* implementation-defined value */ + + .. summary:: + Key format option to encode Weierstrass elliptic curve points in compressed form. + + By default, Weierstrass elliptic curve points are encoded in uncompressed form for key export. + The `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` option results in using compressed form instead. + + The compressed and uncompressed ECPoint format is defined by :cite-title:`SEC1` ยง2.3.3. + + This option can be used with the default key format, when exporting elliptic curve public keys. + + .. subsection:: Related key formats + + * `PSA_KEY_FORMAT_EC_PRIVATE_KEY` + * `PSA_KEY_FORMAT_ONE_ASYMMETRIC_KEY` + * `PSA_KEY_FORMAT_SUBJECT_PUBLIC_KEY_INFO` + +.. macro:: PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN + :definition: /* implementation-defined value */ + + .. summary:: + Key format option to output the Weierstrass elliptic curve domain parameters in the key format. + + By default, key formats that include the *ECParameters* element specify a *namedCurve* for key export. + The `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` option results in specifying the full domain parameters for the elliptic curve instead. + + The ECParameters format is defined by :RFC-title:`5480#2.1.1`. + + This option is not applicable to the default key format. + + .. subsection:: Related key formats + + * `PSA_KEY_FORMAT_EC_PRIVATE_KEY` + * `PSA_KEY_FORMAT_ONE_ASYMMETRIC_KEY` + * `PSA_KEY_FORMAT_SUBJECT_PUBLIC_KEY_INFO` + +.. _key-import: + +Key import +---------- + +.. function:: psa_import_key + + .. summary:: + Import a key in binary format. + + .. param:: const psa_key_attributes_t * attributes + The attributes for the new key. + + The following attributes are required for all keys: + + * The key type determines how the ``data`` buffer is interpreted. + + The following attributes must be set for keys used in cryptographic operations: + + * The key permitted-algorithm policy, see :secref:`permitted-algorithms`. + * The key usage flags, see :secref:`key-usage-flags`. + + The following attributes must be set for keys that do not use the default volatile lifetime: + + * The key lifetime, see :secref:`key-lifetimes`. + * The key identifier is required for a key with a persistent lifetime, see :secref:`key-identifiers`. + + The following attributes are optional: + + * If the key size is nonzero, it must be equal to the key size determined from ``data``. + + .. note:: + This is an input parameter: it is not updated with the final key attributes. + The final attributes of the new key can be queried by calling `psa_get_key_attributes()` with the key's identifier. + + .. param:: const uint8_t * data + Buffer containing the key data. + The content of this buffer is interpreted according to the type declared in ``attributes``. + .. param:: size_t data_length + Size of the ``data`` buffer in bytes. + .. param:: psa_key_id_t * key + On success, an identifier for the newly created key. `PSA_KEY_ID_NULL` on failure. + + .. return:: psa_status_t + .. 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 + The key attributes, as a whole, are not supported, either by the implementation in general or in the specified storage location. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * The key type is invalid. + * The key size is nonzero, and is incompatible with the key data in ``data``. + * The key lifetime is invalid. + * The key identifier is not valid for the key lifetime. + * The key usage flags include invalid values. + * The key's permitted-usage algorithm is invalid. + * The key attributes, as a whole, are invalid. + * The key data is not correctly formatted for the key type. + .. retval:: PSA_ERROR_NOT_PERMITTED + The implementation does not permit creating a key with the specified attributes due to some implementation-specific policy. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + The key is extracted from the provided ``data`` buffer. Its location, policy, and type are taken from ``attributes``. + + The key data determines the key size. :code:``psa_get_key_bits(attributes)`` must either match the determined key size or be ``0``. Implementations must reject an attempt to import a key of size zero. + + This function supports any output from `psa_export_key()`. + The default format is defined in the *Key format* section for each key type. + Other key formats can be imported using `psa_import_formatted_key()`. + + Implementations can optionally support other formats in calls to `psa_import_key()`, in addition to the default format. + + .. note:: + The |API| does not support asymmetric private key objects outside of a key pair. To import a private key, the ``attributes`` must specify the corresponding key pair type. Depending on the key type, either the import format contains the public key data or the implementation will reconstruct the public key from the private key as needed. + + .. admonition:: Implementation note + + It is recommended that implementations that support other formats ensure that the formats are clearly unambiguous, to minimize the risk that an invalid input is accidentally interpreted according to a different format. + + It is recommended that implementations reject key data if it might be erroneous, for example, if it is the wrong type or is truncated. + +.. function:: psa_import_formatted_key + + .. summary:: + Import a key in a specified format. + + .. param:: const psa_key_attributes_t * attributes + The attributes for the new key. + + Depending on the specified key format, and the attributes encoded in the key data, some of the key attributes can be optional. + + The following attributes are required for formats that do not specify a key type: + + * When the format does not specify a key type: the key type in ``attributes`` determines how the ``data`` buffer is interpreted. + * When the format does specify a key type: if the key type in ``attributes`` has a non-default value, it must be equal to the determined key type. + + The following attributes must be set for keys used in cryptographic operations: + + * The key permitted-algorithm policy, see :secref:`permitted-algorithms`. + * The key usage flags, see :secref:`key-usage-flags`. + + These attributes are combined with any policy that is encoded in the key data, so that both sets of restrictions apply :issue:`(this needs further thought & discussion)`. + + The following attributes must be set for keys that do not use the default volatile lifetime: + + * The key lifetime, see :secref:`key-lifetimes`. + * The key identifier is required for a key with a persistent lifetime, see :secref:`key-identifiers`. + + The following attributes are optional: + + * If the key size is nonzero, it must be equal to the key size determined from ``data``. + + .. note:: + This is an input parameter: it is not updated with the final key attributes. + The final attributes of the new key can be queried by calling `psa_get_key_attributes()` with the key's identifier. + .. param:: psa_key_format_t format + The format of the key data. + One of the ``PSA_KEY_FORMAT_XXX`` values, or an implementation-specific format. + .. param:: const uint8_t * data + Buffer containing the key data. + The content of this buffer is interpreted according to the key format ``format``. + The type declared in ``attributes`` is used if the format and key data do not specify a key type. + .. param:: size_t data_length + Size of the ``data`` buffer in bytes. + .. param:: psa_key_id_t * key + On success, an identifier for the newly created key. `PSA_KEY_ID_NULL` on failure. + + .. return:: psa_status_t + .. 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 + The following conditions can result in this error: + + * The key format is not supported by the implementation. + * The key attributes, as a whole, are not supported, either by the implementation in general or in the specified storage location. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * The key type is invalid, or is `PSA_KEY_TYPE_NONE` when a type is required. + * The key size is nonzero, and is incompatible with the key data in ``data``. + * The key lifetime is invalid. + * The key identifier is not valid for the key lifetime. + * The key usage flags include invalid values. + * The key's permitted-usage algorithm is invalid. + * The key attributes, as a whole, are invalid. + * The key format is invalid. + * The key data is not correctly formatted for the key format or the key type. + .. retval:: PSA_ERROR_NOT_PERMITTED + The implementation does not permit creating a key with the specified attributes due to some implementation-specific policy. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + The key is extracted from the provided ``data`` buffer, which is interpreted according to the specified key format. Its location is taken from ``attributes``, its type and policy are determined by the ``format``, the ``data``, and the ``attributes``. + + If the format is `PSA_KEY_FORMAT_DEFAULT`, this is equivalent to calling `psa_import_key()`. + + For non-default key formats, the key format either specifies the key type, or the formatted data encodes the key type. + For example, `PSA_KEY_FORMAT_RSA_PRIVATE_KEY` is always an RSA key pair, while the `PSA_KEY_FORMAT_ONE_ASYMMETRIC_KEY` format includes a data element that specifies whether it is an RSA or elliptic curve key-pair. + If the key type is determined by the format and the data, then :code:``psa_get_key_type(attributes)`` must either match the determined key type or be `PSA_KEY_TYPE_NONE`. + + The key data determines the key size. + :code:``psa_get_key_bits(attributes)`` must either match the determined key size or be ``0``. + Implementations must reject an attempt to import a key of size zero. + + The resulting key can only be used in a way that conforms to both the policy included in the key data, and the policy specified in the ``attributes`` parameter :issue:`(the following is place-holder cut and paste from psa_copy_key())`: + + * The usage flags on the resulting key are the bitwise-and of the usage flags on the source policy and the usage flags in ``attributes``. + * If both permit the same algorithm or wildcard-based algorithm, the resulting key has the same permitted algorithm. + * If either of the policies permits an algorithm and the other policy permits a wildcard-based permitted algorithm that includes this algorithm, the resulting key uses this permitted algorithm. + * If the policies do not permit any algorithm in common, this function fails with the status :code:`PSA_ERROR_INVALID_ARGUMENT`. + + As a result, the new key cannot be used for operations that were not permitted by the imported key data. + + .. todo:: The proposed constraints on key policy are probably too strict. + + * Most of the X.509 formats include a mandatory *AlgorithmIdentifier* element which does constrain the algorithm, *almost* well enough to match a |API| permitted algorithm encoding. + * Many of the formats include an optional *KeyUsage* element that defines a set of permitted uses. + These partially map onto |API| usage flags. + + 1. What to do if the format does not include a algorithm identifier? + 2. What to do if the algorithm identifier is too general for the algorithm encodings in |API|? + 3. If a *KeyUsage* is provided, do we take an intersection with the ``attributes`` usage flags? - what about when there is no 1:1 mapping? + 4. If a *KeyUsage* is **not** provided, do we just use the ``attributes`` usage flags? + 5. Are some |API| usage flags specific to the |API|, or to the application use of the key store. For example USAGE_EXPORT, USAGE_COPY, USAGE_CACHE? + + Implementations can define implementation-specific formats that may have other behaviors relating to ``attributes``. + + .. note:: + The |API| does not support asymmetric private key objects outside of a key pair. + When importing a private key, the corresponding key-pair type is created. + If the imported key data does not contain the public key, then the implementation will reconstruct the public key from the private key as needed. + + .. admonition:: Implementation note + + It is recommended that implementation-specific formats are clearly unambiguous, to minimize the risk that an invalid input is accidentally interpreted according to a different format. + + It is recommended that implementations reject key data if it might be erroneous, for example, if it is the wrong type or is truncated. + +.. _key-export: + +Key export +---------- + +.. function:: psa_export_key + + .. summary:: + Export a key in binary format. + + .. param:: psa_key_id_t key + Identifier of the key to export. + It must permit the usage `PSA_KEY_USAGE_EXPORT`, unless it is a public key. + .. param:: uint8_t * data + Buffer where the key data is to be written. + .. param:: size_t data_size + Size of the ``data`` buffer in bytes. + This must be appropriate for the key: + + * The required output size is :code:`PSA_EXPORT_KEY_OUTPUT_SIZE(type, bits)` where ``type`` is the key type and ``bits`` is the key size in bits. + * `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or key pair. + * `PSA_EXPORT_KEY_PAIR_MAX_SIZE` evaluates to the maximum output size of any supported key pair. + * `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key. + * This API defines no maximum size for symmetric keys. Arbitrarily large data items can be stored in the key store, for example certificates that correspond to a stored private key or input material for key derivation. + + .. param:: size_t * data_length + On success, the number of bytes that make up the key data. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The first ``(*data_length)`` bytes of ``data`` contain the exported key. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The key does not have the `PSA_KEY_USAGE_EXPORT` flag. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * The key's storage location does not support export of the key. + * The implementation does not support export of keys with this key type. + .. retval:: PSA_ERROR_BUFFER_TOO_SMALL + The size of the ``data`` buffer is too small. + `PSA_EXPORT_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`, or `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE` can be used to determine a sufficient buffer size. + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + Extract a key from the key store into a data buffer using the default key format. + If the key is not a public-key type, then the policy on the key must have the usage flag `PSA_KEY_USAGE_EXPORT` set. + + The output of this function can be passed to `psa_import_key()` to create an equivalent object. + + If the implementation supports importing non-default key formats, the output from `psa_export_key()` must use the default representation specified in :secref:`key-types`, not the originally imported representation. + + For standard key types, the output format is defined in the relevant *Key format* section in :secref:`key-types`. + To export a key in another format, use `psa_export_formatted_key()`. + + To export the public key from a key-pair, use `psa_export_public_key()` or `psa_export_formatted_public_key()`. + +.. function:: psa_export_public_key + + .. summary:: + Export a public key or the public part of a key-pair in binary format. + + .. param:: psa_key_id_t key + Identifier of the key to export. + .. param:: uint8_t * data + Buffer where the key data is to be written. + .. param:: size_t data_size + Size of the ``data`` buffer in bytes. + This must be appropriate for the key: + + * The required output size is :code:`PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(type, bits)` where ``type`` is the key type and ``bits`` is the key size in bits. + * `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or public part of a key pair. + * `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or key pair. + + .. param:: size_t * data_length + On success, the number of bytes that make up the key data. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The first ``(*data_length)`` bytes of ``data`` contain the exported public key. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The key is neither a public key nor a key pair. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * The key's storage location does not support export of the key. + * The implementation does not support export of keys with this key type. + .. retval:: PSA_ERROR_BUFFER_TOO_SMALL + The size of the ``data`` buffer is too small. + `PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`, or `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE` can be used to determine a sufficient buffer size. + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + Extract a public key, or a public part of a key-pair, from the key store into a data buffer using the default key format. + + The output of this function can be passed to `psa_import_key()` to create an object that is equivalent to the public key. + + If the implementation supports importing non-default key formats, the output from `psa_export_public_key()` must use the default representation specified in :secref:`key-types`, not the originally imported representation. + + For standard key types, the output format is defined in the relevant *Key format* section in :secref:`key-types`. + To export a public key in another format, use `psa_export_formatted_public_key()`. + + Exporting a public key object or the public part of a key-pair is always permitted, regardless of the key's usage flags. + +.. function:: psa_export_formatted_key + + .. summary:: + Export a key in a specified format. + + .. param:: psa_key_format_t format + The required export format. + One of the ``PSA_KEY_FORMAT_XXX`` values, or an implementation-specific format. + .. param:: psa_key_format_option_t options + Formatting options to use. + One of the ``PSA_KEY_FORMAT_OPTION_XXX`` values, an implementation-specific option, or a bitwise-or of them. + .. param:: psa_key_id_t key + Identifier of the key to export. + It must permit the usage `PSA_KEY_USAGE_EXPORT`, unless it is a public key. + .. param:: uint8_t * data + Buffer where the key data is to be written. + .. param:: size_t data_size + Size of the ``data`` buffer in bytes. + This must be appropriate for the key: + + * The required output size is :code:`PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE(format, options, type, bits)`, where ``format`` is the key format, ``options`` is the format options, ``type`` is the key type, and ``bits`` is the key size in bits. + * `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or key pair, in any supported combination of key format and options. + * `PSA_EXPORT_FORMATTED_KEY_PAIR_MAX_SIZE` evaluates to the maximum output size of any supported key pair, in any supported combination of key format and options. + * `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key, in any supported combination of key format and options. + * This API defines no maximum size for symmetric keys. Arbitrarily large data items can be stored in the key store, for example certificates that correspond to a stored private key or input material for key derivation. + + .. param:: size_t * data_length + On success, the number of bytes that make up the key data. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The first ``(*data_length)`` bytes of ``data`` contain the exported key. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The key does not have the `PSA_KEY_USAGE_EXPORT` flag. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * The key format is not valid. + * The key format is not applicable to the key type. + * The key format option is not applicable to the key format. + + .. todo:: + Decide on appropriate behavior if the format option does not match the key type. + My preference is to ignore the option if the key format does not use that option when encoding the provided key type. + + If the option is never applicable to the format, that should (I think) be an error. + However, that means that format options cannot have overlapping values, even if they never apply to the same format? + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * The key's storage location does not support export of the key. + * The implementation does not support export of keys with this key type. + * The implementation does not support key export in the requested key format or format options. + .. retval:: PSA_ERROR_BUFFER_TOO_SMALL + The size of the ``data`` buffer is too small. + `PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_FORMATTED_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE`, or `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE` can be used to determine a sufficient buffer size. + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + Extract a key from the key store into a data buffer using a specified key format. + The output contains the key value, and, depending on the format, some of the key attributes. + If the key is not a public-key type, then the policy on the key must have the usage flag `PSA_KEY_USAGE_EXPORT` set. + + If :code:`format==PSA_KEY_FORMAT_DEFAULT` and :code:`options==PSA_KEY_FORMAT_OPTION_DEFAULT`, this is equivalent to calling `psa_export_key()`. + Some of the options can be used with the default key format for some key types, see `PSA_KEY_FORMAT_DEFAULT`. + + For standard key types, the default output format is defined in the relevant *Key format* section in :secref:`key-types`. + Other key formats are defined in :secref:`key-formats`. + + Some key formats can optionally include additional content or use different encodings. + These can be selected by using one or more of the ``PSA_KEY_FORMAT_OPTION_XXX`` values. + + The output of this function can be passed to `psa_import_formatted_key()`, specifying the same format, to create an equivalent key object. + + To export the public key from a key-pair, use `psa_export_public_key()` or `psa_export_formatted_public_key()`. + +.. function:: psa_export_formatted_public_key + + .. summary:: + Export a public key or the public part of a key-pair in a specified format. + + .. param:: psa_key_format_t format + The required export format. + One of the ``PSA_KEY_FORMAT_XXX`` values, or an implementation-specific format. + .. param:: psa_key_format_option_t options + Formatting options to use. + One of the ``PSA_KEY_FORMAT_OPTION_XXX`` values, an implementation-specific option, or a bitwise-or of them. + .. param:: psa_key_id_t key + Identifier of the key to export. + .. param:: uint8_t * data + Buffer where the key data is to be written. + .. param:: size_t data_size + Size of the ``data`` buffer in bytes. + This must be appropriate for the key: + + * The required output size is :code:`PSA_EXPORT_FORMATTED_PUBLIC_KEY_OUTPUT_SIZE(format, options, type, bits)`, where ``format`` is the key format, ``options`` is the format options, ``type`` is the key type, and ``bits`` is the key size in bits. + * `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or public part of a key pair, in any supported combination of key format and options. + * `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE` evaluates to the maximum output size of any supported public key or key pair, in any supported combination of key format and options. + + .. param:: size_t * data_length + On success, the number of bytes that make up the key data. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The first ``(*data_length)`` bytes of ``data`` contain the exported public key. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * The key is neither a public key nor a key pair. + * The key format is not valid. + * The key format is not applicable to the key type. + * The key format option is not applicable to the key format. + + .. todo:: + Decide on appropriate behavior if the format option does not match the key type. + My preference is to ignore the option if the key format does not use that option when encoding the provided key type. + + If the option is never applicable to the format, that should (I think) be an error. + However, that means that format options cannot have overlapping values, even if they never apply to the same format? + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * The key's storage location does not support export of the key. + * The implementation does not support export of keys with this key type. + * The implementation does not support public key export in the requested key format or format options. + .. retval:: PSA_ERROR_BUFFER_TOO_SMALL + The size of the ``data`` buffer is too small. + `PSA_EXPORT_FORMATTED_PUBLIC_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE`, or `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE` can be used to determine a sufficient buffer size. + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + Extract a public key, or a public part of a key-pair, from the key store into a data buffer using a specified key format. + The output contains the public-key value, and, depending on the format, some of the key attributes. + + If :code:`format==PSA_KEY_FORMAT_DEFAULT` and :code:`options==PSA_KEY_FORMAT_OPTION_DEFAULT`, this is equivalent to calling `psa_export_public_key()`. + Some of the options can be used with the default key format for some key types, see `PSA_KEY_FORMAT_DEFAULT`. + + The output of this function can be passed to `psa_import_key()` to create an object that is equivalent to the public key. + + For standard key types, the default output format is defined in the *Key format* section for the applicable public-key type in :secref:`key-types`. + Other key formats are defined in :secref:`key-formats`. + + Some key formats can optionally include additional content or use different encodings. + These can be selected by using one or more of the ``PSA_KEY_FORMAT_OPTION_XXX`` values. + + The output of this function can be passed to `psa_import_formatted_key()`, specifying the same format, to create an equivalent public-key object. + + Exporting a public key object or the public part of a key-pair is always permitted, regardless of the key's usage flags. + +.. macro:: PSA_EXPORT_KEY_OUTPUT_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient output buffer size for `psa_export_key()`. + + .. 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_export_key()` will not fail with :code:`PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified. + + The following code illustrates how to allocate enough memory to export a key by querying the key type and size at runtime. + + .. code-block:: xref + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + status = psa_get_key_attributes(key, &attributes); + if (status != PSA_SUCCESS) + handle_error(...); + psa_key_type_t key_type = psa_get_key_type(&attributes); + size_t key_bits = psa_get_key_bits(&attributes); + size_t buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits); + psa_reset_key_attributes(&attributes); + uint8_t *buffer = malloc(buffer_size); + if (buffer == NULL) + handle_error(...); + size_t buffer_length; + status = psa_export_key(key, buffer, buffer_size, &buffer_length); + if (status != PSA_SUCCESS) + handle_error(...); + + See also `PSA_EXPORT_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`, and `PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE`. + +.. macro:: PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient output buffer size for `psa_export_public_key()`. + + .. param:: key_type + A public key or key pair 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_export_public_key()` will not fail with :code:`PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified. + + If the parameters are valid and supported, it is recommended that this macro returns the same result as :code:`PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type), key_bits)`. + + The following code illustrates how to allocate enough memory to export a public key by querying the key type and size at runtime. + + .. code-block:: xref + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + status = psa_get_key_attributes(key, &attributes); + if (status != PSA_SUCCESS) + handle_error(...); psa_key_type_t key_type = psa_get_key_type(&attributes); size_t key_bits = psa_get_key_bits(&attributes); size_t buffer_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits); @@ -700,3 +1323,76 @@ Key export This value must be a sufficient buffer size when calling `psa_export_key()` or `psa_export_public_key()` to export any asymmetric key pair or public key that is supported by the implementation, regardless of the exact key type and key size. See also `PSA_EXPORT_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`, and `PSA_EXPORT_KEY_OUTPUT_SIZE()`. + + +.. macro:: PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient output buffer size for `psa_export_formatted_key()`. + + .. param:: format + A supported key format. + .. param:: options + A set of supported key format options. + .. 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_export_formatted_key()` will not fail with :code:`PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified. + + See also `PSA_EXPORT_FORMATTED_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE`, and `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE`. + +.. macro:: PSA_EXPORT_FORMATTED_PUBLIC_KEY_OUTPUT_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient output buffer size for `psa_export_formatted_public_key()`. + + .. param:: format + A supported public-key format. + .. param:: options + A set of supported key format options. + .. param:: key_type + A public key or key pair 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_export_formatted_public_key()` will not fail with :code:`PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified. + + If the parameters are valid and supported, it is recommended that this macro returns the same result as :code:`PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE(format, options, PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type), key_bits)`. + + See also `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE` and `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE`. + +.. macro:: PSA_EXPORT_FORMATTED_KEY_PAIR_MAX_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient buffer size for exporting any formatted asymmetric key pair. + + This value must be a sufficient buffer size when calling `psa_export_formatted_key()` to export any asymmetric key pair that is supported by the implementation, regardless of the exact key type, key size, key format, and format options. + + See also `PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE`, and `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE`. + +.. macro:: PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient buffer size for exporting any formatted asymmetric public key. + + This value must be a sufficient buffer size when calling `psa_export_formatted_key()` or `psa_export_formatted_public_key()` to export any asymmetric public key that is supported by the implementation, regardless of the exact key type, key size, key format, and format options. + + See also `PSA_EXPORT_FORMATTED_PUBLIC_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_FORMATTED_KEY_PAIR_MAX_SIZE`, and `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE`. + +.. macro:: PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient buffer size for exporting any formatted asymmetric key pair or public key. + + This value must be a sufficient buffer size when calling `psa_export_formatted_key()` or `psa_export_formatted_public_key()` to export any asymmetric key pair or public key that is supported by the implementation, regardless of the exact key type, key size, key format, and format options. + + See also `PSA_EXPORT_FORMATTED_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE`, and `PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE()`. diff --git a/doc/crypto/api/keys/policy.rst b/doc/crypto/api/keys/policy.rst index 614cb78b..9d1fca0d 100644 --- a/doc/crypto/api/keys/policy.rst +++ b/doc/crypto/api/keys/policy.rst @@ -250,6 +250,28 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. If this flag is present on all keys used in calls to `psa_key_derivation_input_key()` for a key derivation operation, then it permits calling `psa_key_derivation_verify_bytes()` or `psa_key_derivation_verify_key()` at the end of the operation. +.. macro:: PSA_KEY_USAGE_WRAP + :definition: ((psa_key_usage_t)0x00010000) + + .. summary:: + Permission to wrap another key with the key. + + This flag is required to use the key in a key-wrapping operation. + The flag must be present on keys used with the following APIs: + + * `psa_wrap_key()` + +.. macro:: PSA_KEY_USAGE_UNWRAP + :definition: ((psa_key_usage_t)0x00020000) + + .. summary:: + Permission to unwrap another key with the key. + + This flag is required to use the key in a key-unwrapping operation. + The flag must be present on keys used with the following APIs: + + * `psa_unwrap_key()` + .. function:: psa_set_key_usage_flags .. summary:: diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index ea18391c..25974770 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -117,7 +117,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -157,7 +157,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -225,7 +225,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -250,7 +250,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -275,7 +275,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -320,7 +320,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -365,7 +365,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -406,7 +406,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. The parity bits in each 64-bit DES key element must be correct. .. subsection:: Key derivation @@ -459,7 +459,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -496,7 +496,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -523,7 +523,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -550,7 +550,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -577,7 +577,7 @@ Symmetric keys .. subsection:: Key format - The data format for import and export of the key is the raw bytes of the key. + The default data format for import and export of the key is the raw bytes of the key. .. subsection:: Key derivation @@ -621,7 +621,7 @@ RSA keys .. subsection:: Key format - The data format for import and export of a key-pair is the non-encrypted DER encoding of the representation defined by in :RFC-title:`8017` as ``RSAPrivateKey``, version ``0``. + The default data format for import and export of a key-pair is the non-encrypted :term:`DER` encoding of the representation defined by in :RFC-title:`8017#A.1.2` as ``RSAPrivateKey``, version ``0``. .. code-block:: none @@ -643,6 +643,9 @@ RSA keys See `PSA_KEY_TYPE_RSA_PUBLIC_KEY` for the data format used when exporting the public key with `psa_export_public_key()`. + RSA key-pairs can also be imported from and exported using the `PSA_KEY_FORMAT_RSA_PRIVATE_KEY` and `PSA_KEY_FORMAT_ONE_ASYMMETRIC_KEY` key formats. + See :secref:`key-formats`. + .. subsection:: Key generation A call to `psa_generate_key()` will generate an RSA key-pair with the default public exponent of ``65537``. The modulus :math:`n=pq` is a product of two probabilistic primes :math:`p\ \text{and}\ q`, where :math:`2^{r-1} \le n < 2^r` and :math:`r` is the bit size specified in the attributes. @@ -686,7 +689,7 @@ RSA keys .. subsection:: Key format - The data format for import and export of a public key is the DER encoding of the representation defined by :RFC-title:`3279#2.3.1` as ``RSAPublicKey``. + The default data format for import and export of a public key is the :term:`DER` encoding of the representation defined by :RFC-title:`8017#A.1.1` as ``RSAPublicKey``. .. code-block:: none @@ -694,6 +697,9 @@ RSA keys modulus INTEGER, -- n publicExponent INTEGER } -- e + RSA public keys can also be imported from and exported using the `PSA_KEY_FORMAT_RSA_PUBLIC_KEY` and `PSA_KEY_FORMAT_SUBJECT_PUBLIC_KEY_INFO` key formats. + See :secref:`key-formats`. + .. macro:: PSA_KEY_TYPE_IS_RSA :definition: /* specification-defined value */ @@ -821,7 +827,7 @@ The curve type affects the key format, the key derivation procedure, and the alg .. subsection:: Key format - The data format for import and export of the key-pair depends on the type of elliptic curve. + The default data format for import and export of the key-pair depends on the type of elliptic curve. :numref:`tab-ecc-key-pair-format` shows the format for each type of elliptic curve key-pair. See `PSA_KEY_TYPE_ECC_PUBLIC_KEY` for the data format used when exporting the public key with `psa_export_public_key()`. @@ -851,6 +857,9 @@ The curve type affects the key format, the key derivation procedure, and the alg This is a 32-byte string for Edwards25519, and a 57-byte string for Edwards448. + Elliptic curve key-pairs can also be imported from and exported using the `PSA_KEY_FORMAT_EC_PRIVATE_KEY` and `PSA_KEY_FORMAT_ONE_ASYMMETRIC_KEY` key formats. + See :secref:`key-formats`. + .. subsection:: Key derivation The key derivation method used when calling `psa_key_derivation_output_key()` depends on the type of elliptic curve. @@ -939,7 +948,7 @@ The curve type affects the key format, the key derivation procedure, and the alg .. subsection:: Key format - The data format for import and export of the public key depends on the type of elliptic curve. + The default data format for import and export of the public key depends on the type of elliptic curve. :numref:`tab-ecc-public-key-format` shows the format for each type of elliptic curve public key. .. list-table:: Public key formats for elliptic curve keys @@ -970,6 +979,9 @@ The curve type affects the key format, the key derivation procedure, and the alg This is a 32-byte string for Edwards25519, and a 57-byte string for Edwards448. + Elliptic curve public keys can also be imported from and exported using the `PSA_KEY_FORMAT_SUBJECT_PUBLIC_KEY_INFO` key format. + See :secref:`key-formats`. + .. macro:: PSA_ECC_FAMILY_SECP_K1 :definition: ((psa_ecc_family_t) 0x17) @@ -1215,7 +1227,7 @@ Diffie Hellman keys .. subsection:: Key format - The data format for import and export of the key-pair is the representation of the private key :math:`x` as a big-endian byte string. + The default data format for import and export of the key-pair is the representation of the private key :math:`x` as a big-endian byte string. The length of the byte string is the private key size in bytes, and leading zeroes are not stripped. See `PSA_KEY_TYPE_DH_PUBLIC_KEY` for the data format used when exporting the public key with `psa_export_public_key()`. @@ -1250,7 +1262,7 @@ Diffie Hellman keys .. subsection:: Key format - The data format for export of the public key is the representation of the public key :math:`y = g^x\!\mod p` as a big-endian byte string. + The default data format for export of the public key is the representation of the public key :math:`y = g^x\!\mod p` as a big-endian byte string. The length of the byte string is the length of the base prime :math:`p` in bytes. .. macro:: PSA_DH_FAMILY_RFC7919 @@ -1372,7 +1384,7 @@ SPAKE2+ keys A SPAKE2+ key-pair consists of the two values :math:`w0` and :math:`w1`, which result from the SPAKE2+ registration phase, see :secref:`spake2p-registration`. :math:`w0` and :math:`w1` are scalars in the same range as an elliptic curve private key from the group used as the SPAKE2+ primitive group. - The data format for import and export of the key-pair is the concatenation of the formatted values for :math:`w0` and :math:`w1`, using the standard formats for elliptic curve keys used by the |API|. + The default data format for import and export of the key-pair is the concatenation of the formatted values for :math:`w0` and :math:`w1`, using the default formats for elliptic curve keys used by the |API|. For example, for SPAKE2+ over P-256 (secp256r1), the output from :code:`psa_export_key()` would be the concatenation of: * The P-256 private key :math:`w0`. @@ -1431,7 +1443,7 @@ SPAKE2+ keys :math:`w0` is a scalar in the same range as a elliptic curve private key from the group used as the SPAKE2+ primitive group. :math:`L` is a point on the curve, similar to a public key from the same group, corresponding to the :math:`w1` value in the key pair. - The data format for import and export of the public key is the concatenation of the formatted values for :math:`w0` and :math:`L`, using the standard formats for elliptic curve keys used by the |API|. + The default data format for import and export of the public key is the concatenation of the formatted values for :math:`w0` and :math:`L`, using the default formats for elliptic curve keys used by the |API|. For example, for SPAKE2+ over P-256 (secp256r1), the output from :code:`psa_export_public_key()` would be the concatenation of: * The P-256 private key :math:`w0`. diff --git a/doc/crypto/api/ops/index.rst b/doc/crypto/api/ops/index.rst index 903c79cf..fc00fc64 100644 --- a/doc/crypto/api/ops/index.rst +++ b/doc/crypto/api/ops/index.rst @@ -19,4 +19,5 @@ Cryptographic operation reference pk-encryption key-agreement pake + wrap rng diff --git a/doc/crypto/api/ops/pake.rst b/doc/crypto/api/ops/pake.rst index 016ddec5..8cd2ebde 100644 --- a/doc/crypto/api/ops/pake.rst +++ b/doc/crypto/api/ops/pake.rst @@ -2,7 +2,7 @@ .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. header:: psa/crypto - :seq: 30 + :seq: 29 .. _pake: diff --git a/doc/crypto/api/ops/rng.rst b/doc/crypto/api/ops/rng.rst index ffb2202c..c2f6dfe9 100644 --- a/doc/crypto/api/ops/rng.rst +++ b/doc/crypto/api/ops/rng.rst @@ -2,7 +2,7 @@ .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. header:: psa/crypto - :seq: 30 + :seq: 31 Other cryptographic services ============================ diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index d802a9ea..9ad7ba62 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -57,7 +57,7 @@ Asymmetric signature algorithms This signature scheme is defined by :RFC-title:`8017#8.2` under the name RSASSA-PKCS1-v1_5. - The ``hash`` parameter to `psa_sign_hash()` or `psa_verify_hash()` is used as :math:`T` from step 3 onwards in the message encoding algorithm ``EMSA-PKCS1-V1_5-ENCODE()`` in :RFC:`8017#9.2`. :math:`T` is normally the DER encoding of the *DigestInfo* structure produced by step 2 in the message encoding algorithm, but it can be any byte string within the available length. + The ``hash`` parameter to `psa_sign_hash()` or `psa_verify_hash()` is used as :math:`T` from step 3 onwards in the message encoding algorithm ``EMSA-PKCS1-V1_5-ENCODE()`` in :RFC:`8017#9.2`. :math:`T` is normally the :term:`DER` encoding of the *DigestInfo* structure produced by step 2 in the message encoding algorithm, but it can be any byte string within the available length. The wildcard key policy :code:`PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)` also permits a key to be used with the `PSA_ALG_RSA_PKCS1V15_SIGN_RAW` signature algorithm. diff --git a/doc/crypto/api/ops/wrap.rst b/doc/crypto/api/ops/wrap.rst new file mode 100644 index 00000000..76f1c9d5 --- /dev/null +++ b/doc/crypto/api/ops/wrap.rst @@ -0,0 +1,418 @@ +.. SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates +.. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license + +.. header:: psa/crypto + :seq: 30 + +.. _key-wrap: + +Key wrapping +============ + +Key wrapping is the process of encrypting a key, so that the resulting ciphertext can be stored, or transported, in a form that maintains the confidentiality of the key material. +Key unwrapping reverses this process, extracting the key from the ciphertext. + +Some key-wrapping algorithms also provide integrity protection, to ensure that modification of the ciphertext can be detected. +Key-wrapping algorithms can wrap some of the key attributes and policy in the output. + + +.. _wrapped-key-formats: + +Wrapped key formats +------------------- + +Some key-wrapping algorithms do not require a specific format for the key material that is input to the wrapping procedure. +For this kind of key-wrapping algorithm, the |API| permits any of the supported key export formats to be used to prepare the data for wrapping. +This includes the default key formats described in the :secref:`key-types` chapter, and the additional formats described in :secref:`key-formats`. +For example, `PSA_ALG_AES_KWP` is a generic wrapping algorithm that provides confidentiality for the key. + +Other key-wrapping procedures define both the format of the wrapped key material and the algorithm that is used to perform the wrapping. +These specialized wrapped-key formats are defined here. + +Wrapped-key formats typically encode the wrapping algorithm within the output data. +If a wrapped-key format has a single associated wrapping algorithm, use the generic `PSA_ALG_WRAP` algorithm identifier to wrap and unwrap keys. +If there is a choice of wrapping algorithm, the chosen algorithm must be specified when wrapping a key, but `PSA_ALG_WRAP` can be used to unwrap the key. + + +.. todo:: RFC 5958/PKCS#8 also supports encryption and authentication of the key data. + + This would either be a *EncryptedPrivateKeyInfo* structure (PKCS#8) or one of the CMS content types. + This requires one or more additional format specifiers. + +.. macro:: PSA_KEY_FORMAT_ENCRYPTED_PRIVATE_KEY_INFO + :definition: /* implementation-defined value */ + + .. summary:: + The *EncryptedPrivateKeyInfo* key format for RSA and elliptic curve key-pairs. + + .. todo:: Update all of this for EncryptedPrivateKeyInfo + + OneAsymmetricKey is defined by :RFC-title:`5958#2`. + OneAsymmetricKey is an update to the PKCS#8 *PrivateKeyInfo* format defined by :RFC-title:`5208`. + Encoding of specific key types is defined in other documents: + + * :RFC-title:`8017` defines the encoding of RSA keys. + * :RFC-title:`5915` defines the encoding of Weierstrass elliptic curve keys. + * :RFC-title:`8410` defines the encoding of Montgomery and Edwards elliptic curve keys. + + When exporting a key in this format: + + * The public key is always included in the output. + * The output is :term:`DER` encoded by default. + For output that is :term:`PEM` encoded, use the `PSA_KEY_FORMAT_OPTION_PEM` option. + + When exporting a Weierstrass elliptic curve key in this format: + + * The *ECPoint* containing the key value is uncompressed by default. + For the compressed encoding, use the `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` option. + * The *ECParameters* element uses a *namedCurve* by default. + To output specified domain parameters instead, use the `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` option. + + .. subsection:: Compatible key types + + * `PSA_KEY_TYPE_ECC_KEY_PAIR` + * `PSA_KEY_TYPE_RSA_KEY_PAIR` + + .. subsection:: Key format options + + * `PSA_KEY_FORMAT_OPTION_PEM` + * `PSA_KEY_FORMAT_OPTION_EC_POINT_COMPRESSED` (for Weierstrass elliptic curve keys) + * `PSA_KEY_FORMAT_OPTION_SPECIFIED_EC_DOMAIN` (for Weierstrass elliptic curve keys) + + .. subsection:: Compatible key-wrapping algorithms + + * :issue:`TBD` + +.. todo:: Do we also need a CMS content type format for encrypted OneAsymmetricKey data? + + +.. _key-wrap-algorithms: + +Key-wrapping algorithms +----------------------- + +.. macro:: PSA_ALG_WRAP + :definition: /* TBD */ + + .. summary:: + Generic key-wrapping algorithm. + + Use this algorithm with wrapped-key formats: + + * When wrapping a key, for formats that have a single applicable wrapping algorithm. + * When unwrapping a key, for formats that encode the wrapping algorithm. + + .. subsection:: Compatible key formats + + * `PSA_KEY_FORMAT_ENCRYPTED_PRIVATE_KEY_INFO` + + .. todo:: + I introduced this to simplify the application code when the key-wrapping algorithm is determined by the wrapped-key format, or the wrapped key data itself. + + The other parameters to the wrap/unwrap APIs match the behavior of formatted import and export, which is to expect a default value such as `PSA_KEY_TYPE_NONE` or ``0`` to indicate 'use the determined value'. In contrast to the suggestion here to use a dedicated value. + + The approach here more closely matches the `PSA_ALG_STREAM_CIPHER` algorithm for use with key types that pre-determine the algorithm (such as ChaCha). + + There is additional issue to consider: what should the permitted-algorithm be for wrapping keys that might be used with this algorithm? Or can this be a wild card that matches itself, or any specific algorithm that is applicable to the chosen key format? + + +.. macro:: PSA_ALG_AES_KW + :definition: /* TBD */ + + .. summary:: + The AES-KW key-wrapping algorithm. + + To wrap formatted keys that are not a multiple of the AES block size, `PSA_ALG_AES_KWP` can be used. + + .. subsection:: Compatible key formats + + This algorithm can wrap any formatted key that is an exact multiple of the 16-byte AES block size. + For example, use `PSA_KEY_FORMAT_DEFAULT` to wrap 128-bit and 256-bit AES keys. + + +.. macro:: PSA_ALG_AES_KWP + :definition: /* TBD */ + + .. summary:: + The AES-KWP key-wrapping algorithm with padding. + + .. subsection:: Compatible key formats + + This algorithm can wrap any formatted key that is no longer than 255 blocks of the AES block-cipher. + That is, a maximum of 4080 bytes. + +Key wrapping functions +---------------------- + +.. todo:: + Do we need a new pair of usage flags for wrapping keys? + + Could we reuse `PSA_KEY_USAGE_ENCRYPT` and `PSA_KEY_USAGE_DECRYPT` - these are already reused for ciphers, AEAD and asymmetric encryption. + + * This matches the existing usage of these flags for 'encrypt' or 'encrypt and integrity protect' operations. + * This would not enable key reuse, as the permitted-algorithm would have to be a specific key wrapping algorithm. + +.. function:: psa_unwrap_key + + .. summary:: + Unwrap and import a key using a specified wrapping key. + + .. param:: const psa_key_attributes_t * attributes + The attributes for the new key. + + Depending on the specified key format, and the attributes encoded in the wrapped-key data, some of the key attributes can be optional. + + The following attributes are required for formats that do not specify a key type: + + * When the format does not specify a key type: the key type in ``attributes`` determines how the decrypted ``data`` buffer is interpreted. + * When the format does specify a key type: if the key type in ``attributes`` has a non-default value, it must be equal to the determined key type. + + The following attributes must be set for keys used in cryptographic operations: + + * The key permitted-algorithm policy, see :secref:`permitted-algorithms`. + * The key usage flags, see :secref:`key-usage-flags`. + + These attributes are combined with any policy that is encoded in the wrapped-key data, so that both sets of restrictions apply :issue:`(this needs further thought & discussion)`. + + The following attributes must be set for keys that do not use the default volatile lifetime: + + * The key lifetime, see :secref:`key-lifetimes`. + * The key identifier is required for a key with a persistent lifetime, see :secref:`key-identifiers`. + + The following attributes are optional: + + * If the key size is nonzero, it must be equal to the key size determined from ``data``. + + .. note:: + This is an input parameter: it is not updated with the final key attributes. + The final attributes of the new key can be queried by calling `psa_get_key_attributes()` with the key's identifier. + .. param:: psa_key_id_t wrapping_key + Identifier of the key to use for the unwrapping operation. + It must permit the usage `PSA_KEY_USAGE_UNWRAP`. + .. param:: psa_algorithm_t alg + The key-wrapping algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_WRAP(alg)` is true. + .. param:: psa_key_format_t format + The format of the wrapped key data. + One of the ``PSA_KEY_FORMAT_XXX`` values, or an implementation-specific format. + .. param:: const uint8_t * data + Buffer containing the wrapped key data. + The content of this buffer is interpreted according to the key format ``format`` and unwrapping algorithm ``alg``. + The type declared in ``attributes`` is used if the format and key data do not specify a key type. + .. param:: size_t data_length + Size of the ``data`` buffer in bytes. + .. param:: psa_key_id_t * key + On success, an identifier for the newly created key. + `PSA_KEY_ID_NULL` on failure. + + .. return:: psa_status_t + .. 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_INVALID_SIGNATURE + The wrapped key data could not be authenticated. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``wrapping_key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported or is not a key-wrapping algorithm. + * ``wrapping_key`` is not supported for use with ``alg``. + * The key format is not supported by the implementation, or not supported with the chosen algorithm. + * The key attributes, as a whole, are not supported, either by the implementation in general or in the specified storage location. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * ``alg`` is not a key-wrapping algorithm. + * ``wrapping_key`` is not compatible with ``alg``. + * The key type is invalid, or is `PSA_KEY_TYPE_NONE` when a type is required. + * The key size is nonzero, and is incompatible with the wrapped key data in ``data``. + * The key lifetime is invalid. + * The key identifier is not valid for the key lifetime. + * The key usage flags include invalid values. + * The key's permitted-usage algorithm is invalid. + * The key attributes, as a whole, are invalid. + * The key format is invalid. + * The key data is not correctly formatted for the key format or the key type. + .. retval:: PSA_ERROR_NOT_PERMITTED + The following conditions can result in this error: + + * The wrapping key does not have the `PSA_KEY_USAGE_UNWRAP` flag, or it does not permit the requested algorithm. + * The implementation does not permit creating a key with the specified attributes due to some implementation-specific policy. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + The key is unwrapped and extracted from the provided ``data`` buffer, which is interpreted according to the specified key format and key-wrapping algorithm. + Its location is taken from ``attributes``, its type and policy are determined by the ``format``, the ``data``, and the ``attributes``. + + If a wrapped-key format, such as `PSA_KEY_FORMAT_ENCRYPTED_PRIVATE_KEY_INFO`, or the wrapped key data determines the key-wrapping algorithm, then ``alg`` must either match the determined key-wrapping algorithm or be `PSA_ALG_WRAP`. + :issue:`Should this be PSA_ALG_NONE, which is more aligned with the other parameters? How does this interact with key policy?` + + For non-default key formats, the key format either specifies the key type, or the wrapped key data encodes the key type. + For example, `PSA_KEY_FORMAT_RSA_PRIVATE_KEY` is always an RSA key pair, while the `PSA_KEY_FORMAT_ENCRYPTED_PRIVATE_KEY_INFO` format includes a data element that specifies whether it is an RSA or elliptic curve key-pair. + If the key type is determined by the format and the data, then :code:``psa_get_key_type(attributes)`` must either match the determined key type or be `PSA_KEY_TYPE_NONE`. + + The wrapped key data determines the key size. + :code:``psa_get_key_bits(attributes)`` must either match the determined key size or be ``0``. + Implementations must reject an attempt to import a key of size zero. + + The resulting key can only be used in a way that conforms to both the policy included in the wrapped key data, and the policy specified in the ``attributes`` parameter :issue:`(the following is place-holder cut and paste from psa_copy_key())`: + + * The usage flags on the resulting key are the bitwise-and of the usage flags on the source policy and the usage flags in ``attributes``. + * If both permit the same algorithm or wildcard-based algorithm, the resulting key has the same permitted algorithm. + * If either of the policies permits an algorithm and the other policy permits a wildcard-based permitted algorithm that includes this algorithm, the resulting key uses this permitted algorithm. + * If the policies do not permit any algorithm in common, this function fails with the status :code:`PSA_ERROR_INVALID_ARGUMENT`. + + As a result, the new key cannot be used for operations that were not permitted by the imported key data. + + .. todo:: The proposed constraints on key policy need to be revised in alignment with the approach decided for `psa_import_formatted_key()`. + + .. note:: + The |API| does not support asymmetric private key objects outside of a key pair. + When unwrapping a private key, the corresponding key-pair type is created. + If the imported key data does not contain the public key, then the implementation will reconstruct the public key from the private key as needed. + + .. admonition:: Implementation note + + To unwrap and import a key using a built-in or hidden key-wrapping key, it is recommended to define an implementation-specific key format, and use this in a call to `psa_import_formatted_key()`. + The custom key format can be used to indicate that the data is a key wrapped with the hidden key. + + It is recommended that implementations reject wrapped key data if it might be erroneous, for example, if it is the wrong type or is truncated. + +.. function:: psa_wrap_key + + .. summary:: + Wrap and export a key using a specified wrapping key. + + .. param:: psa_key_id_t wrapping_key + Identifier of the key to use for the wrapping operation. + It must permit the usage `PSA_KEY_USAGE_WRAP`. + .. param:: psa_algorithm_t alg + The key-wrapping algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_WRAP(alg)` is true. + .. param:: psa_key_format_t format + The required export format. + One of the ``PSA_KEY_FORMAT_XXX`` values, or an implementation-specific format. + .. param:: psa_key_format_option_t options + Formatting options to use. + One of the ``PSA_KEY_FORMAT_OPTION_XXX`` values, an implementation-specific option, or a bitwise-or of them. + .. param:: psa_key_id_t key + Identifier of the key to wrap. + It must permit the usage `PSA_KEY_USAGE_EXPORT`. + .. param:: uint8_t * data + Buffer where the wrapped key data is to be written. + .. param:: size_t data_size + Size of the ``data`` buffer in bytes. + This must be appropriate for the key: + + * The required output size is :code:`PSA_WRAP_KEY_OUTPUT_SIZE(wrap_key_type, alg, format, options, type, bits)`, where ``wrap_key_type`` is the type of the wrapping key, ``alg`` is the key-wrapping algorithm, ``format`` is the key format, ``options`` is the format options, ``type`` is the type of the key being wrapped, and ``bits`` is the bit-size of the key being wrapped. + * `PSA_WRAP_KEY_PAIR_MAX_SIZE` evaluates to the maximum wrapped output size of any supported key pair, in any supported combination of key-wrapping algorithm, wrapping-key type, key format and options. + * This API defines no maximum size for wrapped symmetric keys. Arbitrarily large data items can be stored in the key store, for example certificates that correspond to a stored private key or input material for key derivation. + .. param:: size_t * data_length + On success, the number of bytes that make up the wrapped key data. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The first ``(*data_length)`` bytes of ``data`` contain the wrapped key. + .. retval:: PSA_ERROR_INVALID_HANDLE + The following conditions can result in this error: + + * ``wrapping_key`` is not a valid key identifier. + * ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The following conditions can result in this error: + + * The wrapping key does not have the `PSA_KEY_USAGE_WRAP` flag, or it does not permit the requested algorithm. + * The key to be wrapped does not have the `PSA_KEY_USAGE_EXPORT` flag. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * ``alg`` is not a key-wrapping algorithm. + * ``wrapping_key`` is not compatible with ``alg``. + * The key format is not valid. + * The key format is not compatible with ``alg``. + * The key format is not applicable to the key type of ``key``. + * The key format option is not applicable to the key format. + + .. todo:: + Align behavior with `psa_export_formatted_key()` for inapplicable format options. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported or is not a key-wrapping algorithm. + * ``wrapping_key`` is not supported for use with ``alg``. + * The storage location of ``key`` does not support export of the key. + * The implementation does not support export of keys with the type of ``key``. + * The implementation does not support key export in the requested key format or format options. + .. retval:: PSA_ERROR_BUFFER_TOO_SMALL + The size of the ``data`` buffer is too small. + `PSA_WRAP_KEY_OUTPUT_SIZE()` or `PSA_WRAP_KEY_PAIR_MAX_SIZE` can be used to determine a sufficient buffer size. + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + Wrap a key from the key store into a data buffer using a specified key format, wrapping algorithm, and key-wrapping key. + On success, the output contains the wrapped key value, and, depending on the format, some of the key attributes. + The policy of the key to be wrapped must have the usage flag `PSA_KEY_USAGE_EXPORT` set. + + Some key-wrapping use cases can use a generic key-wrapping algorithm, such as `PSA_ALG_AES_KWP`, to encrypt any type of key, using any key format. See :secref:`key-wrap-algorithms`. + + Other use cases require a specific wrapped key format, such as `PSA_KEY_FORMAT_ENCRYPTED_PRIVATE_KEY_INFO`, which can be used for specific key types and with specific algorithms. Where the algorithm is determined by the wrapped-key format, ``alg`` must either match the key-wrapping algorithm or be `PSA_ALG_WRAP`. + :issue:`Ditto - should this be PSA_ALG_NONE? And how does this interact with key policy?` + + Some key formats can optionally include additional content or use different encodings. + These can be selected by using one or more of the ``PSA_KEY_FORMAT_OPTION_XXX`` values. + The format options that are applicable depend on the chosen key format, and the type of the key to be wrapped. + See :secref:`key-formats`. + + The output of this function can be passed to `psa_unwrap_key()`, specifying the same format, to create an equivalent key object. + +Support macros +-------------- + +.. macro:: PSA_WRAP_KEY_OUTPUT_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient output buffer size for `psa_export_formatted_key()`. + + .. param:: wrap_key_type + A supported key-wrapping key type. + .. param:: alg + A supported key-wrapping algorithm. + .. param:: format + A supported key format. + .. param:: options + A set of supported key format options. + .. 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()` will not fail with :code:`PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified. + + See also `PSA_EXPORT_FORMATTED_KEY_PAIR_MAX_SIZE`, `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE`, and `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE`. + +.. macro:: PSA_WRAP_KEY_PAIR_MAX_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient buffer size for exporting any formatted asymmetric key pair. + + This value must be a sufficient buffer size when calling `psa_wrap_key()` to export any asymmetric key pair that is supported by the implementation, regardless of the exact key type, key size, key format, and format options. + + See also `PSA_EXPORT_FORMATTED_KEY_OUTPUT_SIZE()`, `PSA_EXPORT_FORMATTED_PUBLIC_KEY_MAX_SIZE`, and `PSA_EXPORT_FORMATTED_ASYMMETRIC_KEY_MAX_SIZE`. diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 772524bf..4417efc6 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -33,6 +33,16 @@ Changes to the API See :secref:`asymmetric-key-encoding` and :secref:`appendix-specdef-key-values`. +* Added support for non-default key formats: + + - Added definitions for key formats and and formatting options. + See :secref:`key-formats`. + - Added `psa_import_formatted_key()` to import keys in other formats. + - Added `psa_export_formatted_key()` and `psa_export_formatted_public_key()` to export keys in other formats. + - Added ``PSA_EXPORT_FORMATTED_XXX`` support macros to evaluate buffer sizes for the formatted export functions. + +* Added support for key wrapping using key-wrapping algorithms and wrapped-key data formats. See :secref:`key-wrap`. + Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/crypto/references b/doc/crypto/references index 196e15df..b72fab6a 100644 --- a/doc/crypto/references +++ b/doc/crypto/references @@ -178,12 +178,6 @@ :publication: March 1998 :url: tools.ietf.org/html/rfc2315.html -.. reference:: RFC3279 - :title: Algorithms and Identifiers for the Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile - :author: IETF - :publication: April 2002 - :url: tools.ietf.org/html/rfc3279.html - .. reference:: RFC3610 :title: Counter with CBC-MAC (CCM) :author: IETF @@ -396,3 +390,51 @@ :author: Thread Group :publication: July 2022 :url: www.threadgroup.org/ThreadSpec + +.. reference:: RFC5208 + :title: Public-Key Cryptography Standards (PKCS) #8: Private-Key Information Syntax Specification Version 1.2 + :author: IETF + :publication: May 2008 + :url: tools.ietf.org/html/rfc5208.html + +.. reference:: RFC5280 + :title: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile + :author: IETF + :publication: May 2008 + :url: tools.ietf.org/html/rfc5280.html + +.. reference:: RFC5480 + :title: Elliptic Curve Cryptography Subject Public Key Information + :author: IETF + :publication: March 2009 + :url: tools.ietf.org/html/rfc5480.html + +.. reference:: RFC5958 + :title: Asymmetric Key Packages + :author: IETF + :publication: August 2010 + :url: tools.ietf.org/html/rfc5958.html + +.. reference:: RFC7468 + :title: Textual Encodings of PKIX, PKCS, and CMS Structures + :author: IETF + :publication: April 2015 + :url: tools.ietf.org/html/rfc7468.html + +.. reference:: RFC8410 + :title: Algorithm Identifiers for Ed25519, Ed448, X25519, and X448 for Use in the Internet X.509 Public Key Infrastructure + :author: IETF + :publication: August 2018 + :url: tools.ietf.org/html/rfc8410.html + +.. reference:: X.680 + :title: Information technology - Abstract Syntax Notation One (ASN.1): Specification of basic notation + :author: ITU + :publication: February 2021 + :url: itu.int/itu-t/recommendations/rec.aspx?rec=x.680 + +.. reference:: X.690 + :title: Information Technology - ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER) + :author: ITU + :publication: February 2021 + :url: itu.int/itu-t/recommendations/rec.aspx?rec=x.690 diff --git a/doc/crypto/terms b/doc/crypto/terms index fdcfed71..bd79730a 100644 --- a/doc/crypto/terms +++ b/doc/crypto/terms @@ -186,3 +186,24 @@ application instances. See :secref:`isolation`. + +.. term:: ASN.1 + + Abstract Syntax Notation One (ASN.1) is a language for defining data structures for cross-platform interchange. + It is used in the definition of many common key and certificate formats. + + ASN.1 is defined by :cite-title:`X.680`. + +.. term:: Distinguished Encoding Rules + :abbr: DER + + A binary encoding of structures defined using :term:`ASN.1`, that is used for X.509 certificate and key interchange formats. + + DER is defined by :cite-title:`X.690`. + +.. term:: PEM + + Originally "Privacy Enhanced Mail". + PEM is an ASCII-based encoding format used for X.509 certificates and keys. + + PEM is defined by :RFC-title:`7468`.