/*
 * tee_sha256_digest_TA.c
 *
 * SHA256 digest example
 *
 * NOTE: Test data for SHA256 digest was obtained from BoringSSL project:
 *       boringssl/src/crypto/digest_extra/digest_test.cc
 *       As pre-computed digest is initially presented in form of hex-string the additional
 *       hex-string to byte-array conversion is used.
 *
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <tee_internal_api.h>
#include "crypto_samples_functions.h"

/*************************************************************************************************/

/* Input message */
static const char Message[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
/* Pre-computed message digest */
static const char Digest[] = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1";

/* SHA256 message digest parameters */
#define SAMPLE_SHA_ALGO        TEE_ALG_SHA256
#define SAMPLE_SHA_DIGEST_SIZE 32

/* Defines message path length for digest update example */
#define SAMPLE_MSG_INITIAL_LEN 5

/*************************************************************************************************/

/*
 * Computes message digest using SHA256
 */
TEE_Result sha256_digest(void)
{
    TEE_Result rc;
    TEE_OperationHandle hndl;
    /* Print buffer */
    char pbuf[1024] = "\0";
    uint8_t digest_precomputed[SAMPLE_SHA_DIGEST_SIZE];
    uint8_t digest[SAMPLE_SHA_DIGEST_SIZE];
    uint32_t digest_len = SAMPLE_SHA_DIGEST_SIZE;

    printf("SHA-256 sample\n");

    if ((rc = TEE_AllocateOperation(&hndl, SAMPLE_SHA_ALGO, TEE_MODE_DIGEST, 0))) {
        printf("Error: allocate operation failed, rc = 0x%08x\n", rc);
        return rc;
    }

    printf("Digest computing\n");
    /* TEE_DigestUpdate function is used here in vitro / just for example. If final message
     * is prepared, it's reasonable to use TEE_DigestDoFinal for full message.
     */
    TEE_DigestUpdate(hndl, Message, SAMPLE_MSG_INITIAL_LEN);
    if ((rc = TEE_DigestDoFinal(hndl, Message + SAMPLE_MSG_INITIAL_LEN,
                                sizeof(Message) - 1 - SAMPLE_MSG_INITIAL_LEN,
                                digest, &digest_len))) {
        printf("Error: digest final failed, rc = 0x%08x\n", rc);
        goto L_end;
    }

    bytes2hex_string(pbuf, digest, digest_len);
    printf("Digest: %s\n", pbuf);

    printf("Comparing with pre-computed digest\n");
    if (hex_string2bytes(Digest, digest_precomputed, SAMPLE_SHA_DIGEST_SIZE)) {
        printf("Error: wrong format of pre-computed digest\n");
        rc = TEE_ERROR_GENERIC;
        goto L_end;
    }
    if ((rc = TEE_MemCompare(digest, digest_precomputed, SAMPLE_SHA_DIGEST_SIZE))) {
        bytes2hex_string(pbuf, digest_precomputed, SAMPLE_SHA_DIGEST_SIZE);
        printf("Pre-computed digest differs, rc = 0x%08x\n", rc);
        printf("Digest: %s\n", pbuf);
        goto L_end;
    }
    printf("Pre-computed digest is the same\n");

L_end:

    if (hndl) {
        TEE_FreeOperation(hndl);
    }

    if (rc) {
        printf("Digest failed\n");
    } else {
        printf("Digest passed\n");
    }

    return rc;
}
