.. _hashes:

Message digests
===============

.. _hash-algorithms:

Hash algorithms
---------------

.. macro:: PSA_ALG_MD2
    :definition: ((psa_algorithm_t)0x02000001)

    .. summary::
        MD2.

    .. warning::
        The MD2 hash is weak and deprecated and is only recommended for use in legacy protocols.

.. macro:: PSA_ALG_MD4
    :definition: ((psa_algorithm_t)0x02000002)

    .. summary::
        MD4.

    .. warning::
        The MD4 hash is weak and deprecated and is only recommended for use in legacy protocols.

.. macro:: PSA_ALG_MD5
    :definition: ((psa_algorithm_t)0x02000003)

    .. summary::
        MD5.

    .. warning::
        The MD5 hash is weak and deprecated and is only recommended for use in legacy protocols.

.. macro:: PSA_ALG_RIPEMD160
    :definition: ((psa_algorithm_t)0x02000004)

    .. summary::
        RIPEMD-160.

.. macro:: PSA_ALG_SHA_1
    :definition: ((psa_algorithm_t)0x02000005)

    .. summary::
        SHA-1.

    .. warning::
        The SHA-1 hash is weak and deprecated and is only recommended for use in legacy protocols.

.. macro:: PSA_ALG_SHA_224
    :definition: ((psa_algorithm_t)0x02000008)

    .. summary::
        SHA-224.

.. macro:: PSA_ALG_SHA_256
    :definition: ((psa_algorithm_t)0x02000009)

    .. summary::
        SHA-256.

.. macro:: PSA_ALG_SHA_384
    :definition: ((psa_algorithm_t)0x0200000a)

    .. summary::
        SHA-384.

.. macro:: PSA_ALG_SHA_512
    :definition: ((psa_algorithm_t)0x0200000b)

    .. summary::
        SHA-512.

.. macro:: PSA_ALG_SHA_512_224
    :definition: ((psa_algorithm_t)0x0200000c)

    .. summary::
        SHA-512/224.

.. macro:: PSA_ALG_SHA_512_256
    :definition: ((psa_algorithm_t)0x0200000d)

    .. summary::
        SHA-512/256.

.. macro:: PSA_ALG_SHA3_224
    :definition: ((psa_algorithm_t)0x02000010)

    .. summary::
        SHA3-224.

.. macro:: PSA_ALG_SHA3_256
    :definition: ((psa_algorithm_t)0x02000011)

    .. summary::
        SHA3-256.

.. macro:: PSA_ALG_SHA3_384
    :definition: ((psa_algorithm_t)0x02000012)

    .. summary::
        SHA3-384.

.. macro:: PSA_ALG_SHA3_512
    :definition: ((psa_algorithm_t)0x02000013)

    .. summary::
        SHA3-512.

Single-part hashing functions
-----------------------------

.. function:: psa_hash_compute

    .. summary::
        Calculate the hash (digest) of a message.

    .. param:: psa_algorithm_t alg
        The hash algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_HASH(alg)` is true).
    .. param:: const uint8_t * input
        Buffer containing the message to hash.
    .. param:: size_t input_length
        Size of the ``input`` buffer in bytes.
    .. param:: uint8_t * hash
        Buffer where the hash is to be written.
    .. param:: size_t hash_size
        Size of the ``hash`` buffer in bytes.
        This must be at least :code:`PSA_HASH_LENGTH(alg)`.
    .. param:: size_t * hash_length
        On success, the number of bytes that make up the hash value. This is always :code:`PSA_HASH_LENGTH(alg)`.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        ``alg`` is not supported or is not a hash algorithm.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        ``hash_size`` is too small.
        `PSA_HASH_LENGTH()` 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_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.

    .. note::
        To verify the hash of a message against an expected value, use `psa_hash_compare()` instead.

.. function:: psa_hash_compare

    .. summary::
        Calculate the hash (digest) of a message and compare it with a reference value.

    .. param:: psa_algorithm_t alg
        The hash algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_HASH(alg)` is true).
    .. param:: const uint8_t * input
        Buffer containing the message to hash.
    .. param:: size_t input_length
        Size of the ``input`` buffer in bytes.
    .. param:: const uint8_t * hash
        Buffer containing the expected hash value.
    .. param:: size_t hash_length
        Size of the ``hash`` buffer in bytes.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        The expected hash is identical to the actual hash of the input.
    .. retval:: PSA_ERROR_INVALID_SIGNATURE
        The hash of the message was calculated successfully, but it differs from the expected hash.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        ``alg`` is not supported or is not a hash algorithm.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        ``input_length`` or ``hash_length`` do not match the hash size for ``alg``
    .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
    .. retval:: PSA_ERROR_HARDWARE_FAILURE
    .. retval:: PSA_ERROR_CORRUPTION_DETECTED
    .. 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.

.. _hash-mp:

Multi-part hashing operations
-----------------------------

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

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

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

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

      .. autocode::
          psa_hash_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_hash_operation_t operation;

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

      .. autocode::
          psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;

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

      .. autocode::
          psa_hash_operation_t operation;
          operation = psa_hash_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_HASH_OPERATION_INIT
    :definition: /* implementation-defined value */

    .. summary::
        This macro returns a suitable initializer for a hash operation object of type `psa_hash_operation_t`.

.. function:: psa_hash_operation_init

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

    .. return:: psa_hash_operation_t

.. function:: psa_hash_setup

    .. summary::
        Set up a multi-part hash operation.

    .. param:: psa_hash_operation_t * operation
        The operation object to set up. It must have been initialized as per the documentation for `psa_hash_operation_t` and not yet in use.
    .. param:: psa_algorithm_t alg
        The hash algorithm to compute (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_HASH(alg)` is true).

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        ``alg`` is not a supported hash algorithm.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        ``alg`` is not a hash algorithm.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be inactive.
    .. 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 sequence of operations to calculate a hash (message digest) 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_hash_operation_t`, e.g. `PSA_HASH_OPERATION_INIT`.
    #. Call `psa_hash_setup()` to specify the algorithm.
    #. Call `psa_hash_update()` zero, one or more times, passing a fragment of the message each time. The hash that is calculated is the hash of the concatenation of these messages in order.
    #. To calculate the hash, call `psa_hash_finish()`. To compare the hash with an expected value, call `psa_hash_verify()`. To suspend the hash operation and extract the current state, call `psa_hash_suspend()`.

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

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

    * A successful call to `psa_hash_finish()` or `psa_hash_verify()` or `psa_hash_suspend()`.
    * A call to `psa_hash_abort()`.

.. function:: psa_hash_update

    .. summary::
        Add a message fragment to a multi-part hash operation.

    .. param:: psa_hash_operation_t * operation
        Active hash operation.
    .. param:: const uint8_t * input
        Buffer containing the message fragment to hash.
    .. param:: size_t input_length
        Size of the ``input`` buffer 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.
    .. 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 `psa_hash_setup()` or `psa_hash_resume()` before calling this function.

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

.. function:: psa_hash_finish

    .. summary::
        Finish the calculation of the hash of a message.

    .. param:: psa_hash_operation_t * operation
        Active hash operation.
    .. param:: uint8_t * hash
        Buffer where the hash is to be written.
    .. param:: size_t hash_size
        Size of the ``hash`` buffer in bytes. This must be at least :code:`PSA_HASH_LENGTH(alg)` where ``alg`` is the algorithm that the operation performs.
    .. param:: size_t * hash_length
        On success, the number of bytes that make up the hash value. This is always :code:`PSA_HASH_LENGTH(alg)` where ``alg`` is the hash algorithm that the operation performs.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``hash`` buffer is too small.
        `PSA_HASH_LENGTH()` 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_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_hash_setup()` or `psa_hash_resume()` before calling this function. This function calculates the hash of the message formed by concatenating the inputs passed to preceding calls to `psa_hash_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_hash_abort()`.

    .. warning::
        It is not recommended to use this function when a specific value is expected for the hash. Call `psa_hash_verify()` instead with the expected hash value.

        Comparing integrity or authenticity data such as hash values with a function such as ``memcmp()`` is risky because the time taken by the comparison might leak information about the hashed data which could allow an attacker to guess a valid hash and thereby bypass security controls.

.. function:: psa_hash_verify

    .. summary::
        Finish the calculation of the hash of a message and compare it with an expected value.

    .. param:: psa_hash_operation_t * operation
        Active hash operation.
    .. param:: const uint8_t * hash
        Buffer containing the expected hash value.
    .. param:: size_t hash_length
        Size of the ``hash`` buffer in bytes.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        The expected hash is identical to the actual hash of the message.
    .. retval:: PSA_ERROR_INVALID_SIGNATURE
        The hash of the message was calculated successfully, but it differs from the expected hash.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active.
    .. 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 `psa_hash_setup()` before calling this function. This function calculates the hash of the message formed by concatenating the inputs passed to preceding calls to `psa_hash_update()`. It then compares the calculated hash with the expected hash passed as a parameter to this function.

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

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

.. function:: psa_hash_abort

    .. summary::
        Abort a hash operation.

    .. param:: psa_hash_operation_t * operation
        Initialized hash 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_hash_setup()` again.

    This function can be called any time after the operation object has been initialized by one of the methods described in `psa_hash_operation_t`.

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

.. function:: psa_hash_suspend

    .. summary::
        Halt the hash operation and extract the intermediate state of the hash computation.

    .. param:: psa_hash_operation_t * operation
        Active hash operation.
    .. param:: uint8_t * hash_state
        Buffer where the hash suspend state is to be written.
    .. param:: size_t hash_state_size
        Size of the ``hash_state`` buffer in bytes.
        This must be appropriate for the selected algorithm:

        * A sufficient output size is :code:`PSA_HASH_SUSPEND_OUTPUT_SIZE(alg)`  where ``alg`` is the algorithm that was used to set up the operation.
        * `PSA_HASH_SUSPEND_OUTPUT_MAX_SIZE` evaluates to the maximum output size of any supported hash algorithm.

    .. param:: size_t * hash_state_length
        On success, the number of bytes that make up the hash suspend state.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be active.
    .. retval:: PSA_ERROR_BUFFER_TOO_SMALL
        The size of the ``hash_state`` buffer is too small.
        `PSA_HASH_SUSPEND_OUTPUT_SIZE()` or `PSA_HASH_SUSPEND_OUTPUT_MAX_SIZE` can be used to determine the required buffer size.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        The hash algorithm being computed does not support suspend and resume.
    .. 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 `psa_hash_setup()` or `psa_hash_resume()` before calling this function. This function extracts an intermediate state of the hash computation of the message formed by concatenating the inputs passed to preceding calls to `psa_hash_update()`.

    This function can be used to halt a hash operation, and then resume the hash operation at a later time, or in another application, by transferring the extracted hash suspend state to a call to `psa_hash_resume()`.

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

    Hash suspend and resume is not defined for the SHA3 family of hash algorithms. :title:`hash-suspend-state` defines the format of the output from `psa_hash_suspend()`.

    .. warning::
        Applications must not use any of the hash suspend state as if it was a hash output. Instead, the suspend state must only be used to resume a hash operation, and `psa_hash_finish()` or `psa_hash_verify()` can then calculate or verify the final hash value.

    .. rubric:: Usage

    The sequence of operations to suspend and resume a hash operation is as follows:

    #. Compute the first part of the hash.

        #. Allocate an operation object and initialize it as described in the documentation for `psa_hash_operation_t`.
        #. Call `psa_hash_setup()` to specify the algorithm.
        #. Call `psa_hash_update()` zero, one or more times, passing a fragment of the message each time.
        #. Call `psa_hash_suspend()` to extract the hash suspend state into a buffer.

    #. Pass the hash state buffer to the application which will resume the operation.

    #. Compute the rest of the hash.

        #. Allocate an operation object and initialize it as described in the documentation for `psa_hash_operation_t`.
        #. Call `psa_hash_resume()` with the extracted hash state.
        #. Call `psa_hash_update()` zero, one or more times, passing a fragment of the message each time.
        #. To calculate the hash, call `psa_hash_finish()`. To compare the hash with an expected value, call `psa_hash_verify()`.

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

.. function:: psa_hash_resume

    .. summary::
        Set up a multi-part hash operation using the hash suspend state from a previously suspended hash operation.

    .. param:: psa_hash_operation_t * operation
        The operation object to set up. It must have been initialized as per the documentation for `psa_hash_operation_t` and not yet in use.
    .. param:: const uint8_t * hash_state
        A buffer containing the suspended hash state which is to be resumed. This must be in the format output by `psa_hash_suspend()`, which is described in :title:`hash-suspend-state-format`.
    .. param:: size_t hash_state_length
        Length of ``hash_state`` in bytes.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
        Success.
    .. retval:: PSA_ERROR_NOT_SUPPORTED
        The provided hash suspend state is for an algorithm that is not supported.
    .. retval:: PSA_ERROR_INVALID_ARGUMENT
        ``hash_state`` does not correspond to a valid hash suspend state. See :title:`hash-suspend-state-format` for the definition.
    .. retval:: PSA_ERROR_BAD_STATE
        The operation state is not valid: it must be inactive.
    .. 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.

    See `psa_hash_suspend()` for an example of how to use this function to suspend and resume a hash operation.

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

    * A successful call to `psa_hash_finish()`, `psa_hash_verify()` or `psa_hash_suspend()`.
    * A call to `psa_hash_abort()`.

.. function:: psa_hash_clone

    .. summary::
        Clone a hash operation.

    .. param:: const psa_hash_operation_t * source_operation
        The active hash operation to clone.
    .. param:: psa_hash_operation_t * target_operation
        The operation object to set up. It must be initialized but not active.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
    .. retval:: PSA_ERROR_BAD_STATE
        The ``source_operation`` state is not valid: it must be active.
    .. retval:: PSA_ERROR_BAD_STATE
        The ``target_operation`` state is not valid: it must be inactive.
    .. retval:: PSA_ERROR_COMMUNICATION_FAILURE
    .. retval:: PSA_ERROR_HARDWARE_FAILURE
    .. retval:: PSA_ERROR_CORRUPTION_DETECTED
    .. 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.

    This function copies the state of an ongoing hash operation to a new operation object. In other words, this function is equivalent to calling `psa_hash_setup()` on ``target_operation`` with the same algorithm that ``source_operation`` was set up for, then `psa_hash_update()` on ``target_operation`` with the same input that that was passed to ``source_operation``. After this function returns, the two objects are independent, i.e. subsequent calls involving one of the objects do not affect the other object.

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

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

    .. summary::
        The size of the output of `psa_hash_compute()` and `psa_hash_finish()`, in bytes.

    .. param:: alg
        A hash algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_HASH(alg)` is true), or an HMAC algorithm (:code:`PSA_ALG_HMAC(hash_alg)` where ``hash_alg`` is a hash algorithm).

    .. return::
        The hash length for the specified hash algorithm. If the hash algorithm is not recognized, return ``0``. An implementation can return either ``0`` or the correct size for a hash algorithm that it recognizes, but does not support.

    This is also the hash length that `psa_hash_compare()` and `psa_hash_verify()` expect.

    See also `PSA_HASH_MAX_SIZE`.

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

    .. summary::
        Maximum size of a hash.

    This macro must expand to a compile-time constant integer.
    It is recommended that this value is the maximum size of a hash supported by the implementation, in bytes. The value must not be smaller than this maximum.

    See also `PSA_HASH_LENGTH()`.

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

    .. summary::
        A sufficient hash suspend state buffer size for `psa_hash_suspend()`.

    .. param:: alg
        A hash algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_HASH(alg)` is true).

    .. return::
        A sufficient output size for the algorithm. If the hash algorithm is not recognized, or is not supported by `psa_hash_suspend()`, return ``0``. An implementation can return either ``0`` or a correct size for a hash algorithm that it recognizes, but does not support.

        For a supported hash algorithm ``alg``, the following expression is true:

        .. autocode::
            PSA_HASH_SUSPEND_OUTPUT_SIZE(alg) == PSA_HASH_SUSPEND_ALGORITHM_FIELD_LENGTH +
                                                 PSA_HASH_SUSPEND_INPUT_LENGTH_FIELD_LENGTH(alg) +
                                                 PSA_HASH_SUSPEND_HASH_STATE_FIELD_LENGTH(alg) +
                                                 PSA_HASH_BLOCK_LENGTH(alg) - 1

    If the size of the hash state buffer is at least this large, it is guaranteed that `psa_hash_suspend()` 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_HASH_SUSPEND_OUTPUT_MAX_SIZE`.

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

    .. summary::
        A sufficient hash suspend state buffer size for `psa_hash_suspend()`, for any supported hash algorithms.

    See also `PSA_HASH_SUSPEND_OUTPUT_SIZE()`.

.. macro:: PSA_HASH_SUSPEND_ALGORITHM_FIELD_LENGTH
    :definition: ((size_t)4)

    .. summary::
        The size of the *algorithm* field that is part of the output of `psa_hash_suspend()`, in bytes.

    Applications can use this value to unpack the hash suspend state that is output by `psa_hash_suspend()`.

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

    .. summary::
        The size of the *input-length* field that is part of the output of `psa_hash_suspend()`, in bytes.

    .. param:: alg
        A hash algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_HASH(alg)` is true).

    .. return::
        The size, in bytes, of the *input-length* field of the hash suspend state for the specified hash algorithm. If the hash algorithm is not recognized, return ``0``. An implementation can return either ``0`` or the correct size for a hash algorithm that it recognizes, but does not support.

        The algorithm-specific values are defined in :title:`hash-suspend-state-constants`.

    Applications can use this value to unpack the hash suspend state that is output by `psa_hash_suspend()`.

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

    .. summary::
        The size of the *hash-state* field that is part of the output of `psa_hash_suspend()`, in bytes.

    .. param:: alg
        A hash algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_HASH(alg)` is true).

    .. return::
        The size, in bytes, of the *hash-state* field of the hash suspend state for the specified hash algorithm. If the hash algorithm is not recognized, return ``0``. An implementation can return either ``0`` or the correct size for a hash algorithm that it recognizes, but does not support.

        The algorithm-specific values are defined in :title:`hash-suspend-state-constants`.

    Applications can use this value to unpack the hash suspend state that is output by `psa_hash_suspend()`.

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

    .. summary::
        The input block size of a hash algorithm.

    .. param:: alg
        A hash algorithm (``PSA_ALG_XXX`` value such that :code:`PSA_ALG_IS_HASH(alg)` is true).

    .. return::
        The block size for the specified hash algorithm. If the hash algorithm is not recognized, return ``0``. An implementation can return either ``0`` or the correct size for a hash algorithm that it recognizes, but does not support.

    Hash algorithms process their input data in blocks. Hash operations will retain any partial blocks until they have enough input to fill the block or until the operation is finished.

    This affects the output from `psa_hash_suspend()`.


.. _hash-suspend-state:

Hash suspend state
------------------

The hash suspend state is output by `psa_hash_suspend()` and input to `psa_hash_resume()`.

.. note::
    Hash suspend and resume is not defined for the SHA3 family of hash algorithms.

.. _hash-suspend-state-format:

.. rubric:: Hash suspend state format

The hash suspend state has the following format:

*hash-suspend-state* = *algorithm* || *input-length* || *hash-state* || *unprocessed-input*

The fields in the hash suspend state are defined as follows:

.. tabularcolumns:: \Y{.25}\Y{.75}

.. list-table::
    :header-rows: 0
    :widths: 1,3

    *   -   *algorithm*

            big-endian 32-bit unsigned integer

        -   The PSA Crypto API algorithm identifier. Encoded as a big-endian 32-bit unsigned integer.

            The byte length of the *algorithm* field can be evaluated using `PSA_HASH_SUSPEND_ALGORITHM_FIELD_LENGTH`.

    *   -   *input-length*

            big-endian unsigned integer

        -   The content of this field is algorithm-specific:

            - For MD2, this is the number of bytes in the *unprocessed-input*.
            - For all other hash algorithms, this is the total number of bytes of input to the hash computation. This includes the *unprocessed-input* bytes.

            The size of this field is algorithm-specific:

            - For MD2: *input-length* is an 8-bit unsigned integer.
            - For MD4, MD5, RIPEMD-160, SHA-1, SHA-224 and SHA-256: *input-length* is a 64-bit unsigned integer.
            - For SHA-512, SHA-384 and SHA-512/256: *input-length* is a 128-bit unsigned integer.

            The length, in bytes, of the *input-length* field can be calculated using :code:`PSA_HASH_SUSPEND_INPUT_LENGTH_FIELD_LENGTH(alg)` where ``alg`` is a hash algorithm.
            See :title:`hash-suspend-state-constants`.

    *   -   *hash-state*

            array of bytes

        -   Algorithm-specific intermediate hash state:

            - For MD2: 16 bytes of internal checksum, then 48 bytes of intermediate digest.
            - For MD4 and MD5: 4x 32-bit integers, in little-endian encoding.
            - For RIPEMD-160: 5x 32-bit integers, in little-endian encoding.
            - For SHA-1: 5x 32-bit integers, in big-endian encoding.
            - For SHA-224 and SHA-256: 8x 32-bit integers, in big-endian encoding.
            - For SHA-512, SHA-384 and SHA-512/256: 8x 64-bit integers, in big-endian encoding.

            The length of this field is specific to the algorithm.
            The length, in bytes, of the *hash-state* field can be calculated using :code:`PSA_HASH_SUSPEND_HASH_STATE_FIELD_LENGTH(alg)` where ``alg`` is a hash algorithm.
            See :title:`hash-suspend-state-constants`.

    *   -   *unprocessed-input*

            0 to (*hash-block-size*-1) bytes

        -   A partial block of unprocessed input data. This is between zero and *hash-block-size*-1 bytes of data, the length can be calculated by:

            ``length(``\ *unprocessed-input*\ ``)`` ``=`` *input-length* ``%`` *hash-block-size*.

            The *hash-block-size* is specific to the algorithm.
            The size of a hash block can be calculated using :code:`PSA_HASH_BLOCK_LENGTH(alg)` where ``alg`` is a hash algorithm.
            See :title:`hash-suspend-state-constants`.

.. _hash-suspend-state-constants:

..  rubric:: Hash suspend state field sizes

The following table defines the algorithm-specific field lengths for the hash suspend state returned by `psa_hash_suspend()`. All of the field lengths are in bytes. To compute the field lengths for algorithm ``alg``, use the following expressions:

- :code:`PSA_HASH_SUSPEND_ALGORITHM_FIELD_LENGTH` returns the length of the *algorithm* field.
- :code:`PSA_HASH_SUSPEND_INPUT_LENGTH_FIELD_LENGTH(alg)` returns the length of the *input-length* field.
- :code:`PSA_HASH_SUSPEND_HASH_STATE_FIELD_LENGTH(alg)` returns the length of the *hash-state* field.
- :code:`PSA_HASH_BLOCK_LENGTH(alg)-1` is the maximum length of the *unprocessed-bytes* field.
- :code:`PSA_HASH_SUSPEND_OUTPUT_SIZE(slg)` returns the maximum size of the hash suspend state.

.. tabularcolumns:: LLLL

.. csv-table::
    :header-rows: 1

    Hash algorithm, *input-length* size (bytes), *hash-state* length (bytes), *unprocessed-bytes* length (bytes)
    `PSA_ALG_MD2`, 1, 64, 0 - 15
    `PSA_ALG_MD4`, 8, 16, 0 - 63
    `PSA_ALG_MD5`, 8, 16, 0 - 63
    `PSA_ALG_RIPEMD160`, 8, 20, 0 - 63
    `PSA_ALG_SHA_1`, 8, 20, 0 - 63
    `PSA_ALG_SHA_224`, 8, 32, 0 - 63
    `PSA_ALG_SHA_256`, 8, 32, 0 - 63
    `PSA_ALG_SHA_512_256`, 16, 64, 0 - 127
    `PSA_ALG_SHA_384`, 16, 64, 0 - 127
    `PSA_ALG_SHA_512`, 16, 64, 0 - 127
