/*
 * app_getDeviceStatus.h
 */

#ifndef _TZ_ICCC_APP_GETDEVICESTATUS_H_
#define _TZ_ICCC_APP_GETDEVICESTATUS_H_

#include <stdbool.h>

#include "app_main.h"
#include "app_core.h"
#include "app_drk.h"

#include "icccOperations_v4.h"

extern tz_iccc_rsakey_t rsakey;
extern uint8_t srctmpData[ICCC_MAX_KEY_BUF];
extern uint8_t dsttmpData[ICCC_MAX_KEY_BUF];

// ICCC certs
extern uint8_t *iccc_certs[MAX_CERTS];
extern uint32_t iccc_certs_len[MAX_CERTS];
extern uint8_t iccc_certs_num;

#define ICCC_NONCE_SIZE 64 /* Random of 32 bytes. In hex, 64 chars */
#define ICCC_STATUS_APP_MAX_RESPONSE 8192
#define ICCC_NUMBER_OF_COMPONENT_TYPES 2

typedef int (*iccc_status_check_func_t)(uint32_t);
typedef uint8_t comp_type_array_t[ICCC_NUMBER_OF_COMPONENT_TYPES];

#define INSECURE_MSG_TYPE 0
#define FLAG_NOT_READ 1

typedef struct {
    const char *name;
    const uint8_t name_size;
    const uint32_t type;
    const uint32_t type_bitwise;
    iccc_status_check_func_t is_secure;
    const uint8_t * comp_type_array;
} iccc_status_flags_t;

//                                                                HARD_INTEGRITY  SOFT_INTEGRITY
static comp_type_array_t const comp_types_for_sec_boot        = { false,          false  };
static comp_type_array_t const comp_types_for_react_lock      = { false,          false  };
static comp_type_array_t const comp_types_for_kiwi_lock       = { false,          false  };
static comp_type_array_t const comp_types_for_frp_lock        = { false,          false  };
static comp_type_array_t const comp_types_for_cc_mode         = { false,          false  };
static comp_type_array_t const comp_types_for_curr_bin_status = { false,          false  };
static comp_type_array_t const comp_types_for_warrant_bit     = { false,          true   };
static comp_type_array_t const comp_types_for_kap_status      = { false,          false  };
static comp_type_array_t const comp_types_for_image_status1   = { false,          false  };
static comp_type_array_t const comp_types_for_pkm_text        = { false,          false  };
static comp_type_array_t const comp_types_for_pkm_ro          = { false,          false  };
static comp_type_array_t const comp_types_for_selinux_status  = { false,          false  };
static comp_type_array_t const comp_types_for_dmv_status      = { false,          false  };
static comp_type_array_t const comp_types_for_sysscope_flag   = { false,          false  };
static comp_type_array_t const comp_types_for_trustboot_flag  = { true,           true   };

static int is_sec_boot_secure(uint32_t value) {
    const uint32_t SEC_BOOT_SECURE_VALUE = 1;
    return value == SEC_BOOT_SECURE_VALUE ? true : false;
}

static int is_react_lock_secure(uint32_t value) {
    const uint32_t REACT_LOCK_SECURE_VALUE = 1;
    return value == REACT_LOCK_SECURE_VALUE ? true : false;
}

static int is_kiwi_lock_secure(uint32_t value) {
    const uint32_t KIWI_LOCK_SECURE_VALUE = 1;
    return value == KIWI_LOCK_SECURE_VALUE ? true : false;
}

static int is_frp_lock_secure(uint32_t value) {
    const uint32_t FRP_LOCK_SECURE_VALUE = 1;
    return value == FRP_LOCK_SECURE_VALUE ? true : false;
}

static int is_cc_mode_secure(uint32_t value) {
    const uint32_t CC_MODE_SECURE_VALUE = 1;
    return value == CC_MODE_SECURE_VALUE ? true : false;
}

static int is_curr_bin_status_secure(uint32_t value) {
    const uint32_t CURR_BIN_STATUS_SECURE_VALUE = 0;
    return value == CURR_BIN_STATUS_SECURE_VALUE ? true : false;
}

static int is_warranty_bit_secure(uint32_t value) {
    const uint32_t WARRANTY_BIT_SECURE_VALUE = 0;
    return value == WARRANTY_BIT_SECURE_VALUE ? true : false;
}

static int is_kap_secure(uint32_t value) {
    const uint32_t KAP_SECURE_VALUE = 1;
    return value == KAP_SECURE_VALUE ? true : false;
}

/**
  * 0:Market   User(01)      Official
  * 1:Factory  Eng(10)/Knox(11)  Custom
  *
  * Secure values:
  * No Download History  = 0 0 0 0
  * Market+User+Official = 0 0 1 0
  * Market+Knox+Official = 0 1 1 0
  * we are not using knox bit until now.
**/
static int is_image_status1_secure(uint32_t value) {
    const uint32_t IMAGE_STATUS1_SECURE_VALUE_NO_HISTORY = 0;
    const uint32_t IMAGE_STATUS1_SECURE_VALUE_USER = 2;
    return (value == IMAGE_STATUS1_SECURE_VALUE_NO_HISTORY) || (value == IMAGE_STATUS1_SECURE_VALUE_USER) ? true : false;
}

static int is_pkm_text_secure(uint32_t value) {
    const uint32_t PKM_TEXT_SECURE_VALUE = 0;
    const uint32_t PKM_TEXT_UNINITIALIZED_VALUE = -1;
    return (value == PKM_TEXT_SECURE_VALUE) || (value == PKM_TEXT_UNINITIALIZED_VALUE) ? true : false;
}

static int is_pkm_ro_secure(uint32_t value) {
    const uint32_t PKM_RO_SECURE_VALUE = 0;
    const uint32_t PKM_RO_UNINITIALIZED_VALUE = -1;
    return (value == PKM_RO_SECURE_VALUE) || (value == PKM_RO_UNINITIALIZED_VALUE) ? true : false;
}

static int is_selinux_secure(uint32_t value) {
    const uint32_t SELINUX_SECURE_VALUE = 0;
    const uint32_t SELINUX_UNINITIALIZED_VALUE = -1;
    return (value == SELINUX_SECURE_VALUE) || (value == SELINUX_UNINITIALIZED_VALUE) ? true : false;
}

static int is_dmv_secure(uint32_t value) {
    const uint32_t DMV_SECURE_VALUE = 0;
    return value == DMV_SECURE_VALUE ? true : false;
}

static int is_sysscope_secure(uint32_t value) {
    const uint32_t SYSSCOPE_INSECURE_VALUE = 1;
    return value != SYSSCOPE_INSECURE_VALUE ? true : false;
}

static int is_trust_boot_secure(uint32_t value) {
    const uint32_t TRUSTBOOT_SECURE_VALUE = 0;
    return value == TRUSTBOOT_SECURE_VALUE ? true : false;
}

static iccc_status_flags_t const iccc_status_flags[] =
{
//   Name                          Size    Value             Bit value                         Function                   Component Types
    {"Secure Boot",                11,     SEC_BOOT,         ICCC_STATUS_FLAG_SEC_BOOT,        is_sec_boot_secure,        comp_types_for_sec_boot },
    {"Reactivation Lock",          17,     REACT_LOCK,       ICCC_STATUS_FLAG_REACT_LOCK,      is_react_lock_secure,      comp_types_for_react_lock },
    {"KIWI Lock",                   9,     KIWI_LOCK,        ICCC_STATUS_FLAG_KIWI_LOCK,       is_kiwi_lock_secure,       comp_types_for_kiwi_lock },
    {"Factory Reset Protection",   24,     FRP_LOCK,         ICCC_STATUS_FLAG_FRP_LOCK,        is_frp_lock_secure,        comp_types_for_frp_lock },
    {"CC Mode",                     7,     CC_MODE,          ICCC_STATUS_FLAG_CC_MODE,         is_cc_mode_secure,         comp_types_for_cc_mode },
    {"Current Binary Status",      21,     CURR_BIN_STATUS,  ICCC_STATUS_FLAG_CURR_BIN_STATUS, is_curr_bin_status_secure, comp_types_for_curr_bin_status },
    {"Warranty Bit",               12,     WARRANTY_BIT,     ICCC_STATUS_FLAG_WARRANT_BIT,     is_warranty_bit_secure,    comp_types_for_warrant_bit },
    {"Knox Active Protection",     22,     KAP_STATUS,       ICCC_STATUS_FLAG_KAP_STATUS,      is_kap_secure,             comp_types_for_kap_status },
    {"Status of Boot Image",       20,     IMAGE_STATUS1,    ICCC_STATUS_FLAG_IMAGE_STATUS1,   is_image_status1_secure,   comp_types_for_image_status1 },
    {"PKM Text",                    8,     PKM_TEXT,         ICCC_STATUS_FLAG_PKM_TEXT,        is_pkm_text_secure,        comp_types_for_pkm_text },
    {"PKM Read Only",              13,     PKM_RO,           ICCC_STATUS_FLAG_PKM_RO,          is_pkm_ro_secure,          comp_types_for_pkm_ro },
    {"SELINUX",                     7,     SELINUX_STATUS,   ICCC_STATUS_FLAG_SELINUX_STATUS,  is_selinux_secure,         comp_types_for_selinux_status },
    {"dm-verity",                   9,     DMV_STATUS,       ICCC_STATUS_FLAG_DMV_STATUS,      is_dmv_secure,             comp_types_for_dmv_status },
    {"Sysscope",                    8,     SYSSCOPE_FLAG,    ICCC_STATUS_FLAG_SYSSCOPE_FLAG,   is_sysscope_secure,        comp_types_for_sysscope_flag },
    {"Trusted Boot",               12,     TRUSTBOOT_FLAG,   ICCC_STATUS_FLAG_TRUSTBOOT_FLAG,  is_trust_boot_secure,      comp_types_for_trustboot_flag }
};

typedef struct iccc_status_req_s {
    uint32_t cmd_id;
    uint32_t comp_type;
    uint8_t nonce[ICCC_NONCE_SIZE + 1];
    uint32_t key_buffer_len;
    uint8_t key_buffer[ICCC_MAX_KEY_BUF];
    int is_wrapped_key;
} __attribute__ ((packed)) iccc_status_req_t;

typedef struct iccc_status_rsp_s {
    uint32_t cmd_id;
    int ret;
    uint32_t buflen;
    uint8_t buffer[ICCC_STATUS_APP_MAX_RESPONSE];
    struct {
        uint32_t wrapped_keylen;
        uint8_t wrapped_keybuf[MAX_WRAPPED_KEY_LEN];
    }__attribute__ ((packed)) wrapped_key;
} __attribute__ ((packed)) iccc_status_rsp_t;

typedef struct {
    union status_content_u {
        iccc_status_req_t iccc_req;
        iccc_status_rsp_t iccc_rsp;
    } __attribute__ ((packed)) content;
} __attribute__ ((packed)) tz_iccc_status_payload_t;

uint32_t Iccc_Core_DeviceStatus_TA(uint32_t comp_type, uint8_t *resp_msg_buf, uint32_t resp_msg_buf_size, uint32_t *resp_msg_len, uint32_t *result_code);
uint32_t ICCC_device_status(tz_iccc_status_payload_t *sendmsg, tz_iccc_status_payload_t *respmsg);

#endif // _TZ_ICCC_APP_GETDEVICESTATUS_H_
