/* SPDX-License-Identifier: GPL-2.0-only */


#ifndef __HWKM_H_
#define __HWKM_H_

#include <linux/types.h>
#include <stdbool.h>
#include <stddef.h>

#include <linux/tme_hwkm_master_defs.h>
#include <linux/crypto-qti-common.h>

#if IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER)

#define HWKM_MAX_KEY_SIZE TME_PT_KEY_BYTES_MAX

#define HWKM_MAX_CTX_SIZE TME_KDF_SW_CONTEXT_BYTES_MAX

#define HWKM_MAX_BLOB_SIZE TME_WK_CONTEXT_BYTES_MAX

#define HWKM_TPKEY_SLOT_MASTER TME_KID_TP
#define HWKM_TPKEY_SLOT_ICE		0x8C

#define HWKM_EXPECTED_UNWRAP_KEY_SIZE 100

#else

#define HWKM_MAX_KEY_SIZE 32

#define HWKM_MAX_CTX_SIZE 64

#define HWKM_MAX_BLOB_SIZE 68
#endif 


enum hwkm_op {
	
	NIST_KEYGEN = 0,
	
	SYSTEM_KDF,
	
	QFPROM_KEY_RDWR,
	
	KEY_WRAP_EXPORT,
	
	KEY_UNWRAP_IMPORT,
	
	KEY_SLOT_CLEAR,
	
	KEY_SLOT_RDWR,
	
	SET_TPKEY,


	HWKM_MAX_OP,
	HWKM_UNDEF_OP = 0xFF
};


#if IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER)
enum hwkm_alg {
	
	AES128_ECB = TME_KT_Symmetric | TME_KAL_AES128_ECB | TME_KL_128,
	AES256_ECB = TME_KT_Symmetric | TME_KAL_AES256_ECB | TME_KL_256,
	DES_ECB = TME_KT_Symmetric | TME_KAL_DES_ECB | TME_KL_64,
	TDES_ECB = TME_KT_Symmetric | TME_KAL_TDES_ECB | TME_KL_192,
	AES128_CBC = TME_KT_Symmetric | TME_KAL_AES128_CBC | TME_KL_128,
	AES256_CBC = TME_KT_Symmetric | TME_KAL_AES256_CBC | TME_KL_256,
	DES_CBC = TME_KT_Symmetric | TME_KAL_DES_CBC | TME_KL_64,
	TDES_CBC = TME_KT_Symmetric | TME_KAL_TDES_CBC | TME_KL_192,
	AES128_CCM_TC = TME_KT_Symmetric | TME_KAL_AES128_CCM_TC | TME_KL_128,
	AES128_CCM_NTC = TME_KT_Symmetric | TME_KAL_AES128_CCM_NTC | TME_KL_128,
	AES256_CCM_TC = TME_KT_Symmetric | TME_KAL_AES256_CCM_TC | TME_KL_256,
	AES256_CCM_NTC = TME_KT_Symmetric | TME_KAL_AES256_CCM_NTC | TME_KL_256,
	AES256_SIV = TME_KT_Symmetric | TME_KAL_AES256_SIV | TME_KL_512,
	AES128_CTR = TME_KT_Symmetric | TME_KAL_AES128_CTR | TME_KL_128,
	AES256_CTR = TME_KT_Symmetric | TME_KAL_AES256_CTR | TME_KL_256,
	AES128_XTS = TME_KT_Symmetric | TME_KAL_AES128_XTS | TME_KL_512,
	AES256_XTS = TME_KT_Symmetric | TME_KAL_AES256_XTS | TME_KL_512,
	SHA1_HMAC = TME_KT_Symmetric | TME_KAL_SHA1_HMAC | TME_KL_512,
	SHA256_HMAC = TME_KT_Symmetric | TME_KAL_SHA256_HMAC | TME_KL_512,
	AES128_CMAC = TME_KT_Symmetric | TME_KAL_AES128_CMAC | TME_KL_128,
	AES256_CMAC = TME_KT_Symmetric | TME_KAL_AES256_CMAC | TME_KL_256,
	SHA384_HMAC = TME_KT_Symmetric | TME_KAL_SHA384_HMAC | TME_KL_512,
	SHA512_HMAC = TME_KT_Symmetric | TME_KAL_SHA512_HMAC | TME_KL_512,
	AES128_GCM = TME_KT_Symmetric | TME_KAL_AES128_GCM | TME_KL_128,
	AES256_GCM = TME_KT_Symmetric | TME_KAL_AES256_GCM | TME_KL_256,

	// TODO: Verify Key Lengths for these algorithms
	KASUMI = TME_KT_Symmetric | TME_KAL_KASUMI | TME_KL_128,
	SNOW3G = TME_KT_Symmetric | TME_KAL_SNOW3G | TME_KL_128,
	ZUC = TME_KT_Symmetric | TME_KAL_ZUC | TME_KL_128,
	PRINCE = TME_KT_Symmetric | TME_KAL_PRINCE | TME_KL_128,
	SIPHASH = TME_KT_Symmetric | TME_KAL_SIPHASH | TME_KL_128,

	KDF_NIST = TME_KT_Symmetric | TME_KAL_KDF_NIST | TME_KL_512,
	KDF_HKDF = TME_KT_Symmetric | TME_KAL_KDF_HKDF,

	
	ECDSA_P224_NIST = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDSA | TME_KL_224 |
						TME_KAL_ECC_CURVE_NIST,
	ECDSA_P256_NIST = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDSA | TME_KL_256 |
						TME_KAL_ECC_CURVE_NIST,
	ECDSA_P384_NIST = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDSA | TME_KL_384 |
						TME_KAL_ECC_CURVE_NIST,
	ECDSA_P521_NIST = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDSA | TME_KL_521 |
						TME_KAL_ECC_CURVE_NIST,
	ECDSA_P224_BP = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDSA | TME_KL_224 |
						TME_KAL_ECC_CURVE_BPOOL,
	ECDSA_P256_BP = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDSA | TME_KL_256 |
						TME_KAL_ECC_CURVE_BPOOL,
	ECDSA_P384_BP = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDSA | TME_KL_384 |
						TME_KAL_ECC_CURVE_BPOOL,
	ECDSA_P512_BP = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDSA | TME_KL_512 |
						TME_KAL_ECC_CURVE_BPOOL,
	ECDH_P224_NIST = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDH | TME_KL_224 |
						TME_KAL_ECC_CURVE_NIST,
	ECDH_P256_NIST = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDH | TME_KL_256 |
						TME_KAL_ECC_CURVE_NIST,
	ECDH_P384_NIST = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDH | TME_KL_384 |
						TME_KAL_ECC_CURVE_NIST,
	ECDH_P521_NIST = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDH | TME_KL_521 |
						TME_KAL_ECC_CURVE_NIST,
	ECDH_P224_BP = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDH | TME_KL_224 |
						TME_KAL_ECC_CURVE_BPOOL,
	ECDH_P256_BP = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDH | TME_KL_256 |
						TME_KAL_ECC_CURVE_BPOOL,
	ECDH_P384_BP = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDH | TME_KL_384 |
						TME_KAL_ECC_CURVE_BPOOL,
	ECDH_P512_BP = TME_KT_Asymmetric_ECC | TME_KAL_ECC_ALGO_ECDH | TME_KL_512 |
						TME_KAL_ECC_CURVE_BPOOL,

	HWKM_UNDEF_ALG = 0xFFFFFFFF
};


enum hwkm_type {
	KEY_DERIVATION_KEY = TME_KP_KeyDerivation,
	KEY_WRAPPING_KEY = TME_KP_KWK_STORAGE,
	KEY_SWAPPING_KEY = TME_KP_KWK_SESSION,
	TRANSPORT_KEY = TME_KP_KWK_TRANSPORT,
	GENERIC_KEY = TME_KP_Generic,
	EXPORT_KEY = TME_KP_KWK_XPORT,

	HWKM_UNDEF_KEY_TYPE = 0xFFFFFFFF
};


enum hwkm_destination {
	KM_MASTER = TME_KD_TME_HW,
	GPCE_SLAVE = TME_KD_GPCE,
	MCE_SLAVE = TME_KD_MDM_CE,
	ICE_SLAVE = TME_KD_ICE,

	HWKM_UNDEF_DESTINATION = 0xFFFFFFFF
};


enum hwkm_security_level {
	
	SW_KEY = TME_KSL_SWKey,
	
	MANAGED_KEY = TME_KSL_HWManagedKey,
	
	HW_KEY = TME_KSL_HWKey,

	HWKM_UNDEF_SECURITY_LEVEL = 0xFFFFFFFF
};

enum hwkm_key_lineage {
	KEY_LINEAGE_NA = TME_KLI_NA,
	KEY_LINEAGE_NOT_PROVISIONED_UNIQUE = TME_KLI_NP_CU,
	KEY_LINEAGE_NOT_PROVISIONED_NOT_UNIQUE = TME_KLI_P_NCU,
	KEY_LINEAGE_PROVISIONED_UNIQUE = TME_KLI_P_CU,

	HWKM_UNDEF_KEY_LINEAGE = 0xFFFFFFFF
};

#define HWKM_CRED_SLOT_NONE TME_CRED_SLOT_ID_NONE
#define HWKM_CRED_SLOT_1 TME_CRED_SLOT_ID_1
#define HWKM_CRED_SLOT_2 TME_CRED_SLOT_ID_2


enum hwkm_master_key_slots {
	
	TZ_NKDK_L2 = TME_KID_CHIP_FAM_L1,
	TZ_PKDK_L2 = TME_KID_CHIP_UNIQUE_SEED,
	TZ_SKDK_L2 = TME_KID_CHIP_UNIQUE_SEED,
	TZ_UKDK_L2 = TME_KID_CHIP_RAND_BASE,

	
	TPKEY_SLOT = TME_KID_TP,

	
	TZ_SWAP_KEY_SLOT = 18,

	
	TZ_WRAP_KEY_SLOT = 19,

	
	TZ_GENERAL_PURPOSE_SLOT1 = 20,
	TZ_GENERAL_PURPOSE_SLOT2 = 21,

	
	TZ_MIXING_KEY_SLOT = 22,

	
	TZ_ASYMMETRIC_OPERATION_SLOT = 23,

	
	PERSISTENT_SHARED_SLOT_PAIR1 = 24,
	PERSISTENT_SHARED_SLOT_PAIR2 = 25,

	MASTER_SLOT_MAX,

	UNDEF_SLOT = 0xFF
};

struct hwkm_key_policy_v2_extension {
	bool expand_allowed;
	bool extract_allowed;
	enum hwkm_key_lineage lineage;
	u32 credential_slot;
	bool export_key_wrap_allowed;
};

#else

enum hwkm_alg {
	AES128_ECB = 0,
	AES256_ECB = 1,
	DES_ECB = 2,
	TDES_ECB = 3,
	AES128_CBC = 4,
	AES256_CBC = 5,
	DES_CBC = 6,
	TDES_CBC = 7,
	AES128_CCM_TC = 8,
	AES128_CCM_NTC = 9,
	AES256_CCM_TC = 10,
	AES256_CCM_NTC = 11,
	AES256_SIV = 12,
	AES128_CTR = 13,
	AES256_CTR = 14,
	AES128_XTS = 15,
	AES256_XTS = 16,
	SHA1_HMAC = 17,
	SHA256_HMAC = 18,
	AES128_CMAC = 19,
	AES256_CMAC = 20,
	SHA384_HMAC = 21,
	SHA512_HMAC = 22,
	AES128_GCM = 23,
	AES256_GCM = 24,
	KASUMI = 25,
	SNOW3G = 26,
	ZUC = 27,
	PRINCE = 28,
	SIPHASH = 29,
	QARMA64 = 30,
	QARMA128 = 31,

	HWKM_ALG_MAX,

	HWKM_UNDEF_ALG = 0xFF
};

enum hwkm_type {
	KEY_DERIVATION_KEY = 0,
	KEY_WRAPPING_KEY = 1,
	KEY_SWAPPING_KEY = 2,
	TRANSPORT_KEY = 3,
	GENERIC_KEY = 4,

	HWKM_TYPE_MAX,

	HWKM_UNDEF_KEY_TYPE = 0xFF
};


enum hwkm_destination {
	KM_MASTER = 0,
	GPCE_SLAVE = 1,
	MCE_SLAVE = 2,
	PIMEM_SLAVE = 3,
	ICE0_SLAVE = 4,
	ICE1_SLAVE = 5,
	ICE2_SLAVE = 6,
	ICE3_SLAVE = 7,
	DP0_HDCP_SLAVE = 8,
	DP1_HDCP_SLAVE = 9,
	ICEMEM_SLAVE = 10,

	HWKM_DESTINATION_MAX,

	HWKM_UNDEF_DESTINATION = 0xFF
};

enum hwkm_security_level {
	
	SW_KEY = 0,
	
	MANAGED_KEY = 1,
	
	HW_KEY = 2,

	HWKM_SECURITY_LEVEL_MAX,

	HWKM_UNDEF_SECURITY_LEVEL = 0xFF
};

enum hwkm_master_key_slots {
	
	NKDK_L1 = 0,
	PKDK_L1 = 1,
	SKDK_L1 = 2,
	UKDK_L1 = 3,

	
	TZ_NKDK_L2 = 4,
	TZ_PKDK_L2 = 5,
	TZ_SKDK_L2 = 6,
	MODEM_PKDK_L2 = 7,
	MODEM_SKDK_L2 = 8,
	TZ_UKDK_L2 = 9,

	
	TPKEY_EVEN_SLOT = 10,
	TPKEY_KEY_ODD_SLOT = 11,

	
	MASTER_GENERIC_SLOTS_START,

	UNDEF_SLOT = 0xFF
};

#endif

struct hwkm_key_policy {
	bool km_by_spu_allowed;
	bool km_by_modem_allowed;
	bool km_by_nsec_allowed;
	bool km_by_tz_allowed;

	enum hwkm_alg alg_allowed;

	bool enc_allowed;
	bool dec_allowed;

	enum hwkm_type key_type;
	u8 kdf_depth;

	bool wrap_export_allowed;
	bool swap_export_allowed;

	enum hwkm_security_level security_lvl;

	enum hwkm_destination hw_destination;

	bool wrap_with_tpk_allowed;
#if IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER)
	struct hwkm_key_policy_v2_extension v2;
#endif
};

struct hwkm_bsve {
	bool enabled;
	bool km_key_policy_ver_en;
	bool km_apps_secure_en;
	bool km_msa_secure_en;
	bool km_lcm_fuse_en;
	bool km_boot_stage_otp_en;
	bool km_swc_en;
	bool km_child_key_policy_en;
	bool km_mks_en;
	u64 km_fuse_region_sha_digest_en;
#if IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER)
	bool km_oem_id_en;
	bool km_pkhash_en;
	bool km_oem_product_id_en;
	bool km_oem_product_seed_en;
#endif
};

struct hwkm_keygen_cmd {
	u8 dks;					
	struct hwkm_key_policy policy;		
};

struct hwkm_rdwr_cmd {
	uint8_t slot;			
	bool is_write;			
	struct hwkm_key_policy policy;	
	uint8_t key[HWKM_MAX_KEY_SIZE];	
	size_t sz;			
};

struct hwkm_kdf_cmd {
	uint8_t dks;			
	uint8_t kdk;			
	uint8_t mks;			
	struct hwkm_key_policy policy;	
	struct hwkm_bsve bsve;		
	uint8_t ctx[HWKM_MAX_CTX_SIZE];	
	size_t sz;			
#if IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER)
	enum hwkm_alg parent_alg;	
#endif
};

struct hwkm_set_tpkey_cmd {
	uint8_t sks;			
};

struct hwkm_unwrap_cmd {
	uint8_t dks;			
	uint8_t kwk;			
	uint8_t wkb[HWKM_MAX_BLOB_SIZE];
	uint8_t sz;			
};

struct hwkm_wrap_cmd {
	uint8_t sks;			
	uint8_t kwk;			
	struct hwkm_bsve bsve;		
};

struct hwkm_clear_cmd {
	uint8_t dks;			
	bool is_double_key;		
};


struct hwkm_cmd {
	enum hwkm_op op;		
#if IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER)
	enum hwkm_destination dest;
#endif
	union 
	{
		struct hwkm_keygen_cmd keygen;
		struct hwkm_rdwr_cmd rdwr;
		struct hwkm_kdf_cmd kdf;
		struct hwkm_set_tpkey_cmd set_tpkey;
		struct hwkm_unwrap_cmd unwrap;
		struct hwkm_wrap_cmd wrap;
		struct hwkm_clear_cmd clear;
	};
};

struct hwkm_rdwr_rsp {
	struct hwkm_key_policy policy;	
	uint8_t key[HWKM_MAX_KEY_SIZE];	
	size_t sz;			
};

struct hwkm_wrap_rsp {
	uint8_t wkb[HWKM_MAX_BLOB_SIZE];	
	size_t sz;				
};

struct hwkm_rsp {
	u32 status;
	union 
	{
		struct hwkm_rdwr_rsp rdwr;
		struct hwkm_wrap_rsp wrap;
	};
};

#if (IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER) || IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER_V1))
int qti_hwkm_handle_cmd(struct hwkm_cmd *cmd, struct hwkm_rsp *rsp);
int qti_hwkm_clocks(bool on);
int qti_hwkm_init(const struct ice_mmio_data *mmio_data);
bool qti_hwkm_init_required(const struct ice_mmio_data *mmio_data);
#else
static inline int qti_hwkm_add_req(struct hwkm_cmd *cmd,
				   struct hwkm_rsp *rsp)
{
	return -EOPNOTSUPP;
}
static inline int qti_hwkm_clocks(bool on)
{
	return -EOPNOTSUPP;
}
static inline int qti_hwkm_init(const struct ice_mmio_data *mmio_data)
{
	return -EOPNOTSUPP;
}
static inline bool qti_hwkm_init_required(const struct ice_mmio_data *mmio_data)
{
	return -EOPNOTSUPP;
}
#endif 
#endif 
