#ifndef SSP_UTIL_H
#define SSP_UTIL_H

#include "ssp.h"
#include "crypto_module.h"

#define SET_APDU_SSP_COMMAND( HCMD, CLA, INS, CMDLEN ) \
    { \
        HCMD.cla = CLA; \
        HCMD.ins = INS; \
        HCMD.p1 = 0; \
        HCMD.p2 = 0; \
        HCMD.lc = CMDLEN; \
    }

#define CHECK_OP_STATUS( operation ) \
    status = operation; \
    if( SSPSTATUS_SUCCESS != status && SSPSTATUS_CERT_NOT_EXIST != status ) \
    { \
        LOGE( "In %s: %s failed. SSPSTATUS = 0x%08x", __FUNCTION__, #operation, status ); \
        goto ret_point; \
    }

#define BUFFER_APPEND( buf, buf_size, data, data_size ) \
    { \
        memcpy( (uint8_t*)buf + buf_size, data, data_size ); \
        buf_size += data_size; \
    }

#define BUFFER_APPEND_FRONT( tempbuf, buf, buf_size, data, data_size ) \
    { \
        memcpy( (uint8_t*)tempbuf, data, data_size ); \
        memcpy( (uint8_t*)tempbuf + data_size, buf, buf_size ); \
        buf_size += data_size; \
        memcpy( (uint8_t*)buf, tempbuf, buf_size); \
    }

#define BER_TLV_LENGTH( size, tlv_buf, tlv_buf_len ) \
    { \
        if (size > 255 ) { \
            tlv_buf[0] = 0x82; \
            tlv_buf[1] = (size >> 8) & 0xFF; \
            tlv_buf[2] = size & 0xFF; \
            tlv_buf_len = 3; \
            \
        } else if (size > 127 ) { \
            tlv_buf[0] = 0x81; \
            tlv_buf[1] = size & 0xFF; \
            tlv_buf_len = 2; \
        } else { \
            tlv_buf[0] = size & 0xFF; \
            tlv_buf_len = 1; \
        } \
    }


SSPSTATUS verify_casd_cert(uint8_t *cert, uint32_t cert_size, uint8_t eSEPubKey[SSP_ECC_PUBKEY_SIZE], uint8_t sspVer[2]);
SSPSTATUS verify_ecdsa_signature(uint8_t *in, uint32_t in_size, uint8_t *sig, uint8_t eSEPubKey[SSP_ECC_PUBKEY_SIZE]);
SSPSTATUS generate_ecdsa_signature(uint8_t *in, uint32_t in_size, uint8_t *sig, uint8_t teePrivKey[SSP_ECC_PRIVKEY_SIZE]);

SSPSTATUS generatePutCertData(uint8_t *root_cert, uint32_t root_cert_size, 
    uint8_t *service_cert, uint32_t service_cert_size, uint8_t *out, uint32_t *out_size);

SSPSTATUS extractRawSigFromAsn1WithEcc(uint8_t *sig, uint32_t sig_len, uint8_t *rawSig);
SSPSTATUS rebuildAsn1FromRawSigWithEcc(uint8_t *rawSig, uint8_t *sig, uint32_t *sig_len);

SSPSTATUS  ssp_genEntryID( const uint8_t *input, uint32_t inputLen, uint8_t eID[SSP_ENTRY_ID_SIZE] );
SSPSTATUS  ssp_genTaID( const uint8_t *input, uint32_t inputLen, uint8_t taID[SSP_TID_SIZE] );

SSPSTATUS ssp_wrap_secure_object(const uint8_t *appId, const uint8_t *input, uint32_t input_size, uint8_t *output, uint32_t *output_size);
#if defined(USE_BLOWFISH) || defined(USE_QSEE) || defined(USE_TRUSTY_UNISOC)
SSPSTATUS ssp_unwrap_secure_object(const uint8_t *sourceTid, const uint8_t *input, uint32_t input_size, uint8_t *output, uint32_t *output_size);
#else
SSPSTATUS ssp_unwrap_secure_object(const uint8_t *input, uint32_t input_size, uint8_t *output, uint32_t *output_size);
#endif

#if defined(USE_TRUSTY_UNISOC)
SSPSTATUS wrapInternalData(char *name, uint8_t* input, uint32_t inputSize);
SSPSTATUS unwrapInternalData(char *name, uint8_t* output, uint32_t *outputSize);
#else
SSPSTATUS wrapInternalData(uint8_t* input, uint32_t inputSize,
                         uint8_t* output, uint32_t *outputSize);
SSPSTATUS unwrapInternalData(uint8_t* input, uint32_t inputSize,
                            uint8_t* output, uint32_t *outputSize);
#endif

#endif /* SSP_UTIL_H */
