#ifndef TZ_DK_SCP03LIB_MSG_H
#define TZ_DK_SCP03LIB_MSG_H

#include <stdint.h>
#include <tz_dk_defs.h>

/**
 * Open Secure Channel message struct.
 * Fields will be defined later.
 */
// typedef union lib_key {
//     uint8_t b_128[16];
//     uint8_t b_192[24];
//     uint8_t b_256[32];
// } __attribute__ ((packed)) lib_key_t;

typedef struct keys_128
{
    uint8_t kenc[16];
    uint8_t kmac[16];
    uint8_t kdek[16];
} __attribute__ ((packed)) keys_128_t;

typedef struct keys_192
{
    uint8_t kenc[24];
    uint8_t kmac[24];
    uint8_t kdek[24];
} __attribute__ ((packed)) keys_192_t;

typedef struct keys_256
{
    uint8_t kenc[32];
    uint8_t kmac[32];
    uint8_t kdek[32];
} __attribute__ ((packed)) keys_256_t;

typedef union lib_buffer {
    keys_128_t keys_128;
    keys_192_t keys_192;
    keys_256_t keys_256;
} __attribute__ ((packed)) lib_buffer_t;

// typedef struct lib_buffer {
//     lib_key_t kenc;
//     lib_key_t kmac;
//     lib_key_t kdek;
// } __attribute__ ((packed)) lib_buffer_t;

typedef struct tz_scp03_credential
{
    uint8_t kvn;
    uint32_t buffer_len;
    uint8_t buffer[TZ_CREDENTIAL_BUFFER_SIZE];
} __attribute__ ((packed)) tz_scp03_credential_t;

typedef struct tz_scp03_open_session_cmd
{
    uint8_t kvn;
    uint32_t buffer_len;
    uint8_t buffer[TZ_CREDENTIAL_BUFFER_SIZE];
} __attribute__ ((packed)) tz_scp03_open_session_cmd_t;

typedef struct tz_scp03_open_session_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
    uint8_t channel_id;
} __attribute__ ((packed)) tz_scp03_open_session_resp_t;

typedef struct tz_scp03_open_session_payload
{
    union scp03_open_session_payload_u {
        tz_scp03_open_session_cmd_t cmd;
        tz_scp03_open_session_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_open_session_payload_t;

typedef struct tz_scp03_transceive_cmd
{
    tz_scp03_credential_t credential;
    uint32_t data_len;
    uint8_t data[TZ_DK_APDU_MAX_LENGTH];
    uint8_t channel_id;
} __attribute__ ((packed)) tz_scp03_transceive_cmd_t;

typedef struct tz_scp03_transceive_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
    uint32_t data_len;
    uint8_t data[TZ_DK_APDU_MAX_LENGTH];
} __attribute__ ((packed)) tz_scp03_transceive_resp_t;

typedef struct tz_scp03_transceive_payload
{
    union scp03_transceive_payload_u {
        tz_scp03_transceive_cmd_t cmd;
        tz_scp03_transceive_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_transceive_payload_t;

typedef struct tz_scp03_set_private_data_cmd
{
    tz_scp03_credential_t credential;
    uint32_t key_len;
    uint8_t key_id[KEY_IDENTIFIER_TLV_LENGTH];
    uint32_t sig_bmp_offset;
    uint8_t sig_bmp;
    uint32_t data_offset;
    uint32_t payload_len;
    uint8_t payload[TZ_DK_MAX_INTERNAL_BUFFER];
} __attribute__ ((packed)) tz_scp03_set_private_data_cmd_t;

typedef struct tz_scp03_set_private_data_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
} __attribute__ ((packed)) tz_scp03_set_private_data_resp_t;

typedef struct tz_scp03_get_private_data_cmd
{
    tz_scp03_credential_t credential;
    uint32_t key_len;
    uint8_t key_id[KEY_IDENTIFIER_TLV_LENGTH];
    uint16_t offset;
    uint32_t size;
} __attribute__ ((packed)) tz_scp03_get_private_data_cmd_t;

typedef struct tz_scp03_get_private_data_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
    uint32_t data_len;
    uint8_t data[TZ_DK_MAX_INTERNAL_BUFFER];
} __attribute__ ((packed)) tz_scp03_get_private_data_resp_t;

typedef struct tz_scp03_set_private_data_payload
{
    union scp03_set_private_data_payload_u {
        tz_scp03_set_private_data_cmd_t cmd;
        tz_scp03_set_private_data_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_set_private_data_payload_t;

typedef struct tz_scp03_get_private_data_payload
{
    union scp03_get_private_data_payload_u {
        tz_scp03_get_private_data_cmd_t cmd;
        tz_scp03_get_private_data_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_get_private_data_payload_t;

typedef struct tz_scp03_write_invoke_cmd
{
    tz_scp03_credential_t credential;
    uint32_t inputbuffer_len;
    uint8_t inputbuffer[TZ_DK_MAX_INTERNAL_BUFFER];
    uint32_t commandapdu_len;
    uint8_t commandapdu[TZ_DK_APDU_MAX_LENGTH];
} __attribute__ ((packed)) tz_scp03_write_invoke_cmd_t;

typedef struct tz_scp03_write_invoke_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
    uint32_t data_len;
    uint8_t data[TZ_DK_APDU_MAX_LENGTH];
} __attribute__ ((packed)) tz_scp03_write_invoke_resp_t;

typedef struct tz_scp03_write_invoke_payload
{
    union scp03_write_invoke_payload_u {
        tz_scp03_write_invoke_cmd_t cmd;
        tz_scp03_write_invoke_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_write_invoke_payload_t;

typedef struct tz_scp03_write_invoke_read_cmd
{
    tz_scp03_credential_t credential;
    uint32_t inputbuffer_len;
    uint8_t inputbuffer[TZ_DK_MAX_INTERNAL_BUFFER];
    uint32_t commandapdu_len;
    uint8_t commandapdu[TZ_DK_APDU_MAX_LENGTH];
} __attribute__ ((packed)) tz_scp03_write_invoke_read_cmd_t;

typedef struct tz_scp03_write_invoke_read_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
    uint32_t data_len;
    uint8_t data[TZ_DK_MAX_INTERNAL_BUFFER];
} __attribute__ ((packed)) tz_scp03_write_invoke_read_resp_t;

typedef struct tz_scp03_write_invoke_read_payload
{
    union scp03_write_invoke_read_payload_u {
        tz_scp03_write_invoke_read_cmd_t cmd;
        tz_scp03_write_invoke_read_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_write_invoke_read_payload_t;

typedef struct tz_scp03_create_ca_cmd
{
    tz_scp03_credential_t credential;
    uint32_t data_len;
	  uint8_t data[TZ_DK_APDU_MAX_LENGTH];
} __attribute__ ((packed)) tz_scp03_create_ca_cmd_t;

typedef struct tz_create_ca_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
    uint32_t data_len;
    uint8_t data[TZ_DK_MAX_INTERNAL_BUFFER];
} __attribute__ ((packed)) tz_scp03_create_ca_resp_t;

typedef struct tz_scp03_invoke_read_cmd
{
    tz_scp03_credential_t credential;
    uint32_t apdu_len;
	  uint8_t apdu[TZ_DK_APDU_MAX_LENGTH];
} __attribute__ ((packed)) tz_scp03_invoke_read_cmd_t;

typedef struct tz_invoke_read_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
    uint32_t data_len;
    uint8_t data[TZ_DK_MAX_INTERNAL_BUFFER];
} __attribute__ ((packed)) tz_scp03_invoke_read_resp_t;


typedef struct tz_scp03_create_ca_payload
{
    union scp03_create_ca_payload_u {
        tz_scp03_create_ca_cmd_t cmd;
        tz_scp03_create_ca_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_create_ca_payload_t;

typedef struct tz_scp03_invoke_read_payload
{
    union scp03_invoke_read_payload_u {
        tz_scp03_invoke_read_cmd_t cmd;
        tz_scp03_invoke_read_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_invoke_read_payload_t;

typedef struct tz_close_session_cmd
{
    uint32_t dummy;
} __attribute__ ((packed)) tz_scp03_close_session_cmd_t;

typedef struct tz_close_session_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    uint16_t sw;
} __attribute__ ((packed)) tz_scp03_close_session_resp_t;

typedef struct tz_close_session_payload
{
    union scp03_close_session_payload_u {
        tz_scp03_close_session_cmd_t cmd;
        tz_scp03_close_session_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_close_session_payload_t;

typedef struct tz_setup_keys_cmd
{
    uint32_t key_blob_size;
    uint8_t key_blob[320];
} __attribute__ ((packed)) tz_scp03_setup_keys_cmd_t;

typedef struct tz_scp_credential_so {
    uint32_t encrypted_keys_len;
    uint8_t encrypted_keys[320];
} __attribute__((packed)) tz_scp_credential_so_t;

typedef struct tz_setup_keys_resp
{
    uint32_t return_code;
    uint8_t error_msg[TZ_DK_MAX_ERROR_STR_LEN];
    tz_scp_credential_so_t so;
} __attribute__ ((packed)) tz_scp03_setup_keys_resp_t;


typedef struct tz_scp03_setup_keys_payload
{
    union scp03_setup_keys_u {
        tz_scp03_setup_keys_cmd_t cmd;
        tz_scp03_setup_keys_resp_t resp;
    } __attribute__ ((packed)) payload;
} __attribute__ ((packed)) tz_scp03_setup_keys_payload_t;

#endif
