#include <stdint.h>
#include "Log.h"
#include "systemConfig.h"
#include "Tlv.h"


using vendor::samsung::hardware::security::drk::TLV;

extern int32_t DRKAPI_process_cmd_wrap(int32_t cmd, uint8_t *in, uint32_t in_len, uint8_t **out, uint32_t *out_len);
extern int32_t SFI_generateServiceKey(uint8_t *serviceName, int32_t keyType, uint8_t *tlv, uint32_t tlv_len, uint8_t *out, uint32_t *out_len);
extern void    SFI_releaseSession();

int32_t process_verify_prov_cert(int32_t commandId, uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)
{
    int32_t   ret = NOT_ERROR;
    uint8_t  *lcOut = NULL;
    uint32_t  lcOutLen = 0;

    LOGMI("%s start", __func__);
    ret = DRKAPI_process_cmd_wrap(commandId, in, inLen, &lcOut, &lcOutLen);
    if (ret != NOT_ERROR) {
        LOGME("process_cmd was failed. (%d)", ret);
        goto err;
    }

    if (lcOutLen > 0) {
        if (*outLen > lcOutLen) {
            memcpy(out, lcOut, lcOutLen);
            *outLen = lcOutLen;
        } else {
            *outLen = 0;
            LOGME("Failed to copy buffer.");
            ret =  ERR_BUFFER_OVERFLOW;
        }
    } else {
        *outLen = 0;
    }

err:
    if (lcOut) {
        memset(lcOut, 0x0, lcOutLen);
        free(lcOut);
        lcOut = NULL;
    }
    LOGMI("%s end (%d)", __func__, ret);
    return ret;
}

int32_t selftestProvServiceBlob(uint8_t *serviceName, int keytype, uint8_t *tlv, uint32_t tlvLen, uint8_t *serviceCert,
                                uint32_t *serviceCertLen)
{
    int32_t     ret = NOT_ERROR;
    uint8_t     keyData[MAX_SKM_BUF_SIZE] = {0};
    uint32_t    keyDataLen = MAX_SKM_BUF_SIZE;
    Bytes       lcReq;
    TLV         lcTlv;

    LOGMI("%s start", __func__);

    if (serviceName == NULL || serviceCert == NULL || serviceCertLen == NULL) {
        LOGME("Invalid argument.");
        ret = ERR_INVALID_ARGUMENT;
        goto end;
    }

    ret = SFI_generateServiceKey(serviceName, keytype, tlv, tlvLen, keyData, &keyDataLen);
    if (ret != NOT_ERROR) {
        LOGME("Generating the service key blob for prov is failed. (%X)", ret);
        goto end;
    }

    if ((ret = lcTlv.add(TLV_WRAPPED_KEY, (uint8_t *)keyData, keyDataLen)) != NOT_ERROR) {
        LOGME("Getting tlv was failed s: %d", ret);
        goto end;
    }

    if ((ret = lcTlv.encode(lcReq)) != NOT_ERROR) {
        LOGME("To encode tlv is failed. (%d)", ret);
        goto end;
    }

    ret = process_verify_prov_cert(CMD_VERIFY_SERVICE_KEY, (uint8_t *)lcReq, lcReq.length(), serviceCert, serviceCertLen);
    if (ret != NOT_ERROR) {
        LOGME("Verifying the service key blob for prov is failed. (%X)", ret);
    }
end:
    SFI_releaseSession();
    memset(keyData, 0, sizeof(keyData));
    LOGMI("%s end (%d)", __func__, ret);
    return ret;
}
