[PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands

Neeraj Sanjay Kale posted 11 patches 1 week, 6 days ago
There is a newer version of this series
[PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands
Posted by Neeraj Sanjay Kale 1 week, 6 days ago
This adds support for command encryption for sensitive HCI commands when
secure interface is enabled. This commands containt sensitive data such
as Link Key in plain text over UART lines.

AES-GCM encryption is used to encrypt sensitive commands using
encryption key and IV derived from traffic keys.

Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
 drivers/bluetooth/btnxpuart.c | 82 +++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 4b03b0321e82..452fff651d82 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -159,6 +159,7 @@
 #define NXP_FW_UUID_SIZE		16
 #define NXP_FW_ECDH_PUBKEY_SIZE		64
 #define NXP_FW_ECDSA_PUBKEY_SIZE	65
+#define NXP_MAX_ENCRYPT_CMD_LEN		256
 
 struct ps_data {
 	u8    target_ps_mode;	/* ps mode to be set */
@@ -226,6 +227,7 @@ struct btnxpuart_crypto {
 	u8 handshake_h2_hash[SHA256_DIGEST_SIZE];
 	u8 handshake_secret[SHA256_DIGEST_SIZE];
 	u8 master_secret[SHA256_DIGEST_SIZE];
+	u64 enc_seq_no;
 	struct completion completion;
 	int decrypt_result;
 	struct nxp_tls_traffic_keys keys;
@@ -2681,6 +2683,72 @@ static int nxp_authenticate_device(struct hci_dev *hdev)
 	return ret;
 }
 
+static void nxp_data_calc_nonce(u8 iv[GCM_AES_IV_SIZE], u64 seq_no,
+				u8 nonce[GCM_AES_IV_SIZE])
+{
+	u64 tmp;
+
+	/* XOR sequence number with IV to create unique nonce */
+	memcpy(&tmp, iv, sizeof(tmp));
+	tmp ^= seq_no;
+	memcpy(nonce, &tmp, sizeof(tmp));
+	memcpy(nonce + sizeof(tmp), iv + sizeof(tmp),
+	       GCM_AES_IV_SIZE - sizeof(tmp));
+}
+
+static struct sk_buff *nxp_crypto_encrypt_cmd(struct hci_dev *hdev,
+					      struct sk_buff *skb)
+{
+	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+	__le16 vendor_opcode = __cpu_to_le16(HCI_NXP_SHI_ENCRYPT);
+	u8 nonce[GCM_AES_IV_SIZE];
+	u8 tag[NXP_ENC_AUTH_TAG_SIZE];
+	u8 *enc_data;
+	u8 sub_opcode = 0x10;
+	int ret;
+	u32 plen, enc_data_len;
+	struct nxp_tls_traffic_keys *keys = &nxpdev->crypto.keys;
+
+	if (skb->len > NXP_MAX_ENCRYPT_CMD_LEN) {
+		bt_dev_err(hdev, "Invalid skb->len: %d", skb->len);
+		return skb;
+	}
+
+	nxp_data_calc_nonce(keys->h2d_iv, nxpdev->crypto.enc_seq_no, nonce);
+
+	enc_data_len = skb->len;
+	enc_data = kzalloc(skb->len, GFP_KERNEL);
+	if (!enc_data)
+		return skb;
+	memcpy(enc_data, skb->data, skb->len);
+
+	ret = nxp_aes_gcm_encrypt(hdev, enc_data, enc_data_len, tag,
+				  keys->h2d_key, nonce);
+	if (ret) {
+		kfree(enc_data);
+		return skb;
+	}
+
+	kfree_skb(skb);
+
+	plen = enc_data_len + NXP_ENC_AUTH_TAG_SIZE + 1;
+	skb = bt_skb_alloc(plen, GFP_ATOMIC);
+	if (!skb) {
+		kfree(enc_data);
+		return ERR_PTR(-ENOMEM);
+	}
+	hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
+	skb_put_data(skb, &vendor_opcode, 2);
+	skb_put_data(skb, &plen, 1);
+	skb_put_data(skb, &sub_opcode, 1);
+	skb_put_data(skb, enc_data, enc_data_len);
+	skb_put_data(skb, tag, NXP_ENC_AUTH_TAG_SIZE);
+
+	nxpdev->crypto.enc_seq_no++;
+	kfree(enc_data);
+	return skb;
+}
+
 /* NXP protocol */
 static int nxp_setup(struct hci_dev *hdev)
 {
@@ -2884,6 +2952,20 @@ static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb)
 				goto free_skb;
 			}
 			break;
+		case HCI_OP_LINK_KEY_REPLY:
+		case HCI_OP_LE_START_ENC:
+		case HCI_OP_LE_LTK_REPLY:
+		case HCI_OP_LE_ADD_TO_RESOLV_LIST:
+			if (nxpdev->secure_interface) {
+				/* Re-alloc skb and encrypt sensitive command
+				 * and payload. Command complete event
+				 * won't be encrypted.
+				 */
+				skb = nxp_crypto_encrypt_cmd(hdev, skb);
+				if (IS_ERR(skb))
+					return PTR_ERR(skb);
+			}
+			break;
 		default:
 			break;
 		}
-- 
2.43.0
Re: [PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands
Posted by kernel test robot 1 week, 4 days ago
Hi Neeraj,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bluetooth/master]
[also build test WARNING on bluetooth-next/master linus/master v6.18-rc6 next-20251119]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Neeraj-Sanjay-Kale/Bluetooth-btnxpuart-Add-firmware-metadata-parsing-for-secure-interface/20251118-223605
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git master
patch link:    https://lore.kernel.org/r/20251118142025.1982263-10-neeraj.sanjaykale%40nxp.com
patch subject: [PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands
config: x86_64-randconfig-103-20251119 (https://download.01.org/0day-ci/archive/20251120/202511201407.MPGCEuhy-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511201407.MPGCEuhy-lkp@intel.com/

cocci warnings: (new ones prefixed by >>)
>> drivers/bluetooth/btnxpuart.c:2720:12-19: WARNING opportunity for kmemdup

vim +2720 drivers/bluetooth/btnxpuart.c

  2698	
  2699	static struct sk_buff *nxp_crypto_encrypt_cmd(struct hci_dev *hdev,
  2700						      struct sk_buff *skb)
  2701	{
  2702		struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
  2703		__le16 vendor_opcode = __cpu_to_le16(HCI_NXP_SHI_ENCRYPT);
  2704		u8 nonce[GCM_AES_IV_SIZE];
  2705		u8 tag[NXP_ENC_AUTH_TAG_SIZE];
  2706		u8 *enc_data;
  2707		u8 sub_opcode = 0x10;
  2708		int ret;
  2709		u32 plen, enc_data_len;
  2710		struct nxp_tls_traffic_keys *keys = &nxpdev->crypto.keys;
  2711	
  2712		if (skb->len > NXP_MAX_ENCRYPT_CMD_LEN) {
  2713			bt_dev_err(hdev, "Invalid skb->len: %d", skb->len);
  2714			return skb;
  2715		}
  2716	
  2717		nxp_data_calc_nonce(keys->h2d_iv, nxpdev->crypto.enc_seq_no, nonce);
  2718	
  2719		enc_data_len = skb->len;
> 2720		enc_data = kzalloc(skb->len, GFP_KERNEL);
  2721		if (!enc_data)
  2722			return skb;
  2723		memcpy(enc_data, skb->data, skb->len);
  2724	
  2725		ret = nxp_aes_gcm_encrypt(hdev, enc_data, enc_data_len, tag,
  2726					  keys->h2d_key, nonce);
  2727		if (ret) {
  2728			kfree(enc_data);
  2729			return skb;
  2730		}
  2731	
  2732		kfree_skb(skb);
  2733	
  2734		plen = enc_data_len + NXP_ENC_AUTH_TAG_SIZE + 1;
  2735		skb = bt_skb_alloc(plen, GFP_ATOMIC);
  2736		if (!skb) {
  2737			kfree(enc_data);
  2738			return ERR_PTR(-ENOMEM);
  2739		}
  2740		hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
  2741		skb_put_data(skb, &vendor_opcode, 2);
  2742		skb_put_data(skb, &plen, 1);
  2743		skb_put_data(skb, &sub_opcode, 1);
  2744		skb_put_data(skb, enc_data, enc_data_len);
  2745		skb_put_data(skb, tag, NXP_ENC_AUTH_TAG_SIZE);
  2746	
  2747		nxpdev->crypto.enc_seq_no++;
  2748		kfree(enc_data);
  2749		return skb;
  2750	}
  2751	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki