Key management functions
========================

.. _key-creation:

Key creation
------------

.. 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 key size is always determined from the ``data`` buffer. If the key size in ``attributes`` is nonzero, it must be equal to the size from ``data``.
    .. 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 documentation of `psa_export_key()` or `psa_export_public_key()` for the chosen 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.

    .. 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 type or key size is not supported, either by the implementation in general or in this particular persistent location.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The key attributes, as a whole, are invalid.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The key data is not correctly formatted.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The size in ``attributes`` is nonzero and does not match the size of the key data.
    .. 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_HARDWARE_FAILURE
    .. retval:: PSA_ERROR_CORRUPTION_DETECTED
    .. retval:: PSA_ERROR_BAD_STATE
        The library has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    This function supports any output from `psa_export_key()`. Refer to the documentation of `psa_export_public_key()` for the format of public keys and to the documentation of `psa_export_key()` for the format for other key types.

    The 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`` indicates that the key size is solely determined by the key data.

    Implementations must reject an attempt to import 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.

.. function:: psa_generate_key

    .. summary::
        Generate a key or key pair.

    .. param:: const psa_key_attributes_t * attributes
        The attributes for the new key.
    .. 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
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. retval:: PSA_ERROR_INSUFFICIENT_ENTROPY
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
    .. retval:: PSA_ERROR_HARDWARE_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 has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    The key is generated randomly. Its location, usage policy, type and size are taken from ``attributes``.

    Implementations must reject an attempt to generate a key of size ``0``.

    The following type-specific considerations apply:

    * For RSA keys (`PSA_KEY_TYPE_RSA_KEY_PAIR`), the public exponent is 65537. The modulus is a product of two probabilistic primes between 2^{n-1} and 2^n where n is the bit size specified in the attributes.

.. function:: psa_copy_key

    .. summary::
        Make a copy of a key.

    .. param:: psa_key_id_t source_key
        The key to copy.
        It must allow the usage `PSA_KEY_USAGE_COPY`.
        If a private or secret key is being copied outside of a secure element it must also allow `PSA_KEY_USAGE_EXPORT`.
    .. param:: const psa_key_attributes_t * attributes
        The attributes for the new key. They are used as follows:

        * The key type and size can be ``0``. If either is nonzero, it must match the corresponding attribute of the source key.
        * The key location (the lifetime and, for persistent keys, the key identifier) is used directly.
        * The policy constraints (usage flags and algorithm policy) are combined from the source key and ``attributes`` so that both sets of restrictions apply, as described in the documentation of this function.

    .. param:: psa_key_id_t * target_key
        On success, an identifier for the newly created key. `PSA_KEY_ID_NULL` on failure.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
    .. retval:: PSA_ERROR_INVALID_HANDLE
        ``source_key`` is invalid.
    .. retval:: PSA_ERROR_ALREADY_EXISTS
        This is an attempt to create a persistent key, and there is already a persistent key with the given identifier.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The lifetime or identifier in ``attributes`` are invalid.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The policy constraints on ``source_key`` and specified in ``attributes`` are incompatible.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        ``attributes`` specifies a key type or key size which does not match the attributes of ``source key``.
    .. retval:: PSA_ERROR_NOT_PERMITTED
        ``source_key`` does not have the `PSA_KEY_USAGE_COPY` usage flag.
    .. retval:: PSA_ERROR_NOT_PERMITTED
        ``source_key`` does not have the `PSA_KEY_USAGE_EXPORT` usage flag and its lifetime does not allow copying it to the target's lifetime.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
    .. retval:: PSA_ERROR_HARDWARE_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 has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    Copy key material from one location to another.

    This function is primarily useful to copy a key from one location to another, as it populates a key using the material from another key which can have a different lifetime.

    This function can be used to share a key with a different party, subject to implementation-defined restrictions on key sharing.

    The policy on the source key must have the usage flag `PSA_KEY_USAGE_COPY` set. This flag is sufficient to permit the copy if the key has the lifetime `PSA_KEY_LIFETIME_VOLATILE` or `PSA_KEY_LIFETIME_PERSISTENT`. Some secure elements do not provide a way to copy a key without making it extractable from the secure element. If a key is located in such a secure element, then the key must have both usage flags `PSA_KEY_USAGE_COPY` and `PSA_KEY_USAGE_EXPORT` in order to make a copy of the key outside the secure element.

    The resulting key can only be used in a way that conforms to both the policy of the original key and the policy specified in the ``attributes`` parameter:

    * 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 allow the same algorithm or wildcard-based algorithm policy, the resulting key has the same algorithm policy.
    * If either of the policies allows an algorithm and the other policy allows a wildcard-based algorithm policy that includes this algorithm, the resulting key allows the same algorithm.
    * If the policies do not allow any algorithm in common, this function fails with the status `PSA_ERROR_INVALID_ARGUMENT`.

    The effect of this function on implementation-defined attributes is implementation-defined.


.. _key-destruction:

Key destruction
---------------

.. function:: psa_destroy_key

    .. summary::
        Destroy a key.

    .. param:: psa_key_id_t key
        Identifier of the key to erase.
        If this is `PSA_KEY_ID_NULL`, do nothing and return `PSA_SUCCESS`.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        ``key`` was a valid key identifier and the key material that it referred to has been erased.
        Alternatively, ``key`` is `PSA_KEY_ID_NULL`.
    .. retval:: PSA_ERROR_NOT_PERMITTED
        The key cannot be erased because it is read-only, either due to a policy or due to physical restrictions.
    .. retval:: PSA_ERROR_INVALID_HANDLE
        ``key`` is not a valid handle nor `PSA_KEY_ID_NULL`.
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
        There was an failure in communication with the cryptoprocessor. The key material might still be present in the cryptoprocessor.
    .. retval:: PSA_ERROR_STORAGE_FAILURE
        The storage operation failed. Implementations must make a best effort to erase key material even in this situation, however, it might be impossible to guarantee that the key material is not recoverable in such cases.
    .. retval:: PSA_ERROR_DATA_CORRUPT
        The storage is corrupted. Implementations must make a best effort to erase key material even in this situation, however, it might be impossible to guarantee that the key material is not recoverable in such cases.
    .. retval:: PSA_ERROR_DATA_INVALID
    .. retval:: PSA_ERROR_CORRUPTION_DETECTED
        An unexpected condition which is not a storage corruption or a communication failure occurred. The cryptoprocessor might have been compromised.
    .. retval:: PSA_ERROR_BAD_STATE
        The library has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    This function destroys a key from both volatile memory and, if applicable, non-volatile storage. Implementations must make a best effort to ensure that that the key material cannot be recovered.

    This function also erases any metadata such as policies and frees resources associated with the key.

    Destroying the key makes the key identifier invalid, and the key identifier must not be used again by the application.

    If a key is currently in use in a multi-part operation, then destroying the key will cause the multi-part operation to fail.

.. function:: psa_purge_key

    .. summary::
        Remove non-essential copies of key material from memory.

    .. param:: psa_key_id_t key
        Identifier of the key to purge.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        The key material will have been removed from memory if it is not currently required.
    .. retval:: PSA_ERROR_INVALID_HANDLE
    .. 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 has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    An implementation is permitted to make additional copies of key material
    For keys that have been created with the `PSA_KEY_USAGE_CACHE` policy, an implementation is permitted to make additional copies of the key material that are not in storage and not for the purpose of ongoing operations.

    This function will remove these extra copies of the key material from memory.

    This function is not required to remove key material from memory in any of the following situations:

    - The key is currently in use in a cryptographic operation.
    - The key is volatile.

    See also :title:`key-material`.


.. _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 allow 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.
        * For asymmetric keys, `PSA_EXPORT_KEY_PAIR_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
    .. retval:: PSA_ERROR_INVALID_HANDLE
    .. retval:: PSA_ERROR_NOT_PERMITTED
        The key does not have the `PSA_KEY_USAGE_EXPORT` flag.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``data`` buffer is too small.
        `PSA_EXPORT_KEY_OUTPUT_SIZE()` or `PSA_EXPORT_KEY_PAIR_MAX_SIZE` can be used to determine the required buffer size.
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
    .. retval:: PSA_ERROR_HARDWARE_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 has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    The output of this function can be passed to `psa_import_key()` to create an equivalent object.

    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 here, not the original representation.

    For standard key types, the output format is as follows:

    * For symmetric keys, including MAC keys, the format is the raw bytes of the key.

    * For DES, the key data consists of 8 bytes. The parity bits must be correct.

    * For Triple-DES, the format is the concatenation of the two or three DES keys.

    * For RSA key pairs, with key type `PSA_KEY_TYPE_RSA_KEY_PAIR`, the format is the non-encrypted DER encoding of the representation defined by PKCS#1 in :RFC:`8017` as ``RSAPrivateKey``, version ``0``.

      .. code:: none

          RSAPrivateKey ::= SEQUENCE {
              version             INTEGER,  -- must be 0
              modulus             INTEGER,  -- n
              publicExponent      INTEGER,  -- e
              privateExponent     INTEGER,  -- d
              prime1              INTEGER,  -- p
              prime2              INTEGER,  -- q
              exponent1           INTEGER,  -- d mod (p-1)
              exponent2           INTEGER,  -- d mod (q-1)
              coefficient         INTEGER,  -- (inverse of q) mod p
          }

    * For elliptic curve key pairs, with key types for which `PSA_KEY_TYPE_IS_ECC_KEY_PAIR()` is true, the format is a representation of the private value.

      - For Weierstrass curve families ``PSA_ECC_FAMILY_SECT_XX``, ``PSA_ECC_FAMILY_SECP_XX``, `PSA_ECC_FAMILY_FRP` and `PSA_ECC_FAMILY_BRAINPOOL_P_R1`, the content of the ``privateKey`` field of the ``ECPrivateKey`` format defined by :RFC:`5915`. This is a ``ceiling(m/8)``-byte string in big-endian order where ``m`` is the key size in bits.

      - For curve family `PSA_ECC_FAMILY_MONTGOMERY`, the scalar value of the 'private key' in little-endian order as defined by :RFC:`7748#6`. This is a ``ceiling(m/8)``-byte string where ``m`` is the key size in bits. This is 32 bytes for Curve25519, and 56 bytes for Curve448.

    * For Diffie-Hellman key exchange key pairs, with key types for which `PSA_KEY_TYPE_IS_DH_KEY_PAIR()` is true, the format is the representation of the private key ``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.

    * For public keys, with key types for which `PSA_KEY_TYPE_IS_PUBLIC_KEY()` is true, the format is the same as for `psa_export_public_key()`.

    The policy on the key must have the usage flag `PSA_KEY_USAGE_EXPORT` set.

.. 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.

    .. param:: size_t * data_length
        On success, the number of bytes that make up the key data.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
    .. retval:: PSA_ERROR_INVALID_HANDLE
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The key is neither a public key nor a key pair.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``data`` buffer is too small.
        `PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE()` or `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE` can be used to determine the required buffer size.
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
    .. retval:: PSA_ERROR_HARDWARE_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 has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    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 of `psa_import_key()` supports other formats beyond the format specified here, the output from `psa_export_public_key()` must use the representation specified here, not the original representation.

    For standard key types, the output format is as follows:

    * For RSA public keys, with key type `PSA_KEY_TYPE_RSA_PUBLIC_KEY`, the DER encoding of the representation defined by :RFC:`3279#2.3.1` as ``RSAPublicKey``.

      .. code:: none

          RSAPublicKey ::= SEQUENCE {
             modulus            INTEGER,    -- n
             publicExponent     INTEGER  }  -- e

    * For elliptic curve key pairs, with key types for which `PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY()` is true, the format depends on the key family:

      - For Weierstrass curve families ``PSA_ECC_FAMILY_SECT_XX``, ``PSA_ECC_FAMILY_SECP_XX``, `PSA_ECC_FAMILY_FRP` and `PSA_ECC_FAMILY_BRAINPOOL_P_R1`, the uncompressed representation defined by *Standards for Efficient Cryptography*, |SEC1|_ §2.3.3 as the content of an ``ECPoint``. If ``m`` is the bit size associated with the curve, i.e. the bit size of ``q`` for a curve over ``F_q``. The representation consists of:

        * The byte ``0x04``;
        * ``x_P`` as a ``ceiling(m/8)``-byte string, big-endian;
        * ``y_P`` as a ``ceiling(m/8)``-byte string, big-endian.

        .. |SEC1| replace:: *SEC 1: Elliptic Curve Cryptography*
        .. _SEC1: https://www.secg.org/sec1-v2.pdf

      - For curve family `PSA_ECC_FAMILY_MONTGOMERY`, the scalar value of the 'public key' in little-endian order as defined by :RFC:`7748#6`. This is a ``ceiling(m/8)``-byte string where ``m`` is the key size in bits.

        * This is 32 bytes for Curve25519, computed as ``X25519(private_key, 9)``.
        * This is 56 bytes for Curve448, computed as ``X448(private_key, 5)``.

    * For Diffie-Hellman key exchange public keys, with key types for which `PSA_KEY_TYPE_IS_DH_PUBLIC_KEY` is true, the format is the representation of the public key ``y = g^x mod p`` as a big-endian byte string. The length of the byte string is the length of the base prime ``p`` in bytes.

    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()` or `psa_export_public_key()` will not fail with `PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified.

    This macro returns a compile-time constant if its arguments are compile-time constants.

    .. warning::
        This function can evaluate its arguments multiple times or zero times. Providing arguments that have side effects will result in implementation-specific behavior, and is non-portable.

    The following code illustrates how to allocate enough memory to export a key by querying the key type and size at runtime.

    .. autocode::

        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` and `PSA_EXPORT_PUBLIC_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 `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)`.

    This macro returns a compile-time constant if its arguments are compile-time constants.

    .. warning::
        This function can evaluate its arguments multiple times or zero times. Providing arguments that have side effects will result in implementation-specific behavior, and is non-portable.

    The following code illustrates how to allocate enough memory to export a public key by querying the key type and size at runtime.

    .. autocode::

        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);
        psa_reset_key_attributes(&attributes);
        uint8_t *buffer = malloc(buffer_size);
        if (buffer == NULL)
            handle_error(...);
        size_t buffer_length;
        status = psa_export_public_key(key, buffer, buffer_size, &buffer_length);
        if (status != PSA_SUCCESS)
            handle_error(...);

    See also `PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`.

.. macro:: PSA_EXPORT_KEY_PAIR_MAX_SIZE
    :definition: /* implementation-defined value */

    .. summary::
        Sufficient buffer size for exporting any asymmetric key pair.

    This macro must expand to a compile-time constant integer.
    This value must be a sufficient buffer size when calling `psa_export_key()` to export any asymmetric key pair that is supported by the implementation, regardless of the exact key type and key size.

    See also `PSA_EXPORT_KEY_OUTPUT_SIZE()`.

.. macro:: PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
    :definition: /* implementation-defined value */

    .. summary::
        Sufficient buffer size for exporting any asymmetric public key.

    This macro must expand to a compile-time constant integer.
    This value must be a sufficient buffer size when calling `psa_export_key()` or `psa_export_public_key()` to export any asymmetric public key that is supported by the implementation, regardless of the exact key type and key size.

    See also `PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE()`.
