Browse Source

securemsm-kernel: Enable tmecom module compilation

Enable compilation for tmecom-intf_dlkm.ko compilation.

Change-Id: I049c769abea1a53160d82f4c85ec49089f485f7e
Sheik Anwar Shabic Y 3 years ago
parent
commit
72ec3a4a48

+ 10 - 0
Android.mk

@@ -69,3 +69,13 @@ LOCAL_MODULE_DEBUG_ENABLE := true
 LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
 include $(DLKM_DIR)/Build_external_kernelmodule.mk
 #################################################
+#################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES           := $(SSG_SRC_FILES)
+LOCAL_MODULE              := tmecom-intf_dlkm.ko
+LOCAL_MODULE_KBUILD_NAME  := tmecom-intf_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/Build_external_kernelmodule.mk
+#################################################

+ 3 - 0
Kbuild

@@ -22,3 +22,6 @@ qcrypto-msm_dlkm-objs := crypto-qti/qcrypto.o
 
 obj-$(CONFIG_HDCP_QSEECOM) += hdcp_qseecom_dlkm.o
 hdcp_qseecom_dlkm-objs := hdcp/hdcp_qseecom.o
+
+obj-$(CONFIG_MSM_TMECOM_QMP) := tmecom-intf_dlkm.o
+tmecom-intf_dlkm-objs := tmecom/tmecom.o tmecom/tme_hwkm_master.o

+ 2 - 1
config/ssg_smcinvoke.conf

@@ -5,4 +5,5 @@ export CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=m
 export CONFIG_CRYPTO_DEV_QCRYPTO=m
 export CONFIG_SCSI_UFS_CRYPTO=m
 export CONFIG_SCSI_UFS_CRYPTO_QTI=m
-export CONFIG_HDCP_QSEECOM=m
+export CONFIG_HDCP_QSEECOM=m
+export CONFIG_MSM_TMECOM_QMP=m

+ 120 - 0
linux/tme_hwkm_master.h

@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+#ifndef _TME_HWKM_MASTER_H_
+#define _TME_HWKM_MASTER_H_
+
+#include <linux/tme_hwkm_master_defs.h>
+
+/**
+ * API functions
+ */
+
+/**
+ *  Clear a Key Table entry.
+ *
+ *  @param  [in]   key_id      The ID of the key to clear.
+ *  @param  [out]  err_info    Extended error info
+ *
+ *  @return  0 if successful, error code otherwise.
+ */
+uint32_t tme_hwkm_master_clearkey(uint32_t key_id,
+		struct tme_ext_err_info *err_info);
+
+/**
+ *  Generate a random key with an associated policy.
+ *
+ *  @param  [in]   key_id      The ID of the key to be generated.
+ *  @param  [in]   policy      The policy specifying the key to be generated.
+ *  @param  [in]   cred_slot   Credential slot to which this key will be bound.
+ *  @param  [out]  err_info    Extended error info
+ *
+ *  @return  0 if successful, error code otherwise.
+ */
+uint32_t tme_hwkm_master_generatekey(uint32_t key_id,
+		struct tme_key_policy *policy,
+		uint32_t cred_slot,
+		struct tme_ext_err_info *err_info);
+
+/**
+ *  Derive a KEY using either HKDF or NIST algorithms.
+ *
+ *  @param  [in]   key_id     The ID of the key to be derived.
+ *  @param  [in]   kdf_info   Specifies how the key is to be derived
+ *                            and the properties of the derived key.
+ *  @param  [in]   cred_slot  Credential slot to which this key will be bound.
+ *  @param  [out]  err_info    Extended error info
+ *
+ *  @return  0 if successful, error code otherwise.
+ */
+uint32_t tme_hwkm_master_derivekey(uint32_t key_id,
+		struct tme_kdf_spec *kdf_info,
+		uint32_t cred_slot,
+		struct tme_ext_err_info *err_info);
+
+/**
+ *  Wrap a key so that it can be safely moved outside the TME.
+ *
+ *  @param  [in]   kwkey_id     Denotes a key, already present in the
+ *                              Key Table, to be used to secure the target key.
+ *  @param  [in]   targetkey_id Denotes the key to be wrapped.
+ *  @param  [in]   cred_slot    Credential slot to which this key is bound.
+ *  @param  [out]  wrapped      Buffer for wrapped key output from response
+ *  @param  [out]  err_info     Extended error info
+ *
+ *  @return  0 if successful, error code otherwise.
+ */
+uint32_t tme_hwkm_master_wrapkey(uint32_t key_id,
+		uint32_t targetkey_id,
+		uint32_t cred_slot,
+		struct tme_wrapped_key *wrapped,
+		struct tme_ext_err_info *err_info);
+
+/**
+ *  Unwrap a key from outside the TME and store in the Key Table.
+ *
+ *  @param  [in]   key_id      The ID of the key to be unwrapped.
+ *  @param  [in]   kwkey_id    Denotes a key, already present in the
+ *                             Key Table, to be used to unwrap the key.
+ *  @param  [in]   cred_slot   Credential slot to which this key will be bound.
+ *  @param  [in]   wrapped     The key to be unwrapped.
+ *  @param  [out]  err_info    Extended error info
+ *
+ *  @return  0 if successful, error code otherwise.
+ */
+uint32_t tme_hwkm_master_unwrapkey(uint32_t key_id,
+		uint32_t kwkey_id,
+		uint32_t cred_slot,
+		struct tme_wrapped_key *wrapped,
+		struct tme_ext_err_info *err_info);
+
+/**
+ *  Import a plaintext key from outside the TME and store in the Key Table.
+ *
+ *  @param  [in]   key_id      The ID of the key to be imported.
+ *  @param  [in]   policy      The Key Policy to be associated with the key.
+ *  @param  [in]   keyMaterial The plaintext key material.
+ *  @param  [in]   cred_slot   Credential slot to which this key will be bound.
+ *  @param  [out]  err_info    Extended error info
+ *
+ *  @return  0 if successful, error code otherwise.
+ */
+uint32_t tme_hwkm_master_importkey(uint32_t key_id,
+		struct tme_key_policy *policy,
+		struct tme_plaintext_key *key_material,
+		uint32_t cred_slot,
+		struct tme_ext_err_info *err_info);
+
+/**
+ *  Broadcast Transport Key to HWKM slaves.
+ *
+ *  @param  [out]  err_info    Extended error info
+ *
+ *  @return  0 if successful, error code otherwise.
+ */
+uint32_t tme_hwkm_master_broadcast_transportkey(
+		struct tme_ext_err_info *err_info);
+
+#endif /* _TME_HWKM_MASTER_H_ */
+

+ 462 - 0
linux/tme_hwkm_master_defs.h

@@ -0,0 +1,462 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+#ifndef _TME_HWKM_MASTER_DEFS_H_
+#define _TME_HWKM_MASTER_DEFS_H_
+
+#include <linux/types.h>
+
+#define UINT32_C(x)  (x ## U)
+
+/**
+ * Key ID
+ */
+/* L1 Key IDs that are Key Table slot numbers */
+/**< CUS, 512 bits, in fuses */
+#define TME_KID_CHIP_UNIQUE_SEED 8
+/**< CRBK, 512 bits, in fuses */
+#define TME_KID_CHIP_RAND_BASE   9
+/**< L1 Key derived from L0 slot numbers 0-3 or 4-7 */
+#define TME_KID_CHIP_FAM_L1      10
+
+/* Transport Key ID */
+#define TME_KID_TP               11/**< 528 bits, retained */
+
+/**
+ * KeyPolicy
+ */
+/** Key Policy: 64-bit integer with bit encoded values */
+struct tme_key_policy {
+	uint32_t low;
+	uint32_t high;
+} __packed;
+
+#define TME_KPHALFBITS                32
+
+#define TME_KPCOMBINE(lo32, hi32) (((uint64_t)(lo32)) | \
+		(((uint64_t)(hi32)) << TME_KPHALFBITS))
+
+/**
+ * Fields in Key Policy low word
+ */
+
+/** Key Type: Fundamental crypto algorithm groups */
+/**< Position of Key Type bits */
+#define TME_KT_Shift          0
+/**< Mask for Key Type bits */
+#define TME_KT_Mask           (UINT32_C(0x07) << TME_KT_Shift)
+/**< Symmetric algorithms */
+#define TME_KT_Symmetric      (UINT32_C(0x00) << TME_KT_Shift)
+/**< Asymmetric algorithms: ECC */
+#define TME_KT_Asymmetric_ECC (UINT32_C(0x01) << TME_KT_Shift)
+/**< Asymmetric algorithms: RSA */
+#define TME_KT_Asymmetric_RSA (UINT32_C(0x05) << TME_KT_Shift)
+
+/** Key Length */
+/**< Position of Key Length bits */
+#define TME_KL_Shift 3
+/**< Mask for Key Length bits */
+#define TME_KL_Mask  (UINT32_C(0x0F) << TME_KL_Shift)
+/**< 64 bits   - AES/2TDES */
+#define TME_KL_64    (UINT32_C(0x00) << TME_KL_Shift)
+/**< 128 bits  - AES/2TDES */
+#define TME_KL_128   (UINT32_C(0x01) << TME_KL_Shift)
+/**< 192 bits  - AES/3TDES */
+#define TME_KL_192   (UINT32_C(0x02) << TME_KL_Shift)
+/**< 224 bits  - ECDSA */
+#define TME_KL_224   (UINT32_C(0x03) << TME_KL_Shift)
+/**< 256 bits  - ECDSA/AES */
+#define TME_KL_256   (UINT32_C(0x04) << TME_KL_Shift)
+/**< 384 bits  - ECDSA */
+#define TME_KL_384   (UINT32_C(0x05) << TME_KL_Shift)
+/**< 448 bits  - ECDSA */
+#define TME_KL_448   (UINT32_C(0x06) << TME_KL_Shift)
+/**< 512 bits  - ECDSA/HMAC/KDF/AES-SIV/AES-XTS */
+#define TME_KL_512   (UINT32_C(0x07) << TME_KL_Shift)
+/**< 521 bits  - ECDSA/HMAC/KDF */
+#define TME_KL_521   (UINT32_C(0x08) << TME_KL_Shift)
+/**< 2048 bits - RSA */
+#define TME_KL_2048  (UINT32_C(0x09) << TME_KL_Shift)
+/**< 3072 bits - RSA */
+#define TME_KL_3072  (UINT32_C(0x0A) << TME_KL_Shift)
+/**< 4096 bits - RSA */
+#define TME_KL_4096  (UINT32_C(0x0B) << TME_KL_Shift)
+
+/**
+ * Key Profile: Only applicable at present
+ * if Key Type is #TME_KT_Symmetric
+ */
+/**< Position of Key Profile bits */
+#define TME_KP_Shift         7
+/**< Mask for Key Class bits */
+#define TME_KP_Mask          (UINT32_C(0x07) << TME_KP_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KP_Generic       (UINT32_C(0x00) << TME_KP_Shift)
+/**< If Key Type is #TME_KT_Symmetric (aka KDK) */
+#define TME_KP_KeyDerivation (UINT32_C(0x01) << TME_KP_Shift)
+/**< If Key Type is #TME_KT_Symmetric (aka KWK) */
+#define TME_KP_KWK_STORAGE   (UINT32_C(0x02) << TME_KP_Shift)
+/**< If Key Type is #TME_KT_Symmetric (aka KSK) */
+#define TME_KP_KWK_SESSION   (UINT32_C(0x03) << TME_KP_Shift)
+/**< If Key Type is #TME_KT_Symmetric (aka TPK) */
+#define TME_KP_KWK_TRANSPORT (UINT32_C(0x04) << TME_KP_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KP_KWK_XPORT     (UINT32_C(0x05) << TME_KP_Shift)
+/**< If Key Type is not #TME_KT_Symmetric */
+#define TME_KP_Unused        (UINT32_C(0x00) << TME_KP_Shift)
+
+/** Key Operation: Crypto operations permitted for a key */
+/**< Position of Key Operation bits */
+#define TME_KOP_Shift             10
+/**< Mask for Key Operation bits */
+#define TME_KOP_Mask              (UINT32_C(0x0F) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KOP_Encryption        (UINT32_C(0x01) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KOP_Decryption        (UINT32_C(0x02) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KOP_MAC               (UINT32_C(0x04) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KOP_NISTDerive        (UINT32_C(0x04) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KOP_HKDFExtract       (UINT32_C(0x08) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KOP_HKDFExpand        (UINT32_C(0x09) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Asymmetric_ECC */
+#define TME_KOP_ECDSASign         (UINT32_C(0x01) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Asymmetric_ECC */
+#define TME_KOP_ECDSAVerify       (UINT32_C(0x02) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Asymmetric_ECC */
+#define TME_KOP_ECDHSharedSecret  (UINT32_C(0x04) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Asymmetric_RSA */
+#define TME_KOP_RSAASign          (UINT32_C(0x01) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Asymmetric_RSA */
+#define TME_KOP_RSAAVerify        (UINT32_C(0x02) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Asymmetric_RSA */
+#define TME_KOP_RSAEnc            (UINT32_C(0x04) << TME_KOP_Shift)
+/**< If Key Type is #TME_KT_Asymmetric_RSA */
+#define TME_KOP_RSADec            (UINT32_C(0x08) << TME_KOP_Shift)
+
+/** Key Algorithm */
+/**< Position of Key Algorithm bits */
+#define TME_KAL_Shift             14
+/**< Mask for Key Algorithm bits */
+#define TME_KAL_Mask              (UINT32_C(0x3F) << TME_KAL_Shift)
+/**< If Key Type is #TME_KT_Symmetric */
+#define TME_KAL_AES128_ECB        (UINT32_C(0x00) << TME_KAL_Shift)
+#define TME_KAL_AES256_ECB        (UINT32_C(0x01) << TME_KAL_Shift)
+#define TME_KAL_DES_ECB           (UINT32_C(0x02) << TME_KAL_Shift)
+#define TME_KAL_TDES_ECB          (UINT32_C(0x03) << TME_KAL_Shift)
+#define TME_KAL_AES128_CBC        (UINT32_C(0x04) << TME_KAL_Shift)
+#define TME_KAL_AES256_CBC        (UINT32_C(0x05) << TME_KAL_Shift)
+#define TME_KAL_DES_CBC           (UINT32_C(0x06) << TME_KAL_Shift)
+#define TME_KAL_TDES_CBC          (UINT32_C(0x07) << TME_KAL_Shift)
+#define TME_KAL_AES128_CCM_TC     (UINT32_C(0x08) << TME_KAL_Shift)
+#define TME_KAL_AES128_CCM_NTC    (UINT32_C(0x09) << TME_KAL_Shift)
+#define TME_KAL_AES256_CCM_TC     (UINT32_C(0x0A) << TME_KAL_Shift)
+#define TME_KAL_AES256_CCM_NTC    (UINT32_C(0x0B) << TME_KAL_Shift)
+#define TME_KAL_AES256_SIV        (UINT32_C(0x0C) << TME_KAL_Shift)
+#define TME_KAL_AES128_CTR        (UINT32_C(0x0D) << TME_KAL_Shift)
+#define TME_KAL_AES256_CTR        (UINT32_C(0x0E) << TME_KAL_Shift)
+#define TME_KAL_AES128_XTS        (UINT32_C(0x0F) << TME_KAL_Shift)
+#define TME_KAL_AES256_XTS        (UINT32_C(0x10) << TME_KAL_Shift)
+#define TME_KAL_SHA1_HMAC         (UINT32_C(0x11) << TME_KAL_Shift)
+#define TME_KAL_SHA256_HMAC       (UINT32_C(0x12) << TME_KAL_Shift)
+#define TME_KAL_AES128_CMAC       (UINT32_C(0x13) << TME_KAL_Shift)
+#define TME_KAL_AES256_CMAC       (UINT32_C(0x14) << TME_KAL_Shift)
+#define TME_KAL_SHA384_HMAC       (UINT32_C(0x15) << TME_KAL_Shift)
+#define TME_KAL_SHA512_HMAC       (UINT32_C(0x16) << TME_KAL_Shift)
+#define TME_KAL_AES128_GCM        (UINT32_C(0x17) << TME_KAL_Shift)
+#define TME_KAL_AES256_GCM        (UINT32_C(0x18) << TME_KAL_Shift)
+#define TME_KAL_KASUMI            (UINT32_C(0x19) << TME_KAL_Shift)
+#define TME_KAL_SNOW3G            (UINT32_C(0x1A) << TME_KAL_Shift)
+#define TME_KAL_ZUC               (UINT32_C(0x1B) << TME_KAL_Shift)
+#define TME_KAL_PRINCE            (UINT32_C(0x1C) << TME_KAL_Shift)
+#define TME_KAL_SIPHASH           (UINT32_C(0x1D) << TME_KAL_Shift)
+#define TME_KAL_TDES_2KEY_CBC     (UINT32_C(0x1E) << TME_KAL_Shift)
+#define TME_KAL_TDES_2KEY_ECB     (UINT32_C(0x1F) << TME_KAL_Shift)
+#define TME_KAL_KDF_NIST          (UINT32_C(0x20) << TME_KAL_Shift)
+#define TME_KAL_KDF_HKDF          (UINT32_C(0x21) << TME_KAL_Shift)
+/**< If Key Type is #TME_KT_Asymmetric, Key Subtype is ECC */
+#define TME_KAL_ECC_ALGO_ECDSA    (UINT32_C(0x00) << TME_KAL_Shift)
+/**< If Key Type is #TME_KT_Asymmetric, Key Subtype is ECC */
+#define TME_KAL_ECC_ALGO_ECDH     (UINT32_C(0x01) << TME_KAL_Shift)
+/**< If Key Type is #TME_KT_Asymmetric, Key Subtype is ECC */
+#define TME_KAL_ECC_CURVE_NIST    (UINT32_C(0x00) << TME_KAL_Shift)
+/**< If Key Type is #TME_KT_Asymmetric, Key Subtype is ECC */
+#define TME_KAL_ECC_CURVE_BPOOL   (UINT32_C(0x08) << TME_KAL_Shift)
+/**< If Key Type is #TME_KT_Asymmetric, Key Subtype is RSA */
+#define TME_KAL_DSA               (UINT32_C(0x00) << TME_KAL_Shift)
+/**< If Key Type is #TME_KT_Asymmetric, Key Subtype is RSA */
+#define TME_KAL_DH                (UINT32_C(0x01) << TME_KAL_Shift)
+
+/** Key Security Level */
+/**< Position of Key Security Level bits */
+#define TME_KSL_Shift             20
+/**< Mask for Key Security Level bits */
+#define TME_KSL_Mask              (UINT32_C(0x03) << TME_KSL_Shift)
+/**< Software Key */
+#define TME_KSL_SWKey             (UINT32_C(0x00) << TME_KSL_Shift)
+/**< Hardware Managed Key */
+#define TME_KSL_HWManagedKey      (UINT32_C(0x01) << TME_KSL_Shift)
+/**< Hardware Key */
+#define TME_KSL_HWKey             (UINT32_C(0x02) << TME_KSL_Shift)
+
+/** Key Destination */
+/**< Position of Key Destination bits */
+#define TME_KD_Shift              22
+/**< Mask for Key Destination bits */
+#define TME_KD_Mask               (UINT32_C(0x0F) << TME_KD_Shift)
+/**< Master */
+#define TME_KD_TME_HW             (UINT32_C(0x01) << TME_KD_Shift)
+/**< ICE Slave */
+#define TME_KD_ICE                (UINT32_C(0x02) << TME_KD_Shift)
+/**< GPCE Slave */
+#define TME_KD_GPCE               (UINT32_C(0x04) << TME_KD_Shift)
+/**< Modem CE Slave */
+#define TME_KD_MDM_CE             (UINT32_C(0x08) << TME_KD_Shift)
+
+/** Key Owner */
+/**< Position of Key Owner bits */
+#define TME_KO_Shift              26
+/**< Mask for Key Owner bits */
+#define TME_KO_Mask               (UINT32_C(0x0F) << TME_KO_Shift)
+/**< TME Hardware */
+#define TME_KO_TME_HW             (UINT32_C(0x00) << TME_KO_Shift)
+/**< TME Firmware */
+#define TME_KO_TME_FW             (UINT32_C(0x01) << TME_KO_Shift)
+/**< TZ         (= APPS-S) */
+#define TME_KO_TZ                 (UINT32_C(0x02) << TME_KO_Shift)
+/**< HLOS / HYP (= APPS-NS) */
+#define TME_KO_HLOS_HYP           (UINT32_C(0x03) << TME_KO_Shift)
+/**< Modem */
+#define TME_KO_MDM                (UINT32_C(0x04) << TME_KO_Shift)
+/**< SPU */
+#define TME_KO_SPU                (UINT32_C(0x0F) << TME_KO_Shift)
+
+/** Key Lineage */
+/**< Position of Key Lineage bits */
+#define TME_KLI_Shift             30
+/**< Mask for Key Lineage bits */
+#define TME_KLI_Mask              (UINT32_C(0x03) << TME_KLI_Shift)
+/**< Not applicable */
+#define TME_KLI_NA                (UINT32_C(0x00) << TME_KLI_Shift)
+/**< Not provisioned, chip unique */
+#define TME_KLI_NP_CU             (UINT32_C(0x01) << TME_KLI_Shift)
+/**< Provisioned, not chip unique */
+#define TME_KLI_P_NCU             (UINT32_C(0x02) << TME_KLI_Shift)
+/**< Provisioned, chip unique */
+#define TME_KLI_P_CU              (UINT32_C(0x03) << TME_KLI_Shift)
+
+/**
+ * Fields in Key Policy high word *
+ */
+
+/** Reserved Bits, Group 1 */
+/**< Position of Reserved bits */
+#define TME_KR1_Shift             (32 - TME_KPHALFBITS)
+/**< Mask for Reserved bits */
+#define TME_KR1_Mask              (UINT32_C(0x01) << TME_KR1_Shift)
+
+/** Key Wrapping Constraints */
+/**< Position of Key Attribute bits */
+#define TME_KWC_Shift             (33 - TME_KPHALFBITS)
+/**< Mask for Key Attribute bits */
+#define TME_KWC_Mask              (UINT32_C(0x0F) << TME_KWC_Shift)
+/**< Key is wrappable with KWK_EXPORT */
+#define TME_KWC_Wrappable_KXP     (UINT32_C(0x01) << TME_KWC_Shift)
+/**< Key is wrappable with KWK_STORAGE */
+#define TME_KWC_Wrappable_KWK     (UINT32_C(0x02) << TME_KWC_Shift)
+/**< Key is wrappable with KWK_TRANSPORT */
+#define TME_KWC_Wrappable_KTP     (UINT32_C(0x04) << TME_KWC_Shift)
+/**< Key is wrappable with KWK_SESSION */
+#define TME_KWC_Wrappable_KSK     (UINT32_C(0x08) << TME_KWC_Shift)
+
+/** Throttling */
+/**< Position of Throttling bits */
+#define TME_KTH_Shift             (37 - TME_KPHALFBITS)
+/**< Mask for Throttling bits */
+#define TME_KTH_Mask              (UINT32_C(0x01) << TME_KTH_Shift)
+/**< Throttling enabled */
+#define TME_KTH_Enabled           (UINT32_C(0x01) << TME_KTH_Shift)
+
+/** Reserved Bits, Group 2 */
+/**< Position of Reserved bits */
+#define TME_KR2_Shift             (38 - TME_KPHALFBITS)
+/**< Mask for Reserved bits */
+#define TME_KR2_Mask              (UINT32_C(0x3F) << TME_KR2_Shift)
+
+/** Key Policy Version */
+/**< Position of Key Policy Version bits */
+#define TME_KPV_Shift             (44 - TME_KPHALFBITS)
+/**< Mask for Key Policy Version bits */
+#define TME_KPV_Mask              (UINT32_C(0x0F) << TME_KPV_Shift)
+/**< Mask for Key Policy Version bits */
+#define TME_KPV_Version           (UINT32_C(0x03) << TME_KPV_Shift)
+
+/** Key Authorised Users */
+/**< Position of Authorised User bits */
+#define TME_KAU_Shift             (48 - TME_KPHALFBITS)
+/**< Mask for Authorised User bits */
+#define TME_KAU_Mask              (UINT32_C(0xFF) << TME_KAU_Shift)
+/**< Key usable by TME Hardware */
+#define TME_KAU_TME_HW            (UINT32_C(0x01) << TME_KAU_Shift)
+/**< Key usable by TME Firmware */
+#define TME_KAU_TME_FW            (UINT32_C(0x02) << TME_KAU_Shift)
+/**< Key usable by TZ         (= APPS_S) */
+#define TME_KAU_TZ                (UINT32_C(0x04) << TME_KAU_Shift)
+/**< Key usable by HLOS / HYP (= APPS_NS) */
+#define TME_KAU_HLOS_HYP          (UINT32_C(0x08) << TME_KAU_Shift)
+/**< Key usable by Modem */
+#define TME_KAU_MDM               (UINT32_C(0x10) << TME_KAU_Shift)
+/**< Key usable by SPU */
+#define TME_KAU_SPU               (UINT32_C(0x20) << TME_KAU_Shift)
+/**< Key usable by all EEs */
+#define TME_KAU_ALL               TME_KAU_Mask
+
+/**
+ * Credentials for throttling
+ */
+#define TME_CRED_SLOT_ID_NONE     0  /**< No throttling */
+#define TME_CRED_SLOT_ID_1        1  /**< Credential slot 1 */
+#define TME_CRED_SLOT_ID_2        2  /**< Credential slot 2 */
+
+/**
+ * KDFSpec and associated structures
+ */
+/** Maximum context size that can be sent to the TME, in bytes */
+#define TME_KDF_SW_CONTEXT_BYTES_MAX  128
+#define TME_KDF_SALT_LABEL_BYTES_MAX   64
+
+/**
+ *  Security info to be appended to a KDF context by the Sequencer
+ *
+ *  These fields allow keys to be tied to specific devices, states,
+ *  OEMs, subsystems, etc.
+ *  Values are obtained by the Sequencer from hardware, such as
+ *  fuses or internal registers.
+ */
+#define TME_KSC_SOCTestSignState  0x00000001  /**<  (32 bits) */
+#define TME_KSC_SOCSecBootState   0x00000002  /**<   (8 bits) */
+#define TME_KSC_SOCDebugState     0x00000004  /**<   (8 bits) */
+#define TME_KSC_TMELifecycleState 0x00000008  /**<   (8 bits) */
+#define TME_KSC_BootStageOTP      0x00000010  /**<   (8 bits) */
+#define TME_KSC_SWContext         0x00000020  /**< (variable) */
+#define TME_KSC_ChildKeyPolicy    0x00000040  /**<  (64 bits) */
+#define TME_KSC_MixingKey         0x00000080  /**<  (key len) */
+#define TME_KSC_ChipUniqueID      0x00000100  /**<  (64 bits) */
+#define TME_KSC_ChipDeviceNumber  0x00000200  /**<  (32 bits) */
+#define TME_KSC_TMEPatchVer       0x00000400  /**< (512 bits) */
+#define TME_KSC_SOCPatchVer       0x00000800  /**< (512 bits) */
+#define TME_KSC_OEMID             0x00001000  /**<  (16 bits) */
+#define TME_KSC_OEMProductID      0x00002000  /**<  (16 bits) */
+#define TME_KSC_TMEImgSecVer      0x00004000  /**< (512 bits) */
+#define TME_KSC_SOCInitImgSecVer  0x00008000  /**< (512 bits) */
+#define TME_KSC_OEMMRCHash        0x00010000  /**< (512 bits) */
+#define TME_KSC_OEMProductSeed    0x00020000  /**< (128 bits) */
+#define TME_KSC_SeqPatchVer       0x00040000  /**< (512 bits) */
+#define TME_KSC_HWMeasurement1    0x00080000  /**< (512 bits) */
+#define TME_KSC_HWMeasurement2    0x00100000  /**< (512 bits) */
+#define TME_KSC_Reserved          0xFFE00000  /**< RFU */
+
+/** KDF Specification: encompasses both HKDF and NIST KDF algorithms */
+struct tme_kdf_spec {
+	/* Info common to HKDF and NIST algorithms */
+	/**< @c TME_KAL_KDF_HKDF or @c TME_KAL_KDF_NIST */
+	uint32_t                kdfalgo;
+	/**< IKM for HKDF; IKS for NIST */
+	uint32_t                inputkey;
+	/**< If @c TME_KSC_MixingKey set in Security Context */
+	uint32_t                mixkey;
+	/**< If deriving a L3 key */
+	uint32_t                l2key;
+	/**< Derived key policy */
+	struct tme_key_policy   policy;
+	/**< Software provided context */
+	uint8_t                 swcontext[TME_KDF_SW_CONTEXT_BYTES_MAX];
+	/**< Length of @c swContext in bytes */
+	uint32_t                swcontextLength;
+	/**< Info to be appended to @c swContext */
+	uint32_t                security_context;
+	/**< Salt for HKDF; Label for NIST */
+	uint8_t                 salt_label[TME_KDF_SALT_LABEL_BYTES_MAX];
+	/**< Length of @c saltLabel in bytes */
+	uint32_t                salt_labelLength;
+	/* Additional info specific to HKDF: kdfAlgo == @c KAL_KDF_HKDF */
+	/**< PRF Digest algorithm: @c KAL_SHA256_HMAC or @c KAL_SHA512_HMAC */
+	uint32_t                prf_digest_algo;
+} __packed;
+
+/**
+ * WrappedKey and associated structures
+ */
+/* Maximum wrapped key context size, in bytes */
+/**< Cipher Text 68B, MAC 16B, KeyPolicy 8B, Nonce 8B */
+#define TME_WK_CONTEXT_BYTES_MAX  100
+struct tme_wrapped_key {
+	/**< Wrapped key context */
+	uint8_t   key[TME_WK_CONTEXT_BYTES_MAX];
+	/**< Length of @c key in bytes*/
+	uint32_t  length;
+} __packed;
+
+/**
+ * Plain text Key and associated structures
+ */
+/* Maximum plain text key size, in bytes */
+#define TME_PT_KEY_BYTES_MAX  68
+
+/**
+ * Key format for intrinsically word aligned key
+ * lengths like 128/256/384/512... bits.
+ *
+ * Example: 256-bit key integer representation,
+ * Key = 0xK31 K30 K29.......K0
+ * Byte array, key[] = {0xK31, 0xK30, 0xK29, ...., 0xK0}
+ *
+ *
+ * Key format for non-word aligned key lengths like 521 bits.
+ * The key length is rounded off to next word ie, 544 bits.
+ *
+ * Example: 521-bit key, Key = 0xK65 K64 K63.......K2 K1 K0
+ * [bits 1-7 of K0 is expected to be zeros]
+ * 544 bit integer representation, Key = 0xK65 K64 K63.......K2 K1 K0 00 00
+ * Byte array, key[] = {0xK65, 0xK64, 0xK63, ...., 0xK2, 0xK1, 0xK0, 0x00, 0x00}
+ *
+ */
+struct tme_plaintext_key {
+	/**< Plain text key */
+	uint8_t   key[TME_PT_KEY_BYTES_MAX];
+	/**< Length of @c key in bytes */
+	uint32_t  length;
+} __packed;
+
+/**
+ * Extended Error Information structure
+ */
+struct tme_ext_err_info {
+	/* TME FW */
+	/**< TME FW Response status. */
+	uint32_t  tme_err_status;
+
+	/* SEQ FW */
+	/**< Contents of CSR_CMD_ERROR_STATUS */
+	uint32_t  seq_err_status;
+
+	/* SEQ HW Key Policy */
+	/**< CRYPTO_ENGINE_CRYPTO_KEY_POLICY_ERROR_STATUS0 */
+	uint32_t  seq_kp_err_status0;
+	/**< CRYPTO_ENGINE_CRYPTO_KEY_POLICY_ERROR_STATUS1 */
+	uint32_t  seq_kp_err_status1;
+
+	/**
+	 * Debug information: log/print this information
+	 * if any of the above fields is non-zero
+	 */
+	/**< Contents of CSR_CMD_RESPONSE_STATUS */
+	uint32_t  seq_rsp_status;
+} __packed;
+
+#endif /* _TME_HWKM_MASTER_DEFS_H_ */
+

+ 1 - 0
securemsm_kernel_product_board.mk

@@ -5,6 +5,7 @@ PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/smcinvoke_dlkm.ko \
   $(KERNEL_MODULES_OUT)/qce50_dlkm.ko \
   $(KERNEL_MODULES_OUT)/qcrypto-msm_dlkm.ko \
   $(KERNEL_MODULES_OUT)/hdcp_qseecom_dlkm.ko \
+  $(KERNEL_MODULES_OUT)/tmecom-intf_dlkm.ko \
 
 
 

+ 1 - 0
securemsm_kernel_vendor_board.mk

@@ -4,4 +4,5 @@ BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/smcinvoke_dlkm.ko \
       $(KERNEL_MODULES_OUT)/qcrypto-msm_dlkm.ko \
       $(KERNEL_MODULES_OUT)/qce50_dlkm.ko \
       $(KERNEL_MODULES_OUT)/hdcp_qseecom_dlkm.ko \
+      $(KERNEL_MODULES_OUT)/tmecom-intf_dlkm.ko \
 

+ 404 - 0
tmecom/tme_hwkm_master.c

@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "tme_hwkm_master_intf.h"
+#include "tmecom.h"
+
+#define TME_MSG_CBOR_TAG_HWKM   (303)
+
+#define TME_CLEAR_KEY_CBOR_TAG     0x482F01D9 /* _be32 0xD9012F48 */
+#define TME_DERIVE_KEY_CBOR_TAG    0x582F01D9 /* _be32 0xD9012F58 */
+#define TME_GENERATE_KEY_CBOR_TAG  0x542F01D9 /* _be32 0xD9012F54 */
+#define TME_IMPORT_KEY_CBOR_TAG    0x582F01D9 /* _be32 0xD9012F58 */
+#define TME_WRAP_KEY_CBOR_TAG      0x502F01D9 /* _be32 0xD9012F50 */
+#define TME_UNWRAP_KEY_CBOR_TAG    0x582F01D9 /* _be32 0xD9012F58 */
+#define TME_BORADCAST_KEY_CBOR_TAG 0x442F01D9 /* _be32 0xD9012F44 */
+
+/*
+ * Static alloc for wrapped key
+ * Protected by tmecom dev mutex
+ */
+static struct wrap_key_resp gwrpk_response = {0};
+
+static inline uint32_t update_ext_err(
+		struct tme_ext_err_info *err_info,
+		struct tme_response_sts *result)
+{
+	bool is_failure = false;
+
+	err_info->tme_err_status     = result->tme_err_status;
+	err_info->seq_err_status     = result->seq_err_status;
+	err_info->seq_kp_err_status0 = result->seq_kp_err_status0;
+	err_info->seq_kp_err_status1 = result->seq_kp_err_status1;
+	err_info->seq_rsp_status     = result->seq_rsp_status;
+
+	is_failure = err_info->tme_err_status ||
+		err_info->seq_err_status ||
+		err_info->seq_kp_err_status0 ||
+		err_info->seq_kp_err_status1;
+
+	print_hex_dump_bytes("err_info decoded bytes : ",
+			DUMP_PREFIX_ADDRESS, (void *)err_info,
+			sizeof(*err_info));
+
+	return  is_failure ? 1 : 0;
+}
+
+uint32_t tme_hwkm_master_clearkey(uint32_t key_id,
+		struct tme_ext_err_info *err_info)
+{
+	struct clear_key_req *request = NULL;
+	struct tme_response_sts *response = NULL;
+	uint32_t ret = 0;
+	size_t response_len = sizeof(*response);
+
+	if (!err_info)
+		return -EINVAL;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	response = kzalloc(response_len, GFP_KERNEL);
+
+	if (!request || !response) {
+		ret = -ENOMEM;
+		goto err_exit;
+	}
+
+	request->cmd.code    = TME_HWKM_CMD_CLEAR_KEY;
+	request->key_id      = key_id;
+	request->cbor_header = TME_CLEAR_KEY_CBOR_TAG;
+
+	ret = tmecom_process_request(request, sizeof(*request), response,
+			&response_len);
+
+	if (ret != 0) {
+		pr_err("HWKM clear key request failed for %d\n", key_id);
+		goto err_exit;
+	}
+
+	if (response_len != sizeof(*response)) {
+		pr_err("HWKM response failed with invalid length: %u, %u\n",
+				response_len, sizeof(response));
+		ret = -EBADMSG;
+		goto err_exit;
+	}
+
+	ret = update_ext_err(err_info, response);
+
+err_exit:
+	kfree(request);
+	kfree(response);
+	return ret;
+}
+EXPORT_SYMBOL(tme_hwkm_master_clearkey);
+
+uint32_t tme_hwkm_master_generatekey(uint32_t key_id,
+		struct tme_key_policy *policy,
+		uint32_t cred_slot,
+		struct tme_ext_err_info *err_info)
+{
+	struct gen_key_req *request = NULL;
+	struct tme_response_sts *response = NULL;
+	uint32_t ret = 0;
+	size_t response_len = sizeof(*response);
+
+	if (!err_info || !policy)
+		return -EINVAL;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	response = kzalloc(response_len, GFP_KERNEL);
+
+	if (!request || !response) {
+		ret = -ENOMEM;
+		goto err_exit;
+	}
+
+	request->cmd.code    = TME_HWKM_CMD_GENERATE_KEY;
+	request->key_id      = key_id;
+	request->cred_slot   = cred_slot;
+	request->cbor_header = TME_GENERATE_KEY_CBOR_TAG;
+	memcpy(&request->key_policy, policy, sizeof(*policy));
+
+	ret = tmecom_process_request(request, sizeof(*request), response,
+			&response_len);
+
+	if (ret != 0) {
+		pr_err("HWKM generate key request failed for %d\n", key_id);
+		goto err_exit;
+	}
+
+	if (response_len != sizeof(*response)) {
+		pr_err("HWKM response failed with invalid length: %u, %u\n",
+				response_len, sizeof(response));
+		ret = -EBADMSG;
+		goto err_exit;
+	}
+
+	ret = update_ext_err(err_info, response);
+
+err_exit:
+	kfree(request);
+	kfree(response);
+	return ret;
+}
+EXPORT_SYMBOL(tme_hwkm_master_generatekey);
+
+uint32_t tme_hwkm_master_derivekey(uint32_t key_id,
+		struct tme_kdf_spec *kdf_info,
+		uint32_t cred_slot,
+		struct tme_ext_err_info *err_info)
+{
+	struct derive_key_req *request = NULL;
+	struct tme_response_sts *response = NULL;
+	uint32_t ret = 0;
+	size_t response_len = sizeof(*response);
+
+	if (!kdf_info || !err_info)
+		return -EINVAL;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	response = kzalloc(response_len, GFP_KERNEL);
+
+	if (!request || !response) {
+		ret = -ENOMEM;
+		goto err_exit;
+	}
+
+	request->cmd.code    = TME_HWKM_CMD_DERIVE_KEY;
+	request->key_id      = key_id;
+	request->cred_slot   = cred_slot;
+	request->cbor_header = TME_DERIVE_KEY_CBOR_TAG;
+	memcpy(&request->kdf_info, kdf_info, sizeof(*kdf_info));
+
+	ret = tmecom_process_request(request, sizeof(*request), response,
+			&response_len);
+
+	if (ret != 0) {
+		pr_err("HWKM derive key request failed for %d\n", key_id);
+		goto err_exit;
+	}
+
+	if (response_len != sizeof(*response)) {
+		pr_err("HWKM response failed with invalid length: %u, %u\n",
+				response_len, sizeof(response));
+		ret = -EBADMSG;
+		goto err_exit;
+	}
+
+	ret = update_ext_err(err_info, response);
+
+err_exit:
+	kfree(request);
+	kfree(response);
+	return ret;
+}
+EXPORT_SYMBOL(tme_hwkm_master_derivekey);
+
+uint32_t tme_hwkm_master_wrapkey(uint32_t key_id,
+		uint32_t targetkey_id,
+		uint32_t cred_slot,
+		struct tme_wrapped_key *wrapped,
+		struct tme_ext_err_info *err_info)
+{
+	struct wrap_key_req *request = NULL;
+	struct wrap_key_resp *wrpk_response = NULL;
+	uint32_t ret = 0;
+	size_t response_len = sizeof(*wrpk_response);
+
+	if (!wrapped || !err_info)
+		return -EINVAL;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	wrpk_response = &gwrpk_response;
+
+	if (!request)
+		return -ENOMEM;
+
+	request->cmd.code       = TME_HWKM_CMD_WRAP_KEY;
+	request->key_id         = key_id;
+	request->target_key_id  = targetkey_id;
+	request->cbor_header    = TME_WRAP_KEY_CBOR_TAG;
+
+	ret = tmecom_process_request(request, sizeof(*request), wrpk_response,
+			&response_len);
+
+	if (ret != 0) {
+		pr_err("HWKM wrap key request failed for %d\n", key_id);
+		goto err_exit;
+	}
+
+	if (response_len != sizeof(*wrpk_response)) {
+		pr_err("HWKM response failed with invalid length: %u, %u\n",
+				response_len, sizeof(wrpk_response));
+		ret = -EBADMSG;
+		goto err_exit;
+	}
+
+	ret = update_ext_err(err_info, &wrpk_response->status);
+
+	if (!ret)
+		memcpy(wrapped, &wrpk_response->wrapped_key, sizeof(*wrapped));
+
+err_exit:
+	kfree(request);
+	return ret;
+}
+EXPORT_SYMBOL(tme_hwkm_master_wrapkey);
+
+uint32_t tme_hwkm_master_unwrapkey(uint32_t key_id,
+		uint32_t kwkey_id,
+		uint32_t cred_slot,
+		struct tme_wrapped_key *wrapped,
+		struct tme_ext_err_info *err_info)
+{
+	struct unwrap_key_req *request = NULL;
+	struct tme_response_sts *response = NULL;
+	uint32_t ret = 0;
+	size_t response_len = sizeof(*response);
+
+	if (!wrapped || !err_info)
+		return -EINVAL;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	response = kzalloc(response_len, GFP_KERNEL);
+
+	if (!request || !response) {
+		ret = -ENOMEM;
+		goto err_exit;
+	}
+
+	request->cmd.code    = TME_HWKM_CMD_UNWRAP_KEY;
+	request->key_id      = key_id;
+	request->kw_key_id   = kwkey_id;
+	request->cbor_header = TME_UNWRAP_KEY_CBOR_TAG;
+	memcpy(&request->wrapped, wrapped, sizeof(*wrapped));
+
+	ret = tmecom_process_request(request, sizeof(*request), response,
+			&response_len);
+
+	if (ret != 0) {
+		pr_err("HWKM unwrap key request failed for %d\n", key_id);
+		goto err_exit;
+	}
+
+	if (response_len != sizeof(*response)) {
+		pr_err("HWKM response failed with invalid length: %u, %u\n",
+				response_len, sizeof(response));
+		ret = -EBADMSG;
+		goto err_exit;
+	}
+
+	ret = update_ext_err(err_info, response);
+
+err_exit:
+	kfree(request);
+	kfree(response);
+	return ret;
+}
+EXPORT_SYMBOL(tme_hwkm_master_unwrapkey);
+
+uint32_t tme_hwkm_master_importkey(uint32_t key_id,
+		struct tme_key_policy *policy,
+		struct tme_plaintext_key *key_material,
+		uint32_t cred_slot,
+		struct tme_ext_err_info *err_info)
+{
+	struct import_key_req *request = NULL;
+	struct tme_response_sts *response = NULL;
+	uint32_t ret = 0;
+	size_t response_len = sizeof(*response);
+
+	if (!key_material || !err_info || !policy)
+		return -EINVAL;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	response = kzalloc(response_len, GFP_KERNEL);
+
+	if (!request || !response) {
+		ret = -ENOMEM;
+		goto err_exit;
+	}
+
+	request->cmd.code     = TME_HWKM_CMD_IMPORT_KEY;
+	request->key_id       = key_id;
+	request->cred_slot    = cred_slot;
+	request->cbor_header  = TME_IMPORT_KEY_CBOR_TAG;
+	memcpy(&request->key_policy, policy, sizeof(*policy));
+	memcpy(&request->key_material, key_material, sizeof(*key_material));
+
+	ret = tmecom_process_request(request, sizeof(*request), response,
+			&response_len);
+
+	if (ret != 0) {
+		pr_err("HWKM import key request failed for %d\n", key_id);
+		goto err_exit;
+	}
+
+	if (response_len != sizeof(*response)) {
+		pr_err("HWKM response failed with invalid length: %u, %u\n",
+				response_len, sizeof(response));
+		ret = -EBADMSG;
+		goto err_exit;
+	}
+
+	ret = update_ext_err(err_info, response);
+
+err_exit:
+	kfree(request);
+	kfree(response);
+	return ret;
+}
+EXPORT_SYMBOL(tme_hwkm_master_importkey);
+
+uint32_t tme_hwkm_master_broadcast_transportkey(
+		struct tme_ext_err_info *err_info)
+{
+	struct broadcast_tpkey_req *request = NULL;
+	struct tme_response_sts *response = NULL;
+	uint32_t ret = 0;
+	size_t response_len = sizeof(*response);
+
+	if (!err_info)
+		return -EINVAL;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	response = kzalloc(response_len, GFP_KERNEL);
+
+	if (!request || !response) {
+		ret = -ENOMEM;
+		goto err_exit;
+	}
+
+	request->cbor_header = TME_BORADCAST_KEY_CBOR_TAG;
+	request->cmd.code    = TME_HWKM_CMD_BROADCAST_TP_KEY;
+
+	ret = tmecom_process_request(request, sizeof(*request), response,
+			&response_len);
+
+	if (ret != 0) {
+		pr_err("HWKM broadcast TP key request failed\n");
+		goto err_exit;
+	}
+
+	if (response_len != sizeof(*response)) {
+		pr_err("HWKM response failed with invalid length: %u, %u\n",
+				response_len, sizeof(response));
+		ret = -EBADMSG;
+		goto err_exit;
+	}
+
+	ret = update_ext_err(err_info, response);
+
+err_exit:
+	kfree(request);
+	kfree(response);
+	return ret;
+}
+EXPORT_SYMBOL(tme_hwkm_master_broadcast_transportkey);
+

+ 132 - 0
tmecom/tme_hwkm_master_intf.h

@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+#ifndef _TME_HWKM_MASTER_INTERFACE_H_
+#define _TME_HWKM_MASTER_INTERFACE_H_
+
+#include <linux/tme_hwkm_master_defs.h>
+
+/**
+ * HWKM Master command IDs
+ */
+enum tme_hwkm_cmd {
+	TME_HWKM_CMD_CLEAR_KEY        = 0,  /**< Clear Key */
+	TME_HWKM_CMD_GENERATE_KEY     = 1,  /**< Generate Key */
+	TME_HWKM_CMD_DERIVE_KEY       = 2,  /**< Derive Key, NIST or HKDF */
+	TME_HWKM_CMD_WRAP_KEY         = 3,  /**< Wrap Key */
+	TME_HWKM_CMD_UNWRAP_KEY       = 4,  /**< Unwrap Key */
+	TME_HWKM_CMD_IMPORT_KEY       = 5,  /**< Import Key */
+	TME_HWKM_CMD_BROADCAST_TP_KEY = 6,  /**< Broadcast Transport Key */
+	TMW_HWKM_CMD_INVALID          = 7,  /**< Invalid cmd */
+};
+
+/**
+ * Opcode and response structures
+ */
+
+/* Values as per TME_HWKM_CMD_* */
+struct tme_hwkm_master_cmd {
+	uint32_t  code;
+} __packed;
+
+
+struct tme_response_sts {
+	/* TME FW */
+	uint32_t  tme_err_status;     /**< TME FW Response status. */
+
+	/* SEQ FW */
+	uint32_t  seq_err_status;     /**< Contents of CSR_CMD_ERROR_STATUS */
+
+	/* SEQ HW Key Policy */
+	uint32_t  seq_kp_err_status0; /**< CRYPTO_ENGINE_CRYPTO_KEY_POLICY_ERROR_STATUS0 */
+	uint32_t  seq_kp_err_status1; /**< CRYPTO_ENGINE_CRYPTO_KEY_POLICY_ERROR_STATUS1 */
+
+	/* Debug information: log/print this information if any of the above fields is non-zero */
+	uint32_t  seq_rsp_status;     /**< Contents of CSR_CMD_RESPONSE_STATUS */
+
+} __packed;
+
+/**
+ * Clear Key ID structures
+ */
+struct clear_key_req {
+	uint32_t cbor_header;             /**< CBOR encoded tag */
+	struct tme_hwkm_master_cmd  cmd;  /**< @c TME_HWKM_CMD_CLEAR_KEY */
+	uint32_t  key_id;                 /**< The ID of the key to clear.*/
+} __packed;
+
+/**
+ * Generate Key ID structures
+ */
+struct gen_key_req {
+	uint32_t cbor_header;             /**< CBOR encoded tag */
+	struct tme_hwkm_master_cmd  cmd;  /**< @c TME_HWKM_CMD_GENERATE_KEY */
+	uint32_t  key_id;                 /**< The ID of the key to be generated. */
+	struct tme_key_policy  key_policy;/**< The policy specifying the key to be generated. */
+	uint32_t  cred_slot;              /**< Credential slot to which this key will be bound. */
+} __packed;
+
+/**
+ * Derive Key ID structures
+ */
+struct derive_key_req {
+	uint32_t cbor_header;            /**< CBOR encoded tag */
+	struct tme_hwkm_master_cmd cmd;  /**< @c TME_HWKM_CMD_DERIVE_KEY */
+	uint32_t  key_id;                /**< The ID of the key to be derived. */
+	struct tme_kdf_spec  kdf_info;   /**< Specifies how the key is to be derived. */
+	uint32_t  cred_slot;             /**< Credential slot to which this key will be bound. */
+} __packed;
+
+/**
+ * Wrap Key ID structures
+ */
+struct wrap_key_req {
+	uint32_t cbor_header;           /**< CBOR encoded tag */
+	struct tme_hwkm_master_cmd  cmd;/**< @c TME_HWKM_CMD_WRAP_KEY */
+	uint32_t  key_id;               /**< The ID of the key to secure the target key. */
+	uint32_t  target_key_id;        /**< Denotes the key to be wrapped. */
+	uint32_t  cred_slot;            /**< Credential slot to which this key is bound. */
+} __packed;
+
+
+struct wrap_key_resp {
+	struct tme_response_sts status;      /**< Response status. */
+	struct tme_wrapped_key  wrapped_key; /**< The wrapped key. */
+} __packed;
+
+/**
+ * Unwrap Key ID structures
+ */
+struct unwrap_key_req {
+	uint32_t cbor_header;           /**< CBOR encoded tag */
+	struct tme_hwkm_master_cmd  cmd;/**< @c TME_HWKM_CMD_UNWRAP_KEY */
+	uint32_t  key_id;               /**< The ID of the key to be unwrapped. */
+	uint32_t  kw_key_id;            /**< The ID of the key to be used to unwrap the key. */
+	struct tme_wrapped_key wrapped; /**< The key to be unwrapped. */
+	uint32_t  cred_slot;            /**< Credential slot to which this key will be bound. */
+} __packed;
+
+/**
+ * Import Key ID structures
+ */
+struct import_key_req {
+	uint32_t cbor_header;                  /**< CBOR encoded tag */
+	struct tme_hwkm_master_cmd  cmd;       /**< @c TME_HWKM_CMD_IMPORT_KEY */
+	uint32_t  key_id;                      /**< The ID of the key to be imported. */
+	struct tme_key_policy  key_policy;/**< The Key Policy to be associated with the key. */
+	struct tme_plaintext_key  key_material;/**< The plain-text key material. */
+	uint32_t  cred_slot;              /**< Credential slot to which this key will be bound. */
+} __packed;
+
+/**
+ * Broadcast Transport Key structures
+ */
+struct broadcast_tpkey_req {
+	uint32_t cbor_header;           /**< CBOR encoded tag */
+	struct tme_hwkm_master_cmd  cmd;/**< @c TME_HWKM_CMD_BROADCAST_TP_KEY */
+} __packed;
+
+
+#endif /* _TME_HWKM_MASTER_INTERFACE_H_ */
+

+ 318 - 0
tmecom/tmecom.c

@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mailbox_client.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/platform_device.h>
+#include <linux/mailbox/qmp.h>
+#include <linux/uaccess.h>
+#include <linux/mailbox_controller.h>
+
+#include "tmecom.h"
+
+struct tmecom {
+	struct device *dev;
+	struct mbox_client cl;
+	struct mbox_chan *chan;
+	struct mutex lock;
+	struct qmp_pkt pkt;
+	wait_queue_head_t waitq;
+	void *txbuf;
+	bool rx_done;
+};
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+#include <linux/tme_hwkm_master_defs.h>
+#include <linux/tme_hwkm_master.h>
+
+char dpkt[MBOX_MAX_MSG_LEN + 1];
+struct dentry *debugfs_file;
+#endif /* CONFIG_DEBUG_FS */
+
+static struct tmecom *tmedev;
+
+/**
+ * tmecom_msg_hdr - Request/Response message header between HLOS and TME.
+ *
+ * This header is proceeding any request specific parameters.
+ * The transaction id is used to match request with response.
+ *
+ * Note: glink/QMP layer provides the rx/tx data size, so user payload size
+ * is calculated by reducing the header size.
+ */
+struct tmecom_msg_hdr {
+	unsigned int reserved; /* for future use */
+	unsigned int txnid;    /* transaction id */
+} __packed;
+#define TMECOM_TX_HDR_SIZE sizeof(struct tmecom_msg_hdr)
+#define CBOR_NUM_BYTES (sizeof(unsigned int))
+#define TMECOM_RX_HDR_SIZE (TMECOM_TX_HDR_SIZE + CBOR_NUM_BYTES)
+
+/*
+ * CBOR encode emulation
+ * Prepend tmecom_msg_hdr space
+ * CBOR tag is prepended in request
+ */
+static inline size_t tmecom_encode(struct tmecom *tdev, const void *reqbuf,
+		size_t size)
+{
+	unsigned int *msg = tdev->txbuf + TMECOM_TX_HDR_SIZE;
+	unsigned int *src = (unsigned int *)reqbuf;
+
+	memcpy(msg, src, size);
+	return (size + TMECOM_TX_HDR_SIZE);
+}
+
+/*
+ * CBOR decode emulation
+ * Strip tmecom_msg_hdr & CBOR tag
+ */
+static inline size_t tmecom_decode(struct tmecom *tdev, void *respbuf)
+{
+	unsigned int *msg = tdev->pkt.data + TMECOM_RX_HDR_SIZE;
+	unsigned int *rbuf = (unsigned int *)respbuf;
+
+	memcpy(rbuf, msg, (tdev->pkt.size - TMECOM_RX_HDR_SIZE));
+	return (tdev->pkt.size - TMECOM_RX_HDR_SIZE);
+}
+
+static bool tmecom_check_rx_done(struct tmecom *tdev)
+{
+	return  tdev->rx_done;
+}
+
+int tmecom_process_request(const void *reqbuf, size_t reqsize, void *respbuf,
+		size_t *respsize)
+{
+	struct tmecom *tdev = tmedev;
+	long time_left = 0;
+	int ret = 0;
+
+	/*
+	 * Check to handle if probe is not successful or not completed yet
+	 */
+	if (!tdev) {
+		pr_err("%s: tmecom dev is NULL\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!reqbuf || !reqsize || (reqsize > MBOX_MAX_MSG_LEN)) {
+		dev_err(tdev->dev, "invalid reqbuf or reqsize\n");
+		return -EINVAL;
+	}
+
+	if (!respbuf || !respsize || (*respsize > MBOX_MAX_MSG_LEN)) {
+		dev_err(tdev->dev, "invalid respbuf or respsize\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&tdev->lock);
+
+	tdev->rx_done = false;
+	tdev->pkt.size = tmecom_encode(tdev, reqbuf, reqsize);
+	/*
+	 * Controller expects a 4 byte aligned buffer
+	 */
+	tdev->pkt.size = (tdev->pkt.size + 0x3) & ~0x3;
+	tdev->pkt.data = tdev->txbuf;
+
+	pr_debug("tmecom encoded request size = %u\n", tdev->pkt.size);
+	print_hex_dump_bytes("tmecom sending bytes : ",
+			DUMP_PREFIX_ADDRESS, tdev->pkt.data, tdev->pkt.size);
+
+	if (mbox_send_message(tdev->chan, &tdev->pkt) < 0) {
+		dev_err(tdev->dev, "failed to send qmp message\n");
+		ret = -EAGAIN;
+		goto err_exit;
+	}
+
+	time_left = wait_event_interruptible_timeout(tdev->waitq,
+			tmecom_check_rx_done(tdev), tdev->cl.tx_tout);
+
+	if (!time_left) {
+		dev_err(tdev->dev, "request timed out\n");
+		ret = -ETIMEDOUT;
+		goto err_exit;
+	}
+
+	dev_info(tdev->dev, "response received\n");
+
+	pr_debug("tmecom received size = %u\n", tdev->pkt.size);
+	print_hex_dump_bytes("tmecom received bytes : ",
+			DUMP_PREFIX_ADDRESS, tdev->pkt.data, tdev->pkt.size);
+
+	*respsize = tmecom_decode(tdev, respbuf);
+
+	tdev->rx_done = false;
+	ret = 0;
+
+err_exit:
+	mutex_unlock(&tdev->lock);
+	return ret;
+}
+EXPORT_SYMBOL(tmecom_process_request);
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+static ssize_t tmecom_debugfs_write(struct file *file,
+		const char __user *userstr, size_t len, loff_t *pos)
+{
+	int ret = 0;
+	size_t rxlen = 0;
+	struct tme_ext_err_info *err_info = (struct tme_ext_err_info *)dpkt;
+
+
+	if (!len || (len > MBOX_MAX_MSG_LEN)) {
+		pr_err("invalid message length\n");
+		return -EINVAL;
+	}
+
+	memset(dpkt, 0, sizeof(*dpkt));
+	ret = copy_from_user(dpkt, userstr, len);
+	if (ret) {
+		pr_err("%s copy from user failed, ret=%d\n", __func__, ret);
+		return len;
+	}
+
+	tmecom_process_request(dpkt, len, dpkt, &rxlen);
+
+	print_hex_dump_bytes("tmecom decoded bytes : ",
+			DUMP_PREFIX_ADDRESS, dpkt, rxlen);
+
+	pr_debug("calling TME_HWKM_CMD_BROADCAST_TP_KEY api\n");
+	ret = tme_hwkm_master_broadcast_transportkey(err_info);
+
+	if (ret == 0)
+		pr_debug("%s successful\n", __func__);
+
+	return len;
+}
+
+static const struct file_operations tmecom_debugfs_ops = {
+	.open = simple_open,
+	.write = tmecom_debugfs_write,
+};
+#endif /* CONFIG_DEBUG_FS */
+
+static void tmecom_receive_message(struct mbox_client *client, void *message)
+{
+	struct tmecom *tdev = dev_get_drvdata(client->dev);
+	struct qmp_pkt *pkt = NULL;
+
+	pr_debug("%s entered\n", __func__);
+
+	if (!message) {
+		dev_err(tdev->dev, "spurious message received\n");
+		goto tmecom_receive_end;
+	}
+
+	if (tdev->rx_done) {
+		dev_err(tdev->dev, "tmecom response pending\n");
+		goto tmecom_receive_end;
+	}
+	pkt = (struct qmp_pkt *)message;
+	tdev->pkt.size = pkt->size;
+	tdev->pkt.data = pkt->data;
+	tdev->rx_done = true;
+tmecom_receive_end:
+	wake_up_interruptible(&tdev->waitq);
+}
+
+static int tmecom_probe(struct platform_device *pdev)
+{
+	struct tmecom *tdev;
+	const char *label;
+	char name[32];
+
+	tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
+	if (!tdev)
+		return -ENOMEM;
+
+	tdev->cl.dev = &pdev->dev;
+	tdev->cl.tx_block = true;
+	tdev->cl.tx_tout = 500;
+	tdev->cl.knows_txdone = false;
+	tdev->cl.rx_callback = tmecom_receive_message;
+
+	label = of_get_property(pdev->dev.of_node, "mbox-names", NULL);
+	if (!label)
+		return -EINVAL;
+	snprintf(name, 32, "%s_send_message", label);
+
+	tdev->chan = mbox_request_channel(&tdev->cl, 0);
+	if (IS_ERR(tdev->chan)) {
+		dev_err(&pdev->dev, "failed to get mbox channel\n");
+		return PTR_ERR(tdev->chan);
+	}
+
+	mutex_init(&tdev->lock);
+
+	if (tdev->chan) {
+		tdev->txbuf =
+			devm_kzalloc(&pdev->dev, MBOX_MAX_MSG_LEN, GFP_KERNEL);
+		if (!tdev->txbuf) {
+			dev_err(&pdev->dev, "message buffer alloc faile\n");
+			return -ENOMEM;
+		}
+	}
+
+	init_waitqueue_head(&tdev->waitq);
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+	debugfs_file = debugfs_create_file(name, 0220, NULL, tdev,
+			&tmecom_debugfs_ops);
+	if (!debugfs_file)
+		goto err;
+#endif /* CONFIG_DEBUG_FS */
+
+	tdev->rx_done = false;
+	tdev->dev = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, tdev);
+
+	tmedev = tdev;
+
+	dev_info(&pdev->dev, "tmecom probe success\n");
+	return 0;
+err:
+	mbox_free_channel(tdev->chan);
+	return -ENOMEM;
+}
+
+static int tmecom_remove(struct platform_device *pdev)
+{
+	struct tmecom *tdev = platform_get_drvdata(pdev);
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+	debugfs_remove(debugfs_file);
+#endif /* CONFIG_DEBUG_FS */
+
+	if (tdev->chan)
+		mbox_free_channel(tdev->chan);
+
+	dev_info(&pdev->dev, "tmecom remove success\n");
+	return 0;
+}
+
+static const struct of_device_id tmecom_match_tbl[] = {
+	{.compatible = "qcom,tmecom-qmp-client"},
+	{},
+};
+
+static struct platform_driver tmecom_driver = {
+	.probe = tmecom_probe,
+	.remove = tmecom_remove,
+	.driver = {
+		.name = "tmecom-qmp-client",
+		.suppress_bind_attrs = true,
+		.of_match_table = tmecom_match_tbl,
+	},
+};
+module_platform_driver(tmecom_driver);
+
+MODULE_DESCRIPTION("MSM TMECom QTI mailbox protocol client");
+MODULE_LICENSE("GPL v2");

+ 12 - 0
tmecom/tmecom.h

@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+#ifndef _TMECOM_H_
+#define _TMECOM_H_
+
+#define MBOX_MAX_MSG_LEN	1024
+
+int tmecom_process_request(const void *reqbuf, size_t reqsize, void *respbuf,
+		size_t *respsize);
+#endif  /*_TMECOM_H_ */