.. _ciphers:

Unauthenticated ciphers
=======================

.. warning::

    The unauthenticated cipher API is provided to implement legacy protocols and
    for use cases where the data integrity and authenticity is guaranteed by
    non-cryptographic means.

    It is recommended that newer protocols use :title:`aead`.

.. _cipher-algorithms:

Cipher algorithms
-----------------

.. macro:: PSA_ALG_STREAM_CIPHER
    :definition: ((psa_algorithm_t)0x04800100)

    .. summary::
        The stream cipher mode of a stream cipher algorithm.

    The underlying stream cipher is determined by the key type:

    * To use ChaCha20, use a key type of `PSA_KEY_TYPE_CHACHA20` and algorithm id `PSA_ALG_STREAM_CIPHER`.
    * To use ARC4, use a key type of `PSA_KEY_TYPE_ARC4` and algorithm id `PSA_ALG_STREAM_CIPHER`.

.. macro:: PSA_ALG_CTR
    :definition: ((psa_algorithm_t)0x04c01000)

    .. summary::
        A stream cipher built using the Counter (CTR) mode of a block cipher.

    CTR is a stream cipher which is built from a block cipher. The underlying block cipher is determined by the key type. For example, to use AES-128-CTR, use this algorithm with a key of type `PSA_KEY_TYPE_AES` and a length of 128 bits (16 bytes).

.. macro:: PSA_ALG_CFB
    :definition: ((psa_algorithm_t)0x04c01100)

    .. summary::
        A stream cipher built using the Cipher Feedback (CFB) mode of a block cipher.

    The underlying block cipher is determined by the key type.

.. macro:: PSA_ALG_OFB
    :definition: ((psa_algorithm_t)0x04c01200)

    .. summary::
        A stream cipher built using the Output Feedback (OFB) mode of a block cipher.

    The underlying block cipher is determined by the key type.

.. macro:: PSA_ALG_XTS
    :definition: ((psa_algorithm_t)0x0440ff00)

    .. summary::
        The XTS cipher mode of a block cipher.

    XTS is a cipher mode which is built from a block cipher. It requires at least one full block of input, but beyond this minimum the input does not need to be a whole number of blocks.

.. macro:: PSA_ALG_ECB_NO_PADDING
    :definition: ((psa_algorithm_t)0x04404400)

    .. summary::
        The Electronic Code Book (ECB) mode of a block cipher, with no padding.

    .. warning::
        ECB mode does not protect the confidentiality of the encrypted data except in extremely narrow circumstances. It is recommended that applications only use ECB if they need to construct an operating mode that the implementation does not provide. Implementations are encouraged to provide the modes that applications need in preference to supporting direct access to ECB.

    The underlying block cipher is determined by the key type.

    This symmetric cipher mode can only be used with messages whose lengths are whole number of blocks for the chosen block cipher.

    ECB mode does not accept an initialization vector (IV). When using a multi-part cipher operation with this algorithm, `psa_cipher_generate_iv()` and `psa_cipher_set_iv()` must not be called.

.. macro:: PSA_ALG_CBC_NO_PADDING
    :definition: ((psa_algorithm_t)0x04404000)

    .. summary::
        The Cipher Block Chaining (CBC) mode of a block cipher, with no padding.

    The underlying block cipher is determined by the key type.

    This symmetric cipher mode can only be used with messages whose lengths are whole number of blocks for the chosen block cipher.

.. macro:: PSA_ALG_CBC_PKCS7
    :definition: ((psa_algorithm_t)0x04404100)

    .. summary::
        The Cipher Block Chaining (CBC) mode of a block cipher, with PKCS#7 padding.

    The underlying block cipher is determined by the key type.

    This is the padding method defined by PKCS#7 :RFC:`2315#10.3`.

Single-part cipher functions
----------------------------

.. function:: psa_cipher_encrypt

    .. summary::
        Encrypt a message using a symmetric cipher.

    .. 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 cipher algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_CIPHER(alg)` is true).
    .. param:: const uint8_t * input
        Buffer containing the message to encrypt.
    .. param:: size_t input_length
        Size of the ``input`` buffer in bytes.
    .. param:: uint8_t * output
        Buffer where the output is to be written. The output contains the IV followed by the ciphertext proper.
    .. 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_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length)`  where ``key_type`` is the type of ``key``.
        * :code:`PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length)` evaluates to the maximum output size of any supported cipher encryption.

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

    .. 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 a cipher algorithm.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        ``output_size`` is too small. `PSA_CIPHER_ENCRYPT_OUTPUT_SIZE()` or `PSA_CIPHER_ENCRYPT_OUTPUT_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 encrypts a message with a random initialization vector (IV).
    The length of the IV is :code:`PSA_CIPHER_IV_LENGTH(key_type, alg)` where ``key_type`` is the type of ``key``.
    The output of `psa_cipher_encrypt()` is the IV followed by the ciphertext.

    Use the multi-part operation interface with a `psa_cipher_operation_t` object to provide other forms of IV or to manage the IV and ciphertext independently.

.. function:: psa_cipher_decrypt

    .. summary::
        Decrypt a message using a symmetric cipher.

    .. 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 cipher algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_CIPHER(alg)` is true).
    .. param:: const uint8_t * input
        Buffer containing the message to decrypt. This consists of the IV followed by the ciphertext proper.
    .. param:: size_t input_length
        Size of the ``input`` buffer in bytes.
    .. param:: uint8_t * output
        Buffer where the plaintext 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_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length)`  where ``key_type`` is the type of ``key``.
        * :code:`PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(input_length)` evaluates to the maximum output size of any supported cipher decryption.

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

    .. 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_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 a cipher algorithm.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        ``output_size`` is too small. `PSA_CIPHER_DECRYPT_OUTPUT_SIZE()` or `PSA_CIPHER_DECRYPT_OUTPUT_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_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.

    This function decrypts a message encrypted with a symmetric cipher.

    The input to this function must contain the IV followed by the ciphertext, as output by `psa_cipher_encrypt()`. The IV must be :code:`PSA_CIPHER_IV_LENGTH(key_type, alg)` bytes in length, where ``key_type`` is the type of ``key``.

    Use the multi-part operation interface with a `psa_cipher_operation_t` object to decrypt data which is not in the expected input format.

Multi-part cipher operations
----------------------------

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

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

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

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

      .. autocode::
          psa_cipher_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_cipher_operation_t operation;

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

      .. autocode::
          psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;

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

      .. autocode::
          psa_cipher_operation_t operation;
          operation = psa_cipher_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_CIPHER_OPERATION_INIT
    :definition: /* implementation-defined value */

    .. summary::
        This macro returns a suitable initializer for a cipher operation object of type `psa_cipher_operation_t`.

.. function:: psa_cipher_operation_init

    .. summary::
        Return an initial value for a cipher operation object.

    .. return:: psa_cipher_operation_t

.. function:: psa_cipher_encrypt_setup

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

    .. param:: psa_cipher_operation_t * operation
        The operation object to set up. It must have been initialized as per the documentation for `psa_cipher_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 cipher algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_CIPHER(alg)` is true).

    .. 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 a cipher 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 operation state is not valid: it must be inactive.
    .. 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 a symmetric cipher 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_cipher_operation_t`, e.g. `PSA_CIPHER_OPERATION_INIT`.
    #. Call `psa_cipher_encrypt_setup()` to specify the algorithm and key.
    #. Call either `psa_cipher_generate_iv()` or `psa_cipher_set_iv()` to generate or set the initialization vector (IV), if the algorithm requires one. It is recommended to use `psa_cipher_generate_iv()` unless the protocol being implemented requires a specific IV value.
    #. Call `psa_cipher_update()` zero, one or more times, passing a fragment of the message each time.
    #. Call `psa_cipher_finish()`.

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

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

    * A successful call to `psa_cipher_finish()`.
    * A call to `psa_cipher_abort()`.

.. function:: psa_cipher_decrypt_setup

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

    .. param:: psa_cipher_operation_t * operation
        The operation object to set up. It must have been initialized as per the documentation for `psa_cipher_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 cipher algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_CIPHER(alg)` is true).

    .. 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_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 a cipher 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 operation state is not valid: it must be inactive.
    .. 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 a symmetric cipher 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_cipher_operation_t`, e.g. `PSA_CIPHER_OPERATION_INIT`.
    #. Call `psa_cipher_decrypt_setup()` to specify the algorithm and key.
    #. Call `psa_cipher_set_iv()` with the initialization vector (IV) for the decryption, if the algorithm requires one. This must match the IV used for the encryption.
    #. Call `psa_cipher_update()` zero, one or more times, passing a fragment of the message each time.
    #. Call `psa_cipher_finish()`.

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

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

    * A successful call to `psa_cipher_finish()`.
    * A call to `psa_cipher_abort()`.

.. function:: psa_cipher_generate_iv

    .. summary::
        Generate an initialization vector (IV) for a symmetric encryption operation.

    .. param:: psa_cipher_operation_t * operation
        Active cipher operation.
    .. param:: uint8_t * iv
        Buffer where the generated IV is to be written.
    .. param:: size_t iv_size
        Size of the ``iv`` buffer in bytes. This must be at least :code:`PSA_CIPHER_IV_LENGTH(key_type, alg)` where ``key_type`` and ``alg`` are type of key and the algorithm respectively that were used to set up the cipher operation.
    .. param:: size_t * iv_length
        On success, the number of bytes of the generated IV.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        Either:

        *  The cipher algorithm does not use an IV.
        *  The operation state is not valid: it must be active, with no IV set.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``iv`` buffer is too small. `PSA_CIPHER_IV_LENGTH()` or `PSA_CIPHER_IV_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 IV, nonce or initial counter value for the encryption operation as appropriate for the chosen algorithm, key type and key size.

    The generated IV is always the default length for the key and algorithm: :code:`PSA_CIPHER_IV_LENGTH(key_type, alg)`, where ``key_type`` is the type of key and ``alg`` is the algorithm that were used to set up the operation. To generate different lengths of IV, use `psa_generate_random()` and `psa_cipher_set_iv()`.

    If the cipher algorithm does not use an IV, calling this function returns a `PSA_ERROR_BAD_STATE` error. For these algorithms, :code:`PSA_CIPHER_IV_LENGTH(key_type, alg)` will be zero.

    The application must call `psa_cipher_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_cipher_abort()`.

.. function:: psa_cipher_set_iv

    .. summary::
        Set the initialization vector (IV) for a symmetric encryption or decryption operation.

    .. param:: psa_cipher_operation_t * operation
        Active cipher operation.
    .. param:: const uint8_t * iv
        Buffer containing the IV to use.
    .. param:: size_t iv_length
        Size of the IV in bytes.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        Either:
        
        *  The cipher algorithm does not use an IV.
        *  The operation state is not valid: it must be an active cipher encrypt operation, with no IV set.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The size of ``iv`` is not acceptable for the chosen algorithm, or the chosen algorithm does not use an IV.
    .. 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 IV, nonce or initial counter value for the encryption or decryption operation.

    If the cipher algorithm does not use an IV, calling this function returns a `PSA_ERROR_BAD_STATE` error. For these algorithms, :code:`PSA_CIPHER_IV_LENGTH(key_type, alg)` will be zero.

    The application must call `psa_cipher_encrypt_setup()` or `psa_cipher_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_cipher_abort()`.

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

.. function:: psa_cipher_update

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

    .. param:: psa_cipher_operation_t * operation
        Active cipher 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_CIPHER_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_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input_length)` evaluates to the maximum output size of any supported cipher 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.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active, with an IV set if required for the algorithm.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``output`` buffer is too small. `PSA_CIPHER_UPDATE_OUTPUT_SIZE()` or `PSA_CIPHER_UPDATE_OUTPUT_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.

    The following must occur before calling this function:

    #. Call either `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`. The choice of setup function determines whether this function encrypts or decrypts its input.
    #. If the algorithm requires an IV, call `psa_cipher_generate_iv()` or `psa_cipher_set_iv()`. `psa_cipher_generate_iv()` is recommended when encrypting.

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

.. function:: psa_cipher_finish

    .. summary::
        Finish encrypting or decrypting a message in a cipher operation.

    .. param:: psa_cipher_operation_t * operation
        Active cipher operation.
    .. 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_CIPHER_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_CIPHER_FINISH_OUTPUT_MAX_SIZE` evaluates to the maximum output size of any supported cipher 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.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        The total input size passed to this operation is not valid for this particular algorithm. For example, the algorithm is a based on block cipher and requires a whole number of blocks, but the total input size is not a multiple of the block size.
    .. retval:: PSA_ERROR_INVALID_PADDING
        This is a decryption operation for an algorithm that includes padding, and the ciphertext does not contain valid padding.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active, with an IV set if required for the algorithm.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``output`` buffer is too small. `PSA_CIPHER_FINISH_OUTPUT_SIZE()` or `PSA_CIPHER_FINISH_OUTPUT_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.

    The application must call `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` before calling this function. The choice of setup function determines whether this function encrypts or decrypts its input.

    This function finishes the encryption or decryption of the message formed by concatenating the inputs passed to preceding calls to `psa_cipher_update()`.

    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_cipher_abort()`.

.. function:: psa_cipher_abort

    .. summary::
        Abort a cipher operation.

    .. param:: psa_cipher_operation_t * operation
        Initialized cipher 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_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` again.

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

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

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

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

    .. summary::
        Whether the specified algorithm is a stream cipher.

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

    .. return::
        ``1`` if ``alg`` is a stream cipher algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier or if it is not a symmetric cipher algorithm.

    A stream cipher is a symmetric cipher that encrypts or decrypts messages by applying a bitwise-xor with a stream of bytes that is generated from a key.

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

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

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

    .. return::
        A sufficient output size for the specified key type and algorithm. If the key type or cipher 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 cipher 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_cipher_encrypt()` will not fail due to an insufficient buffer size. Depending on the algorithm, the actual size of the output might be smaller.

    See also `PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient output buffer size for `psa_cipher_encrypt()`, for any of the supported key types and cipher 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_cipher_encrypt()` will not fail due to an insufficient buffer size.

    See also `PSA_CIPHER_ENCRYPT_OUTPUT_SIZE()`.

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

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

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

    .. return::
        A sufficient output size for the specified key type and algorithm. If the key type or cipher 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 cipher 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_cipher_decrypt()` will not fail due to an insufficient buffer size. Depending on the algorithm, the actual size of the output might be smaller.

    See also `PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient output buffer size for `psa_cipher_decrypt()`, for any of the supported key types and cipher 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_cipher_decrypt()` will not fail due to an insufficient buffer size.

    See also `PSA_CIPHER_DECRYPT_OUTPUT_SIZE()`.

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

    .. summary::
        The default IV size for a cipher algorithm, in bytes.

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

    .. return::
        The default IV size for the specified key type and algorithm.
        If the algorithm does not use an IV, return ``0``.
        If the key type or cipher 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 cipher algorithm that it recognizes, but does not support.

    The IV that is generated as part of a call to `psa_cipher_encrypt()` is always the default IV length for the algorithm.

    This macro can be used to allocate a buffer of sufficient size to store the IV output from `psa_cipher_generate_iv()` when using a multi-part cipher operation.

    See also `PSA_CIPHER_IV_MAX_SIZE`.

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

    .. summary::
        The maximum IV size for all supported cipher algorithms, in bytes.

    See also `PSA_CIPHER_IV_LENGTH()`.

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

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

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

    .. return::
        A sufficient output size for the specified key type and algorithm. If the key type or cipher 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 cipher 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_cipher_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_CIPHER_UPDATE_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient output buffer size for `psa_cipher_update()`, for any of the supported key types and cipher 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_cipher_update()` will not fail due to an insufficient buffer size.

    See also `PSA_CIPHER_UPDATE_OUTPUT_SIZE()`.

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

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

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

    .. return::
        A sufficient output size for the specified key type and algorithm. If the key type or cipher 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 cipher 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_cipher_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_CIPHER_FINISH_OUTPUT_MAX_SIZE`.

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

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

    See also `PSA_CIPHER_FINISH_OUTPUT_SIZE()`.

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

    .. summary::
        The block size of a block cipher.

    .. param:: type
        A cipher key type (value of type `psa_key_type_t`).

    .. return::
        The block size for a block cipher, or ``1`` for a stream cipher. The return value is undefined if ``type`` is not a supported cipher key type.

    .. note::
        It is possible to build stream cipher algorithms on top of a block cipher, for example CTR mode (`PSA_ALG_CTR`). This macro only takes the key type into account, so it cannot be used to determine the size of the data that `psa_cipher_update()` might buffer for future processing in general.

    .. note::
        This macro expression is a compile-time constant if ``type`` is a compile-time constant.

    .. warning::
        This macro is permitted to evaluate its argument multiple times.

    See also `PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE`.

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

    .. summary::
        The maximum size of a block cipher supported by the implementation.

    See also `PSA_BLOCK_CIPHER_BLOCK_LENGTH()`.
