/**
 * @file  tlapi_secdrv_keyman.h
 * @brief tlapi functions for key manager
 *
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * This software is proprietary of Samsung Electronics.
 * No part of this software, either material or conceptual may be copied
 * or distributed, transmitted, transcribed, stored in a retrieval system
 * or translated into any human or computer language in any form by any means,
 * electronic, mechanical, manual or otherwise, or disclosed to third parties
 * without the express written permission of Samsung Electronics.
 */

#ifndef __TLAPI_SECDRV_KEYMAN_H__
#define __TLAPI_SECDRV_KEYMAN_H__

#include "TlApi/TlApiCommon.h"
#include "TlApi/TlApiError.h"

#define AES_KEY_MAX_SIZE		32
#define AES_BLOCK_SIZE			16

#define SHA1_DIGEST_LEN			20
#define SHA1_BLOCK_LEN			64

#define SHA256_DIGEST_LEN		32
#define SHA256_BLOCK_LEN		64

#define SHA384_DIGEST_LEN		48

#define SHA512_DIGEST_LEN		64
#define SHA512_BLOCK_LEN		128

#define HMAC_MAX_KEY_LEN		128

/* HashCode(Digest) MAX Length for SSS-CM0_ECC Service */
#define MAX_DIGEST_LEN			SHA512_DIGEST_LEN

/* ECDSA & ECDH MAX Key Length, Signature Length for SSS-CM0 ECC Service */
#define ECC192_PRIV_KEY_LEN		(192 / 8)
#define ECC192_PUB_KEY_LEN		(ECC192_PRIV_KEY_LEN * 2)
#define ECC224_PRIV_KEY_LEN		(224 / 8)
#define ECC224_PUB_KEY_LEN		(ECC224_PRIV_KEY_LEN * 2)
#define ECC256_PRIV_KEY_LEN		(256 / 8)
#define ECC256_PUB_KEY_LEN		(ECC256_PRIV_KEY_LEN * 2)
#define ECC384_PRIV_KEY_LEN		(384 / 8)
#define ECC384_PUB_KEY_LEN		(ECC384_PRIV_KEY_LEN * 2)
#define ECC521_PRIV_KEY_LEN		(68)
#define ECC521_PUB_KEY_LEN		(ECC521_PRIV_KEY_LEN * 2)

#define MAX_ECC_PRIV_KEY_LEN		ECC521_PRIV_KEY_LEN
#define MAX_ECC_PUB_KEY_LEN		(ECC521_PRIV_KEY_LEN * 2)

#define MAX_ECC_SIG_R_LEN		ECC521_PRIV_KEY_LEN
#define MAX_ECC_SIG_S_LEN		MAX_ECC_SIG_R_LEN

#define MAX_ECDH_AGREEMENT_KEY_LEN	ECC521_PRIV_KEY_LEN

#define RESERVED_LEN			84

/* ECDSA & ECDH Algorithm ID */
#define OID_ECDSA_192			(0x00000011)
#define OID_ECDSA_224			(0x00000012)
#define OID_ECDSA_256			(0x00000013)
#define OID_ECDSA_384			(0x00000014)
#define OID_ECDSA_521			(0x00000015)

#define OID_SHA2_256			(0x00002300)
#define OID_SHA2_384			(0x00002400)
#define OID_SHA2_512			(0x00002500)

#define OID_ECDH_192			(0x00000021)
#define OID_ECDH_224			(0x00000022)
#define OID_ECDH_256			(0x00000023)
#define OID_ECDH_384			(0x00000024)
#define OID_ECDH_521			(0x00000025)

#define OID_ECDSA_192_SHA2_256		((OID_ECDSA_192) | (OID_SHA2_256))
#define OID_ECDSA_192_SHA2_384		((OID_ECDSA_192) | (OID_SHA2_384))
#define OID_ECDSA_192_SHA2_512		((OID_ECDSA_192) | (OID_SHA2_512))

#define OID_ECDSA_224_SHA2_256		((OID_ECDSA_224) | (OID_SHA2_256))
#define OID_ECDSA_224_SHA2_384		((OID_ECDSA_224) | (OID_SHA2_384))
#define OID_ECDSA_224_SHA2_512		((OID_ECDSA_224) | (OID_SHA2_512))

#define OID_ECDSA_256_SHA2_256		((OID_ECDSA_256) | (OID_SHA2_256))
#define OID_ECDSA_256_SHA2_384		((OID_ECDSA_256) | (OID_SHA2_384))
#define OID_ECDSA_256_SHA2_512		((OID_ECDSA_256) | (OID_SHA2_512))

#define OID_ECDSA_384_SHA2_256		((OID_ECDSA_384) | (OID_SHA2_256))
#define OID_ECDSA_384_SHA2_384		((OID_ECDSA_384) | (OID_SHA2_384))
#define OID_ECDSA_384_SHA2_512		((OID_ECDSA_384) | (OID_SHA2_512))

#define OID_ECDSA_521_SHA2_256		((OID_ECDSA_521) | (OID_SHA2_256))
#define OID_ECDSA_521_SHA2_384		((OID_ECDSA_521) | (OID_SHA2_384))
#define OID_ECDSA_521_SHA2_512		((OID_ECDSA_521) | (OID_SHA2_512))

enum cipherMode_t {
	ENCRYPT,
	DECRYPT,
	BYPASS,
};

enum padding_t {
	NO_PADDING,
	PKCS_PADDING,
	CTS_PADDING,
};

enum cache_t {
	CACHEABLE,
	NON_CACHEABLE,
};

enum aesOpMode_t {
	ECB_MODE,
	CBC_MODE,
	CBC_CTS_MODE,
	CTR_MODE,
};

enum addrSpace_t {
	VIRTUAL,
	PHYSICAL,
};

enum ldfw_t {
	CM_MODE,
	CE_MODE,
};

typedef struct cm_data {
	uint8_t *addr;
	size_t	len;
	enum cache_t cache;
	enum addrSpace_t space;
} CM_DATA;

typedef struct cm_data64 {
	uint64_t addr;
	size_t len;
	enum cache_t cache;
	enum addrSpace_t space;
} CM_DATA64;

struct secSss_t {
	uint32_t key;
	uint32_t key_len;
	uint32_t iv;
	uint32_t iv_len;
	uint32_t block_offset;
	CM_DATA input;
	CM_DATA output;
	enum aesOpMode_t mode;
	enum cipherMode_t cipher_mode;
	enum padding_t pad;
};

struct secSss64_t {
	uint32_t key;
	uint32_t key_len;
	uint32_t iv;
	uint32_t iv_len;
	uint32_t block_offset;
	CM_DATA64 input;
	CM_DATA64 output;
	enum aesOpMode_t mode;
	enum cipherMode_t cipher_mode;
	enum padding_t pad;
	enum ldfw_t ldfw_mode;
};

typedef struct aes_ctx_t {
	uint8_t key[AES_KEY_MAX_SIZE * 2];
	uint32_t key_len;
	uint8_t iv[AES_BLOCK_SIZE];
	uint64_t input;
	uint32_t input_len;
	uint64_t output;
	uint32_t output_len;
	uint32_t block_offset;
	enum aesOpMode_t mode;
	enum cipherMode_t cipher_mode;
	enum padding_t pad_type;
} AES_CTX_LIST;

typedef struct hash_ictx {
	uint32_t alg;
	uint32_t key_len;
	uint32_t key[HMAC_MAX_KEY_LEN / 4];
	uint32_t buflen;
	uint8_t buffer[SHA512_BLOCK_LEN];
	uint32_t state[SHA512_DIGEST_LEN / 4];
	uint32_t prelen_high;
	uint32_t prelen_low;
} HASH_ICTX;

typedef struct root_of_trust_t {
	uint32_t verified_boot_state;
	uint32_t device_locked;
	uint32_t os_version;
	uint32_t patch_month_year;
	uint8_t verified_boot_key[SHA256_DIGEST_LEN];
	uint64_t reserved[4];
} ROOT_OF_TRUST;

enum sha_alg_t {
	ALG_SHA1,
	ALG_SHA256,
	ALG_SHA512,
};

enum key_lifetime_t {
	CM_KEY_LIFETIME_PERMANENT,
	CM_KEY_LIFETIME_PERBOOT,
};

typedef struct {
	uint32_t alg_id;
	uint8_t priv_key[MAX_ECC_PRIV_KEY_LEN];
	uint32_t priv_key_len;
	uint8_t pub_key[MAX_ECC_PUB_KEY_LEN];
	uint32_t pub_key_len;
	uint8_t digest[MAX_DIGEST_LEN];
	uint32_t digest_len;
	uint8_t sig_r[MAX_ECC_SIG_R_LEN];
	uint32_t sig_r_len;
	uint8_t sig_s[MAX_ECC_SIG_S_LEN];
	uint32_t sig_s_len;
	uint8_t reserved[RESERVED_LEN];
} tlapi_ecdsa_t;

typedef struct {
	uint32_t alg_id;
	uint8_t priv_key[MAX_ECC_PRIV_KEY_LEN];
	uint32_t priv_key_len;
	uint8_t pub_key[MAX_ECC_PUB_KEY_LEN];
	uint32_t pub_key_len;
	uint8_t peer_pub_key[MAX_ECC_PUB_KEY_LEN];
	uint32_t peer_pub_key_len;
	uint8_t agreement_key[MAX_ECDH_AGREEMENT_KEY_LEN];
	uint32_t agreement_key_len;
	uint8_t reserved[RESERVED_LEN];
} tlapi_ecdh_t;

_TLAPI_EXTERN_C tlApiResult_t tlApiDeriveKeyWithREK(
	uint8_t *input_data,  /* input data for keying material */
	size_t input_length,  /* input length of byte unit */
	uint8_t *output_data, /* derived key */
	size_t output_length, /* output length of byte unit */
	uint32_t lifetime);   /* lifespan for the derived key */

_TLAPI_EXTERN_C tlApiResult_t tlApiGetRpmbHmac(
	const uint8_t *input_data,	/* RPMB frame data */
	const uint32_t input_length,	/* input length in byte */
	uint8_t *output_data);		/* result hamc sha256 value */

_TLAPI_EXTERN_C tlApiResult_t tlApiGetRandom(
	uint8_t *out,
	uint32_t len);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunAES(
	struct secSss_t *secSss);

/* This API can be used when 64bit physical address can be given. In
 * case that the virtual address is given, it can use tlApiRunAES() instead
 * of it because the virtual address can not be 64bit address now. */
_TLAPI_EXTERN_C tlApiResult_t tlApiRunAES64(
	struct secSss64_t *secSss64);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunAESBatch(
	AES_CTX_LIST *ctx_list, uint32_t ctx_cnt);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunSHAInit(
	HASH_ICTX *ctx,
	const enum sha_alg_t alg);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunSHAUpdate(
	HASH_ICTX *ctx,
	const uint8_t *input,
	const uint32_t len,
	const enum cache_t cache);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunSHAFinal(
	HASH_ICTX *ctx,
	uint8_t *out,
	uint32_t out_len);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunSHADigest(
	const enum sha_alg_t alg,
	const uint8_t *input,
	const uint32_t in_len,
	const enum cache_t in_cache,
	uint8_t *out,
	uint32_t out_len);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunHMACInit(
	HASH_ICTX *ctx,
	const enum sha_alg_t alg,
	const uint8_t *key,
	const uint32_t key_len);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunHMACUpdate(
	HASH_ICTX *ctx,
	const uint8_t *input,
	const uint32_t input_len,
	const enum cache_t cache);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunHMACFinal(
	HASH_ICTX *ctx,
	uint8_t *output,
	uint32_t output_len);

_TLAPI_EXTERN_C tlApiResult_t tlApiRunHMACDigest(
	const enum sha_alg_t alg,
	const uint8_t *key,
	const uint32_t key_len,
	const uint8_t *input,
	const uint32_t input_len,
	const enum cache_t input_cache,
	uint8_t *output,
	uint32_t output_len);

_TLAPI_EXTERN_C tlApiResult_t tlApiGetBootInfo(
	uint8_t *output,
	uint32_t output_len);

_TLAPI_EXTERN_C tlApiResult_t tlApiGetRootOfTrustInfo(
	ROOT_OF_TRUST *root_of_trust);

_TLAPI_EXTERN_C tlApiResult_t tlApiECDSAGenPubKey(
	tlapi_ecdsa_t *ctx); /* ECDSA context information */

_TLAPI_EXTERN_C tlApiResult_t tlApiECDSASignDigest(
	tlapi_ecdsa_t *ctx); /* ECDSA context information */

_TLAPI_EXTERN_C tlApiResult_t tlApiECDSAVerifyDigest(
	tlapi_ecdsa_t *ctx); /* ECDSA context information */

_TLAPI_EXTERN_C tlApiResult_t tlApiECDHGenPubKey(
	tlapi_ecdh_t *ctx); /* ECDH context information */

_TLAPI_EXTERN_C tlApiResult_t tlApiECDHGenAgreementKey(
	tlapi_ecdh_t *ctx); /* ECDH context information */

#endif /* __TLAPI_SECDRV_KEYMAN_H__ */
