#ifndef __SSE_H__
#define __SSE_H__

#include "tz_platform.h"
#include "sse_status.h"
#include "ssp.h"
#include "ssp_service.h"

static const uint8_t SSE_AID[MAX_AID_SIZE] = {0xA0, 0x00, 0x00, 0x02, 0x20, 0x53, 0x45, 0x43, 0x53, 0x54, 0x4F, 0x52, 0x41, 0x47, 0x45, 0x31};

//// For SSE spec v2.0 [

// PARAM definitions
/// GET ENTRY DATA
#define GED_AUTH_TYPE_NONE                0x00
#define GED_AUTH_TYPE_PASSWD            0x01
#define GED_AUTH_TYPE_BIO                   0x04

#define GED_DATA_TYPE_NORMAL            0x00
#define GED_DATA_TYPE_PBED                 0x02   // available only when AUTH_TYPE_PASSWD to get DEK

#define GED_DELETE_OPTION_DELETABLE         0x04
#define GED_DELETE_OPTION_RESTRICTED        0x08
#define GED_DELETE_OPTION_PERMANANT        0x0C

#define GED_UPDATE_DATA_N_ACCESS_RULE       0x80
#define GED_UPDATE_ONLY_ACCESS_RULE           0x00

#define GED_SCOPE_PRIVATE                       0x00
#define GED_SCOPE_PUBLIC                        0x20

/// PUT ENTRY DATA
#define PED_ENTRY_CREATE_N_PUT_DATA       0x00
#define PED_ENTRY_EXISTS_N_PUT_DATA       0x20

#define PED_NEXT                                          0x40

#define PED_DATA_TYPE_NORMAL                0x00 // P1 bit 4
#define PED_DATA_TYPE_PBED                      0x11 // P1 bit 4

#define PED_DELETE_OPTION_DELETABLE     0x04 // P1 bit 3~2
#define PED_DELETE_OPTION_RESTRICTED    0x08 // P1 bit 3~2
#define PED_DELETE_OPTION_PERMANENT     0x0C // P1 bit 3~2

#define PED_AUTH_TYPE_PASSWD                0x01 // P1 bit 1~0
#define PED_AUTH_TYPE_BIO                       0x02 // P1 bit 1~0
#define PED_AUTH_TYPE_NONE                     0x00 // P1 bit 1~0

#define PED_UPDATE_DATA_N_ACCESS_RULE 0x80 // P2 bit7
#define PED_UPDATE_ACCESS_RULE              0x00 // P2 bit7

#define PED_SCOPE_PRIVATE                       0x00 // P2 bit5~0
#define PED_SCOPE_PUBLIC                        0x20 // P2 bit5~0 , remain count comes bit4~0

#define PED_PBED_DEK_LEN_128     0x00
#define PED_PBED_DEK_LEN_256     0x01
#define PED_PBED_DEK_LEN_384     0x02
#define PED_PBED_DEK_LEN_512     0x03

/// DELETE ENTRY DATA
#define DED_AUTH_TYPE_NONE          0x00
#define DED_AUTH_TYPE_PASSWD      0x01
#define DED_AUTH_TYPE_BIO             0x04

// UPDATE AUTH
#define UA_CHECK_OLD_AUTH                           0x01
#define UA_APPLY_NEW_AUTH                           0x02
#define UA_CHECK_OLD_N_APPLY_NEW_AUTH    0x03
#define UA_APPEND_NEW_AUTH                         0x07 /* only for adding BIO templateID */

#define UA_AUTH_TYPE_NONE                0x00
#define UA_AUTH_TYPE_PASSWD            0x01
#define UA_AUTH_TYPE_BIO                   0x04

#define UA_DATA_TYPE_NORMAL            0x00
#define UA_DATA_TYPE_PBED                 0x02   // available only when AUTH_TYPE_PASSWD to get DEK
//// For SSE spec v2.0 ]


typedef struct getEntryDataParamStruct {
    uint8_t* entryId;                       /* entry id */
    uint8_t auth_type;                      /* one of GED_AUTH_TYPE_XXXX */
    uint8_t data_type;                      /* one of GED_DATA_TYPE_XXXX */
    uint8_t* password;                  /* if auth_type is GED_AUTH_TYPE_PASSWD */
    uint8_t passwordLen;                /* 0x06 ~ 0x10 */
    uint8_t* templateId;                    /* if auth_type is GED_AUTH_TYPE_BIO. length is 0x20 fixed*/
    uint8_t templateIdLen;             /* Fixed value : 0x20 */
    uint8_t* outData;                    /* out buffer to get data or DEK */
    uint32_t outDataLen;                /* out buffer length */
    uint8_t* outRemainRetryCnt;            /* when SCOPE is public, remain verify count 1byte */
} get_data_param_t;

typedef struct putEntryDataParamStruct {
    uint8_t* entryId;                           /* entry id lenth is 0x04 fixed*/
    uint8_t* accessableApppletAid1;    /* can let maximum 5 applets access this entry data. If not using should set to NULL. */
    uint8_t* accessableApppletAid2;    /* can let maximum 5 applets access this entry data. If not using should set to NULL. */
    uint8_t* accessableApppletAid3;    /* can let maximum 5 applets access this entry data. If not using should set to NULL. */
    uint8_t* accessableApppletAid4;    /* can let maximum 5 applets access this entry data. If not using should set to NULL. */
    uint8_t* accessableApppletAid5;    /* can let maximum 5 applets access this entry data. If not using should set to NULL. */
    uint8_t accessableAppletAid1Len;  /* Length of accessableApppletAid1. If not using should set to 0. */
    uint8_t accessableAppletAid2Len;  /* Length of accessableApppletAid2. If not using should set to 0. */
    uint8_t accessableAppletAid3Len;  /* Length of accessableApppletAid3. If not using should set to 0. */
    uint8_t accessableAppletAid4Len;  /* Length of accessableApppletAid4. If not using should set to 0. */
    uint8_t accessableAppletAid5Len;  /* Length of accessableApppletAid5. If not using should set to 0. */
    uint8_t* accessableTAID;                /* cat let 1 other TA access this entry data. If not using should set to NULL.*/
    uint8_t accessableTAIDLen;           /* Length of accessableTAID. If not using should set to 0.*/
    uint8_t retryCounter;                     /* not valid when auth type is PED_AUTH_TYPE_NONE*/
    uint8_t auth_type;                          /* one of PED_AUTH_TYPE_PASSWD or PED_AUTH_TYPE_BIO or PED_AUTH_TYPE_NONE*/
    uint8_t* password;                          /* Used only when auth_type is PED_AUTH_TYPE_PASSWD */
    uint8_t passwordLen;                      /* size of password */ /* used only when auth_type is PED_AUTH_TYPE_PASSWD */
    uint8_t iterationCounter1;             /* if iterationCounter1 doesn't exists, default interationCounter1 will be set to 1 in eSE*/ /* used only when auth_type is PED_AUTH_TYPE_PASSWD */
    uint8_t iterationCounter2;                /* if iterationCounter2 doesn't exists, default interationCounter2 will be set to 1 in eSE*/ /* used only when auth_type is PED_AUTH_TYPE_PASSWD, and for PED_DATA_TYPE_PBED */
    uint8_t lenDEK;                               /* one of PED_DEK_LEN_128, PED_DEK_LEN_256, PED_DEK_LEN_384, PED_DEK_LEN_512 */ /* used only when auth_type is PED_AUTH_TYPE_PASSWD , and for PED_DATA_TYPE_PBED */
    uint8_t* templateId1;                     /* fingerprint template id length is fixed to 0x20. Used only when auth_type is PED_AUTH_TYPE_BIO */
    uint8_t* templateId2;                     /* fingerprint template id length is fixed to 0x20. Used only when auth_type is PED_AUTH_TYPE_BIO */
    uint8_t* templateId3;                     /* fingerprint template id length is fixed to 0x20. Used only when auth_type is PED_AUTH_TYPE_BIO */
    uint8_t* inData;                             /* data which is stored in the entry*/
    uint32_t inDataLen;                          /* data size to store in this entry. Should be smaller than entryDataLen, should be smaller than 16*16*16 */
    uint8_t entryCreation;                      /* one of PED_ENTRY_CREATE_N_PUT_DATA or PED_ENTRY_EXISTS_N_PUT_DATA*/
    uint8_t data_type;                      /* one of PED_DATA_TYPE_XX */
    uint8_t delete_option;                  /* one of PED_DELETE_OPTION_XX */
    uint8_t update_command;             /* one of PED_UPDATE_XX */
    uint8_t scope;                              /* one of PED_SCOPE_XX */
    uint8_t scope_public_read_count;   /* read count set to 0 ~ 31. if 31 is set, means no read count restriction is set. If scope is PED_SCOPE_PRIVATE, set to 0  */
    uint8_t* outRemainRetryCnt;            /* when SCOPE is public, remain verify count 1byte */
} put_data_param_t;

typedef struct deleteEntryDataParamStruct {
    uint8_t* entryId;                       /* entry id */
    uint8_t auth_type;                      /* one of GED_AUTH_TYPE_XXXX */
    uint8_t data_type;                      /* one of GED_DATA_TYPE_XXXX */
    uint8_t* password;                  /* if auth_type is GED_AUTH_TYPE_PASSWD */
    uint8_t passwordLen;                /* 0x06 ~ 0x10 */
    uint8_t* templateId;                    /* if auth_type is GED_AUTH_TYPE_BIO. length is 0x20 fixed*/
    uint8_t templateIdLen;             /* Fixed value : 0x20 */
    uint8_t* outRemainRetryCnt;            /* when SCOPE is public, remain verify count 1byte */
} delete_data_param_t;

typedef struct updateAuthParamStruct {
    uint8_t ua_command;                   /* one of UA_CHECK_OLD_AUTH, UA_APPLY_NEW_AUTH , UA_CHECK_OLD_N_APPLY_NEW_AUTH, UA_APPEND_NEW_AUTH */
    uint8_t* entryId;                           /* entry id lenth is 0x04 fixed*/
    uint8_t old_auth_type;                  /* one of UA_AUTH_TYPE_XXXX */
    uint8_t old_data_type;                  /* one of UA_DATA_TYPE_XXXX */
    uint8_t* old_password;                  /* if old_auth_type is AUTH_TYPE_PASSWD */
    uint8_t old_passwordLen;                /* 0x06 ~ 0x10 */
    uint8_t* old_templateId;                    /* if old_auth_type is AUTH_TYPE_BIO. length is 0x20 fixed*/
    uint8_t old_templateIdLen;             /* Fixed value : 0x20 */
    uint8_t new_auth_type;                  /* one of AUTH_TYPE_XXXX */
    uint8_t* new_password;                  /* if old_auth_type is AUTH_TYPE_PASSWD */
    uint8_t new_passwordLen;                /* 0x06 ~ 0x10 */
    uint8_t* new_templateId;                    /* if old_auth_type is AUTH_TYPE_BIO. length is 0x20 fixed*/
    uint8_t new_templateIdLen;             /* Fixed value : 0x20 */
    uint8_t new_retryCounter;               /* not valid when auth type is PED_AUTH_TYPE_NONE*/
    uint8_t new_iterationCounter1;             /* if new_iterationCounter1 doesn't exists, default interationCounter1 will be set to 1 in eSE*/ /* used only when auth_type is PED_AUTH_TYPE_PASSWD */
    uint8_t new_iterationCounter2;                /* if new_iterationCounter2 doesn't exists, default interationCounter2 will be set to 1 in eSE*/ /* used only when auth_type is PED_AUTH_TYPE_PASSWD, and for PED_DATA_TYPE_PBED */
    uint8_t new_data_type;                  /* one of UA_DATA_TYPE_XXXX */
    uint8_t new_lenDEK;                               /* one of PED_DEK_LEN_128, PED_DEK_LEN_256, PED_DEK_LEN_384, PED_DEK_LEN_512 */ /* used only when auth_type is PED_AUTH_TYPE_PASSWD , and for PED_DATA_TYPE_PBED */    
    uint8_t* outRemainRetryCnt;            /* when SCOPE is public, remain verify count 1byte */
} update_auth_param_t;

SSESTATUS getEntryData(get_data_param_t* getDataParam);
SSESTATUS putEntryData(put_data_param_t* putDataParam);
SSESTATUS deleteEntryData(delete_data_param_t* deleteParam);
SSESTATUS updateAuth(update_auth_param_t * uaParam);
SSESTATUS startService(const uint8_t *otp_key_blob, uint32_t otp_key_blob_size, const uint8_t tid[SSP_TID_SIZE]);
SSESTATUS stopService(void);

void getSseVer(p_rsp_t rsp);
void deleteAllSSEntry(p_cmd_t cmd, p_rsp_t rsp);
void deleteFIDODefaultEntry(p_cmd_t cmd, p_rsp_t rsp);
void updateDSIEntry(p_cmd_t cmd, p_rsp_t rsp);
void updateDefaultEntryAuth(p_cmd_t cmd, p_rsp_t rsp);
void updateWarrantyBitEntry_Normal(p_cmd_t cmd, p_rsp_t rsp);
void updateWarrantyBitEntry_Abnormal(p_cmd_t cmd, p_rsp_t rsp);
void updateSSEDefaultEntryTaId(p_cmd_t cmd, p_rsp_t rsp);

#ifdef DEBUG_LOW
void putEntryDataTest_stress(p_cmd_t cmd, p_rsp_t rsp);
void getEntryDataTest_stress(p_cmd_t cmd, p_rsp_t rsp);
void deleteEntryTest_stress(p_cmd_t cmd, p_rsp_t rsp);

void genEntryIdTest(void);
void putEntryDataTest(p_cmd_t cmd, p_rsp_t rsp);
void getEntryDataTest(p_cmd_t cmd, p_rsp_t rsp);
void updateAuthTest(p_cmd_t cmd, p_rsp_t rsp);
void deleteEntryTest(p_cmd_t cmd, p_rsp_t rsp);
void deleteAllTest(p_cmd_t cmd, p_rsp_t rsp);
void getDefaultEntryTest(p_cmd_t cmd, p_rsp_t rsp);
void putDefaultEntryTest(p_cmd_t cmd);
#endif

#endif //__SSE_H__

