/*===========================================================================
* Copyright (c) 2021  Qualcomm Technologies, Inc.
* All Rights Reserved.
* Confidential and Proprietary - Qualcomm Technologies, Inc.
*===========================================================================*/
/*
  @file app_certification_test.c
  @brief This file is sample code on getting Certification related HW
  information
*/

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "CCertification.h"
#include "CCertification_open.h"
#include "ICertification.h"
#include "IOpener.h"
#include "IxErrno.h"
#include "check.h"
#include "object.h"
#include "qsee_env.h"
#include "qsee_heap.h"
#include "qsee_log.h"
#include "sampleapp.h"

#define MAX_MODULE_VERSION_HASH_LEN 100

static void print_hash(uint8_t* hash, size_t len)
{
    size_t out_buf_len = (len * 2) + 1;
    char* out = qsee_malloc(out_buf_len);
    if (out == NULL) {
        return;
    }

    for (size_t i = 0; i < len; i++) {
        snprintf(out + (i * 2), out_buf_len - (i * 2), "%02x", hash[i]);
    }

    qsee_log(QSEE_LOG_MSG_DEBUG, "FIPS getHybridPrngInfo Module hash:");
    qsee_log(QSEE_LOG_MSG_DEBUG, "%s", out);
    qsee_free(out);
}

static int test_fips_get_certification_info(Object certification)
{
    uint8_t hash[MAX_MODULE_VERSION_HASH_LEN] = {0};
    uint32_t module_id = 0;
    uint32_t fips_mode = 0;
    size_t out_len = 0;
    int ret = Object_OK;

    ret = ICertification_getHybridPrngInfo(
        certification, ICertification_TYPE_MODULE_VERSION_HASH, hash,
        ICertification_LEN_MODULE_VERSION_HASH, &out_len);
    CHECK_ELSE(ret == Object_OK, goto __Exit);

    print_hash(hash, out_len);

    ret = ICertification_getHybridPrngInfo(
        certification, ICertification_TYPE_MODULE_ID, &module_id,
        ICertification_LEN_MODULE_ID, &out_len);
    CHECK_ELSE(ret == Object_OK, goto __Exit);

    qsee_log(QSEE_LOG_MSG_DEBUG,
             "ICertifiction_getHybridPrngInfo Module ID: %d", module_id);

    ret = ICertification_getHybridPrngInfo(
        certification, ICertification_TYPE_FIPS_MODE, &fips_mode,
        ICertification_LEN_FIPS_MODE, &out_len);
    CHECK_ELSE(ret == Object_OK, goto __Exit);

    qsee_log(QSEE_LOG_MSG_DEBUG,
             "ICertifiction_getHybridPrngInfo fips_mode: %d", fips_mode);

__Exit:
    return ret;
}

int run_certification_test(void)
{
    int status = Object_OK;
    Object certification = Object_NULL;

    qsee_log(
        QSEE_LOG_MSG_DEBUG,
        "----------Start Sample App FIPS certification Tests ------------");

    status = qsee_open(CCertification_UID, &certification);
    if (status == IOpener_ERROR_NOT_SUPPORTED) {
        // Do not run tests if no ICertification support on chipset
        return SAMPLEAPP_SUCCESS;
    }
    CHECK_ELSE(status == Object_OK, goto __Exit);

    status = test_fips_get_certification_info(certification);
    CHECK_ELSE(status == Object_OK, goto __Exit);

    qsee_log(QSEE_LOG_MSG_DEBUG,
             "----------End Sample App FIPS certification Tests ------------");

__Exit:
    Object_ASSIGN_NULL(certification);
    return (Object_isOK(status)) ? SAMPLEAPP_SUCCESS : SAMPLEAPP_FAILED;
}
