/*
 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Created in Samsung Ukraine R&D Center (SRK) under a contract between
 * LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
 * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
 *
 * Created on: Dec 19, 2017
 * Author: Kostiantyn Volobuiev <k.volobuyev@samsung.com>
 * Author: Viktor Kopp (v.kopp@samsung.com)
 * Author: Andrey Orlenko (a.orlenko@samsung.com)
 * Brief: Module that responds for miscellaneous operations.
 */

#include "TzwMisc.h"

#include "TigerLogging.h"
#include "TigerMacroses.h"
#include "TigerTci.h"

#if defined(TIGER_TZ_MODEL_QCOM)
    #include <qsee_heap.h>
    #include <qsee_comstr.h>
    #include <qsee_message.h>
    #include <qsee_ecc.h>
    #include <stdlib.h>
#endif

#define QSEE_TA_ALIAS_MAX_LENGTH (32)

int tzwGenerateRandom(void *randomBuffer, uint32_t randomBufferLen) {
#if defined(TIGER_TZ_MODEL_BLOWFISH)
   TEE_GenerateRandom(randomBuffer, randomBufferLen);
   return 0;
#elif defined(TIGER_TZ_MODEL_QCOM)
   return qsee_get_random_bytes(randomBuffer, randomBufferLen);
#endif
}

TEE_Result tzwUnwrapData(const char* sourceAppName,
                         const uint8_t* wrappedData, uint32_t const wrappedDataLen,
                         uint8_t* plainData, uint32_t* plainDataLen) {
    LOG_FUNC_BEGIN;

    TIGER_CHECK_FUNCTION_ARGUMENT_RETURN(NULL != wrappedData);
    TIGER_CHECK_FUNCTION_ARGUMENT_RETURN(NULL != plainData);
    TIGER_CHECK_FUNCTION_ARGUMENT_RETURN(0 != wrappedDataLen);
    TIGER_CHECK_FUNCTION_ARGUMENT_RETURN(NULL != plainDataLen);
    TIGER_CHECK_FUNCTION_ARGUMENT_RETURN(strlen(sourceAppName) <= QSEE_TA_ALIAS_MAX_LENGTH);

    LOG_D("Trying unwrap data for '%s', size: %d", sourceAppName, wrappedDataLen);

#if defined(TIGER_TZ_MODEL_BLOWFISH)
    TEE_Result result = TEES_UnwrapSecureObject((const unsigned char*) wrappedData,
                                              wrappedDataLen,
                                              plainData,
                                              plainDataLen);
    if (TEE_SUCCESS != result) {
        LOG_E("Couldn't unwrap!, TEES_UnWrapSecureObject() error:%x.", result);
        return result;
    }
#elif defined(TIGER_TZ_MODEL_QCOM)
    char appName[QSEE_TA_ALIAS_MAX_LENGTH] = { 0 };
    int ret = qsee_decapsulate_inter_app_message(appName,
                                                 (uint8_t*) wrappedData, wrappedDataLen,
                                                 plainData, plainDataLen);
    if (QSEE_MESSAGE_SUCESS != ret) {
        LOG_E("Failed to unwrap(), %x", ret);
        *plainDataLen = 0;
        return TEE_ERROR_BAD_FORMAT;
    }

    if (0 != strncmp(appName, sourceAppName, strlen(sourceAppName))) {
        LOG_E("Failed to unwrap, key not from %s", sourceAppName);
        *plainDataLen = 0;
        return TEE_ERROR_BAD_FORMAT;
    }
#else
    LOG_E("Unknown TZ model.");
    return TEE_ERROR_BAD_STATE;
#endif

    LOG_D("Unwrapped successfully! %d bytes", *plainDataLen);
    LOG_FUNC_END;
    return TEE_SUCCESS;
}
