/*
 * =====================================================================================
 *
 *       Filename:  libdk_native_client.h
 *
 *    Description:  Socket handler to communicate DRK service.
 *
 *        Version:  1.2
 *        Created:  10/06/2015 01:43:45 AM
 *
 *         Author:  Dongwook Shim (), dw.shim@samsung.com
 *        Company:  Samsung Electronics
 *
 *        Copyright (c) 2015 by Samsung Electronics, All rights reserved.
 *
 * =====================================================================================
 */

#ifndef __LIBDK_NATIVE_CLIENT_H__
#define __LIBDK_NATIVE_CLIENT_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>

/* =======================================================================
 *
 * Error numbers.
 *
 * =======================================================================
 */
#define NO_ERROR                   0
#define INVALID_DATA              -1
#define NOT_SUPPORTED_VERSION     -2
#define NOT_SUPPORTED_FUNCTION    -3
#define NOT_EXIST_DRK             -4
#define OPERATION_FAILED          -5
#define ACCESS_DENIED             -6
#define TOO_SMALL_BUFFER          -7
#define SYSCALL_FAILED            -8
#define NOT_IMPLEMENTED           -9
#define INVALID_ARGUMENT          -10
#define OPENSSL_API_FAILED        -11
/* =======================================================================
 *
 * Key type definitions.
 *
 * =======================================================================
 */
#define KEY_TYPE_RSA              0x01
#define KEY_TYPE_SYMM             0x02
#define KEY_TYPE_EC               0x04

/* =======================================================================
 *
 * DRK status.
 *
 * =======================================================================
 */
#define DRK_IS_EXIST              1
#define DRK_IS_NOT_EXIST          0
#define DEVICE_STATUS_IS_VALID    1
/* =======================================================================
 *
 * Bigdata type definitions.
 *
 * =======================================================================
 */
#define BIGDATA_KEYSTORE          0x01
#define BIGDATA_GATEKEPR          0x02

/* =======================================================================
 *
 * TLV tags.
 *
 * =======================================================================
 */
#define TLV_TAG_EXPONENT                1
#define TLV_TAG_ISSUER                  2
#define TLV_TAG_HASH_ALGO               3
#define TLV_TAG_SUBJECT                 4
#define TLV_TAG_KEYUSAGE                5
#define TLV_TAG_DN_QUALIFIER            6
#define TLV_TAG_EXT_KEYUSAGE            7
#define TLV_TAG_SIGN_DATA_BLOB          8
#define TLV_TAG_CERT_SM                 9
#define TLV_TAG_CERT_SD                 10
#define TLV_TAG_TIMESTAMP               11
#define TLV_TAG_WRAPPED_PCR             12
#define TLV_TAG_EXTEND_PCR_DATA         13
#define TLV_TAG_TID                     14
#define TLV_TAG_WRAPPED_KEY             15
#define TLV_TAG_TLV_KEY_INFO            16
#define TLV_TAG_ATTRS                   17
#define TLV_TAG_MODEL_NAME              18
#define TLV_TAG_HUID                    19
#define TLV_TAG_PREGEN_KEYPAIR          20
#define TLV_TAG_CSR                     21
#define TLV_TAG_IV                      22
#define TLV_TAG_AUTH_TAG                23
#define TLV_TAG_AUTH_DATA               24
#define TLV_TAG_SIGNATURE               25
#define TLV_TAG_ENCRYPTED_DATA_BLOB     26
#define TLV_TAG_CERT                    27
#define TLV_TAG_IMEI                    28
#define TLV_TAG_SUBJECT_ALTER_NAME      29

#define TLV_DI_STATUS                   101
#define TLV_DI_MODEM                    102
#define TLV_DI_IMEI                     104
#define TLV_DI_SN                       108
#define TLV_DI_MODEL                    116
#define TLV_DI_UID                      132

#define TLV_TAG_START                   0xfe
/* =======================================================================
 *
 * DeviceInfo and Information type definitions.
 *
 * =======================================================================
 */
#define DEVICE_INFO_INTEGRITY_STATUS    0x01
#define DEVICE_INFO_MODEM               0x02
#define DEVICE_INFO_IMEI                0x04
#define DEVICE_INFO_SERIAL              0x08
#define DEVICE_INFO_IMEI_SERIAL         (DEVICE_INFO_IMEI  | DEVICE_INFO_SERIAL)
#define DEVICE_INFO_IMEI_MODEM          (DEVICE_INFO_IMEI  | DEVICE_INFO_MODEM)
#define DEVICE_INFO_MODEM_SERIAL        (DEVICE_INFO_MODEM | DEVICE_INFO_SERIAL)
#define DEVICE_INFO_ALL                 (DEVICE_INFO_IMEI  | DEVICE_INFO_MODEM | DEVICE_INFO_SERIAL)

#define MAX_DEVICE_INFO_SIZE            32
#define MAX_STATUS_LENGTH               1
#define TAGLENGTH_FIELD_SIZE            3
#define LENGTH_FIELD_SIZE               2

#define GET_UINT16(x, y) (uint16_t)(((uint16_t)x[y+1] << 8) | (uint16_t)(x[y]))
#define SET_UINT16_FROM_U16(x, y, z) \
    do { \
        x[y+1] = (uint8_t)(((z) >> 8) & 0xFF); \
        x[y]   = (uint8_t)((z) & 0xFF); \
    } while (0);

typedef struct {
    char imei[MAX_DEVICE_INFO_SIZE];
    char modem[MAX_DEVICE_INFO_SIZE];
    char serial[MAX_DEVICE_INFO_SIZE];
    bool isHuidMatched;
} DeviceInfo;

/**
 * Function : isServiceReady()
 * Description : Check whether DeviceRootKeyService is ready.
 * Return value : NOT_ERROR(0) is returned if sevice is ready.
 *                Error number(negative) is returned if service is not ready.
 */
int isServiceReady(void);

/**
 * Function : isExistDeviceRootKey()
 * Description : Check device root key is exist
 * Parameters : @ drkType : KEY_TYPE_RSA or KEY_TYPE_SYMM.
 *                          KEY_TYPE_EC is not supported now.
 * Return value : DRK_IS_EXIST(1) or DRK_IS_NOT_EXIST(0).
 *                On error, error number(negative) is returned.
 */
int isExistDeviceRootKey(int drkType);

/**
 * Function : getDrkUID()
 * Description : Read DRK certificate's UID.
 * Parameters : @ drkType : KEY_TYPE_RSA or KEY_TYPE_SYMM.
 *                          KEY_TYPE_EC is not supported now.
 *              @ drkUid : Output buffer to save UID.
 *              @ drkUidLen : Output buffer's size.
 * Return value : NOT_ERROR(0) is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int getDrkUID(int drkType, char *drkUid, uint32_t drkUidLen);

/**
 * Function : createServiceKeySession()
 * Description : Create service key session and get service key.
 *               Should call releaseServiceKeySession() after parsing service key.
 * Parameters : @ serviceName : service name to ask service key.
 *              @ keyType : KEY_TYPE_RSA or KEY_TYPE_SYMM or KEY_TYPE_EC.
 *              @ isEnableTlv : Use tlv value on making certificate.
 *              @ serviceKey : Output buffer to save encrypted key.
 *              @ serviceKeyLen : Output buffer's size.
 * Return value : Saved servicekey size is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int createServiceKeySession(char *serviceName, int keyType, uint8_t isEnableTlv,
                            char *serviceKey, uint32_t serviceKeyLen);

/**
 * Function : releaseServiceKeySession()
 * Description : Release service key session.
 *               It is only affected on QSEE based models and not affected on Mobicore models.
 *               DeviceRootKeyService service should be waited for next operation in 10s
 *               if this function is not called after calling releaseServiceKeySession().
 * Parameters : None.
 * Return value : NOT_ERROR(0) is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int releaseServiceKeySession(void);

/**
 * Function : initTlv()
 * Description : Initialize tlv sturcture for extention fields in certificate.
 * Parameters : None.
 * Return value : NOT_ERROR(0) is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int initTlv(void);

/**
 * Function : addTlv()
 * Description : Add tag and value to extention fields in certificate.
 * Parameters : @ tlvTag : Extention field number to add.
 *              @ tlvValue : Tlv value to add. It must be ASN.1 format.
 *              @ tlvValueLen : Length of tlvVlaue.
 * Return value : NOT_ERROR(0) is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int addTlv(int tlvTag, char *tlvValue, int tlvValueLen);

/**
 * Function : getDrkCertificate()
 * Description : Read DRK certificate encoded ASN.1 DER.
 * Parameters : @ drkType : KEY_TYPE_RSA or KEY_TYPE_SYMM.
 *                          KEY_TYPE_EC is not supported now.
 *              @ drkCert : Output buffer to save certificate.
 *              @ drkCertLen : Output buffer's size.
 * Return value : NOT_ERROR(0) is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int getDrkCertificate(int drkType, char *drkCert, uint32_t drkCertLen);

/**
 * Function : sendPseudoAtCommand()
 * Description : Send DRK AT command not using RIL.
 *               Only approved user can execute this function and it needs signed data.
 * Parameters : @ atCmd : signed AT command.
 *              @ rawDataLen : AT command's length.
 *              @ atResponse : AT command's response.
 * Return value : Response data length  is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int sendPseudoAtCommand(char *atCmd, uint32_t atCmdLen, char *atResponse, uint32_t atResponseLen);

/**
 * Function : verifyProvServiceBlob()
 * Description : Verify service blob issued from SKM.
 *               This is only for self testing.
 * Parameters : @ serviceName : service name to ask service key.
 *              @ keyType : KEY_TYPE_RSA or KEY_TYPE_SYMM or KEY_TYPE_EC.
 *              @ isEnableTlv : Use tlv value on making certificate.
 *              @ serviceCert : Output buffer to save certificate.
 *              @ serviceCertLen : Output buffer's size.
 * Return value : Service certifcate length is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int verifyProvServiceBlob(char *serviceName, int keyType, uint8_t isEnableTlv,
        char *serviceCert, uint32_t serviceCertLen);

/**
 * Function : sendBigData()
 * Description : Send intent to context framework via DeviceRootKeyService.
 * Parameters : @ serviceType : BIGDATA_KEYSTORE_ATTESTATION.
 *              @ bigData : Input buffer to send intent.
 * Return value : NOT_ERROR(0) is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int sendBigData(int serviceType, char *bigData);

/**
 * Function    : getDeviceInfo()
 * Description : Get device information via DeviceRootKeyService.
 *               Only approved user can execute this function.
 * Parameters : @ infoType[in] : DEVICE_INFO_ALL            All of the Device Information,
 *                               DEVICE_INFO_IMEI           Hashed IMEI,
 *                               DEVICE_INFO_MODEM          Hashed CP information,
 *                               DEVICE_INFO_SERIAL         Hashed AP information,
 *                               DEVICE_INFO_IMEI_MODEM
 *                               DEVICE_INFO_IMEI_SERIAL
 *                               DEVICE_INFO_MODEM_SERIAL
 *                               DEVICE_INFO_HUID           HUID from device instead of DRK Certificate.
 *              @ info   [out] : The result of comparing DRK certificate and huid
 *                               and device information that matches the input type.
 * Return value : NOT_ERROR(0) is returned if it is successful.
 *                On error, error number(negative) is returned.
 */
int getDeviceInfo(int infoType, DeviceInfo *info);


/**
 * REMOTE FUNCTOIN
 */
int checkHwStatus();
int readKmData(char *filename, uint8_t **buf);
int writeKmData(char *filename, uint8_t *buf, uint32_t size);
int hermesCommand(uint32_t cmd, uint8_t *out, uint32_t *out_len);
int getPdpData(uint8_t *pdpData, uint32_t *pdpData_len);

#ifdef __cplusplus
}
#endif

#endif  // End of __LIBDK_NATIVE_CLIENT_H__
