/*
 * =====================================================================================
 *
 *  Filename:  kg_defs.h
 *
 *  Description:  KG struct and constant definition
 *
 *  Version:  1.0
 *  Created:  02/27/2020 13:44:00 PM
 *  Revision:  none
 *  Compiler:  gcc
 *
 *  Company:  Samsung Electronics
 *  Copyright (c) 2020 by Samsung Electronics, All rights reserved.
 *
 * =====================================================================================
 */
#ifndef __KG_DEFS_H__
#define __KG_DEFS_H__

#include <stdint.h>
#include "kg_err.h"
#include <openssl/sha.h>


#define KG_NAME                 "kg_ta"
#define KG_MAX_PAYLOAD_LEN      8192
#define KG_SECURE_DATA_LEN      2048
#define KG_RESERVE_DATA_LEN     2048
#define KG_BUF_LEN              1024
#define KG_B64_BUF_LEN          2048

#define KG_MAGIC                0xEA030000
#define KG_SECURE_DATA_VERSION  1
#define KG_ID_LEN               24
#define KG_HASH_LEN             32
#define KG_IMEI_HASH_LEN        44
#define KG_SN_HASH_LEN          44
#define KG_TIMESTAMP_LEN        13
#define KG_SIG_LEN              256
#define KG_SERVER_DH_PUB_MAX    1024
#define KG_SERVER_DH_PUB_SIGN_MAX  1024
#define KG_DH_CHALLENGE_MAX     1024
#define KG_REG_INFO_LEN_MAX     1024
#define KG_REG_INFO_SIGN_MAX    1024
#define KG_POLICY_LEN_MAX       16384 //51200
#define KG_POLICY_SIGN_MAX      1024
#define KG_ACTION_NAME_MAX      30
#define KG_LOCK_OBJECT_MAX      2048
#define KG_CLIENT_DATA_MAX      2048
#define KG_COMPLETE_MSG_LEN     8
#define KG_NONCE_LEN            16
#define KG_TOKEN_LEN            256

// HAMC_SHA256
#define I_PAD           0x36
#define O_PAD           0x5c
#define KG_HMAC_BLOCK   64

// HOTP
#define KG_OTP_LEN      8
#define KG_HOTP_LEN     32
#define KG_KEY_LEN      32

// REGION
#define REGION_NONE     0
#define REGION_EU       0x100
#define REGION_US       0x200


// DH 

/* The public key is 256 + 1, one extra byte for 00 padding for server BigInteger */
#define KG_DH_PUB_KEY_LEN  (257) 
#define KG_DH_PRIV_KEY_LEN (256)
#define KG_AES_KEY_LEN  32
#define KG_AES_IV_LEN   12
#define KG_AES_TAG_LEN  16

/* Protocol type of client */
#define KG_CMD_PROTOCOL_KG 0x100
#define KG_CMD_PROTOCOL_BL 0x200
#define KG_CMD_PROTOCOL_TA 0x300 // Is there any chance to call other TA ?

typedef struct tz_msg_header {
    uint32_t id;
    uint32_t content_id;
    uint32_t len;
    uint32_t status;
} __attribute__ ((packed)) tz_msg_header_t;


/* common command for most command and return */
typedef struct tz_common_cmd {
    uint32_t input;
    uint32_t data_len;
    uint8_t  data_buf[KG_MAX_PAYLOAD_LEN];
} __attribute__ ((packed)) tz_common_cmd_t;

typedef struct tz_common_resp {
    uint32_t result;
    uint32_t data_len;
    uint8_t  data_buf[KG_MAX_PAYLOAD_LEN];
} __attribute__ ((packed)) tz_common_resp_t;

typedef struct tz_common_payload{
    union{
        tz_common_cmd_t   cmd; 
        tz_common_resp_t  resp; 
    }__attribute__ ((packed))payload;
}__attribute__ ((packed)) tz_common_payload_t;


/* generateHotpDHRequest */ 
typedef struct  tz_dh_req_resp{
    uint32_t result;
    uint32_t data_len;
    uint8_t data_buf[KG_MAX_PAYLOAD_LEN];
} __attribute__ ((packed)) tz_dh_req_resp_t;

typedef struct tz_dh_req_payload{
    union{
        tz_dh_req_resp_t    resp; 
    }__attribute__ ((packed))payload;
}__attribute__ ((packed)) tz_dh_req_payload_t;


/* verifyHotpDHChallenge */
typedef struct tz_dh_verify_cmd{
    uint32_t dh_pub_len; 
    uint8_t  dh_pub[KG_SERVER_DH_PUB_MAX];
    uint32_t dh_pub_sign_len; 
    uint8_t  dh_pub_sign[KG_SERVER_DH_PUB_SIGN_MAX];
    uint32_t dh_challenge_len; 
    uint8_t  dh_challenge[KG_DH_CHALLENGE_MAX];
} __attribute__ ((packed)) tz_dh_verify_cmd_t;

typedef struct tz_dh_verify_resp{
    uint32_t result;
} __attribute__ ((packed)) tz_dh_verify_resp_t;


typedef struct tz_dh_verify_payload{
     union{
        tz_dh_verify_cmd_t     cmd;
        tz_dh_verify_resp_t    resq;
    }__attribute__ ((packed))payload;
} __attribute__ ((packed)) tz_dh_verify_payload_t;


/* verifyRegistrationInfo */ 
typedef struct tz_verify_reg_info_cmd{
    uint32_t reg_info_len; 
    uint8_t  reg_info[KG_REG_INFO_LEN_MAX];
    uint32_t reg_info_sign_len; 
    uint8_t  reg_info_sign[KG_REG_INFO_SIGN_MAX];
} __attribute__ ((packed)) tz_verify_reg_info_cmd_t;

typedef struct tz_verify_reg_info_resp{
    uint32_t kg_id_len; 
    uint8_t  kg_id[KG_ID_LEN];
} __attribute__ ((packed)) tz_verify_reg_info_resp_t;

typedef struct tz_verify_reg_info_payload{
     union{
        tz_verify_reg_info_cmd_t    cmd;
        tz_verify_reg_info_resp_t   resq;
    }__attribute__ ((packed))payload;
} __attribute__ ((packed)) tz_verify_reg_info_payload_t;


/* verifyPolicy */
typedef struct tz_verify_policy_cmd{
    uint32_t policy_len;
    uint8_t  policy_buf[KG_POLICY_LEN_MAX];
    uint32_t policy_sign_len;
    uint8_t  policy_sign_buf[KG_POLICY_SIGN_MAX];
} __attribute__ ((packed)) tz_verify_policy_cmd_t;

typedef struct tz_verify_policy_resp{
    uint32_t policy_len;
    uint8_t  policy_buf[KG_POLICY_LEN_MAX];
} __attribute__ ((packed)) tz_verify_policy_resp_t;

typedef struct tz_verify_policy_payload{
     union{
        tz_verify_policy_cmd_t    cmd;
        tz_verify_policy_resp_t   resp;
    }__attribute__ ((packed))payload;
} __attribute__ ((packed)) tz_verify_policy_payload_t;


/* getPolicy */
typedef struct tz_get_policy_cmd{
    //uint32_t policy_len;
    //uint8_t  policy_buf[KG_POLICY_LEN_MAX];
    //uint32_t policy_sign_len;
    //uint8_t  policy_sign_buf[KG_POLICY_SIGN_MAX];
} __attribute__ ((packed)) tz_get_policy_cmd_t;

typedef struct tz_get_policy_resp{
    uint32_t policy_len;
    uint8_t  policy_buf[KG_POLICY_LEN_MAX];
} __attribute__ ((packed)) tz_get_policy_resp_t;

typedef struct tz_get_policy_payload{
     union{
        tz_get_policy_cmd_t    cmd;
        tz_get_policy_resp_t   resp;
    }__attribute__ ((packed))payload;
} __attribute__ ((packed)) tz_get_policy_payload_t;

/* lock */
typedef struct tz_lock_cmd{
    uint32_t action_name_len;
    uint8_t  action_name_buf[KG_ACTION_NAME_MAX];
    uint32_t lock_object_len;
    uint8_t  lock_object_buf[KG_LOCK_OBJECT_MAX];
} __attribute__ ((packed)) tz_lock_cmd_t;

typedef struct tz_lock_resp{
    uint32_t result;
} __attribute__ ((packed)) tz_lock_resp_t;

typedef struct tz_lock_payload{
     union{
        tz_lock_cmd_t    cmd;
        tz_lock_resp_t   resp;
    }__attribute__ ((packed))payload;
} __attribute__ ((packed)) tz_lock_payload_t;

/* ta nonce */
typedef struct tz_nonce_cmd{
    uint32_t svr_msg_len;
    uint8_t  svr_msg_buf[KG_BUF_LEN];
    uint32_t svr_sig_len;
    uint8_t  svr_sig_buf[KG_BUF_LEN];
} __attribute__ ((packed)) tz_nonce_cmd_t;

typedef struct tz_nonce_resp{
    uint32_t ta_nonce_len;
    uint8_t ta_nonce_buf[KG_BUF_LEN];
} __attribute__ ((packed)) tz_nonce_resp_t;

typedef struct tz_nonce_payload{
     union{
        tz_nonce_cmd_t    cmd;
        tz_nonce_resp_t   resp;
    }__attribute__ ((packed))payload;
} __attribute__ ((packed)) tz_nonce_payload_t;

typedef struct tci_message {
    tz_msg_header_t  header;
    union{
        tz_common_payload_t             msg_common;
        tz_dh_req_payload_t             msg_dh_req;
        tz_dh_verify_payload_t          msg_dh_verify;
        tz_verify_reg_info_payload_t    msg_verify_reg_info;
        tz_verify_policy_payload_t      msg_verify_policy;
        tz_get_policy_payload_t         msg_get_policy;
        tz_lock_payload_t               msg_lock;
        tz_nonce_payload_t              msg_nonce;
    }__attribute__ ((packed))payload;
} __attribute__ ((packed)) tci_message_t;

typedef struct kg_rpmb_complete_token{
    uint8_t       token[KG_TOKEN_LEN];
} __attribute__((packed)) kg_rpmb_complete_token_t;

typedef struct kg_metadata {
    uint8_t  imei_hash[KG_IMEI_HASH_LEN]; // 44
    uint8_t  sn_hash[KG_SN_HASH_LEN];     // 44
    uint8_t  kg_id[KG_ID_LEN];            // 24
    uint8_t  hotp_key[KG_KEY_LEN];        // 32
    uint8_t  hotp_cha[KG_OTP_LEN];        // 8
    uint8_t  hotp_secret[KG_OTP_LEN];     // 8
    uint32_t policy_version;              // 4
    uint32_t hotp_retry_counter;          // 4
    uint32_t hotp_iteration;              // 4
    uint32_t policy_counter;              // 4
    uint32_t reg_info;                    // 4
    uint64_t svr_timestamp;               // 8
    uint8_t  ta_nonce[KG_NONCE_LEN];      // 13
} __attribute__ ((packed)) kg_metadata_t;
 
typedef struct kg_dh_data{
    uint8_t     dh_state;     /* 0: initial; 1: enroll; 2: complete */
    uint8_t     dh_key[KG_DH_PRIV_KEY_LEN];   /* dh private key */
} __attribute__((packed)) kg_dh_data_t;   /* size : 289 bytes */

typedef struct kg_secure_data {
    kg_metadata_t kg_metadata;
    kg_dh_data_t kg_dh_data;
} __attribute__ ((packed)) kg_secure_data_t;

#define KG_RPMB_DATA_BLOCK_SIZE 512

typedef struct kg_rpmb_data{
    // block index : 0 [0]
    uint32_t    magic;                                // 0 /* 0xEA030000 */
    uint32_t    version;                              // 4 /* RPMB version number */
    uint8_t     reserved[108];                        // 8
    uint32_t    kg_state;                             // 
    uint32_t    action_name_len;                      // 
    uint8_t     action_name[KG_ACTION_NAME_MAX];      // 
    uint32_t    lock_object_len;                      // 
    uint32_t    client_data_len;                      // 
    uint32_t    policy_file_len;                      // 
    uint32_t    kg_wrap_data_len;                     // 
    uint32_t    kg_reserve_data_len;                  // 
    uint8_t     reserved2[338];

    // block index : 1 [1-4]
    uint8_t     lock_object[KG_LOCK_OBJECT_MAX];

    // block index : 5 [5-8]
    uint8_t     client_data[KG_CLIENT_DATA_MAX];

    // block index : 9 [9-40]
    uint8_t     policy_file[KG_POLICY_LEN_MAX];

    // block index : 41 [41-44]
    uint8_t     kg_wrap_data[KG_SECURE_DATA_LEN];

    // block index : 45 [45-48]
    uint8_t     kg_reserve_data[KG_RESERVE_DATA_LEN];

    // block index : 49 [49]
    kg_rpmb_complete_token_t   kg_token;
} __attribute__((packed)) kg_rpmb_data_t;

#define INFO_OBJECT_BLOCK_OFFSET 0
#define LOCK_OBJECT_BLOCK_OFFSET 1
#define CLIENT_DATA_BLOCK_OFFSET 5
#define POLICY_FILE_BLOCK_OFFSET 9
#define WRAP_DATA_BLOCK_OFFSET 41
#define COMPLETE_TOKEN_BLOCK_OFFSET 49

#endif /* __KG_DEFS_H__ */
