/* BEGIN_HEADER */

#include <stdint.h>

/* END_HEADER */

/* BEGIN_DEPENDENCIES
 * depends_on:MBEDTLS_PSA_CRYPTO_C
 * END_DEPENDENCIES
 */

/* BEGIN_CASE */
void hash_finish(int alg_arg, data_t *input, data_t *expected_hash)
{
    psa_algorithm_t alg = alg_arg;
    unsigned char actual_hash[PSA_HASH_MAX_SIZE];
    size_t actual_hash_length;
    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;

    PSA_ASSERT(psa_crypto_init());

    PSA_ASSERT(psa_hash_setup(&operation, alg));
    PSA_ASSERT(psa_hash_update(&operation,
                               input->x, input->len));
    PSA_ASSERT(psa_hash_finish(&operation,
                               actual_hash, sizeof(actual_hash),
                               &actual_hash_length));
    ASSERT_COMPARE(expected_hash->x, expected_hash->len,
                   actual_hash, actual_hash_length);

exit:
    psa_hash_abort(&operation);
    PSA_DONE();
}
/* END_CASE */

/* BEGIN_CASE */
void hash_verify(int alg_arg, data_t *input, data_t *expected_hash)
{
    psa_algorithm_t alg = alg_arg;
    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;

    PSA_ASSERT(psa_crypto_init());

    PSA_ASSERT(psa_hash_setup(&operation, alg));
    PSA_ASSERT(psa_hash_update(&operation,
                               input->x,
                               input->len));
    PSA_ASSERT(psa_hash_verify(&operation,
                               expected_hash->x,
                               expected_hash->len));

exit:
    psa_hash_abort(&operation);
    PSA_DONE();
}
/* END_CASE */

/* BEGIN_CASE */
void hash_multi_part(int alg_arg, data_t *input, data_t *expected_hash)
{
    psa_algorithm_t alg = alg_arg;
    unsigned char actual_hash[PSA_HASH_MAX_SIZE];
    size_t actual_hash_length;
    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
    psa_hash_operation_t operation2 = PSA_HASH_OPERATION_INIT;
    uint32_t len = 0;

    PSA_ASSERT(psa_crypto_init());

    do {
        memset(actual_hash, 0, sizeof(actual_hash));
        PSA_ASSERT(psa_hash_setup(&operation, alg));

        PSA_ASSERT(psa_hash_update(&operation,
                                   input->x, len));
        PSA_ASSERT(psa_hash_clone(&operation, &operation2));
        PSA_ASSERT(psa_hash_update(&operation,
                                   input->x + len, input->len - len));
        PSA_ASSERT(psa_hash_update(&operation2,
                                   input->x + len, input->len - len));

        PSA_ASSERT(psa_hash_finish(&operation,
                                   actual_hash, sizeof(actual_hash),
                                   &actual_hash_length));
        ASSERT_COMPARE(expected_hash->x, expected_hash->len,
                       actual_hash, actual_hash_length);

        PSA_ASSERT(psa_hash_finish(&operation2,
                                   actual_hash, sizeof(actual_hash),
                                   &actual_hash_length));
        ASSERT_COMPARE(expected_hash->x, expected_hash->len,
                       actual_hash, actual_hash_length);
    } while (len++ != input->len);

exit:
    psa_hash_abort(&operation);
    psa_hash_abort(&operation2);
    PSA_DONE();
}
/* END_CASE */