#include "SCP03_cmdGenerator.h"
#include "dk_log.h"

#define LOGE DK_LOG_ERR

SCPSTATUS getInitialUpdateCmd(p_secEse_7816_cpdu_t pCpdu, uint8_t kvn) {
    SCPSTATUS rand_result = SCP_SUCCESS;
    //uint8_t test_hostChallenge[8] = {0x80, 0x82, 0x9B, 0x08, 0x8F, 0x4A, 0xB6, 0xEE}; // test
    //uint8_t test_hostChallenge[8] = {0x2C, 0xC1, 0x23, 0x3D, 0x35, 0x7F, 0xC4, 0xEB};

    // fill out madatory data for Initial update cmd
    pCpdu->cla = 0x80;
    pCpdu->ins = 0x50;
    pCpdu->p1 = kvn;
    pCpdu->p2 = KID_Key_ENC;
    pCpdu->lc = HostChallenge_LENGH;

    // fill out extra data
    pCpdu->cpdu_type = 0x00;
    pCpdu->le_type = 0x01;
    pCpdu->le = 0x00;

    // generate random hostChallenge
    //rand_result = RAND_bytes(pCpdu->pdata,HostChallenge_LENGH); //test
    rand_result = scp03_gen_random(pCpdu->pdata,HostChallenge_LENGH);
    //memcpy(pCpdu->pdata,test_hostChallenge,HostChallenge_LENGH);
    if (rand_result != 0) {
        LOGE("RANDOM GEN FAIL\n");
        //error
        return rand_result;
    }
    return rand_result;
    //memcpy(pCpdu->pdata,test_hostChallenge,HostChallenge_LENGH);
}

void getExternalAuthenticateCmd(uint8_t* S_MAC, p_secEse_7816_cpdu_t pCpdu, uint8_t securityLevel, uint8_t* hostCryptogram, uint8_t* MCV) {
    uint8_t C_MAC[8] = {0,};

    // fill out madatory data for external authenticate cmd
    pCpdu->cla = 0x84;
    pCpdu->ins = 0x82;
    pCpdu->p1 = securityLevel;
    pCpdu->p2 = 0x00;
    pCpdu->lc = 0x08;

    // fill out extra data
    pCpdu->cpdu_type = 0x00;
    pCpdu->le_type = 0x00;
    pCpdu->le = 0x00;
    memcpy(pCpdu->pdata, hostCryptogram, 8);

    // generate APDU CMAC
    genApduC_MAC(S_MAC, MCV, pCpdu, C_MAC);

    // generate final APDU
    genFinalApdu(pCpdu, C_MAC);
}

void getSCP03Cmd(p_secEse_7816_cpdu_t pCpdu, uint8_t* encrypted_data, uint8_t* S_ENC, uint8_t* S_MAC, uint8_t* ICV, uint8_t* MCV, uint8_t* security_level_status) {
    uint8_t C_MAC[8] = {0,};
    int padding_length = 0;
    int encrypted_data_length = 0;

    if ((security_level_status[1] != 0) && (pCpdu->lc != 0)) { // C-DECRYPTION security level is enabled and data is exist
        // encrypt data field
        scp03_aes_encrypt (S_ENC, pCpdu->pdata, pCpdu->lc, encrypted_data, ICV, PADDING);

        padding_length = 16 - (pCpdu->lc%16);
        encrypted_data_length = pCpdu->lc+padding_length;

        // replace CPDU field to encrypted data and data length
        pCpdu->pdata = encrypted_data;
        pCpdu->lc = encrypted_data_length;
    }

    if ((security_level_status[0] != 0) /*&& (pCpdu->lc != 0)*/) { // C-MAC security level is enabled
        // generate C-MAC
        genApduC_MAC(S_MAC, MCV, pCpdu, C_MAC);

        // generate final APDU (lc+8 & attach C-MAC in data field)
        genFinalApdu(pCpdu, C_MAC);
    }
}
