#ifndef _SC_API_H_
#define _SC_API_H_

/* version 2:
 * 	1) add support of RSA CRT algorithm;
 * 	2) add check version command;
 * 	3) directly map input and output buffer so that there is no max size for them
 * */
#define SC_VERSION_NUMBER       0x00000002

#define SC_OK                   0x00000000
#define SC_INVALID_INPUT_PARAM  0x00000001
#define SC_TIMA_DR_ERROR        0x00000002
#define SC_UNSUPPORTED_ALG      0x00000003
#define SC_NULL_POINTER         0x00000004
#define SC_ENC_ERROR            0x00000005
#define SC_DEC_ERROR            0x00000006
#define SC_BUF_TOO_SMALL        0x00000007
#define SC_EVP_ERROR            0x00000008
#define SC_SIGN_ERROR           0x00000009
#define SC_VERIFY_ERROR         0x0000000A
#define SC_UNKNOWN_ERROR        0xFFFFFFFF


/* The format of IPC command id (unsigned32_t).
 * +----------------+-------------+-------------+-------------+------------+-----------+
 * | bit 31 ~ 28    | bit 27 ~ 24 | bit 23 ~ 20 | bit 19 ~ 16 | bit 15 ~ 8 | bit 7 ~ 0 |
 * +----------------+-------------+-------------+-------------+------------+-----------+
 * | algorithm type | algorithm   | block mode  | padding     | key size   | reserved  |
 * |                |             | or sig_hash |             |            |           |
 * +----------------+-------------+-------------+-------------+------------+-----------+
 */

/* mask */
#define SC_MASK_TYPE        0xF0000000
#define SC_MASK_ALG         0x0F000000
#define SC_MASK_BLOCK_MODE  0x00F00000
#define SC_MASK_SIG_MD      0x00F00000
#define SC_MASK_PADDING     0x000F0000
#define SC_MASK_KEYSIZE     0x0000FF00
#define SC_MASK_OP          0x000000F0
#define SC_MASK_RESERVE     0x0000000F

/* ------- bit 31 ~ bit 28 -------- */
/* algorithm type flags */
#define SC_CIPHER        (1U << 28)
#define SC_SIG           (2U << 28)
#define SC_MD            (3U << 28)
#define SC_RNG           (4U << 28)
/* we use following types for SC_IPC version 2
 * When version 1 tz_driver return SC_INVALID_INPUT_PARAM,
 * we know the tz_driver has version 1 SC_IPC
 */
#define SC2_CIPHER       (5U << 28)
#define SC2_SIG          (6U << 28)
#define SC2_MD           (7U << 28)
#define SC2_RNG          (8U << 28)
#define SC2_VER          (9U << 28)

/* ------- bit 27 ~ bit 24 -------- */
/* cipher algorithm */
#define SC_CIPHER_AES    (1U << 24)
#define SC_CIPHER_TDEA   (2U << 24)
#define SC_CIPHER_RSA    (3U << 24)

/* sig algorithm */
#define SC_SIG_DES       (1U << 24)
#define SC_SIG_HMAC      (2U << 24)
#define SC_SIG_RSA       (3U << 24)
#define SC_SIG_AES       (4U << 24)
#define SC_SIG_DSA       (5U << 24)
#define SC_SIG_ECDSA     (6U << 24)

/* md algorithm */
#define SC_MD_SHA1       (1U << 24)
#define SC_MD_SHA224     (2U << 24)
#define SC_MD_SHA256     (3U << 24)
#define SC_MD_SHA384     (4U << 24)
#define SC_MD_SHA512     (5U << 24)

/* -------- bit 23 ~ bit 20 -------- */
/* block mode for AES */
#define SC_BLOCK_ECB     (1U << 20)
#define SC_BLOCK_CBC     (2U << 20)
#define SC_BLOCK_CFB     (3U << 20)
#define SC_BLOCK_CFB1    (4U << 20)
#define SC_BLOCK_CFB8    (5U << 20)
#define SC_BLOCK_CFB128  (6U << 20)
#define SC_BLOCK_OFB     (7U << 20)
#define SC_BLOCK_CTR     (8U << 20)
#define SC_BLOCK_GCM     (9U << 20)
#define SC_BLOCK_CCM     (10U << 20)
#define SC_BLOCK_XTS     (11U << 20)
/* hash alg for RSA/ECDSA sign/verify */
#define SC_SIG_MD_SHA1   (1U << 20)
#define SC_SIG_MD_SHA224 (2U << 20)
#define SC_SIG_MD_SHA256 (3U << 20)
#define SC_SIG_MD_SHA384 (4U << 20)
#define SC_SIG_MD_SHA512 (5U << 20)

/* -------- bit 19 ~ bit 16 --------- */
/* padding */
#define SC_PAD_NOPAD      (1U << 16)
#define SC_PAD_PKCS5      (2U << 16)
/* RSA encryption/decryption */
#define SC_PAD_PKCS1      (3U << 16)
#define SC_PAD_PKCS1_OAEP (4U << 16)
#define SC_PAD_SSLV23     (5U << 16)
/* only for RSA sign/verify */
#define SC_PAD_RSA_X931   (6U << 16)
#define SC_PAD_PKCS1_PSS  (7U << 16)

/* -------- bit 15 ~ bit 8 -------- */
#define SC_KEYSIZE_56    (1U << 8)
#define SC_KEYSIZE_112   (2U << 8)
#define SC_KEYSIZE_128   (3U << 8)
#define SC_KEYSIZE_168   (4U << 8)
#define SC_KEYSIZE_192   (5U << 8)
#define SC_KEYSIZE_256   (6U << 8)

/* -------- bit 7 ~ bit 4 --------- */
#define SC_OP_ENC        (1U << 4)
#define SC_OP_DEC        (2U << 4)
#define SC_OP_SIGN       (3U << 4)
#define SC_OP_VERIFY     (4U << 4)

/* -------- last 4 bits are reserved ------ */

typedef enum {
	/* version 1 ipc call commands */
	/* AES ciphers */
	SC_ALG_AES_CBC    = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_CBC),
	SC_ALG_AES_ECB    = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_ECB),
	SC_ALG_AES_CFB1   = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_CFB1), /* no support */
	SC_ALG_AES_CFB8   = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_CFB8), /* no support */
	SC_ALG_AES_CFB128 = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_CFB128),
	SC_ALG_AES_OFB    = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_OFB),
	SC_ALG_AES_GCM    = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_GCM), /* no support */
	SC_ALG_AES_CCM    = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_CCM), /* no support */
	SC_ALG_AES_CTR    = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_CTR),
	SC_ALG_AES_XTS    = (SC_CIPHER | SC_CIPHER_AES | SC_BLOCK_XTS), /* no support */

	/* TDEA */
	SC_ALG_TDEA_2KEY_ECB = (SC_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_ECB | SC_KEYSIZE_112),
	SC_ALG_TDEA_3KEY_ECB = (SC_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_ECB | SC_KEYSIZE_168),
	SC_ALG_TDEA_2KEY_CFB = (SC_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_CFB | SC_KEYSIZE_112),
	SC_ALG_TDEA_3KEY_CFB = (SC_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_CFB | SC_KEYSIZE_168),
	SC_ALG_TDEA_2KEY_OFB = (SC_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_OFB | SC_KEYSIZE_112),
	SC_ALG_TDEA_3KEY_OFB = (SC_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_OFB | SC_KEYSIZE_168),
	SC_ALG_TDEA_2KEY_CBC = (SC_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_CBC | SC_KEYSIZE_112),
	SC_ALG_TDEA_3KEY_CBC = (SC_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_CBC | SC_KEYSIZE_168),

	/* RSA ciphers */
	SC_ALG_RSA_NOPAD      = (SC_CIPHER | SC_CIPHER_RSA | SC_PAD_NOPAD),
	SC_ALG_RSA_PKCS1      = (SC_CIPHER | SC_CIPHER_RSA | SC_PAD_PKCS1),
	SC_ALG_RSA_PKCS1_OAEP = (SC_CIPHER | SC_CIPHER_RSA | SC_PAD_PKCS1_OAEP),
	SC_ALG_RSA_SSLV23     = (SC_CIPHER | SC_CIPHER_RSA | SC_PAD_SSLV23),

	/* RSA sig */
	SC_SIG_RSA_SHA1_PKCS1   = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA1 | SC_PAD_PKCS1),
	SC_SIG_RSA_SHA224_PKCS1 = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA224 | SC_PAD_PKCS1),
	SC_SIG_RSA_SHA256_PKCS1 = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA256 | SC_PAD_PKCS1),
	SC_SIG_RSA_SHA384_PKCS1 = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA384 | SC_PAD_PKCS1),
	SC_SIG_RSA_SHA512_PKCS1 = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA512 | SC_PAD_PKCS1),
	SC_SIG_RSA_SHA1_X931    = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA1 | SC_PAD_RSA_X931),
	SC_SIG_RSA_SHA224_X931  = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA224 | SC_PAD_RSA_X931),
	SC_SIG_RSA_SHA256_X931  = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA256 | SC_PAD_RSA_X931),
	SC_SIG_RSA_SHA384_X931  = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA384 | SC_PAD_RSA_X931),
	SC_SIG_RSA_SHA512_X931  = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA512 | SC_PAD_RSA_X931),
	SC_SIG_RSA_SHA1_PSS     = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA1 | SC_PAD_PKCS1_PSS),
	SC_SIG_RSA_SHA224_PSS   = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA224 | SC_PAD_PKCS1_PSS),
	SC_SIG_RSA_SHA256_PSS   = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA256 | SC_PAD_PKCS1_PSS),
	SC_SIG_RSA_SHA384_PSS   = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA384 | SC_PAD_PKCS1_PSS),
	SC_SIG_RSA_SHA512_PSS   = (SC_SIG | SC_SIG_RSA | SC_SIG_MD_SHA512 | SC_PAD_PKCS1_PSS),

	/*------- DSA starts here -------*/
	SC_SIG_DSA_RAW                       = (SC_SIG | SC_SIG_DSA | 1),    /**< DSA with raw data. No digest calculation. */

	/*------- ECDSA starts here -------*/
	SC_SIG_ECDSA_RAW                     = (SC_SIG | SC_SIG_ECDSA | 1),  /**< ECDSA with raw data. No digest calculation. */

	SC_ALG_SHA1                          = (SC_MD | SC_MD_SHA1),
	SC_ALG_SHA224                        = (SC_MD | SC_MD_SHA224),
	SC_ALG_SHA256                        = (SC_MD | SC_MD_SHA256),
	SC_ALG_SHA384                        = (SC_MD | SC_MD_SHA384),
	SC_ALG_SHA512                        = (SC_MD | SC_MD_SHA512),

	/* version 2 ipc call commands */
	/* AES ciphers */
	SC2_ALG_AES_CBC    = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_CBC),
	SC2_ALG_AES_ECB    = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_ECB),
	SC2_ALG_AES_CFB1   = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_CFB1), /* no support */
	SC2_ALG_AES_CFB8   = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_CFB8), /* no support */
	SC2_ALG_AES_CFB128 = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_CFB128),
	SC2_ALG_AES_OFB    = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_OFB),
	SC2_ALG_AES_GCM    = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_GCM), /* no support */
	SC2_ALG_AES_CCM    = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_CCM), /* no support */
	SC2_ALG_AES_CTR    = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_CTR),
	SC2_ALG_AES_XTS    = (SC2_CIPHER | SC_CIPHER_AES | SC_BLOCK_XTS), /* no support */

	/* TDEA */
	SC2_ALG_TDEA_2KEY_ECB = (SC2_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_ECB | SC_KEYSIZE_112),
	SC2_ALG_TDEA_3KEY_ECB = (SC2_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_ECB | SC_KEYSIZE_168),
	SC2_ALG_TDEA_2KEY_CFB = (SC2_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_CFB | SC_KEYSIZE_112),
	SC2_ALG_TDEA_3KEY_CFB = (SC2_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_CFB | SC_KEYSIZE_168),
	SC2_ALG_TDEA_2KEY_OFB = (SC2_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_OFB | SC_KEYSIZE_112),
	SC2_ALG_TDEA_3KEY_OFB = (SC2_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_OFB | SC_KEYSIZE_168),
	SC2_ALG_TDEA_2KEY_CBC = (SC2_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_CBC | SC_KEYSIZE_112),
	SC2_ALG_TDEA_3KEY_CBC = (SC2_CIPHER | SC_CIPHER_TDEA | SC_BLOCK_CBC | SC_KEYSIZE_168),

	/* RSA ciphers */
	SC2_ALG_RSA_NOPAD      = (SC2_CIPHER | SC_CIPHER_RSA | SC_PAD_NOPAD),
	SC2_ALG_RSA_PKCS1      = (SC2_CIPHER | SC_CIPHER_RSA | SC_PAD_PKCS1),
	SC2_ALG_RSA_PKCS1_OAEP = (SC2_CIPHER | SC_CIPHER_RSA | SC_PAD_PKCS1_OAEP),
	SC2_ALG_RSA_SSLV23     = (SC2_CIPHER | SC_CIPHER_RSA | SC_PAD_SSLV23),

	/* RSA sig */
	SC2_SIG_RSA_SHA1_PKCS1   = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA1 | SC_PAD_PKCS1),
	SC2_SIG_RSA_SHA224_PKCS1 = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA224 | SC_PAD_PKCS1),
	SC2_SIG_RSA_SHA256_PKCS1 = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA256 | SC_PAD_PKCS1),
	SC2_SIG_RSA_SHA384_PKCS1 = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA384 | SC_PAD_PKCS1),
	SC2_SIG_RSA_SHA512_PKCS1 = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA512 | SC_PAD_PKCS1),
	SC2_SIG_RSA_SHA1_X931    = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA1 | SC_PAD_RSA_X931),
	SC2_SIG_RSA_SHA224_X931  = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA224 | SC_PAD_RSA_X931),
	SC2_SIG_RSA_SHA256_X931  = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA256 | SC_PAD_RSA_X931),
	SC2_SIG_RSA_SHA384_X931  = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA384 | SC_PAD_RSA_X931),
	SC2_SIG_RSA_SHA512_X931  = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA512 | SC_PAD_RSA_X931),
	SC2_SIG_RSA_SHA1_PSS     = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA1 | SC_PAD_PKCS1_PSS),
	SC2_SIG_RSA_SHA224_PSS   = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA224 | SC_PAD_PKCS1_PSS),
	SC2_SIG_RSA_SHA256_PSS   = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA256 | SC_PAD_PKCS1_PSS),
	SC2_SIG_RSA_SHA384_PSS   = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA384 | SC_PAD_PKCS1_PSS),
	SC2_SIG_RSA_SHA512_PSS   = (SC2_SIG | SC_SIG_RSA | SC_SIG_MD_SHA512 | SC_PAD_PKCS1_PSS),

	/*------- DSA starts here -------*/
	SC2_SIG_DSA_RAW                       = (SC2_SIG | SC_SIG_DSA | 1),    /**< DSA with raw data. No digest calculation. */

	/*------- ECDSA starts here -------*/
	SC2_SIG_ECDSA_RAW                     = (SC2_SIG | SC_SIG_ECDSA | 1),  /**< ECDSA with raw data. No digest calculation. */

	SC2_ALG_SHA1                          = (SC2_MD | SC_MD_SHA1),
	SC2_ALG_SHA224                        = (SC2_MD | SC_MD_SHA224),
	SC2_ALG_SHA256                        = (SC2_MD | SC_MD_SHA256),
	SC2_ALG_SHA384                        = (SC2_MD | SC_MD_SHA384),
	SC2_ALG_SHA512                        = (SC2_MD | SC_MD_SHA512),

} scrypto_cmd_id_t;

/* AES */
#define AES_KEY_MAX_SIZE    32
#define AES_BLOCK_SIZE      16
#define INPUT_MAX_SIZE  2048
#define OUTPUT_MAX_SIZE 2048
#define AES_128_KEY_SIZE 16
#define AES_192_KEY_SIZE 24
#define AES_256_KEY_SIZE 32

typedef struct {
	uint8_t key_len;
	uint8_t key[AES_KEY_MAX_SIZE];
	uint8_t iv_len;
	uint8_t iv[AES_BLOCK_SIZE];
	uint32_t input_len;
	uint8_t input[INPUT_MAX_SIZE];
	uint32_t output_len;
	uint8_t output[OUTPUT_MAX_SIZE];
} sc_aes_t;

#define DES_KEY_SIZE 8
#define DES_BLOCK_SIZE 8
typedef struct {
	uint8_t key_len;
	uint8_t key[3*DES_KEY_SIZE];
	uint8_t iv_len;
	uint8_t iv[DES_BLOCK_SIZE];
	uint32_t input_len;
	uint8_t input[INPUT_MAX_SIZE];
	uint32_t output_len;
	uint8_t output[OUTPUT_MAX_SIZE];
} sc_tdea_t;

#define RSA_KEY_MAX_SIZE 512 /* 1024/8 ~ 16384/8 */

typedef struct {
	 uint32_t n_len;
	 uint8_t n[RSA_KEY_MAX_SIZE];
	 uint32_t e_len;
	 uint8_t e[RSA_KEY_MAX_SIZE];
	 uint32_t d_len;
	 uint8_t d[RSA_KEY_MAX_SIZE];
	 uint32_t input_len;
	 uint8_t input[INPUT_MAX_SIZE];
	 uint32_t output_len;
	 uint8_t output[OUTPUT_MAX_SIZE];
} sc_rsa_t;

#define SC_MD_DIGEST_MAX_SIZE 64
typedef struct {
	uint32_t input_len;
	uint8_t input[INPUT_MAX_SIZE];
	uint32_t digest_len;
	uint8_t digest[SC_MD_DIGEST_MAX_SIZE];
} sc_md_t;

/* new data structure for version 2 */

#define AES_AAD_MAX_SIZE 2048
#define AES_TAG_MAX_SIZE 16

/* http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf page 8,9
 * tag_len in bit length may be 128, 120, 112, 104, 96, 64, or 32
 * i.e. 16, 15, 14, 13, 12, 8, 4 in bytes
 * */
typedef struct {
	uint8_t key_len;
	void * key_addr;
	uint8_t iv_len;
	void * iv_addr;
	uint32_t aad_len;
	void * aad_addr;
	uint32_t input_len;
	void * input_addr;
	uint32_t output_len;
	void * output_addr;
	uint8_t tag_len;
	void * tag_addr;
} sc_aes_t2;

typedef struct {
	uint8_t key_len;
	uint8_t key[3*DES_KEY_SIZE];
	uint8_t iv_len;
	uint8_t iv[DES_BLOCK_SIZE];
	uint32_t input_len;
	void * input_addr;
	uint32_t output_len;
	void * output_addr;
} sc_tdea_t2;

typedef struct {
	 uint32_t n_len;
	 void * n_addr;
	 uint32_t e_len;
	 void * e_addr;
	 uint32_t d_len;
	 void * d_addr;
	 uint32_t p_len;
	 void * p_addr;
	 uint32_t q_len;
	 void * q_addr;
	 uint32_t dp_len;
	 void * dp_addr;
	 uint32_t dq_len;
	 void * dq_addr;
	 uint32_t qp_len;
	 void * qp_addr;
	 uint32_t input_len;
	 void * input_addr;
	 uint32_t output_len;
	 void * output_addr;
} sc_rsa_t2;

typedef struct {
	uint32_t input_len;
	void * input_addr;
	uint32_t digest_len;
	uint8_t digest[SC_MD_DIGEST_MAX_SIZE];
} sc_md_t2;

typedef struct {
	uint32_t version;
} sc_version_t;
#endif /* end of ifndef _SC_API_H_ */
