#ifdef SCP11_ENABLE
#ifndef __SCP11_H__
#define __SCP11_H__

#include <openssl/ec.h>

#ifdef USE_QSEE
#include <comdef.h>
#include <stdint.h>
#endif
#ifdef USE_MOBICORE
#include <stdint.h>
#endif

#ifdef USE_BLOWFISH
#include <stdint.h>
#include <tee_spi.h>
#include <stdio.h>
extern TEES_SPIHandler handler;
#define MAX_BUFFER_SIZE 258
#endif

#include "tz_platform.h"
#include "sec_EseStatus.h"
#include "sec_apdu.h"
#include "tz_log.h"
#include "ccm.h"

#define CHAIN_OCE_CERT

//#ifdef USE_BLOWFISH
//#define NULL '\0'
//#define FALSE 0
//#define TRUE  1
//#endif

#define ICVCMD 1
#define MAX_SCP11_DATA_SIZE     256

#define SCP11STATUS   uint16_t
#define SCP11_SUCCESS						0x0000
#define SCP11_CHANNEL_OPEN_FAIL					0x0001
#define SCP11_SELECT_AID_FAIL					0x0002
#define SCP11_PARBERTLV_FAIL					0x0003
#define SCP11_GET_DATA_APDU_SEND_FAIL				0x0004
#define SCP11_GET_DATA_APDU_RETURN_FAIL				0x0005
#define SCP11_VERIFY_SIGNATURE_FAIL				0x0006
#define SCP11_PERFORM_SECURITY_OPERATION_APDU_SEND_FAIL		0x0007
#define SCP11_PERFORM_SECURITY_OPERATION_APDU_RETURN_FAIL	0x0008
#define SCP11_GENERATE_ECC_KEYPAIR_FAIL				0x0009
#define SCP11_MUTUAL_AUTHENTICATE_APDU_SEND_FAIL		0x000A
#define SCP11_MUTUAL_AUTHENTICATE_APDU_RETURN_FAIL		0x000B
#define SCP11_INTERNAL_AUTHENTICATE_APDU_SEND_FAIL		0x000C
#define SCP11_INTERNAL_AUTHENTICATE_APDU_RETURN_FAIL		0x000D
#define SCP11_SHARED_SECRET_SHSS_FAIL				0x000E
#define SCP11_SHARED_SECRET_SHSE_FAIL				0x000F
#define SCP11_CRYPTO_SHA256_FAIL				0x0010
#define SCP11_CRYPTO_SECURE_MAC_CMP_FAIL			0x0011
#define SCP11_CRYPTO_ECC_KEY_OBJECT_FAIL			0x0012
#define SCP11_CRYPTO_ECDSA_DO_VERIFY_FAIL			0x0013
#define SCP11_FAIL						0xFFFF

#define TAG_CERT_SD_ECKA_BF21        (0xBF21)
#define TAG_CERT_SD_ECKA_7F21        (0x7F21)
#define TAG_CERT_SD_ECKA_93          (0x93)
#define TAG_CERT_SD_ECKA_42          (0x42)
#define TAG_CERT_SD_ECKA_5F20        (0x5F20)
#define TAG_CERT_SD_ECKA_95          (0x95)
#define TAG_CERT_SD_ECKA_5F25        (0x5F25)
#define TAG_CERT_SD_ECKA_5F24        (0x5F24)
#define TAG_CERT_SD_ECKA_45          (0x45)
#define TAG_CERT_SD_ECKA_53          (0x53)
#define TAG_CERT_SD_ECKA_73          (0x73)
#define TAG_CERT_SD_ECKA_7F49        (0x7F49)
#define TAG_CERT_SD_ECKA_5F37        (0x5F37)
#define TAG_CERT_SD_ECKA_7F49_REAL   (0xB0)

#define TAG_ePK_SD_ECKA_5F49         (0x5F49)
#define TAG_RECEIPT_86               (0x86)

#define TAG_CERT_OCE_ECKA_7F21        (0x7F21)
#define TAG_CERT_OCE_ECKA_93          (0x93)
#define TAG_CERT_OCE_ECKA_42          (0x42)
#define TAG_CERT_OCE_ECKA_5F20        (0x5F20)
#define TAG_CERT_OCE_ECKA_95          (0x95)
#define TAG_CERT_OCE_ECKA_5F25        (0x5F25)
#define TAG_CERT_OCE_ECKA_5F24        (0x5F24)
#define TAG_CERT_OCE_ECKA_53          (0x53)
#define TAG_CERT_OCE_ECKA_73          (0x73)
#define TAG_CERT_OCE_ECKA_7F49        (0x7F49)
#define TAG_CERT_OCE_ECKA_5F37        (0x5F37)
#define TAG_CERT_OCE_ECKA_7F49_REAL   (0xB0)

typedef struct card_meta_struct_CERT_SD_ECKA {
    tlv_t  CERT_SD_ECKA_BF21_TLV;       // 0xBF21
    tlv_t  CERT_SD_ECKA_7F21_TLV;       // 0x7F21
    tlv_t  CERT_SD_ECKA_93_TLV;         // 0x93
    tlv_t  CERT_SD_ECKA_42_TLV;         // 0x42
    tlv_t  CERT_SD_ECKA_5F20_TLV;       // 0x5F20
    tlv_t  CERT_SD_ECKA_95_TLV;         // 0x95
    tlv_t  CERT_SD_ECKA_5F25_TLV;       // 0x5F25
    tlv_t  CERT_SD_ECKA_5F24_TLV;       // 0x5F24
    tlv_t  CERT_SD_ECKA_45_TLV;         // 0x45
    tlv_t  CERT_SD_ECKA_53_TLV;         // 0x53
    tlv_t  CERT_SD_ECKA_73_TLV;         // 0x73
    tlv_t  CERT_SD_ECKA_7F49_TLV;       // 0x7F49
    tlv_t  CERT_SD_ECKA_5F37_TLV;       // 0x5F37
    tlv_t  CERT_SD_ECKA_7F49_REAL_TLV;  // 04~
} card_meta_struct_t_CERT_SD_ECKA;

typedef struct card_meta_struct_CERT_OCE_ECKA {
    tlv_t  CERT_OCE_ECKA_7F21_TLV;       // 0x7F21
    tlv_t  CERT_OCE_ECKA_93_TLV;         // 0x93
    tlv_t  CERT_OCE_ECKA_42_TLV;         // 0x42
    tlv_t  CERT_OCE_ECKA_5F20_TLV;       // 0x5F20
    tlv_t  CERT_OCE_ECKA_95_TLV;         // 0x95
    tlv_t  CERT_OCE_ECKA_5F25_TLV;       // 0x5F25
    tlv_t  CERT_OCE_ECKA_5F24_TLV;       // 0x5F24
    tlv_t  CERT_OCE_ECKA_53_TLV;         // 0x53
    tlv_t  CERT_OCE_ECKA_73_TLV;         // 0x73
    tlv_t  CERT_OCE_ECKA_7F49_TLV;       // 0x7F49
    tlv_t  CERT_OCE_ECKA_5F37_TLV;       // 0x5F37
    tlv_t  CERT_OCE_ECKA_7F49_REAL_TLV;  // 04~
} card_meta_struct_t_CERT_OCE_ECKA;

typedef struct card_meta_struct_MUTUAL_AUTH {
    tlv_t  ePK_SD_ECKA_5F49_TLV;  // 0x5F49
    tlv_t  RECEIPT_86_TLV;        // 0x86
} card_meta_struct_t_MUTUAL_AUTH;

typedef struct card_meta_struct_INTERNAL_AUTH {
    tlv_t  ePK_SD_ECKA_5F49_TLV;  // 0x5F49
    tlv_t  RECEIPT_86_TLV;        // 0x86
} card_meta_struct_t_INTERNAL_AUTH;


typedef struct {
    uint16_t pk_ecc_key_size;
    uint8_t  pk_ecc_key[MAX_SCP11_DATA_SIZE];
} pk_ecc_key_t;

typedef struct {
    uint16_t sk_ecc_key_size;
    uint8_t  sk_ecc_key[MAX_SCP11_DATA_SIZE];
} sk_ecc_key_t;

typedef struct {
    uint16_t ss_key_size;
    uint8_t  ss_key[MAX_SCP11_DATA_SIZE];
} ss_key_t;

typedef struct {
    uint32_t digest_len;
    uint32_t signature_len;
    uint32_t pk_ca_klcc_len;
    uint8_t digest[MAX_SCP11_DATA_SIZE];
    uint8_t signature[MAX_SCP11_DATA_SIZE];
    uint8_t pk_ca_klcc[MAX_SCP11_DATA_SIZE];
} verify_signature_t;

typedef struct {
    uint32_t pk_sd_ecka_len;
    uint8_t pk_sd_ecka[MAX_SCP11_DATA_SIZE];
} get_data_t;

typedef struct {
    uint32_t pk_oce_ecka_len;
    uint8_t pk_oce_ecka[MAX_SCP11_DATA_SIZE];
} perform_security_operation_t;

typedef struct {
    uint32_t cert_oce_ecka_len;
    uint32_t sk_oce_key_len;
    uint8_t cert_oce_ecka[MAX_SCP11_DATA_SIZE];
    uint8_t sk_oce_key[MAX_SCP11_DATA_SIZE];
} skpm_cert_key_t;

typedef struct {
    uint8_t s_enc[MAX_SCP11_DATA_SIZE];
    uint8_t s_mac[MAX_SCP11_DATA_SIZE];
    uint8_t s_rmac[MAX_SCP11_DATA_SIZE];
    uint8_t Receipt[MAX_SCP11_DATA_SIZE];
} secure_session_key_t;

int32_t scp11_parseBERTLV(uint8_t isContainValue, uint8_t* data, uint32_t* offset, uint32_t dataLen, uint32_t tag, tlv_t* pTarget);
int32_t scp11_ecc_key_Object(uint8_t* pk_ca_klcc, uint32_t pk_ca_klcc_len, EC_KEY **out);
int32_t scp11_generate_ecc_keypair(sk_ecc_key_t *out1, pk_ecc_key_t *out2);
int32_t scp11_shared_secret(uint8_t* pk_a_ecka, uint8_t* sk_a_key, uint8_t* pk_b_ecka, uint32_t pk_b_ecka_len, uint32_t sk_a_key_len, ss_key_t *out);
int32_t scp11_verify_signature(verify_signature_t input);
#ifdef CHAIN_OCE_CERT
SCP11STATUS scp11_skpm_cert(skpm_cert_key_t *skpm_ka_kloc_cert_key, skpm_cert_key_t *skpm_cert_key);
#else
SCP11STATUS scp11_skpm_cert(skpm_cert_key_t *skpm_cert_key);
#endif
SCP11STATUS scp11_get_data(uint8_t channelId, get_data_t *get_data_key);
#ifdef CHAIN_OCE_CERT
SCP11STATUS scp11_perform_security_operation(uint8_t channelId, skpm_cert_key_t *skpm_ka_kloc_cert_key, skpm_cert_key_t *skpm_cert_key, perform_security_operation_t *perform_security_operation_key);
#else
SCP11STATUS scp11_perform_security_operation(uint8_t channelId, skpm_cert_key_t *skpm_cert_key, perform_security_operation_t *perform_security_operation_key);
#endif
SCP11STATUS scp11_mutual_authenticate(uint8_t channelId, uint8_t securityLevel, skpm_cert_key_t *skpm_cert_key, get_data_t *get_data_key, perform_security_operation_t *perform_security_operation_key, secure_session_key_t *secure_session_key);
SCP11STATUS scp11_internal_authenticate(uint8_t channelId, uint8_t securityLevel, get_data_t *get_data_key, perform_security_operation_t *perform_security_operation_key, secure_session_key_t *secure_session_key);

void scp11a_test(p_cmd_t cmd, p_rsp_t rsp);
void scp11b_test(p_cmd_t cmd, p_rsp_t rsp);
#endif
#endif
