/*
 * Copyright (C) 2014 Samsung Electronics. Co. Ltd,
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __CCM_H__
#define __CCM_H__

#include "tz_log.h"

#include "tz_platform.h"
#include "ssp.h"
#include "GPCmd.h"
#include "SCP03_transceive.h"
#include "crypto_module.h"

#define RECEIPT_SIZE                16 //128bit received from eSE
#define RECEIPT_SHA256_SIZE         32

#define MAX_TLV_VALUE_BUF_SIZE      (90*1024) // define 100K. Each CAP file max size is 64K + apdu headers for each command line
#define FAKE_ARA_ARR_MAX_SIZE       50

#define RET_SUCCESS_LCCM            1818

#define MAX_C_APDU_LEN              (255+6)
#define MAX_R_APDU_LEN              (256)

#define CCM_V01                     1  // Noble
#define CCM_V10                     10 // PEARL4.0/JCOP3.3/UT2.0 - M
#define CCM_V11                     11 // PEARL4.0/JCOP3.3/UT2.0 - N
#define CCM_V20                     20 // PEARL4.0+/JCOP4.0/UT3.0
#define CCM_V30                     30 // JCOP5.2 SEMS
#define CCM_V31                     31 // UT6.0

#define TAG_V1X_HEADER              (0x37)
#define TAG_V1X_PACKAGE_INFO        (0x3F20)
#define TAG_V1X_AID_ELF             (0x3F21)
#define TAG_V1X_AID_ASSOCIATED_SD   (0x3F22)
#define TAG_V1X_AID_APP             (0x3F23)
#define TAG_V1X_VERSION_ELF         (0x3F24)
#define TAG_V1X_EXTRA_INFO          (0x3F30)
#define TAG_V1X_DATE_SCRIPTS        (0x3F31)
#define TAG_V1X_PROFILE             (0x3F32)
#define TAG_V1X_VERSION_LCCM        (0x3F33)
#define TAG_V1X_SIGNATURE_ALGO      (0x3F34)
#define TAG_V1X_PURPOSE             (0x3F35)
#define TAG_V1X_APDU_SCRIPT_INFO    (0x3F36)
#define TAG_V1X_APDU                (0xF1)
#define TAG_V1X_DFIELD_STOREDATA    (0x3F37)
#define TAG_V1X_RECEIPT             (0x3F38)
#define TAG_V1X_ARA_ADD_INFO        (0x3F39)
#define TAG_V1X_DEVICE_ACCESS_INFO  (0x3F40)
#define TAG_V1X_NUM_ARA_RULES       (0xF2)
#define TAG_V1X_ARA_APP_AID         (0xF3)
#define TAG_V1X_NUM_DEVICES         (0xE6)
#define TAG_V1X_DEVICE_SE_IDS       (0xE7)
#define TAG_V1X_SIGNATURE           (0x38)
//TAG V20 add
#define TAG_V20_HEADER              (0x37)
#define TAG_V20_SCRIPT_INFO         (0x3F50)
#define TAG_V20_DATE_SCRIPTS        (0x3F31)
#define TAG_V20_APDU_SCRIPT_INFO    (0x3F36)
#define TAG_V20_DFIELD_STOREDATA    (0x3F37)
#define TAG_V20_RECEIPT             (0x3F38)
#define TAG_V20_ARA_ADD_INFO        (0x3F39)
#define TAG_V20_DEVICE_ACCESS_INFO  (0x3F40)
#define TAG_V20_ARA_DEL_INFO        (0x3F41)
#define TAG_V20_APDU                (0xF1)
#define TAG_V20_NUM_ARA_RULES       (0xF2)
#define TAG_V20_ARA_APP_AID         (0xF3)
#define TAG_V20_NUM_DEVICES         (0xE6)
#define TAG_V20_DEVICE_SE_IDS       (0xE7)
#define TAG_V20_SIGNATURE           (0x38)
//TAG V31 add
#define TAG_V31_HEADER              (0x37)
#define TAG_V31_SCRIPT_INFO         (0x3F50)
#define TAG_V31_DATE_SCRIPTS        (0x3F31)
#define TAG_V31_APDU_SCRIPT_INFO    (0x3F36)
#define TAG_V31_DEVICE_ACCESS_INFO  (0x3F40)
#define TAG_V31_SCENARIO_DFILED     (0x3F51)
#define TAG_V31_APDU                (0xF1)
#define TAG_V31_NUM_DEVICES         (0xE6)
#define TAG_V31_DEVICE_SE_IDS       (0xE7)
#define TAG_V31_SIGNATURE           (0x38)


typedef struct tlv {
    uint32_t tag;
    uint32_t dataLen;
//    uint8_t* Value;
//    uint8_t Len_size;
    uint32_t dataOffset;
} tlv_t;

typedef struct card_meta_struct_v1x {
    tlv_t headerTLV;                // '37'
    tlv_t pkgInfoTLV;               // '3f20'
    tlv_t ElfAidTLV;                // '3f21'
    tlv_t SdAidTLV;                 // '3f22'
    tlv_t AppAidTLV;                // '3f23'
    tlv_t ElfVersionTLV;            // '3f24'
    tlv_t extrainfoTLV;             // '3f30'
    tlv_t DateTLV;                  // '3f31'
    tlv_t ProfileIdTLV;             // '3f32'
    tlv_t LccmVerTLV;               // '3f33'
    tlv_t SigAlgoTLV;               // '3f34'
    tlv_t PurposeTLV;               // '3f35'
    tlv_t ApduScriptTLV;            // '3f36'
    tlv_t StoreDataFieldTLV;        // '3f37'
    tlv_t ReceiptTLV;               // '3f38'
    tlv_t AraAppInfoForAddTLV;      // '3f39' , format of v1.0 and v1.1 are different
    tlv_t DeviceInfoTlv;            // '3f40' , only for v1.1
    tlv_t signatureTLV;             // '38'
} card_meta_struct_t_v1x;

typedef struct card_meta_struct_v20 {
    tlv_t headerTLV;                // '37'
    tlv_t scriptInfoTLV;            // '3f50' , only for v2.0
    tlv_t DateTLV;                  // '3f31'
    tlv_t ApduScriptTLV;            // '3f36'
    tlv_t StoreDataFieldTLV;        // '3f37'
    tlv_t ReceiptTLV;               // '3f38'
    tlv_t AraAppInfoForAddTLV;      // '3f39'
    tlv_t DeviceInfoTlv;            // '3f40'
    tlv_t AraAppInfoForDelTLV;      // '3f41'
    tlv_t signatureTLV;             // '38'
} card_meta_struct_t_v20;

typedef struct card_meta_struct_v31 {
    tlv_t headerTLV;                // '37'
    tlv_t scriptInfoTLV;            // '3f50'
    tlv_t DateTLV;                  // '3f31'
    tlv_t ApduScriptTLV;            // '3f36'
    tlv_t DeviceInfoTlv;            // '3f40'
    tlv_t StoreScenarioFieldTLV;    // '3f51' , only for v3.1
    //tlv_t StoreScenario01TLV;
    //tlv_t StoreScenario03TLV;
    tlv_t signatureTLV;             // '38'
} card_meta_struct_t_v31;


void initCCMMetaStruct(uint32_t ccmVersion, void* cardMeta);
void releaseCCMMetaStruct(uint32_t ccmVersion);
int32_t parseMetadataFromBin(uint32_t ccmVersion, uint8_t* inCcmMetaData, uint32_t inCcmMetaDataLen, void *pCardMetadata,
        uint32_t* signLen, uint8_t* signatureFromBin);
void printParseResult (uint32_t ccmVersion, void* pCardMetadata);
int32_t enforceDeviceAccessControl(uint8_t* data, uint32_t dataLen);
int32_t manageAracRules(uint32_t tag, uint8_t* data, uint32_t dataLen);
int32_t doScenario3(uint8_t storeDataLen, uint8_t *pStoredata, uint8_t receiptLen, uint8_t *pReceipt,
        uint8_t *otp_key_blob, uint32_t otp_key_blob_size);
int32_t compareReceipts(uint8_t* receipt1, uint8_t* receipt2, uint8_t receiptLen);
int32_t parseBERTLV(uint8_t isContainValue, uint8_t* data, uint32_t* offset, uint32_t dataLen, uint32_t tag, tlv_t* pTarget);
int32_t genKVN31keyset(uint8_t *out_key_enc, uint8_t *out_key_mac, uint8_t *out_key_dek);
SSPSTATUS metadataSigVerification(uint8_t* message, uint32_t messageLen, uint8_t* sigLeft, int32_t sigLeftLen, uint8_t* sigRight, int32_t sigRightLen);
int32_t tz_KDF_AES128( uint8_t *keySalt, uint16_t keySaltLen, uint8_t out[AES_128_KEY_SIZE] );
int32_t getKVN30Keyset(uint8_t channelId, const uint8_t *otp_key_blob, uint32_t otp_key_blob_size, uint8_t* outKeySet, uint32_t* outKeySetLen);
int32_t getCPLC4DeviceAccessControl(uint8_t *cplc);

// function proto
void genAraCStoreDataApdu(uint32_t tag, uint8_t* appletAid, uint32_t appletAidLen, uint8_t* hash, uint32_t hashLen,
        uint8_t* araStoradataApdu, uint32_t *araStoradataApduLen);

void handleCCMDataPart1(p_cmd_t cmd, p_rsp_t rsp);
#ifdef LCCM_SPI
void handleCCMDataPart2(p_cmd_t cmd, p_rsp_t rsp);
int32_t nextApduOffset(uint8_t* inData, int32_t start, int32_t inLen, uint8_t* outData, int32_t *outLen, uint8_t* expSw, int32_t *expSwLen);
#endif

#endif
