.. _aead:

Authenticated encryption with associated data (AEAD)
====================================================

.. _aead-algorithms:

AEAD algorithms
---------------

.. macro:: PSA_ALG_CCM
    :definition: ((psa_algorithm_t)0x05500100)

    .. summary::
        The CCM authenticated encryption algorithm.

    The underlying block cipher is determined by the key type.

.. macro:: PSA_ALG_GCM
    :definition: ((psa_algorithm_t)0x05500200)

    .. summary::
        The GCM authenticated encryption algorithm.

    The underlying block cipher is determined by the key type.

.. macro:: PSA_ALG_CHACHA20_POLY1305
    :definition: ((psa_algorithm_t)0x05100500)

    .. summary::
        The Chacha20-Poly1305 AEAD algorithm.

    The ChaCha20_Poly1305 construction is defined in :RFC:`7539`.

    Variants of this algorithm are defined by the length of the nonce:

    - Implementations must support a 12-byte nonce, as defined in :RFC:`7539`.
    - Implementations can optionally support an 8-byte nonce, the original variant.
    - It is recommended that implementations do not support other sizes of nonce.

    Implementations must support 16-byte tags. It is recommended that truncated tag sizes are rejected.

.. macro:: PSA_ALG_AEAD_WITH_SHORTENED_TAG
    :definition: /* specification-defined value */

    .. summary::
        Macro to build a AEAD algorithm with a shortened tag.

    .. param:: aead_alg
        An AEAD algorithm identifier (value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_AEAD(alg)` is true).
    .. param:: tag_length
        Desired length of the authentication tag in bytes.

    .. return::
        The corresponding AEAD algorithm with the specified tag length.

        Unspecified if ``alg`` is not a supported AEAD algorithm or if ``tag_length`` is not valid for the specified AEAD algorithm.

    An AEAD algorithm with a shortened tag is similar to the corresponding AEAD algorithm, but has an authentication tag that consists of fewer bytes. Depending on the algorithm, the tag length might affect the calculation of the ciphertext.

    The AEAD algorithm with a default length tag can be recovered using `PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG()`.

Single-part AEAD functions
--------------------------

.. function:: psa_aead_encrypt

    .. summary::
        Process an authenticated encryption operation.

    .. param:: psa_key_id_t key
        Identifier of the key to use for the operation.
        It must allow the usage `PSA_KEY_USAGE_ENCRYPT`.
    .. param:: psa_algorithm_t alg
        The AEAD algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).
    .. param:: const uint8_t * nonce
        Nonce or IV to use.
    .. param:: size_t nonce_length
        Size of the ``nonce`` buffer in bytes. This must be appropriate for the selected algorithm. The default nonce size is :code:`PSA_AEAD_NONCE_LENGTH(key_type, alg)` where ``key_type`` is the type of ``key``.
    .. param:: const uint8_t * additional_data
        Additional data that will be authenticated but not encrypted.
    .. param:: size_t additional_data_length
        Size of ``additional_data`` in bytes.
    .. param:: const uint8_t * plaintext
        Data that will be authenticated and encrypted.
    .. param:: size_t plaintext_length
        Size of ``plaintext`` in bytes.
    .. param:: uint8_t * ciphertext
        Output buffer for the authenticated and encrypted data. The additional data is not part of this output. For algorithms where the encrypted data and the authentication tag are defined as separate outputs, the authentication tag is appended to the encrypted data.
    .. param:: size_t ciphertext_size
        Size of the ``ciphertext`` buffer in bytes. This must be appropriate for the selected algorithm and key:

        * A sufficient output size is :code:`PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length)`  where ``key_type`` is the type of ``key``.
        * :code:`PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(plaintext_length)` evaluates to the maximum ciphertext size of any supported AEAD encryption.

    .. param:: size_t * ciphertext_length
        On success, the size of the output in the ``ciphertext`` buffer.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_INVALID_HANDLE
    .. retval:: PSA_ERROR_NOT_PERMITTED
        The key does not have the `PSA_KEY_USAGE_ENCRYPT` flag, or it does not permit the requested algorithm.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        ``key`` is not compatible with ``alg``.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        ``alg`` is not supported or is not an AEAD algorithm.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        ``ciphertext_size`` is too small. `PSA_AEAD_ENCRYPT_OUTPUT_SIZE()` or `PSA_AEAD_ENCRYPT_OUTPUT_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_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.

.. function:: psa_aead_decrypt

    .. summary::
        Process an authenticated decryption operation.

    .. param:: psa_key_id_t key
        Identifier of the key to use for the operation.
        It must allow the usage `PSA_KEY_USAGE_DECRYPT`.
    .. param:: psa_algorithm_t alg
        The AEAD algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).
    .. param:: const uint8_t * nonce
        Nonce or IV to use.
    .. param:: size_t nonce_length
        Size of the ``nonce`` buffer in bytes. This must be appropriate for the selected algorithm. The default nonce size is :code:`PSA_AEAD_NONCE_LENGTH(key_type, alg)` where ``key_type`` is the type of ``key``.
    .. param:: const uint8_t * additional_data
        Additional data that has been authenticated but not encrypted.
    .. param:: size_t additional_data_length
        Size of ``additional_data`` in bytes.
    .. param:: const uint8_t * ciphertext
        Data that has been authenticated and encrypted. For algorithms where the encrypted data and the authentication tag are defined as separate inputs, the buffer must contain the encrypted data followed by the authentication tag.
    .. param:: size_t ciphertext_length
        Size of ``ciphertext`` in bytes.
    .. param:: uint8_t * plaintext
        Output buffer for the decrypted data.
    .. param:: size_t plaintext_size
        Size of the ``plaintext`` buffer in bytes. This must be appropriate for the selected algorithm and key:

        * A sufficient output size is :code:`PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length)`  where ``key_type`` is the type of ``key``.
        * :code:`PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length)` evaluates to the maximum plaintext size of any supported AEAD decryption.

    .. param:: size_t * plaintext_length
        On success, the size of the output in the ``plaintext`` buffer.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_INVALID_HANDLE
    .. retval:: PSA_ERROR_INVALID_SIGNATURE
        The ciphertext is not authentic.
    .. retval:: PSA_ERROR_NOT_PERMITTED
        The key does not have the `PSA_KEY_USAGE_DECRYPT` flag, or it does not permit the requested algorithm.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        ``key`` is not compatible with ``alg``.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        ``alg`` is not supported or is not an AEAD algorithm.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        ``plaintext_size`` is too small. `PSA_AEAD_DECRYPT_OUTPUT_SIZE()` or `PSA_AEAD_DECRYPT_OUTPUT_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_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.

Multi-part AEAD operations
--------------------------

.. _aead-multi-part-warning:

.. warning::
    When decrypting using a multi-part AEAD operation, there is no guarantee that the input or output is valid until `psa_aead_verify()` has returned `PSA_SUCCESS`.

    A call to `psa_aead_update()` or `psa_aead_update_ad()` returning `PSA_SUCCESS` **does not** indicate that the input and output is valid.

    Until an application calls `psa_aead_verify()` and it has returned `PSA_SUCCESS`, the following rules apply to input and output data from a multi-part AEAD operation:

    * Do not trust the input. If the application takes any action that depends on the input data, this action will need to be undone if the input turns out to be invalid.

    * Store the output in a confidential location. In particular, the application must not copy the output to a memory or storage space which is shared.

    * Do not trust the output. If the application takes any action that depends on the tentative decrypted data, this action will need to be undone if the input turns out to be invalid. Furthermore, if an adversary can observe that this action took place, for example, through timing, they might be able to use this fact as an oracle to decrypt any message encrypted with the same key.

    An application that does not follow these rules might be vulnerable to maliciously constructed AEAD input data.


.. typedef:: /* implementation-defined type */ psa_aead_operation_t

    .. summary::
        The type of the state object for multi-part AEAD operations.

    Before calling any function on an AEAD operation object, the application must initialize it by any of the following means:

    * Set the object to all-bits-zero, for example:

      .. autocode::
          psa_aead_operation_t operation;
          memset(&operation, 0, sizeof(operation));

    * Initialize the object to logical zero values by declaring the object as static or global without an explicit initializer, for example:

      .. autocode::
          static psa_aead_operation_t operation;

    * Initialize the object to the initializer `PSA_AEAD_OPERATION_INIT`, for example:

      .. autocode::
          psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;

    * Assign the result of the function `psa_aead_operation_init()` to the object, for example:

      .. autocode::
          psa_aead_operation_t operation;
          operation = psa_aead_operation_init();

    This is an implementation-defined type. Applications that make assumptions about the content of this object will result in in implementation-specific behavior, and are non-portable.

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

    .. summary::
        This macro returns a suitable initializer for an AEAD operation object of type `psa_aead_operation_t`.

.. function:: psa_aead_operation_init

    .. summary::
        Return an initial value for an AEAD operation object.

    .. return:: psa_aead_operation_t

.. function:: psa_aead_encrypt_setup

    .. summary::
        Set the key for a multi-part authenticated encryption operation.

    .. param:: psa_aead_operation_t * operation
        The operation object to set up. It must have been initialized as per the documentation for `psa_aead_operation_t` and not yet in use.
    .. param:: psa_key_id_t key
        Identifier of the key to use for the operation. It must remain valid until the operation terminates.
        It must allow the usage `PSA_KEY_USAGE_ENCRYPT`.
    .. param:: psa_algorithm_t alg
        The AEAD algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be inactive.
    .. retval:: PSA_ERROR_INVALID_HANDLE
    .. retval:: PSA_ERROR_NOT_PERMITTED
        The key does not have the `PSA_KEY_USAGE_ENCRYPT` flag, or it does not permit the requested algorithm.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        ``key`` is not compatible with ``alg``.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        ``alg`` is not supported or is not an AEAD algorithm.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. 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_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 sequence of operations to encrypt a message with authentication is as follows:

    #. Allocate an operation object which will be passed to all the functions listed here.
    #. Initialize the operation object with one of the methods described in the documentation for `psa_aead_operation_t`, e.g. `PSA_AEAD_OPERATION_INIT`.
    #. Call `psa_aead_encrypt_setup()` to specify the algorithm and key.
    #. If needed, call `psa_aead_set_lengths()` to specify the length of the inputs to the subsequent calls to `psa_aead_update_ad()` and `psa_aead_update()`. See the documentation of `psa_aead_set_lengths()` for details.
    #. Call either `psa_aead_generate_nonce()` or `psa_aead_set_nonce()` to generate or set the nonce. It is recommended to use `psa_aead_generate_nonce()` unless the protocol being implemented requires a specific nonce value.
    #. Call `psa_aead_update_ad()` zero, one or more times, passing a fragment of the non-encrypted additional authenticated data each time.
    #. Call `psa_aead_update()` zero, one or more times, passing a fragment of the message to encrypt each time.
    #. Call `psa_aead_finish()`.

    If an error occurs at any step after a call to `psa_aead_encrypt_setup()`, the operation will need to be reset by a call to `psa_aead_abort()`. The application can call `psa_aead_abort()` at any time after the operation has been initialized.

    After a successful call to `psa_aead_encrypt_setup()`, the application must eventually terminate the operation. The following events terminate an operation:

    * A successful call to `psa_aead_finish()`.
    * A call to `psa_aead_abort()`.

.. function:: psa_aead_decrypt_setup

    .. summary::
        Set the key for a multi-part authenticated decryption operation.

    .. param:: psa_aead_operation_t * operation
        The operation object to set up. It must have been initialized as per the documentation for `psa_aead_operation_t` and not yet in use.
    .. param:: psa_key_id_t key
        Identifier of the key to use for the operation. It must remain valid until the operation terminates.
        It must allow the usage `PSA_KEY_USAGE_DECRYPT`.
    .. param:: psa_algorithm_t alg
        The AEAD algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be inactive.
    .. retval:: PSA_ERROR_INVALID_HANDLE
    .. retval:: PSA_ERROR_NOT_PERMITTED
        The key does not have the `PSA_KEY_USAGE_DECRYPT` flag, or it does not permit the requested algorithm.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        ``key`` is not compatible with ``alg``.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        ``alg`` is not supported or is not an AEAD algorithm.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. 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_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 sequence of operations to decrypt a message with authentication is as follows:

    #. Allocate an operation object which will be passed to all the functions listed here.
    #. Initialize the operation object with one of the methods described in the documentation for `psa_aead_operation_t`, e.g. `PSA_AEAD_OPERATION_INIT`.
    #. Call `psa_aead_decrypt_setup()` to specify the algorithm and key.
    #. If needed, call `psa_aead_set_lengths()` to specify the length of the inputs to the subsequent calls to `psa_aead_update_ad()` and `psa_aead_update()`. See the documentation of `psa_aead_set_lengths()` for details.
    #. Call `psa_aead_set_nonce()` with the nonce for the decryption.
    #. Call `psa_aead_update_ad()` zero, one or more times, passing a fragment of the non-encrypted additional authenticated data each time.
    #. Call `psa_aead_update()` zero, one or more times, passing a fragment of the ciphertext to decrypt each time.
    #. Call `psa_aead_verify()`.

    If an error occurs at any step after a call to `psa_aead_decrypt_setup()`, the operation will need to be reset by a call to `psa_aead_abort()`. The application can call `psa_aead_abort()` at any time after the operation has been initialized.

    After a successful call to `psa_aead_decrypt_setup()`, the application must eventually terminate the operation. The following events terminate an operation:

    * A successful call to `psa_aead_verify()`.
    * A call to `psa_aead_abort()`.

.. function:: psa_aead_generate_nonce

    .. summary::
        Generate a random nonce for an authenticated encryption operation.

    .. param:: psa_aead_operation_t * operation
        Active AEAD operation.
    .. param:: uint8_t * nonce
        Buffer where the generated nonce is to be written.
    .. param:: size_t nonce_size
        Size of the ``nonce`` buffer in bytes. This must be at least :code:`PSA_AEAD_NONCE_LENGTH(key_type, alg)` where ``key_type`` and ``alg`` are type of key and the algorithm respectively that were used to set up the AEAD operation.
    .. param:: size_t * nonce_length
        On success, the number of bytes of the generated nonce.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be an active AEAD encryption operation, with no nonce set.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``nonce`` buffer is too small. `PSA_AEAD_NONCE_LENGTH()` or `PSA_AEAD_NONCE_MAX_SIZE` can be used to determine the required buffer size.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. 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_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 generates a random nonce for the authenticated encryption operation with an appropriate size for the chosen algorithm, key type and key size.

    The application must call `psa_aead_encrypt_setup()` before calling this function.

    If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_aead_abort()`.

.. function:: psa_aead_set_nonce

    .. summary::
        Set the nonce for an authenticated encryption or decryption operation.

    .. param:: psa_aead_operation_t * operation
        Active AEAD operation.
    .. param:: const uint8_t * nonce
        Buffer containing the nonce to use.
    .. param:: size_t nonce_length
        Size of the nonce in bytes. This must be a valid nonce size for the chosen algorithm. The default nonce size is :code:`PSA_AEAD_NONCE_LENGTH(key_type, alg)` where ``key_type`` and ``alg`` are type of key and the algorithm respectively that were used to set up the AEAD operation.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active, with no nonce set.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The size of ``nonce`` is not acceptable for the chosen algorithm.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. 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_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 sets the nonce for the authenticated encryption or decryption operation.

    The application must call `psa_aead_encrypt_setup()` or `psa_aead_decrypt_setup()` before calling this function.

    If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_aead_abort()`.

    .. note::
        When encrypting, `psa_aead_generate_nonce()` is recommended instead of using this function, unless implementing a protocol that requires a non-random IV.

.. function:: psa_aead_set_lengths

    .. summary::
        Declare the lengths of the message and additional data for AEAD.

    .. param:: psa_aead_operation_t * operation
        Active AEAD operation.
    .. param:: size_t ad_length
        Size of the non-encrypted additional authenticated data in bytes.
    .. param:: size_t plaintext_length
        Size of the plaintext to encrypt in bytes.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active, and `psa_aead_update_ad()` and `psa_aead_update()` must not have been called yet.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        At least one of the lengths is not acceptable for the chosen algorithm.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
    .. retval:: PSA_ERROR_HARDWARE_FAILURE
    .. retval:: PSA_ERROR_CORRUPTION_DETECTED
    .. retval:: PSA_ERROR_BAD_STATE
        The library has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    The application must call this function before calling `psa_aead_update_ad()` or `psa_aead_update()` if the algorithm for the operation requires it. If the algorithm does not require it, calling this function is optional, but if this function is called then the implementation must enforce the lengths.

    This function can be called before or after setting the nonce with `psa_aead_set_nonce()` or `psa_aead_generate_nonce()`.

    * For `PSA_ALG_CCM`, calling this function is required.
    * For the other AEAD algorithms defined in this specification, calling this function is not required.
    * For vendor-defined algorithm, refer to the vendor documentation.

    If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_aead_abort()`.

.. function:: psa_aead_update_ad

    .. summary::
        Pass additional data to an active AEAD operation.

    .. param:: psa_aead_operation_t * operation
        Active AEAD operation.
    .. param:: const uint8_t * input
        Buffer containing the fragment of additional data.
    .. param:: size_t input_length
        Size of the ``input`` buffer in bytes.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.

        .. warning::
            When decrypting, do not trust the input until `psa_aead_verify()` succeeds.

            See the :ref:`detailed warning <aead-multi-part-warning>`.

    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active, have a nonce set, have lengths set if required by the algorithm, and `psa_aead_update()` must not have been called yet.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The total input length overflows the additional data length that was previously specified with `psa_aead_set_lengths()`.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. 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_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.

    Additional data is authenticated, but not encrypted.

    This function can be called multiple times to pass successive fragments of the additional data. This function must not be called after passing data to encrypt or decrypt with `psa_aead_update()`.

    The following must occur before calling this function:

    #. Call either `psa_aead_encrypt_setup()` or `psa_aead_decrypt_setup()`.
    #. Set the nonce with `psa_aead_generate_nonce()` or `psa_aead_set_nonce()`.

    If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_aead_abort()`.

.. function:: psa_aead_update

    .. summary::
        Encrypt or decrypt a message fragment in an active AEAD operation.

    .. param:: psa_aead_operation_t * operation
        Active AEAD operation.
    .. param:: const uint8_t * input
        Buffer containing the message fragment to encrypt or decrypt.
    .. param:: size_t input_length
        Size of the ``input`` buffer in bytes.
    .. param:: uint8_t * output
        Buffer where the output is to be written.
    .. param:: size_t output_size
        Size of the ``output`` buffer in bytes. This must be appropriate for the selected algorithm and key:

        * A sufficient output size is :code:`PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_length)` where ``key_type`` is the type of key and ``alg`` is the algorithm that were used to set up the operation.
        * :code:`PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_length)` evaluates to the maximum output size of any supported AEAD algorithm.

    .. param:: size_t * output_length
        On success, the number of bytes that make up the returned output.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.

        .. warning::
            When decrypting, do not use the output until `psa_aead_verify()` succeeds.

            See the :ref:`detailed warning <aead-multi-part-warning>`.

    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active, have a nonce set, and have lengths set if required by the algorithm.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``output`` buffer is too small. `PSA_AEAD_UPDATE_OUTPUT_SIZE()` or `PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE()` can be used to determine the required buffer size.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The total length of input to `psa_aead_update_ad()` so far is less than the additional data length that was previously specified with `psa_aead_set_lengths()`.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The total input length overflows the plaintext length that was previously specified with `psa_aead_set_lengths()`.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. 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_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 following must occur before calling this function:

    #. Call either `psa_aead_encrypt_setup()` or `psa_aead_decrypt_setup()`. The choice of setup function determines whether this function encrypts or decrypts its input.
    #. Set the nonce with `psa_aead_generate_nonce()` or `psa_aead_set_nonce()`.
    #. Call `psa_aead_update_ad()` to pass all the additional data.

    If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_aead_abort()`.

    This function does not require the input to be aligned to any particular block boundary. If the implementation can only process a whole block at a time, it must consume all the input provided, but it might delay the end of the corresponding output until a subsequent call to `psa_aead_update()`, `psa_aead_finish()` or `psa_aead_verify()` provides sufficient input. The amount of data that can be delayed in this way is bounded by `PSA_AEAD_UPDATE_OUTPUT_SIZE()`.

.. function:: psa_aead_finish

    .. summary::
        Finish encrypting a message in an AEAD operation.

    .. param:: psa_aead_operation_t * operation
        Active AEAD operation.
    .. param:: uint8_t * ciphertext
        Buffer where the last part of the ciphertext is to be written.
    .. param:: size_t ciphertext_size
        Size of the ``ciphertext`` buffer in bytes. This must be appropriate for the selected algorithm and key:

        * A sufficient output size is :code:`PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg)` where ``key_type`` is the type of key and ``alg`` is the algorithm that were used to set up the operation.
        * `PSA_AEAD_FINISH_OUTPUT_MAX_SIZE` evaluates to the maximum output size of any supported AEAD algorithm.

    .. param:: size_t * ciphertext_length
        On success, the number of bytes of returned ciphertext.
    .. param:: uint8_t * tag
        Buffer where the authentication tag is to be written.
    .. param:: size_t tag_size
        Size of the ``tag`` buffer in bytes.
        This must be appropriate for the selected algorithm and key:

        * The exact tag size is :code:`PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg)` where ``key_type`` and ``key_bits`` are the type and bit-size of the key, and ``alg`` is the algorithm that were used in the call to `psa_aead_encrypt_setup()`.
        * `PSA_AEAD_TAG_MAX_SIZE` evaluates to the maximum tag size of any supported AEAD algorithm.

    .. param:: size_t * tag_length
        On success, the number of bytes that make up the returned tag.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be an active encryption operation with a nonce set.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``ciphertext`` or ``tag`` buffer is too small.
        `PSA_AEAD_FINISH_OUTPUT_SIZE()` or `PSA_AEAD_FINISH_OUTPUT_MAX_SIZE` can be used to determine the required ``ciphertext`` buffer size.
        `PSA_AEAD_TAG_LENGTH()` or `PSA_AEAD_TAG_MAX_SIZE` can be used to determine the required ``tag`` buffer size.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The total length of input to `psa_aead_update_ad()` so far is less than the additional data length that was previously specified with `psa_aead_set_lengths()`.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The total length of input to `psa_aead_update()` so far is less than the plaintext length that was previously specified with `psa_aead_set_lengths()`.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. 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_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 operation must have been set up with `psa_aead_encrypt_setup()`.

    This function finishes the authentication of the additional data formed by concatenating the inputs passed to preceding calls to `psa_aead_update_ad()` with the plaintext formed by concatenating the inputs passed to preceding calls to `psa_aead_update()`.

    This function has two output buffers:

    * ``ciphertext`` contains trailing ciphertext that was buffered from preceding calls to `psa_aead_update()`.
    * ``tag`` contains the authentication tag.

    When this function returns successfully, the operation becomes inactive. If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_aead_abort()`.

.. function:: psa_aead_verify

    .. summary::
        Finish authenticating and decrypting a message in an AEAD operation.

    .. param:: psa_aead_operation_t * operation
        Active AEAD operation.
    .. param:: uint8_t * plaintext
        Buffer where the last part of the plaintext is to be written. This is the remaining data from previous calls to `psa_aead_update()` that could not be processed until the end of the input.
    .. param:: size_t plaintext_size
        Size of the ``plaintext`` buffer in bytes. This must be appropriate for the selected algorithm and key:

        * A sufficient output size is :code:`PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg)` where ``key_type`` is the type of key and ``alg`` is the algorithm that were used to set up the operation.
        * `PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE` evaluates to the maximum output size of any supported AEAD algorithm.

    .. param:: size_t * plaintext_length
        On success, the number of bytes of returned plaintext.
    .. param:: const uint8_t * tag
        Buffer containing the authentication tag.
    .. param:: size_t tag_length
        Size of the ``tag`` buffer in bytes.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_INVALID_SIGNATURE
        The calculations were successful, but the authentication tag is not correct.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be an active decryption operation with a nonce set.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``plaintext`` buffer is too small. `PSA_AEAD_VERIFY_OUTPUT_SIZE()` or `PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE` can be used to determine the required buffer size.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The total length of input to `psa_aead_update_ad()` so far is less than the additional data length that was previously specified with `psa_aead_set_lengths()`.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The total length of input to `psa_aead_update()` so far is less than the plaintext length that was previously specified with `psa_aead_set_lengths()`.
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. 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_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 operation must have been set up with `psa_aead_decrypt_setup()`.

    This function finishes the authenticated decryption of the message components:

    * The additional data consisting of the concatenation of the inputs passed to preceding calls to `psa_aead_update_ad()`.
    * The ciphertext consisting of the concatenation of the inputs passed to preceding calls to `psa_aead_update()`.
    * The tag passed to this function call.

    If the authentication tag is correct, this function outputs any remaining plaintext and reports success. If the authentication tag is not correct, this function returns `PSA_ERROR_INVALID_SIGNATURE`.

    When this function returns successfully, the operation becomes inactive. If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_aead_abort()`.

    .. note::
        Implementations must make the best effort to ensure that the comparison between the actual tag and the expected tag is performed in constant time.

.. function:: psa_aead_abort

    .. summary::
        Abort an AEAD operation.

    .. param:: psa_aead_operation_t * operation
        Initialized AEAD operation.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
    .. retval:: PSA_ERROR_HARDWARE_FAILURE
    .. retval:: PSA_ERROR_CORRUPTION_DETECTED
    .. retval:: PSA_ERROR_BAD_STATE
        The library has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    Aborting an operation frees all associated resources except for the ``operation`` object itself. Once aborted, the operation object can be reused for another operation by calling `psa_aead_encrypt_setup()` or `psa_aead_decrypt_setup()` again.

    This function can be called any time after the operation object has been initialized as described in `psa_aead_operation_t`.

    In particular, calling `psa_aead_abort()` after the operation has been terminated by a call to `psa_aead_abort()`, `psa_aead_finish()` or `psa_aead_verify()` is safe and has no effect.

Support macros
--------------

.. macro:: PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER
    :definition: /* specification-defined value */

    .. summary::
        Whether the specified algorithm is an AEAD mode on a block cipher.

    .. param:: alg
        An algorithm identifier (value of type `psa_algorithm_t`).

    .. return::
        ``1`` if ``alg`` is an AEAD algorithm which is an AEAD mode based on a block cipher, ``0`` otherwise.

        This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier.

.. macro:: PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG
    :definition: /* specification-defined value */

    .. summary::
        An AEAD algorithm with the default tag length.

    .. param:: aead_alg
        An AEAD algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).

    .. return::
        The corresponding AEAD algorithm with the default tag length for that algorithm.

    This macro can be used to construct the AEAD algorithm with default tag length from an AEAD algorithm with a shortened tag. See also `PSA_ALG_AEAD_WITH_SHORTENED_TAG()`.

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

    .. summary::
        The maximum size of the output of `psa_aead_encrypt()`, in bytes.

    .. param:: key_type
        A symmetric key type that is compatible with algorithm ``alg``.
    .. param:: alg
        An AEAD algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).
    .. param:: plaintext_length
        Size of the plaintext in bytes.

    .. return::
        The AEAD ciphertext size for the specified key type and algorithm. If the key type or AEAD algorithm is not recognized, or the parameters are incompatible, return ``0``. An implementation can return either ``0`` or a correct size for a key type and AEAD algorithm that it recognizes, but does not support.

    If the size of the ciphertext buffer is at least this large, it is guaranteed that `psa_aead_encrypt()` will not fail due to an insufficient buffer size. Depending on the algorithm, the actual size of the ciphertext might be smaller.

    See also `PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient output buffer size for `psa_aead_encrypt()`, for any of the supported key types and AEAD algorithms.

    .. param:: plaintext_length
        Size of the plaintext in bytes.

    If the size of the ciphertext buffer is at least this large, it is guaranteed that `psa_aead_encrypt()` will not fail due to an insufficient buffer size.

    See also `PSA_AEAD_ENCRYPT_OUTPUT_SIZE()`.

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

    .. summary::
        The maximum size of the output of `psa_aead_decrypt()`, in bytes.

    .. param:: key_type
        A symmetric key type that is compatible with algorithm ``alg``.
    .. param:: alg
        An AEAD algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).
    .. param:: ciphertext_length
        Size of the ciphertext in bytes.

    .. return::
        The AEAD plaintext size for the specified key type and algorithm. If the key type or AEAD algorithm is not recognized, or the parameters are incompatible, return ``0``. An implementation can return either ``0`` or a correct size for a key type and AEAD algorithm that it recognizes, but does not support.

    If the size of the plaintext buffer is at least this large, it is guaranteed that `psa_aead_decrypt()` will not fail due to an insufficient buffer size. Depending on the algorithm, the actual size of the plaintext might be smaller.

    See also `PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient output buffer size for `psa_aead_decrypt()`, for any of the supported key types and AEAD algorithms.

    .. param:: ciphertext_length
        Size of the ciphertext in bytes.

    If the size of the plaintext buffer is at least this large, it is guaranteed that `psa_aead_decrypt()` will not fail due to an insufficient buffer size.

    See also `PSA_AEAD_DECRYPT_OUTPUT_SIZE()`.

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

    .. summary::
        The default nonce size for an AEAD algorithm, in bytes.

    .. param:: key_type
        A symmetric key type that is compatible with algorithm ``alg``.
    .. param:: alg
        An AEAD algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).

    .. return::
        The default nonce size for the specified key type and algorithm. If the key type or AEAD algorithm is not recognized, or the parameters are incompatible, return ``0``. An implementation can return either ``0`` or a correct size for a key type and AEAD algorithm that it recognizes, but does not support.

    This macro can be used to allocate a buffer of sufficient size to store the nonce output from `psa_aead_generate_nonce()`.

    See also `PSA_AEAD_NONCE_MAX_SIZE`.

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

    .. summary::
        The maximum nonce size for all supported AEAD algorithms, in bytes.

    See also `PSA_AEAD_NONCE_LENGTH()`.

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

    .. summary::
        A sufficient output buffer size for `psa_aead_update()`.

    .. param:: key_type
        A symmetric key type that is compatible with algorithm ``alg``.
    .. param:: alg
        An AEAD algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).
    .. param:: input_length
        Size of the input in bytes.

    .. return::
        A sufficient output buffer size for the specified key type and algorithm. If the key type or AEAD algorithm is not recognized, or the parameters are incompatible, return ``0``. An implementation can return either ``0`` or a correct size for a key type and AEAD algorithm that it recognizes, but does not support.

    If the size of the output buffer is at least this large, it is guaranteed that `psa_aead_update()` will not fail due to an insufficient buffer size. The actual size of the output might be smaller in any given call.

    See also `PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient output buffer size for `psa_aead_update()`, for any of the supported key types and AEAD algorithms.

    .. param:: input_length
        Size of the input in bytes.

    If the size of the output buffer is at least this large, it is guaranteed that `psa_aead_update()` will not fail due to an insufficient buffer size.

    See also `PSA_AEAD_UPDATE_OUTPUT_SIZE()`.

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

    .. summary::
        A sufficient ciphertext buffer size for `psa_aead_finish()`.

    .. param:: key_type
        A symmetric key type that is compatible with algorithm ``alg``.
    .. param:: alg
        An AEAD algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).

    .. return::
        A sufficient ciphertext buffer size for the specified key type and algorithm. If the key type or AEAD algorithm is not recognized, or the parameters are incompatible, return ``0``. An implementation can return either ``0`` or a correct size for a key type and AEAD algorithm that it recognizes, but does not support.

    If the size of the ciphertext buffer is at least this large, it is guaranteed that `psa_aead_finish()` will not fail due to an insufficient ciphertext buffer size. The actual size of the output might be smaller in any given call.

    See also `PSA_AEAD_FINISH_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient ciphertext buffer size for `psa_aead_finish()`, for any of the supported key types and AEAD algorithms.

    See also `PSA_AEAD_FINISH_OUTPUT_SIZE()`.

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

    .. summary::
        The length of a tag for an AEAD algorithm, in bytes.

    .. param:: key_type
        The type of the AEAD key.
    .. param:: key_bits
        The size of the AEAD key in bits.
    .. param:: alg
        An AEAD algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).

    .. return::
        The tag length for the specified algorithm and key.
        If the AEAD algorithm does not have an identified tag that can be distinguished from the rest of the ciphertext, return ``0``. If the AEAD algorithm is not recognized, return ``0``. An implementation can return either ``0`` or a correct size for an AEAD algorithm that it recognizes, but does not support.

    This macro can be used to allocate a buffer of sufficient size to store the tag output from `psa_aead_finish()`.

    See also `PSA_AEAD_TAG_MAX_SIZE`.

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

    .. summary::
        The maximum tag size for all supported AEAD algorithms, in bytes.

    See also `PSA_AEAD_TAG_LENGTH()`.

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

    .. summary::
        A sufficient plaintext buffer size for `psa_aead_verify()`.

    .. param:: key_type
        A symmetric key type that is compatible with algorithm ``alg``.
    .. param:: alg
        An AEAD algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_AEAD(alg)` is true).

    .. return::
        A sufficient plaintext buffer size for the specified key type and algorithm. If the key type or AEAD algorithm is not recognized, or the parameters are incompatible, return ``0``. An implementation can return either ``0`` or a correct size for a key type and AEAD algorithm that it recognizes, but does not support.

    If the size of the plaintext buffer is at least this large, it is guaranteed that `psa_aead_verify()` will not fail due to an insufficient plaintext buffer size. The actual size of the output might be smaller in any given call.

    See also `PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient plaintext buffer size for `psa_aead_verify()`, for any of the supported key types and AEAD algorithms.

    See also `PSA_AEAD_VERIFY_OUTPUT_SIZE()`.
