* [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-18 15:07 ` Bluetooth: btnxpuart: Add secure interface support for NXP chipsets bluez.test.bot
2025-11-20 7:12 ` [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface kernel test robot
2025-11-18 14:20 ` [PATCH v1 02/11] Bluetooth: btnxpuart: Print FW version and enable chip specific features Neeraj Sanjay Kale
` (9 subsequent siblings)
10 siblings, 2 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This adds support for parsing firmware metadata TLVs to extract FW UUID and
ECDSA Public Key from FW metadata for secure interface authentication.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 133 ++++++++++++++++++++++++++++++++--
1 file changed, 125 insertions(+), 8 deletions(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 3b1e9224e965..3f94ca18a225 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -15,6 +15,7 @@
#include <linux/string.h>
#include <linux/crc8.h>
#include <linux/crc32.h>
+#include <linux/math.h>
#include <linux/string_helpers.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
@@ -134,6 +135,14 @@
#define BT_CTRL_WAKEUP_METHOD_EXT_BREAK 0x04
#define BT_CTRL_WAKEUP_METHOD_RTS 0x05
+/* FW Metadata */
+#define FW_METADATA_TLV_UUID 0x40
+#define FW_METADATA_TLV_ECDSA_KEY 0x50
+#define FW_METADATA_FLAG_BT 0x02
+
+#define NXP_FW_UUID_SIZE 16
+#define NXP_FW_ECDSA_PUBKEY_SIZE 65
+
struct ps_data {
u8 target_ps_mode; /* ps mode to be set */
u8 cur_psmode; /* current ps_mode */
@@ -180,6 +189,11 @@ enum bootloader_param_change {
changed
};
+struct btnxpuart_crypto {
+ u8 ecdsa_public[NXP_FW_ECDSA_PUBKEY_SIZE]; /* ECDSA public key, Authentication*/
+ u8 fw_uuid[NXP_FW_UUID_SIZE];
+};
+
struct btnxpuart_dev {
struct hci_dev *hdev;
struct serdev_device *serdev;
@@ -213,6 +227,7 @@ struct btnxpuart_dev {
struct btnxpuart_data *nxp_data;
struct reset_control *pdn;
struct hci_uart hu;
+ struct btnxpuart_crypto crypto;
};
#define NXP_V1_FW_REQ_PKT 0xa5
@@ -362,6 +377,26 @@ union nxp_set_bd_addr_payload {
u8 buf[8];
};
+/* FW Meta Data */
+struct fw_metadata_hdr {
+ __le32 cmd;
+ __le32 addr;
+ __le32 len;
+ __le32 crc;
+};
+
+struct fw_metadata_tail {
+ __le32 len;
+ u8 magic[8];
+ __le32 crc;
+};
+
+struct fw_metadata_tlv {
+ __le16 id;
+ __le16 flag;
+ __le32 len;
+};
+
static u8 crc8_table[CRC8_TABLE_SIZE];
/* Default configurations */
@@ -1190,6 +1225,85 @@ static void nxp_handle_fw_download_error(struct hci_dev *hdev, struct v3_data_re
}
}
+static u32 nxp_process_fw_metadata_tlv(struct hci_dev *hdev, char **payload)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct fw_metadata_tlv *tlv = (struct fw_metadata_tlv *)(*payload);
+ u32 ret = sizeof(*tlv) + le32_to_cpu(tlv->len);
+
+ /* Process only BT specific metadata TLVs */
+ if (!(le16_to_cpu(tlv->flag) & FW_METADATA_FLAG_BT))
+ goto align_and_return;
+
+ switch (le16_to_cpu(tlv->id)) {
+ case FW_METADATA_TLV_UUID:
+ if (le32_to_cpu(tlv->len) == NXP_FW_UUID_SIZE)
+ memcpy(nxpdev->crypto.fw_uuid,
+ *payload + sizeof(*tlv), NXP_FW_UUID_SIZE);
+ break;
+ case FW_METADATA_TLV_ECDSA_KEY:
+ if (le32_to_cpu(tlv->len) == NXP_FW_ECDSA_PUBKEY_SIZE)
+ memcpy(nxpdev->crypto.ecdsa_public,
+ *payload + sizeof(*tlv), NXP_FW_ECDSA_PUBKEY_SIZE);
+ break;
+ default:
+ bt_dev_err(hdev, "Unknown metadata TLV ID: 0x%x", le16_to_cpu(tlv->id));
+ break;
+ }
+
+align_and_return:
+ /* Align the pointer to 4 byte structure alignment */
+ ret = round_up(ret, 4);
+ *payload += ret;
+
+ return ret;
+}
+
+static void nxp_process_fw_meta_data(struct hci_dev *hdev, const struct firmware *fw)
+{
+ const char *metamagc = "metamagc";
+ struct fw_metadata_hdr *hdr = NULL;
+ struct fw_metadata_tail *tail;
+ u32 hdr_crc = 0;
+ u32 payload_crc = 0;
+ char *payload;
+ u32 payload_len = 0;
+
+ /* FW metadata should contain at least header and tail */
+ if (fw->size < (sizeof(*hdr) + sizeof(*tail)))
+ return;
+
+ tail = (struct fw_metadata_tail *)&fw->data[fw->size - sizeof(*tail)];
+
+ /* If tail doesn't contain the string "metamagc", this is invalid FW metadata */
+ if (memcmp(metamagc, tail->magic, strlen(metamagc)))
+ return;
+
+ hdr = (struct fw_metadata_hdr *)&fw->data[fw->size -
+ sizeof(*tail) -
+ tail->len];
+
+ /* If metadata header isn't cmd24, this is invalid FW metadata */
+ if (le32_to_cpu(hdr->cmd) != 24)
+ return;
+
+ /* If header CRC doesn't match, this is invalid FW metadata */
+ hdr_crc = crc32_be(0, (u8 *)hdr, offsetof(struct fw_metadata_hdr, crc));
+ if (hdr_crc != hdr->crc)
+ return;
+
+ /* If payload CRC doesn't match, this is invalid FW metadata */
+ payload = (u8 *)hdr + sizeof(*hdr);
+ payload_crc = crc32_be(0, payload, hdr->len - 4);
+ if (payload_crc != tail->crc)
+ return;
+
+ payload_len = hdr->len - sizeof(*tail);
+
+ while (payload_len > sizeof(struct fw_metadata_tlv))
+ payload_len -= nxp_process_fw_metadata_tlv(hdev, &payload);
+}
+
static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
@@ -1248,14 +1362,6 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
goto free_skb;
}
- if (req->len == 0) {
- bt_dev_info(hdev, "FW Download Complete: %zu bytes",
- nxpdev->fw->size);
- clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
- wake_up_interruptible(&nxpdev->fw_dnld_done_wait_q);
- goto free_skb;
- }
-
offset = __le32_to_cpu(req->offset);
if (offset < nxpdev->fw_v3_offset_correction) {
/* This scenario should ideally never occur. But if it ever does,
@@ -1267,6 +1373,17 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
}
nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
+
+ if (req->len == 0) {
+ if (nxpdev->fw_dnld_v3_offset < nxpdev->fw->size)
+ nxp_process_fw_meta_data(hdev, nxpdev->fw);
+ bt_dev_info(hdev, "FW Download Complete: %u bytes.",
+ req->offset - nxpdev->fw_v3_offset_correction);
+ clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
+ wake_up_interruptible(&nxpdev->fw_dnld_done_wait_q);
+ goto free_skb;
+ }
+
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
nxpdev->fw_dnld_v3_offset, len);
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* RE: Bluetooth: btnxpuart: Add secure interface support for NXP chipsets
2025-11-18 14:20 ` [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface Neeraj Sanjay Kale
@ 2025-11-18 15:07 ` bluez.test.bot
2025-11-20 7:12 ` [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface kernel test robot
1 sibling, 0 replies; 20+ messages in thread
From: bluez.test.bot @ 2025-11-18 15:07 UTC (permalink / raw)
To: linux-bluetooth, neeraj.sanjaykale
[-- Attachment #1: Type: text/plain, Size: 2377 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1024897
---Test result---
Test Summary:
CheckPatch PENDING 0.49 seconds
GitLint PENDING 0.38 seconds
SubjectPrefix PASS 2.65 seconds
BuildKernel PASS 26.39 seconds
CheckAllWarning PASS 28.81 seconds
CheckSparse PASS 32.64 seconds
BuildKernel32 PASS 25.57 seconds
TestRunnerSetup PASS 564.06 seconds
TestRunner_l2cap-tester PASS 24.55 seconds
TestRunner_iso-tester PASS 83.26 seconds
TestRunner_bnep-tester PASS 6.20 seconds
TestRunner_mgmt-tester FAIL 122.95 seconds
TestRunner_rfcomm-tester PASS 9.43 seconds
TestRunner_sco-tester PASS 14.50 seconds
TestRunner_ioctl-tester PASS 10.08 seconds
TestRunner_mesh-tester FAIL 10.58 seconds
TestRunner_smp-tester PASS 8.58 seconds
TestRunner_userchan-tester PASS 6.65 seconds
IncrementalBuild PENDING 1.14 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 488 (98.8%), Failed: 2, Not Run: 4
Failed Test Cases
Read Exp Feature - Success Failed 0.100 seconds
LL Privacy - Start Discovery 1 (Disable RL) Failed 0.173 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Failed 0.132 seconds
Mesh - Send cancel - 2 Timed out 2.699 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface
2025-11-18 14:20 ` [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface Neeraj Sanjay Kale
2025-11-18 15:07 ` Bluetooth: btnxpuart: Add secure interface support for NXP chipsets bluez.test.bot
@ 2025-11-20 7:12 ` kernel test robot
1 sibling, 0 replies; 20+ messages in thread
From: kernel test robot @ 2025-11-20 7:12 UTC (permalink / raw)
To: Neeraj Sanjay Kale, marcel, luiz.dentz
Cc: oe-kbuild-all, linux-bluetooth, linux-kernel, amitkumar.karwar,
sherry.sun, dmitrii.lebed, neeraj.sanjaykale
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]
[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-2-neeraj.sanjaykale%40nxp.com
patch subject: [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface
config: i386-randconfig-061-20251120 (https://download.01.org/0day-ci/archive/20251120/202511201312.njyFmd0I-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251120/202511201312.njyFmd0I-lkp@intel.com/reproduce)
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/202511201312.njyFmd0I-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
>> drivers/bluetooth/btnxpuart.c:1284:55: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1292:27: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1297:47: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1298:32: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1301:26: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1380:17: sparse: sparse: restricted __le32 degrades to integer
vim +1284 drivers/bluetooth/btnxpuart.c
1261
1262 static void nxp_process_fw_meta_data(struct hci_dev *hdev, const struct firmware *fw)
1263 {
1264 const char *metamagc = "metamagc";
1265 struct fw_metadata_hdr *hdr = NULL;
1266 struct fw_metadata_tail *tail;
1267 u32 hdr_crc = 0;
1268 u32 payload_crc = 0;
1269 char *payload;
1270 u32 payload_len = 0;
1271
1272 /* FW metadata should contain at least header and tail */
1273 if (fw->size < (sizeof(*hdr) + sizeof(*tail)))
1274 return;
1275
1276 tail = (struct fw_metadata_tail *)&fw->data[fw->size - sizeof(*tail)];
1277
1278 /* If tail doesn't contain the string "metamagc", this is invalid FW metadata */
1279 if (memcmp(metamagc, tail->magic, strlen(metamagc)))
1280 return;
1281
1282 hdr = (struct fw_metadata_hdr *)&fw->data[fw->size -
1283 sizeof(*tail) -
> 1284 tail->len];
1285
1286 /* If metadata header isn't cmd24, this is invalid FW metadata */
1287 if (le32_to_cpu(hdr->cmd) != 24)
1288 return;
1289
1290 /* If header CRC doesn't match, this is invalid FW metadata */
1291 hdr_crc = crc32_be(0, (u8 *)hdr, offsetof(struct fw_metadata_hdr, crc));
1292 if (hdr_crc != hdr->crc)
1293 return;
1294
1295 /* If payload CRC doesn't match, this is invalid FW metadata */
1296 payload = (u8 *)hdr + sizeof(*hdr);
1297 payload_crc = crc32_be(0, payload, hdr->len - 4);
1298 if (payload_crc != tail->crc)
1299 return;
1300
1301 payload_len = hdr->len - sizeof(*tail);
1302
1303 while (payload_len > sizeof(struct fw_metadata_tlv))
1304 payload_len -= nxp_process_fw_metadata_tlv(hdev, &payload);
1305 }
1306
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v1 02/11] Bluetooth: btnxpuart: Print FW version and enable chip specific features
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 03/11] Bluetooth: btnxpuart: Add secure interface TLS authentication support Neeraj Sanjay Kale
` (8 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This adds a print for FW version after FW is downloaded, and a way to
enable chip specific features.
Currently, secure interface feature is enabled for AW693 chipset.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 46 +++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 3f94ca18a225..483d812042df 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -105,6 +105,8 @@
#define PS_STATE_SLEEP 1
/* NXP Vendor Commands. Refer user manual UM11628 on nxp.com */
+/* Get FW version */
+#define HCI_NXP_GET_FW_VERSION 0xfc0f
/* Set custom BD Address */
#define HCI_NXP_SET_BD_ADDR 0xfc22
/* Set Auto-Sleep mode */
@@ -227,6 +229,7 @@ struct btnxpuart_dev {
struct btnxpuart_data *nxp_data;
struct reset_control *pdn;
struct hci_uart hu;
+ bool secure_interface;
struct btnxpuart_crypto crypto;
};
@@ -1554,6 +1557,47 @@ static int nxp_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
return 0;
}
+static void nxp_handle_chip_specific_features(struct hci_dev *hdev, u8 *version)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+
+ if (!version || strlen(version) == 0)
+ return;
+
+ if (!strncmp(version, "aw693n-V1", strlen("aw693n-V1")))
+ nxpdev->secure_interface = true;
+}
+
+static void nxp_get_fw_version(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ u8 version[100] = {0};
+ u8 cmd = 0;
+ u8 *status;
+
+ skb = nxp_drv_send_cmd(hdev, HCI_NXP_GET_FW_VERSION, 1, &cmd, true);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Failed to get firmware version (%ld)",
+ PTR_ERR(skb));
+ return;
+ }
+
+ status = skb_pull_data(skb, 1);
+ if (status) {
+ if (*status) {
+ bt_dev_err(hdev, "Error get FW version: %d", *status);
+ } else if (skb->len < 10 || skb->len >= 100) {
+ bt_dev_err(hdev, "Invalid FW version");
+ } else {
+ memcpy(version, skb->data, skb->len);
+ bt_dev_info(hdev, "FW Version: %s", version);
+ nxp_handle_chip_specific_features(hdev, version);
+ }
+ }
+
+ kfree_skb(skb);
+}
+
/* NXP protocol */
static int nxp_setup(struct hci_dev *hdev)
{
@@ -1583,6 +1627,8 @@ static int nxp_setup(struct hci_dev *hdev)
serdev_device_set_baudrate(nxpdev->serdev, nxpdev->fw_init_baudrate);
nxpdev->current_baudrate = nxpdev->fw_init_baudrate;
+ nxp_get_fw_version(hdev);
+
ps_init(hdev);
if (test_and_clear_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state))
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 03/11] Bluetooth: btnxpuart: Add secure interface TLS authentication support
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 01/11] Bluetooth: btnxpuart: Add firmware metadata parsing for secure interface Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 02/11] Bluetooth: btnxpuart: Print FW version and enable chip specific features Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 04/11] Bluetooth: btnxpuart: Implement TLS authentication crypto framework Neeraj Sanjay Kale
` (7 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This includes a placeholder nxp_authenticate_device() function if the
chip supports secure interface feature.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 483d812042df..084914e72c44 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -1598,6 +1598,23 @@ static void nxp_get_fw_version(struct hci_dev *hdev)
kfree_skb(skb);
}
+/* Secure Interface */
+static int nxp_authenticate_device(struct hci_dev *hdev)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ int ret = 0;
+
+ /* TODO: Implement actual TLS handshake protocol
+ * This will include:
+ * 1. Crypto allocation (SHA256, ECDH-P256)
+ * 2. Host/Device hello message exchange
+ * 3. Master secret and traffic key derivation
+ * 4. Proper error handling and cleanup
+ */
+
+ return ret;
+}
+
/* NXP protocol */
static int nxp_setup(struct hci_dev *hdev)
{
@@ -1629,6 +1646,12 @@ static int nxp_setup(struct hci_dev *hdev)
nxp_get_fw_version(hdev);
+ if (nxpdev->secure_interface) {
+ err = nxp_authenticate_device(hdev);
+ if (err)
+ return -EACCES;
+ }
+
ps_init(hdev);
if (test_and_clear_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state))
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 04/11] Bluetooth: btnxpuart: Implement TLS authentication crypto framework
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
` (2 preceding siblings ...)
2025-11-18 14:20 ` [PATCH v1 03/11] Bluetooth: btnxpuart: Add secure interface TLS authentication support Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 05/11] Bluetooth: btnxpuart: Add TLS host hello handshake implementation Neeraj Sanjay Kale
` (6 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This adds nxp_authenticate_device() function that sets up cryptographic
resources for TLS handshake authentication. Allocates SHA256 hash and
ECDH-P256 key exchange with proper cleanup after handshake completion
to maintain only traffic keys.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 48 ++++++++++++++++++++++++++++++++---
1 file changed, 44 insertions(+), 4 deletions(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 084914e72c44..3a8fa5266eca 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -22,6 +22,11 @@
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
+#include <linux/crypto.h>
+#include <crypto/sha2.h>
+#include <crypto/hash.h>
+#include <crypto/kpp.h>
+
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -192,6 +197,9 @@ enum bootloader_param_change {
};
struct btnxpuart_crypto {
+ struct crypto_shash *tls_handshake_hash_tfm;
+ struct shash_desc *tls_handshake_hash_desc;
+ struct crypto_kpp *kpp;
u8 ecdsa_public[NXP_FW_ECDSA_PUBKEY_SIZE]; /* ECDSA public key, Authentication*/
u8 fw_uuid[NXP_FW_UUID_SIZE];
};
@@ -1602,16 +1610,48 @@ static void nxp_get_fw_version(struct hci_dev *hdev)
static int nxp_authenticate_device(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ size_t desc_size = 0;
int ret = 0;
+ nxpdev->crypto.tls_handshake_hash_tfm = crypto_alloc_shash("sha256", 0, 0);
+ if (IS_ERR(nxpdev->crypto.tls_handshake_hash_tfm))
+ return PTR_ERR(nxpdev->crypto.tls_handshake_hash_tfm);
+
+ desc_size = sizeof(struct shash_desc) +
+ crypto_shash_descsize(nxpdev->crypto.tls_handshake_hash_tfm);
+ nxpdev->crypto.tls_handshake_hash_desc = kzalloc(desc_size, GFP_KERNEL);
+ if (!nxpdev->crypto.tls_handshake_hash_desc) {
+ ret = -ENOMEM;
+ goto free_tfm;
+ }
+
+ nxpdev->crypto.kpp = crypto_alloc_kpp("ecdh-nist-p256", 0, 0);
+ if (IS_ERR(nxpdev->crypto.kpp)) {
+ ret = PTR_ERR(nxpdev->crypto.kpp);
+ goto free_desc;
+ }
+
+ nxpdev->crypto.tls_handshake_hash_desc->tfm = nxpdev->crypto.tls_handshake_hash_tfm;
+ crypto_shash_init(nxpdev->crypto.tls_handshake_hash_desc);
+
/* TODO: Implement actual TLS handshake protocol
* This will include:
- * 1. Crypto allocation (SHA256, ECDH-P256)
- * 2. Host/Device hello message exchange
- * 3. Master secret and traffic key derivation
- * 4. Proper error handling and cleanup
+ * 1. Host/Device hello message exchange
+ * 2. Master secret and traffic key derivation
*/
+free_kpp:
+ crypto_free_kpp(nxpdev->crypto.kpp);
+ nxpdev->crypto.kpp = NULL;
+free_desc:
+ kfree(nxpdev->crypto.tls_handshake_hash_desc);
+ nxpdev->crypto.tls_handshake_hash_desc = NULL;
+free_tfm:
+ crypto_free_shash(nxpdev->crypto.tls_handshake_hash_tfm);
+ nxpdev->crypto.tls_handshake_hash_tfm = NULL;
+ if (ret)
+ bt_dev_err(hdev, "Device Authentication failed: %d", ret);
+
return ret;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 05/11] Bluetooth: btnxpuart: Add TLS host hello handshake implementation
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
` (3 preceding siblings ...)
2025-11-18 14:20 ` [PATCH v1 04/11] Bluetooth: btnxpuart: Implement TLS authentication crypto framework Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-22 3:31 ` kernel test robot
2025-11-18 14:20 ` [PATCH v1 06/11] Bluetooth: btnxpuart: Add TLS device hello processing Neeraj Sanjay Kale
` (5 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
Implement TLS handshake initiation for secure interface authentication.
Includes ECDH public key generation, host hello message creation, and
handshake hash computation for secure chip authentication.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 189 +++++++++++++++++++++++++++++++++-
1 file changed, 188 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 3a8fa5266eca..44073eae0df3 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -26,6 +26,7 @@
#include <crypto/sha2.h>
#include <crypto/hash.h>
#include <crypto/kpp.h>
+#include <crypto/ecdh.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -124,6 +125,8 @@
#define HCI_NXP_IND_RESET 0xfcfc
/* Bluetooth vendor command: Trigger FW dump */
#define HCI_NXP_TRIGGER_DUMP 0xfe91
+/* Bluetooth vendor command: Secure Host Interface */
+#define HCI_NXP_SHI_ENCRYPT 0xfe9c
/* Bluetooth Power State : Vendor cmd params */
#define BT_PS_ENABLE 0x02
@@ -388,6 +391,55 @@ union nxp_set_bd_addr_payload {
u8 buf[8];
};
+/* Secure Host Interface */
+#define NXP_TLS_MAGIC 0x43b826f3
+#define NXP_TLS_VERSION 1
+
+#define NXP_TLS_ECDH_PUBLIC_KEY_SIZE 64
+
+enum nxp_tls_signature_algorithm {
+ NXP_TLS_ECDSA_SECP256R1_SHA256 = 0x0403,
+};
+
+enum nxp_tls_key_exchange_type {
+ NXP_TLS_ECDHE_SECP256R1 = 0x0017,
+};
+
+enum nxp_tls_cipher_suite {
+ NXP_TLS_AES_128_GCM_SHA256 = 0x1301,
+};
+
+enum nxp_tls_message_id {
+ NXP_TLS_HOST_HELLO = 1,
+ NXP_TLS_DEVICE_HELLO = 2,
+ NXP_TLS_HOST_FINISHED = 3,
+};
+
+struct nxp_tls_message_hdr {
+ __le32 magic;
+ __le16 len;
+ u8 message_id;
+ u8 protocol_version;
+};
+
+struct nxp_tls_host_hello {
+ struct nxp_tls_message_hdr hdr;
+ __le16 sig_alg;
+ __le16 key_exchange_type;
+ __le16 cipher_suite;
+ __le16 reserved;
+ u8 random[32];
+ u8 pubkey[NXP_TLS_ECDH_PUBLIC_KEY_SIZE]; /* ECDHE */
+};
+
+union nxp_tls_host_hello_payload {
+ struct {
+ u8 msg_type;
+ struct nxp_tls_host_hello host_hello;
+ } __packed;
+ u8 buf[113];
+};
+
/* FW Meta Data */
struct fw_metadata_hdr {
__le32 cmd;
@@ -1607,10 +1659,137 @@ static void nxp_get_fw_version(struct hci_dev *hdev)
}
/* Secure Interface */
+static int nxp_generate_ecdh_public_key(struct crypto_kpp *tfm, u8 public_key[64])
+{
+ DECLARE_CRYPTO_WAIT(result);
+ struct kpp_request *req;
+ u8 *tmp;
+ struct scatterlist dst;
+ int err;
+
+ tmp = kzalloc(64, GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ req = kpp_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ err = -ENOMEM;
+ goto free_tmp;
+ }
+
+ sg_init_one(&dst, tmp, 64);
+ kpp_request_set_input(req, NULL, 0);
+ kpp_request_set_output(req, &dst, 64);
+ kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_req_done, &result);
+
+ err = crypto_kpp_generate_public_key(req);
+ err = crypto_wait_req(err, &result);
+ if (err < 0)
+ goto free_all;
+
+ memcpy(public_key, tmp, 64);
+
+free_all:
+ kpp_request_free(req);
+free_tmp:
+ kfree(tmp);
+ return err;
+}
+
+static inline void nxp_tls_hdr_init(struct nxp_tls_message_hdr *hdr, size_t len,
+ enum nxp_tls_message_id id)
+{
+ hdr->magic = cpu_to_le32(NXP_TLS_MAGIC);
+ hdr->len = cpu_to_le16((u16)len);
+ hdr->message_id = (u8)id;
+ hdr->protocol_version = NXP_TLS_VERSION;
+}
+
+static struct sk_buff *nxp_host_do_hello(struct hci_dev *hdev)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ union nxp_tls_host_hello_payload tls_hello;
+ struct nxp_tls_host_hello *host_hello = &tls_hello.host_hello;
+ struct ecdh p = {0};
+ u8 *buf = NULL;
+ unsigned int buf_len;
+ struct sk_buff *skb;
+ int ret;
+
+ nxp_tls_hdr_init(&host_hello->hdr, sizeof(*host_hello), NXP_TLS_HOST_HELLO);
+
+ host_hello->sig_alg = cpu_to_le16(NXP_TLS_ECDSA_SECP256R1_SHA256);
+ host_hello->key_exchange_type = cpu_to_le16(NXP_TLS_ECDHE_SECP256R1);
+ host_hello->cipher_suite = cpu_to_le16(NXP_TLS_AES_128_GCM_SHA256);
+
+ get_random_bytes(host_hello->random, sizeof(host_hello->random));
+
+ /* Generate random private key */
+ p.key_size = 32;
+ p.key = kzalloc(p.key_size, GFP_KERNEL);
+ if (!p.key)
+ return ERR_PTR(-ENOMEM);
+
+ get_random_bytes(p.key, p.key_size);
+
+ buf_len = crypto_ecdh_key_len(&p);
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto free_key;
+ }
+
+ ret = crypto_ecdh_encode_key(buf, buf_len, &p);
+ if (ret) {
+ bt_dev_err(hdev, "crypto_ecdh_encode_key() failed");
+ goto free_buf;
+ }
+
+ ret = crypto_kpp_set_secret(nxpdev->crypto.kpp, buf, buf_len);
+ if (ret) {
+ bt_dev_err(hdev, "crypto_kpp_set_secret() failed");
+ goto free_buf;
+ }
+
+ ret = nxp_generate_ecdh_public_key(nxpdev->crypto.kpp, host_hello->pubkey);
+ if (ret) {
+ bt_dev_err(hdev, "Failed to generate ECDH public key: %d", ret);
+ goto free_buf;
+ }
+
+ ret = crypto_shash_update(nxpdev->crypto.tls_handshake_hash_desc,
+ (u8 *)host_hello, sizeof(*host_hello));
+ if (ret) {
+ bt_dev_err(hdev, "Failed to update handshake hash: %d", ret);
+ goto free_buf;
+ }
+
+ tls_hello.msg_type = 0;
+
+ skb = __hci_cmd_sync(hdev, HCI_NXP_SHI_ENCRYPT, sizeof(tls_hello),
+ tls_hello.buf, HCI_CMD_TIMEOUT);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Host Hello command failed: %ld", PTR_ERR(skb));
+ ret = PTR_ERR(skb);
+ }
+
+free_buf:
+ kfree(buf);
+free_key:
+ memset(p.key, 0, p.key_size);
+ kfree(p.key);
+ if (ret)
+ return ERR_PTR(ret);
+ else
+ return skb;
+}
+
static int nxp_authenticate_device(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
size_t desc_size = 0;
+ struct sk_buff *skb;
int ret = 0;
nxpdev->crypto.tls_handshake_hash_tfm = crypto_alloc_shash("sha256", 0, 0);
@@ -1634,12 +1813,20 @@ static int nxp_authenticate_device(struct hci_dev *hdev)
nxpdev->crypto.tls_handshake_hash_desc->tfm = nxpdev->crypto.tls_handshake_hash_tfm;
crypto_shash_init(nxpdev->crypto.tls_handshake_hash_desc);
+ skb = nxp_host_do_hello(hdev);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ goto free_kpp;
+ }
+
/* TODO: Implement actual TLS handshake protocol
* This will include:
- * 1. Host/Device hello message exchange
+ * 1. Handle Device hello message exchange
* 2. Master secret and traffic key derivation
*/
+free_skb:
+ kfree_skb(skb);
free_kpp:
crypto_free_kpp(nxpdev->crypto.kpp);
nxpdev->crypto.kpp = NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v1 05/11] Bluetooth: btnxpuart: Add TLS host hello handshake implementation
2025-11-18 14:20 ` [PATCH v1 05/11] Bluetooth: btnxpuart: Add TLS host hello handshake implementation Neeraj Sanjay Kale
@ 2025-11-22 3:31 ` kernel test robot
0 siblings, 0 replies; 20+ messages in thread
From: kernel test robot @ 2025-11-22 3:31 UTC (permalink / raw)
To: Neeraj Sanjay Kale, marcel, luiz.dentz
Cc: llvm, oe-kbuild-all, linux-bluetooth, linux-kernel,
amitkumar.karwar, sherry.sun, dmitrii.lebed, neeraj.sanjaykale
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-20251121]
[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-6-neeraj.sanjaykale%40nxp.com
patch subject: [PATCH v1 05/11] Bluetooth: btnxpuart: Add TLS host hello handshake implementation
config: arm-randconfig-001-20251122 (https://download.01.org/0day-ci/archive/20251122/202511221150.4Zd49lpF-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 9e9fe08b16ea2c4d9867fb4974edf2a3776d6ece)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251122/202511221150.4Zd49lpF-lkp@intel.com/reproduce)
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/202511221150.4Zd49lpF-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/bluetooth/btnxpuart.c:438:29: warning: field host_hello within 'struct nxp_tls_host_hello_payload::(anonymous at drivers/bluetooth/btnxpuart.c:436:2)' is less aligned than 'struct nxp_tls_host_hello' and is usually due to 'struct nxp_tls_host_hello_payload::(anonymous at drivers/bluetooth/btnxpuart.c:436:2)' being packed, which can lead to unaligned accesses [-Wunaligned-access]
438 | struct nxp_tls_host_hello host_hello;
| ^
drivers/bluetooth/btnxpuart.c:1828:1: warning: unused label 'free_skb' [-Wunused-label]
1828 | free_skb:
| ^~~~~~~~~
2 warnings generated.
vim +438 drivers/bluetooth/btnxpuart.c
434
435 union nxp_tls_host_hello_payload {
436 struct {
437 u8 msg_type;
> 438 struct nxp_tls_host_hello host_hello;
439 } __packed;
440 u8 buf[113];
441 };
442
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v1 06/11] Bluetooth: btnxpuart: Add TLS device hello processing
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
` (4 preceding siblings ...)
2025-11-18 14:20 ` [PATCH v1 05/11] Bluetooth: btnxpuart: Add TLS host hello handshake implementation Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication Neeraj Sanjay Kale
` (4 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This implements device hello message processing to derive handshake
traffic secrets:
- Add HKDF-SHA256 functions for TLS 1.3 traffic secret derivation
following RFC 5869/8446
- Extract device ECDH public key and compute shared secret using
KPP API with host private key and device public key
- Derive handshake traffic secret from ECDH shared secret
following TLS 1.3 key schedule
- Validate device hello message and update handshake hash state
The handshake traffic secret enables decryption of the
device_finish portion within the device_hello message.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 274 +++++++++++++++++++++++++++++++++-
1 file changed, 270 insertions(+), 4 deletions(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 44073eae0df3..3bff7758fa5e 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -150,8 +150,9 @@
#define FW_METADATA_TLV_ECDSA_KEY 0x50
#define FW_METADATA_FLAG_BT 0x02
-#define NXP_FW_UUID_SIZE 16
-#define NXP_FW_ECDSA_PUBKEY_SIZE 65
+#define NXP_FW_UUID_SIZE 16
+#define NXP_FW_ECDH_PUBKEY_SIZE 64
+#define NXP_FW_ECDSA_PUBKEY_SIZE 65
struct ps_data {
u8 target_ps_mode; /* ps mode to be set */
@@ -203,8 +204,11 @@ struct btnxpuart_crypto {
struct crypto_shash *tls_handshake_hash_tfm;
struct shash_desc *tls_handshake_hash_desc;
struct crypto_kpp *kpp;
+ uint8_t ecdh_public[NXP_FW_ECDH_PUBKEY_SIZE]; /* ECDH public key, Key negotiation */
u8 ecdsa_public[NXP_FW_ECDSA_PUBKEY_SIZE]; /* ECDSA public key, Authentication*/
u8 fw_uuid[NXP_FW_UUID_SIZE];
+ u8 handshake_h2_hash[SHA256_DIGEST_SIZE];
+ u8 handshake_secret[SHA256_DIGEST_SIZE];
};
struct btnxpuart_dev {
@@ -396,6 +400,11 @@ union nxp_set_bd_addr_payload {
#define NXP_TLS_VERSION 1
#define NXP_TLS_ECDH_PUBLIC_KEY_SIZE 64
+#define NXP_DEVICE_UUID_LEN 16
+#define NXP_ENC_AUTH_TAG_SIZE 16
+
+#define NXP_TLS_LABEL(str) str, strlen(str)
+#define NXP_TLS_DEVICE_HS_TS_LABEL NXP_TLS_LABEL("D HS TS")
enum nxp_tls_signature_algorithm {
NXP_TLS_ECDSA_SECP256R1_SHA256 = 0x0403,
@@ -440,6 +449,38 @@ union nxp_tls_host_hello_payload {
u8 buf[113];
};
+struct nxp_tls_device_info {
+ __le16 chip_id;
+ __le16 device_flags;
+ u8 reserved[4];
+ u8 uuid[NXP_DEVICE_UUID_LEN];
+};
+
+struct nxp_tls_signature {
+ u8 sig[64]; /* P-256 ECDSA signature, two points */
+};
+
+struct nxp_tls_finished {
+ u8 verify_data[32];
+};
+
+struct nxp_tls_device_hello {
+ struct nxp_tls_message_hdr hdr;
+ __le32 reserved;
+ u8 random[32];
+ u8 pubkey[NXP_TLS_ECDH_PUBLIC_KEY_SIZE];
+ /* Encrypted portion */
+ struct {
+ struct nxp_tls_device_info device_info;
+ struct nxp_tls_signature device_handshake_sig; /* TLS Certificate Verify */
+ struct nxp_tls_finished device_finished;
+ } enc;
+ u8 auth_tag[NXP_ENC_AUTH_TAG_SIZE]; /* Auth tag for the encrypted portion */
+};
+
+#define DEVICE_HELLO_SIG_CUTOFF_POS \
+ offsetof(struct nxp_tls_device_hello, enc)
+
/* FW Meta Data */
struct fw_metadata_hdr {
__le32 cmd;
@@ -1698,7 +1739,7 @@ static int nxp_generate_ecdh_public_key(struct crypto_kpp *tfm, u8 public_key[64
}
static inline void nxp_tls_hdr_init(struct nxp_tls_message_hdr *hdr, size_t len,
- enum nxp_tls_message_id id)
+ enum nxp_tls_message_id id)
{
hdr->magic = cpu_to_le32(NXP_TLS_MAGIC);
hdr->len = cpu_to_le16((u16)len);
@@ -1785,11 +1826,222 @@ static struct sk_buff *nxp_host_do_hello(struct hci_dev *hdev)
return skb;
}
+static int nxp_crypto_shash_final(struct shash_desc *desc, u8 *out)
+{
+ struct shash_desc *desc_tmp = kzalloc(sizeof(struct shash_desc) +
+ crypto_shash_descsize(desc->tfm),
+ GFP_KERNEL);
+
+ if (!desc_tmp)
+ return -ENOMEM;
+
+ crypto_shash_export(desc, desc_tmp);
+ crypto_shash_final(desc, out);
+ crypto_shash_import(desc, desc_tmp);
+ kfree(desc_tmp);
+
+ return 0;
+}
+
+static int nxp_compute_shared_secret(struct crypto_kpp *tfm, const u8 public_key[64], u8 secret[32])
+{
+ DECLARE_CRYPTO_WAIT(result);
+ struct kpp_request *req;
+ struct scatterlist src, dst;
+ int err;
+
+ req = kpp_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ pr_err("Failed to allocate memory for KPP request\n");
+ return -ENOMEM;
+ }
+
+ sg_init_one(&src, public_key, 64);
+ sg_init_one(&dst, secret, 32);
+ kpp_request_set_input(req, &src, 64);
+ kpp_request_set_output(req, &dst, 32);
+ kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_req_done, &result);
+ err = crypto_kpp_compute_shared_secret(req);
+ err = crypto_wait_req(err, &result);
+ if (err < 0) {
+ pr_err("alg: ecdh: compute shared secret failed. err %d\n", err);
+ goto free_all;
+ }
+
+free_all:
+ kpp_request_free(req);
+ return err;
+}
+
+static int nxp_hkdf_sha256_extract(const void *salt, size_t salt_len,
+ const void *ikm, size_t ikm_len,
+ u8 result[SHA256_DIGEST_SIZE])
+{
+ struct crypto_shash *tfm;
+ struct shash_desc *desc;
+ u8 zeroes[SHA256_DIGEST_SIZE] = {0};
+ int ret = 0;
+
+ tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+
+ desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
+ if (!desc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ desc->tfm = tfm;
+
+ /* RFC 5869: If salt is empty, use HashLen zero octets */
+ if (salt_len == 0)
+ ret = crypto_shash_setkey(tfm, zeroes, SHA256_DIGEST_SIZE);
+ else
+ ret = crypto_shash_setkey(tfm, salt, salt_len);
+
+ if (ret)
+ goto cleanup;
+
+ ret = crypto_shash_init(desc);
+ if (ret)
+ goto cleanup;
+
+ ret = crypto_shash_update(desc, ikm, ikm_len);
+ if (ret)
+ goto cleanup;
+
+ ret = crypto_shash_final(desc, result);
+
+cleanup:
+ kfree(desc);
+ crypto_free_shash(tfm);
+ return ret;
+}
+
+static int nxp_hkdf_expand_label(const u8 secret[SHA256_DIGEST_SIZE],
+ const char *label, size_t label_size,
+ u8 *context, size_t context_size,
+ void *output, size_t output_size)
+{
+ struct crypto_shash *tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+ struct shash_desc *desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ u8 hmac_out[SHA256_DIGEST_SIZE];
+ u16 length = output_size;
+ u8 one = 0x01;
+
+ if (IS_ERR(tfm)) {
+ pr_err("Failed to alloc shash for HMAC\n");
+ return -ENOMEM;
+ }
+
+ if (!desc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ crypto_shash_setkey(tfm, secret, SHA256_DIGEST_SIZE);
+ desc->tfm = tfm;
+
+ crypto_shash_init(desc);
+ crypto_shash_update(desc, (u8 *)&length, sizeof(length));
+ crypto_shash_update(desc, label, label_size);
+
+ if (context && context_size > 0)
+ crypto_shash_update(desc, context, context_size);
+
+ /* RFC 5869: HKDF-Expand counter starts at 0x01 */
+ crypto_shash_update(desc, &one, sizeof(one));
+ crypto_shash_final(desc, hmac_out);
+
+ memcpy(output, hmac_out, output_size);
+
+ kfree(desc);
+ crypto_free_shash(tfm);
+ return 0;
+}
+
+static int nxp_hkdf_derive_secret(u8 secret[32], const char *label, size_t label_size,
+ u8 context[SHA256_DIGEST_SIZE],
+ u8 output[SHA256_DIGEST_SIZE])
+{
+ return nxp_hkdf_expand_label(secret, label, label_size, context, SHA256_DIGEST_SIZE,
+ output, SHA256_DIGEST_SIZE);
+}
+
+static int nxp_process_device_hello(struct hci_dev *hdev, struct nxp_tls_device_hello *msg)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct nxp_tls_message_hdr *hdr;
+ u8 hs_traffic_secret[SHA256_DIGEST_SIZE];
+ u8 *shared_secret = NULL;
+ int ret;
+
+ if (!msg)
+ return -EINVAL;
+
+ hdr = &msg->hdr;
+
+ if (le32_to_cpu(hdr->magic) != NXP_TLS_MAGIC ||
+ le16_to_cpu(hdr->len) != sizeof(*msg) ||
+ hdr->message_id != NXP_TLS_DEVICE_HELLO ||
+ hdr->protocol_version != NXP_TLS_VERSION) {
+ bt_dev_err(hdev, "Invalid device hello header");
+ return -EINVAL;
+ }
+
+ shared_secret = kzalloc(32, GFP_KERNEL);
+ if (!shared_secret)
+ return -ENOMEM;
+
+ ret = crypto_shash_update(nxpdev->crypto.tls_handshake_hash_desc, (u8 *)msg,
+ DEVICE_HELLO_SIG_CUTOFF_POS);
+ if (ret)
+ goto fail;
+
+ ret = nxp_crypto_shash_final(nxpdev->crypto.tls_handshake_hash_desc,
+ nxpdev->crypto.handshake_h2_hash);
+ if (ret)
+ goto fail;
+
+ memcpy(nxpdev->crypto.ecdh_public, msg->pubkey, NXP_FW_ECDH_PUBKEY_SIZE);
+
+ ret = nxp_compute_shared_secret(nxpdev->crypto.kpp, nxpdev->crypto.ecdh_public,
+ shared_secret);
+ if (ret)
+ goto fail;
+
+ ret = nxp_hkdf_sha256_extract(NULL, 0, shared_secret, 32,
+ nxpdev->crypto.handshake_secret);
+ if (ret)
+ goto fail;
+
+ ret = nxp_hkdf_derive_secret(nxpdev->crypto.handshake_secret,
+ NXP_TLS_DEVICE_HS_TS_LABEL,
+ nxpdev->crypto.handshake_h2_hash,
+ hs_traffic_secret);
+ if (ret)
+ goto fail;
+
+ /* TODO: Verify Signature in Device Hello using ECDSA Public Key
+ * extracted from the FW metadata.
+ */
+
+fail:
+ memset(shared_secret, 0, 32);
+ kfree(shared_secret);
+ return ret;
+}
+
static int nxp_authenticate_device(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct nxp_tls_device_hello *device_hello;
size_t desc_size = 0;
struct sk_buff *skb;
+ u8 *status;
int ret = 0;
nxpdev->crypto.tls_handshake_hash_tfm = crypto_alloc_shash("sha256", 0, 0);
@@ -1819,9 +2071,23 @@ static int nxp_authenticate_device(struct hci_dev *hdev)
goto free_kpp;
}
+ status = skb_pull_data(skb, 1);
+ if (*status)
+ goto free_skb;
+
+ if (skb->len != sizeof(struct nxp_tls_device_hello)) {
+ bt_dev_err(hdev, "Invalid Device Hello Length: %d", skb->len);
+ goto free_skb;
+ }
+
+ device_hello = skb_pull_data(skb, sizeof(*device_hello));
+ ret = nxp_process_device_hello(hdev, device_hello);
+ if (ret)
+ goto free_skb;
+
/* TODO: Implement actual TLS handshake protocol
* This will include:
- * 1. Handle Device hello message exchange
+ * 1. Send Host Finish TLS message
* 2. Master secret and traffic key derivation
*/
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
` (5 preceding siblings ...)
2025-11-18 14:20 ` [PATCH v1 06/11] Bluetooth: btnxpuart: Add TLS device hello processing Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-20 14:46 ` kernel test robot
2025-11-22 11:03 ` kernel test robot
2025-11-18 14:20 ` [PATCH v1 08/11] Bluetooth: btnxpuart: Derive traffic keys from TLS 1.3 handshake Neeraj Sanjay Kale
` (3 subsequent siblings)
10 siblings, 2 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This implements secure device authentication during TLS 1.3-like
handshake with ECDSA signature verification.
The authentication flow:
- Derive handshake traffic secret from ECDH shared secret
- Decrypt device hello encrypted section using AES-GCM with traffic secret
- Extract ECDSA public key from firmware metadata for verification
- Verify device handshake signature to authenticate device identity
- Validate device finished message using calculated verify data
- Clear handshake traffic secret after successful authentication
This ensures only devices with valid private keys can complete the
handshake.
Key components added:
- AES-GCM encrypt/decrypt with traffic secret derived keys
- ECDSA P-256 signature verification using kernel crypto API
- X9.62 to P1363 signature format conversion
- TLS 1.3 finished message verification
- Secure memory cleanup of cryptographic material
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 503 +++++++++++++++++++++++++++++++++-
1 file changed, 498 insertions(+), 5 deletions(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 3bff7758fa5e..bfe6a138d78d 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -27,6 +27,12 @@
#include <crypto/hash.h>
#include <crypto/kpp.h>
#include <crypto/ecdh.h>
+#include <linux/scatterlist.h>
+#include <linux/completion.h>
+#include <crypto/aes.h>
+#include <crypto/gcm.h>
+#include <crypto/aead.h>
+#include <crypto/public_key.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -204,11 +210,13 @@ struct btnxpuart_crypto {
struct crypto_shash *tls_handshake_hash_tfm;
struct shash_desc *tls_handshake_hash_desc;
struct crypto_kpp *kpp;
- uint8_t ecdh_public[NXP_FW_ECDH_PUBKEY_SIZE]; /* ECDH public key, Key negotiation */
+ u8 ecdh_public[NXP_FW_ECDH_PUBKEY_SIZE]; /* ECDH public key, Key negotiation */
u8 ecdsa_public[NXP_FW_ECDSA_PUBKEY_SIZE]; /* ECDSA public key, Authentication*/
u8 fw_uuid[NXP_FW_UUID_SIZE];
u8 handshake_h2_hash[SHA256_DIGEST_SIZE];
u8 handshake_secret[SHA256_DIGEST_SIZE];
+ struct completion completion;
+ int decrypt_result;
};
struct btnxpuart_dev {
@@ -405,6 +413,10 @@ union nxp_set_bd_addr_payload {
#define NXP_TLS_LABEL(str) str, strlen(str)
#define NXP_TLS_DEVICE_HS_TS_LABEL NXP_TLS_LABEL("D HS TS")
+#define NXP_TLS_KEYING_IV_LABEL NXP_TLS_LABEL("iv")
+#define NXP_TLS_KEYING_KEY_LABEL NXP_TLS_LABEL("key")
+#define NXP_TLS_FINISHED_LABEL NXP_TLS_LABEL("finished")
+#define NXP_TLS_HOST_HS_TS_LABEL NXP_TLS_LABEL("H HS TS")
enum nxp_tls_signature_algorithm {
NXP_TLS_ECDSA_SECP256R1_SHA256 = 0x0403,
@@ -478,9 +490,42 @@ struct nxp_tls_device_hello {
u8 auth_tag[NXP_ENC_AUTH_TAG_SIZE]; /* Auth tag for the encrypted portion */
};
+struct nxp_tls_data_add {
+ u8 version; /* NXP_TLS_VERSION */
+ u8 reserved[5]; /* zeroes */
+ __le16 len;
+};
+
+struct nxp_tls_host_finished {
+ struct nxp_tls_message_hdr hdr;
+ __le32 reserved;
+ /* Encrypted portion */
+ struct {
+ struct nxp_tls_signature reserved2;
+ struct nxp_tls_finished host_finished;
+ } enc;
+ u8 auth_tag[NXP_ENC_AUTH_TAG_SIZE]; /* Auth tag for the encrypted portion */
+};
+
+union nxp_tls_host_finished_payload {
+ struct {
+ u8 msg_type;
+ struct nxp_tls_host_finished host_finished;
+ } __packed;
+ u8 buf[125];
+};
+
#define DEVICE_HELLO_SIG_CUTOFF_POS \
offsetof(struct nxp_tls_device_hello, enc)
+#define DEVICE_HELLO_FINISHED_ENC_CUTOFF_POS \
+ (offsetof(struct nxp_tls_device_hello, enc.device_finished) - \
+ DEVICE_HELLO_SIG_CUTOFF_POS)
+
+
+#define HOST_FINISHED_CUTOFF_POS \
+ offsetof(struct nxp_tls_host_finished, enc.host_finished)
+
/* FW Meta Data */
struct fw_metadata_hdr {
__le32 cmd;
@@ -1700,6 +1745,37 @@ static void nxp_get_fw_version(struct hci_dev *hdev)
}
/* Secure Interface */
+static int nxp_get_pub_key(struct hci_dev *hdev,
+ const struct nxp_tls_device_info *device_info,
+ u8 ecdsa_pub_key[NXP_FW_ECDSA_PUBKEY_SIZE])
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ const char *fw_name;
+
+ if (ecdsa_pub_key[0] == 0x04)
+ return 0;
+
+ fw_name = nxp_get_fw_name_from_chipid(hdev, device_info->chip_id,
+ device_info->device_flags);
+ if (nxp_request_firmware(hdev, fw_name, NULL))
+ return -ENOENT;
+
+ nxp_process_fw_meta_data(hdev, nxpdev->fw);
+ release_firmware(nxpdev->fw);
+ memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
+
+ if (memcmp(nxpdev->crypto.fw_uuid, device_info->uuid, 16) ||
+ nxpdev->crypto.ecdsa_public[0] != 0x04) {
+ bt_dev_err(hdev,
+ "UUID check failed while trying to read ECDSA public key from FW.");
+ return -EBADF;
+ }
+
+ memcpy(ecdsa_pub_key, nxpdev->crypto.ecdsa_public, 65);
+
+ return 0;
+}
+
static int nxp_generate_ecdh_public_key(struct crypto_kpp *tfm, u8 public_key[64])
{
DECLARE_CRYPTO_WAIT(result);
@@ -1971,6 +2047,320 @@ static int nxp_hkdf_derive_secret(u8 secret[32], const char *label, size_t label
output, SHA256_DIGEST_SIZE);
}
+/*
+ * The digital signature is computed over the concatenation of:
+ * - A string that consists of octet 32 (0x20) repeated 64 times
+ * - The context string
+ * - A single 0 byte which serves as the separator
+ * - The content to be signed
+ */
+static int nxp_handshake_sig_hash(const u8 transcript_hash[SHA256_DIGEST_SIZE],
+ const char *context, size_t context_len,
+ u8 output_hash[SHA256_DIGEST_SIZE])
+{
+ struct crypto_shash *tfm;
+ struct shash_desc *desc;
+ const u8 zero = 0;
+
+ tfm = crypto_alloc_shash("sha256", 0, 0);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+
+ desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
+ if (!desc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ desc->tfm = tfm;
+
+ memset(output_hash, 0x20, SHA256_DIGEST_SIZE);
+
+ crypto_shash_init(desc);
+ /* 2x hash size = block size of 0x20 */
+ crypto_shash_update(desc, output_hash, SHA256_DIGEST_SIZE);
+ crypto_shash_update(desc, output_hash, SHA256_DIGEST_SIZE);
+
+ crypto_shash_update(desc, context, context_len);
+ crypto_shash_update(desc, &zero, sizeof(zero));
+
+ crypto_shash_update(desc, transcript_hash, SHA256_DIGEST_SIZE);
+ crypto_shash_final(desc, output_hash);
+
+ kfree(desc);
+ crypto_free_shash(tfm);
+ return 0;
+}
+
+
+static void nxp_aead_complete(void *req, int err)
+{
+ struct btnxpuart_crypto *crypto = req;
+
+ crypto->decrypt_result = err;
+ complete(&crypto->completion);
+}
+
+static int nxp_aes_gcm_decrypt(struct hci_dev *hdev, void *buf, size_t size,
+ u8 auth_tag[16], u8 key[AES_KEYSIZE_128],
+ u8 iv[GCM_AES_IV_SIZE])
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct crypto_aead *tfm;
+ struct aead_request *req;
+ struct scatterlist src, dst;
+ struct nxp_tls_data_add aad = {
+ .version = NXP_TLS_VERSION,
+ .len = (u16)size
+ };
+ u8 *ciphertext;
+ u8 *plaintext;
+ int ret = 0;
+
+ ciphertext = kzalloc(sizeof(aad) + size + NXP_ENC_AUTH_TAG_SIZE,
+ GFP_KERNEL);
+ if (!ciphertext)
+ return -ENOMEM;
+
+ plaintext = kzalloc(size + NXP_ENC_AUTH_TAG_SIZE, GFP_KERNEL);
+ if (!plaintext) {
+ ret = -ENOMEM;
+ goto free_ciphertext;
+ }
+
+ memcpy(ciphertext, &aad, sizeof(aad));
+ memcpy(ciphertext + sizeof(aad), buf, size);
+ memcpy(ciphertext + sizeof(aad) + size, auth_tag, NXP_ENC_AUTH_TAG_SIZE);
+
+ tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+ if (IS_ERR(tfm)) {
+ ret = PTR_ERR(tfm);
+ goto free_plaintext;
+ }
+
+ crypto_aead_setkey(tfm, key, AES_KEYSIZE_128);
+ crypto_aead_setauthsize(tfm, NXP_ENC_AUTH_TAG_SIZE);
+
+ req = aead_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ ret = -ENOMEM;
+ goto free_tfm;
+ }
+
+ sg_init_one(&src, ciphertext, sizeof(aad) + size + NXP_ENC_AUTH_TAG_SIZE);
+ sg_init_one(&dst, plaintext, size + NXP_ENC_AUTH_TAG_SIZE);
+ init_completion(&nxpdev->crypto.completion);
+
+ aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ nxp_aead_complete, &nxpdev->crypto);
+ aead_request_set_crypt(req, &src, &dst, size + NXP_ENC_AUTH_TAG_SIZE, iv);
+ aead_request_set_ad(req, sizeof(aad));
+
+ ret = crypto_aead_decrypt(req);
+ if (ret == -EINPROGRESS || ret == -EBUSY) {
+ wait_for_completion(&nxpdev->crypto.completion);
+ ret = nxpdev->crypto.decrypt_result;
+ }
+ if (!ret)
+ memcpy(buf, plaintext + sizeof(aad), size);
+
+ aead_request_free(req);
+free_tfm:
+ crypto_free_aead(tfm);
+free_plaintext:
+ kfree(plaintext);
+free_ciphertext:
+ kfree(ciphertext);
+ return ret;
+}
+
+static int nxp_aes_gcm_encrypt(struct hci_dev *hdev, void *buf, size_t size, u8 auth_tag[16],
+ u8 key[AES_KEYSIZE_128], u8 iv[GCM_AES_IV_SIZE])
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct crypto_aead *tfm;
+ struct aead_request *req;
+ struct scatterlist src, dst;
+ struct nxp_tls_data_add aad = {
+ .version = NXP_TLS_VERSION,
+ .len = (u16)size
+ };
+ u8 *ciphertext;
+ u8 *plaintext;
+ int ret = 0;
+
+ ciphertext = kzalloc(sizeof(aad) + size + NXP_ENC_AUTH_TAG_SIZE,
+ GFP_KERNEL);
+ if (!ciphertext)
+ return -ENOMEM;
+
+ plaintext = kzalloc(size + NXP_ENC_AUTH_TAG_SIZE, GFP_KERNEL);
+ if (!plaintext) {
+ ret = -ENOMEM;
+ goto free_ciphertext;
+ }
+
+ memcpy(plaintext, &aad, sizeof(aad));
+ memcpy(plaintext + sizeof(aad), buf, size);
+
+ tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+ if (IS_ERR(tfm)) {
+ ret = PTR_ERR(tfm);
+ goto free_plaintext;
+ }
+
+ crypto_aead_setkey(tfm, key, AES_KEYSIZE_128);
+ crypto_aead_setauthsize(tfm, NXP_ENC_AUTH_TAG_SIZE);
+
+ req = aead_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ ret = -ENOMEM;
+ goto free_tfm;
+ }
+
+ sg_init_one(&src, plaintext, size + NXP_ENC_AUTH_TAG_SIZE);
+ sg_init_one(&dst, ciphertext, sizeof(aad) + size + NXP_ENC_AUTH_TAG_SIZE);
+ init_completion(&nxpdev->crypto.completion);
+
+ aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ nxp_aead_complete, &nxpdev->crypto);
+ aead_request_set_crypt(req, &src, &dst, size, iv);
+ aead_request_set_ad(req, sizeof(aad));
+
+ ret = crypto_aead_encrypt(req);
+ if (ret == -EINPROGRESS || ret == -EBUSY) {
+ wait_for_completion(&nxpdev->crypto.completion);
+ ret = nxpdev->crypto.decrypt_result;
+ }
+ if (!ret) {
+ memcpy(buf, ciphertext + sizeof(aad), size);
+ memcpy(auth_tag, ciphertext + size + sizeof(aad), NXP_ENC_AUTH_TAG_SIZE);
+ }
+
+ aead_request_free(req);
+free_tfm:
+ crypto_free_aead(tfm);
+free_plaintext:
+ kfree(plaintext);
+free_ciphertext:
+ kfree(ciphertext);
+ return ret;
+}
+
+static int nxp_handshake_decrypt_verify(struct hci_dev *hdev, void *buf, size_t size,
+ u8 auth_tag[16],
+ u8 traffic_secret[SHA256_DIGEST_SIZE])
+{
+ u8 key[AES_KEYSIZE_128] = {0};
+ u8 iv[GCM_AES_IV_SIZE] = {0};
+
+ nxp_hkdf_expand_label(traffic_secret, NXP_TLS_KEYING_KEY_LABEL, NULL, 0,
+ key, AES_KEYSIZE_128);
+ nxp_hkdf_expand_label(traffic_secret, NXP_TLS_KEYING_IV_LABEL, NULL, 0,
+ iv, GCM_AES_IV_SIZE);
+
+ return nxp_aes_gcm_decrypt(hdev, buf, size, auth_tag, key, iv);
+}
+
+static int nxp_handshake_encrypt(struct hci_dev *hdev, void *buf,
+ size_t size, u8 auth_tag[16],
+ u8 traffic_secret[SHA256_DIGEST_SIZE])
+{
+ u8 key[AES_KEYSIZE_128] = {0};
+ u8 iv[GCM_AES_IV_SIZE] = {0};
+
+ nxp_hkdf_expand_label(traffic_secret, NXP_TLS_KEYING_KEY_LABEL, NULL,
+ 0, key, AES_KEYSIZE_128);
+ nxp_hkdf_expand_label(traffic_secret, NXP_TLS_KEYING_IV_LABEL, NULL,
+ 0, iv, GCM_AES_IV_SIZE);
+
+ return nxp_aes_gcm_encrypt(hdev, buf, size, auth_tag, key, iv);
+}
+
+static int nxp_p256_ecdsa_verify(const u8 sig[64], const u8 pub[65],
+ const u8 *hash, size_t hash_len)
+{
+ struct public_key_signature sig_info = {0};
+ struct public_key pub_key = {0};
+ int ret;
+
+ sig_info.s = (u8 *)sig;
+ sig_info.s_size = 64;
+ sig_info.digest = (u8 *)hash;
+ sig_info.digest_size = hash_len;
+ sig_info.pkey_algo = "ecdsa";
+ sig_info.hash_algo = "sha256";
+ sig_info.encoding = "p1363";
+
+ pub_key.key = (void *)pub;
+ pub_key.keylen = 65;
+ pub_key.algo = OID_id_ecPublicKey;
+ pub_key.key_is_private = false;
+ pub_key.pkey_algo = "ecdsa-nist-p256";
+ pub_key.id_type = NULL;
+
+ ret = public_key_verify_signature(&pub_key, &sig_info);
+ if (ret)
+ pr_err("ECDSA signature verification failed: %d\n", ret);
+
+ return ret;
+}
+
+static int nxp_device_hello_sig_verify(struct hci_dev *hdev, struct nxp_tls_device_hello *msg)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ u8 hash_sig[SHA256_DIGEST_SIZE];
+
+ nxp_handshake_sig_hash(nxpdev->crypto.handshake_h2_hash,
+ "D HS SIG", 8, hash_sig);
+ return nxp_p256_ecdsa_verify(msg->enc.device_handshake_sig.sig,
+ nxpdev->crypto.ecdsa_public,
+ hash_sig, SHA256_DIGEST_SIZE);
+}
+
+static int nxp_write_finished(struct hci_dev *hdev,
+ const u8 hs_traffic_secret[SHA256_DIGEST_SIZE],
+ u8 verify_data[SHA256_DIGEST_SIZE])
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ u8 transcript_hash[SHA256_DIGEST_SIZE];
+ u8 finished_key[SHA256_DIGEST_SIZE];
+ int ret = 0;
+
+ ret = nxp_crypto_shash_final(nxpdev->crypto.tls_handshake_hash_desc,
+ transcript_hash);
+ if (ret)
+ return ret;
+
+ ret = nxp_hkdf_expand_label(hs_traffic_secret, NXP_TLS_FINISHED_LABEL,
+ NULL, 0, finished_key, sizeof(finished_key));
+ if (ret)
+ return ret;
+
+ nxp_hkdf_sha256_extract(finished_key, SHA256_DIGEST_SIZE, transcript_hash,
+ SHA256_DIGEST_SIZE, verify_data);
+
+ return 0;
+}
+
+static int nxp_verify_device_finished(struct hci_dev *hdev,
+ struct nxp_tls_device_hello *msg,
+ const u8 hs_traffic_secret[SHA256_DIGEST_SIZE])
+{
+ u8 verify_data[SHA256_DIGEST_SIZE] = {0};
+ int ret = 0;
+
+ ret = nxp_write_finished(hdev, hs_traffic_secret, verify_data);
+ if (ret)
+ return ret;
+
+ if (memcmp(verify_data, msg->enc.device_finished.verify_data,
+ SHA256_DIGEST_SIZE))
+ return -EBADMSG;
+
+ return 0;
+}
+
static int nxp_process_device_hello(struct hci_dev *hdev, struct nxp_tls_device_hello *msg)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
@@ -2025,9 +2415,51 @@ static int nxp_process_device_hello(struct hci_dev *hdev, struct nxp_tls_device_
if (ret)
goto fail;
- /* TODO: Verify Signature in Device Hello using ECDSA Public Key
- * extracted from the FW metadata.
+ ret = nxp_handshake_decrypt_verify(hdev, &msg->enc, sizeof(msg->enc),
+ msg->auth_tag, hs_traffic_secret);
+ if (ret)
+ goto fail;
+
+ /*
+ * Verify ECDSA signature handshake_sig using Device's public key from FW metadata.
+ *
+ * This is the key point where Device authentication happens:
+ * - Host generates a random (HostHello.random)
+ * - Device signs the entire handshake (incl. Host's random) with its
+ * private key (DeviceHello.device_handshake_sig)
+ * - Host now verifies ECDSA signature generated by device using Device's
+ * public key
+ *
+ * Only the device that possesses the proper private key could sign the
+ * Host's random.
+ * If the device is an impostor and does not pose a valid private key,
+ * the handshake will fail at this point.
*/
+ ret = nxp_get_pub_key(hdev, &msg->enc.device_info, nxpdev->crypto.ecdsa_public);
+ if (ret)
+ goto fail;
+
+ ret = nxp_device_hello_sig_verify(hdev, msg);
+ if (ret)
+ goto fail;
+
+ ret = crypto_shash_update(nxpdev->crypto.tls_handshake_hash_desc,
+ (u8 *)&msg->enc,
+ DEVICE_HELLO_FINISHED_ENC_CUTOFF_POS);
+ if (ret)
+ goto fail;
+
+ ret = nxp_verify_device_finished(hdev, msg, hs_traffic_secret);
+ if (ret)
+ goto fail;
+
+ ret = crypto_shash_update(nxpdev->crypto.tls_handshake_hash_desc,
+ (u8 *)&msg->enc.device_finished,
+ sizeof(msg->enc.device_finished));
+ if (ret)
+ goto fail;
+
+ memset(hs_traffic_secret, 0, SHA256_DIGEST_SIZE);
fail:
memset(shared_secret, 0, 32);
@@ -2035,6 +2467,64 @@ static int nxp_process_device_hello(struct hci_dev *hdev, struct nxp_tls_device_
return ret;
}
+static int nxp_host_do_finished(struct hci_dev *hdev)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ union nxp_tls_host_finished_payload finished;
+ struct nxp_tls_host_finished *msg = &finished.host_finished;
+ u8 hs_traffic_secret[SHA256_DIGEST_SIZE];
+ struct sk_buff *skb;
+ u8 *status;
+ int ret = 0;
+
+ memset(msg, 0, sizeof(*msg));
+ nxp_tls_hdr_init(&msg->hdr, sizeof(*msg), NXP_TLS_HOST_FINISHED);
+
+ crypto_shash_update(nxpdev->crypto.tls_handshake_hash_desc,
+ (u8 *)msg, HOST_FINISHED_CUTOFF_POS);
+
+ ret = nxp_hkdf_derive_secret(nxpdev->crypto.handshake_secret,
+ NXP_TLS_HOST_HS_TS_LABEL,
+ nxpdev->crypto.handshake_h2_hash,
+ hs_traffic_secret);
+ if (ret)
+ return ret;
+
+ ret = nxp_write_finished(hdev, hs_traffic_secret,
+ msg->enc.host_finished.verify_data);
+ if (ret)
+ return ret;
+
+ crypto_shash_update(nxpdev->crypto.tls_handshake_hash_desc,
+ (u8 *)&msg->enc.host_finished, sizeof(msg->enc.host_finished));
+
+ nxp_handshake_encrypt(hdev, &msg->enc, sizeof(msg->enc),
+ msg->auth_tag, hs_traffic_secret);
+
+ finished.msg_type = 0x01;
+
+ skb = __hci_cmd_sync(hdev, HCI_NXP_SHI_ENCRYPT,
+ sizeof(finished), finished.buf,
+ HCI_CMD_TIMEOUT);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Host Finished error %ld", PTR_ERR(skb));
+ return PTR_ERR(skb);
+ }
+ status = skb_pull_data(skb, 1);
+ if (!status) {
+ ret = -EIO;
+ goto fail;
+ }
+ if (*status) {
+ ret = -EIO;
+ bt_dev_err(hdev, "Host Finished status error: %d", *status);
+ }
+
+fail:
+ kfree_skb(skb);
+ return ret;
+}
+
static int nxp_authenticate_device(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
@@ -2085,10 +2575,13 @@ static int nxp_authenticate_device(struct hci_dev *hdev)
if (ret)
goto free_skb;
+ ret = nxp_host_do_finished(hdev);
+ if (ret)
+ goto free_skb;
+
/* TODO: Implement actual TLS handshake protocol
* This will include:
- * 1. Send Host Finish TLS message
- * 2. Master secret and traffic key derivation
+ * 1. Master secret and traffic key derivation
*/
free_skb:
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication
2025-11-18 14:20 ` [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication Neeraj Sanjay Kale
@ 2025-11-20 14:46 ` kernel test robot
2025-11-22 11:03 ` kernel test robot
1 sibling, 0 replies; 20+ messages in thread
From: kernel test robot @ 2025-11-20 14:46 UTC (permalink / raw)
To: Neeraj Sanjay Kale, marcel, luiz.dentz
Cc: oe-kbuild-all, linux-bluetooth, linux-kernel, amitkumar.karwar,
sherry.sun, dmitrii.lebed, neeraj.sanjaykale
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]
[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-8-neeraj.sanjaykale%40nxp.com
patch subject: [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication
config: i386-randconfig-061-20251120 (https://download.01.org/0day-ci/archive/20251120/202511202234.PN8Zn4v7-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251120/202511202234.PN8Zn4v7-lkp@intel.com/reproduce)
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/202511202234.PN8Zn4v7-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
drivers/bluetooth/btnxpuart.c:1433:55: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1441:27: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1446:47: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1447:32: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1450:26: sparse: sparse: restricted __le32 degrades to integer
drivers/bluetooth/btnxpuart.c:1529:17: sparse: sparse: restricted __le32 degrades to integer
>> drivers/bluetooth/btnxpuart.c:1758:64: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] chipid @@ got restricted __le16 const [usertype] chip_id @@
drivers/bluetooth/btnxpuart.c:1758:64: sparse: expected unsigned short [usertype] chipid
drivers/bluetooth/btnxpuart.c:1758:64: sparse: got restricted __le16 const [usertype] chip_id
>> drivers/bluetooth/btnxpuart.c:1759:58: sparse: sparse: incorrect type in argument 3 (different base types) @@ expected unsigned char [usertype] loader_ver @@ got restricted __le16 const [usertype] device_flags @@
drivers/bluetooth/btnxpuart.c:1759:58: sparse: expected unsigned char [usertype] loader_ver
drivers/bluetooth/btnxpuart.c:1759:58: sparse: got restricted __le16 const [usertype] device_flags
>> drivers/bluetooth/btnxpuart.c:2114:25: sparse: sparse: incorrect type in initializer (different base types) @@ expected restricted __le16 [usertype] len @@ got unsigned short [usertype] @@
drivers/bluetooth/btnxpuart.c:2114:25: sparse: expected restricted __le16 [usertype] len
drivers/bluetooth/btnxpuart.c:2114:25: sparse: got unsigned short [usertype]
drivers/bluetooth/btnxpuart.c:2186:25: sparse: sparse: incorrect type in initializer (different base types) @@ expected restricted __le16 [usertype] len @@ got unsigned short [usertype] @@
drivers/bluetooth/btnxpuart.c:2186:25: sparse: expected restricted __le16 [usertype] len
drivers/bluetooth/btnxpuart.c:2186:25: sparse: got unsigned short [usertype]
vim +1758 drivers/bluetooth/btnxpuart.c
1746
1747 /* Secure Interface */
1748 static int nxp_get_pub_key(struct hci_dev *hdev,
1749 const struct nxp_tls_device_info *device_info,
1750 u8 ecdsa_pub_key[NXP_FW_ECDSA_PUBKEY_SIZE])
1751 {
1752 struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
1753 const char *fw_name;
1754
1755 if (ecdsa_pub_key[0] == 0x04)
1756 return 0;
1757
> 1758 fw_name = nxp_get_fw_name_from_chipid(hdev, device_info->chip_id,
> 1759 device_info->device_flags);
1760 if (nxp_request_firmware(hdev, fw_name, NULL))
1761 return -ENOENT;
1762
1763 nxp_process_fw_meta_data(hdev, nxpdev->fw);
1764 release_firmware(nxpdev->fw);
1765 memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
1766
1767 if (memcmp(nxpdev->crypto.fw_uuid, device_info->uuid, 16) ||
1768 nxpdev->crypto.ecdsa_public[0] != 0x04) {
1769 bt_dev_err(hdev,
1770 "UUID check failed while trying to read ECDSA public key from FW.");
1771 return -EBADF;
1772 }
1773
1774 memcpy(ecdsa_pub_key, nxpdev->crypto.ecdsa_public, 65);
1775
1776 return 0;
1777 }
1778
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication
2025-11-18 14:20 ` [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication Neeraj Sanjay Kale
2025-11-20 14:46 ` kernel test robot
@ 2025-11-22 11:03 ` kernel test robot
1 sibling, 0 replies; 20+ messages in thread
From: kernel test robot @ 2025-11-22 11:03 UTC (permalink / raw)
To: Neeraj Sanjay Kale, marcel, luiz.dentz
Cc: llvm, oe-kbuild-all, linux-bluetooth, linux-kernel,
amitkumar.karwar, sherry.sun, dmitrii.lebed, neeraj.sanjaykale
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-20251121]
[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-8-neeraj.sanjaykale%40nxp.com
patch subject: [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication
config: arm-randconfig-001-20251122 (https://download.01.org/0day-ci/archive/20251122/202511221835.jzKFsvPM-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 9e9fe08b16ea2c4d9867fb4974edf2a3776d6ece)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251122/202511221835.jzKFsvPM-lkp@intel.com/reproduce)
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/202511221835.jzKFsvPM-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/bluetooth/btnxpuart.c:459:29: warning: field host_hello within 'struct nxp_tls_host_hello_payload::(anonymous at drivers/bluetooth/btnxpuart.c:457:2)' is less aligned than 'struct nxp_tls_host_hello' and is usually due to 'struct nxp_tls_host_hello_payload::(anonymous at drivers/bluetooth/btnxpuart.c:457:2)' being packed, which can lead to unaligned accesses [-Wunaligned-access]
459 | struct nxp_tls_host_hello host_hello;
| ^
>> drivers/bluetooth/btnxpuart.c:513:32: warning: field host_finished within 'struct nxp_tls_host_finished_payload::(anonymous at drivers/bluetooth/btnxpuart.c:511:2)' is less aligned than 'struct nxp_tls_host_finished' and is usually due to 'struct nxp_tls_host_finished_payload::(anonymous at drivers/bluetooth/btnxpuart.c:511:2)' being packed, which can lead to unaligned accesses [-Wunaligned-access]
513 | struct nxp_tls_host_finished host_finished;
| ^
2 warnings generated.
vim +513 drivers/bluetooth/btnxpuart.c
455
456 union nxp_tls_host_hello_payload {
457 struct {
458 u8 msg_type;
> 459 struct nxp_tls_host_hello host_hello;
460 } __packed;
461 u8 buf[113];
462 };
463
464 struct nxp_tls_device_info {
465 __le16 chip_id;
466 __le16 device_flags;
467 u8 reserved[4];
468 u8 uuid[NXP_DEVICE_UUID_LEN];
469 };
470
471 struct nxp_tls_signature {
472 u8 sig[64]; /* P-256 ECDSA signature, two points */
473 };
474
475 struct nxp_tls_finished {
476 u8 verify_data[32];
477 };
478
479 struct nxp_tls_device_hello {
480 struct nxp_tls_message_hdr hdr;
481 __le32 reserved;
482 u8 random[32];
483 u8 pubkey[NXP_TLS_ECDH_PUBLIC_KEY_SIZE];
484 /* Encrypted portion */
485 struct {
486 struct nxp_tls_device_info device_info;
487 struct nxp_tls_signature device_handshake_sig; /* TLS Certificate Verify */
488 struct nxp_tls_finished device_finished;
489 } enc;
490 u8 auth_tag[NXP_ENC_AUTH_TAG_SIZE]; /* Auth tag for the encrypted portion */
491 };
492
493 struct nxp_tls_data_add {
494 u8 version; /* NXP_TLS_VERSION */
495 u8 reserved[5]; /* zeroes */
496 __le16 len;
497 };
498
499 struct nxp_tls_host_finished {
500 struct nxp_tls_message_hdr hdr;
501 __le32 reserved;
502 /* Encrypted portion */
503 struct {
504 struct nxp_tls_signature reserved2;
505 struct nxp_tls_finished host_finished;
506 } enc;
507 u8 auth_tag[NXP_ENC_AUTH_TAG_SIZE]; /* Auth tag for the encrypted portion */
508 };
509
510 union nxp_tls_host_finished_payload {
511 struct {
512 u8 msg_type;
> 513 struct nxp_tls_host_finished host_finished;
514 } __packed;
515 u8 buf[125];
516 };
517
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v1 08/11] Bluetooth: btnxpuart: Derive traffic keys from TLS 1.3 handshake
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
` (6 preceding siblings ...)
2025-11-18 14:20 ` [PATCH v1 07/11] Bluetooth: btnxpuart: Add device authentication Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands Neeraj Sanjay Kale
` (2 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This completes the TLS handshake implementation by adding master secret
derivation and traffic key generation. These traffic keys will be used
to encrypt/decrypt sensitive HCI commands, response and events.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 88 +++++++++++++++++++++++++++++++++--
1 file changed, 84 insertions(+), 4 deletions(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index bfe6a138d78d..4b03b0321e82 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -206,6 +206,16 @@ enum bootloader_param_change {
changed
};
+struct nxp_tls_traffic_keys {
+ u8 h2d_secret[SHA256_DIGEST_SIZE];
+ u8 d2h_secret[SHA256_DIGEST_SIZE];
+ /* These keys below should be used for message encryption/decryption */
+ u8 h2d_iv[GCM_AES_IV_SIZE];
+ u8 h2d_key[AES_KEYSIZE_128];
+ u8 d2h_iv[GCM_AES_IV_SIZE];
+ u8 d2h_key[AES_KEYSIZE_128];
+};
+
struct btnxpuart_crypto {
struct crypto_shash *tls_handshake_hash_tfm;
struct shash_desc *tls_handshake_hash_desc;
@@ -215,8 +225,10 @@ struct btnxpuart_crypto {
u8 fw_uuid[NXP_FW_UUID_SIZE];
u8 handshake_h2_hash[SHA256_DIGEST_SIZE];
u8 handshake_secret[SHA256_DIGEST_SIZE];
+ u8 master_secret[SHA256_DIGEST_SIZE];
struct completion completion;
int decrypt_result;
+ struct nxp_tls_traffic_keys keys;
};
struct btnxpuart_dev {
@@ -416,7 +428,10 @@ union nxp_set_bd_addr_payload {
#define NXP_TLS_KEYING_IV_LABEL NXP_TLS_LABEL("iv")
#define NXP_TLS_KEYING_KEY_LABEL NXP_TLS_LABEL("key")
#define NXP_TLS_FINISHED_LABEL NXP_TLS_LABEL("finished")
+#define NXP_TLS_DERIVED_LABEL NXP_TLS_LABEL("derived")
#define NXP_TLS_HOST_HS_TS_LABEL NXP_TLS_LABEL("H HS TS")
+#define NXP_TLS_D_AP_TS_LABEL NXP_TLS_LABEL("D AP TS")
+#define NXP_TLS_H_AP_TS_LABEL NXP_TLS_LABEL("H AP TS")
enum nxp_tls_signature_algorithm {
NXP_TLS_ECDSA_SECP256R1_SHA256 = 0x0403,
@@ -2525,6 +2540,71 @@ static int nxp_host_do_finished(struct hci_dev *hdev)
return ret;
}
+static void nxp_handshake_derive_master_secret(u8 master_secret[SHA256_DIGEST_SIZE],
+ u8 handshake_secret[SHA256_DIGEST_SIZE])
+{
+ u8 zeros[SHA256_DIGEST_SIZE] = {0};
+ u8 dhs[SHA256_DIGEST_SIZE];
+
+ /* Derive intermediate secret */
+ nxp_hkdf_expand_label(handshake_secret, NXP_TLS_DERIVED_LABEL,
+ NULL, 0, dhs, sizeof(dhs));
+ /* Extract master secret from derived handshake secret */
+ nxp_hkdf_sha256_extract(dhs, SHA256_DIGEST_SIZE, zeros,
+ sizeof(zeros), master_secret);
+
+ memset(dhs, 0, sizeof(dhs));
+}
+
+static int nxp_handshake_derive_traffic_keys(struct hci_dev *hdev)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct nxp_tls_traffic_keys *keys = &nxpdev->crypto.keys;
+ u8 hash[SHA256_DIGEST_SIZE];
+ int ret = 0;
+
+ ret = crypto_shash_final(nxpdev->crypto.tls_handshake_hash_desc, hash);
+ if (ret)
+ return ret;
+
+ ret = nxp_hkdf_derive_secret(nxpdev->crypto.master_secret,
+ NXP_TLS_D_AP_TS_LABEL, hash, keys->d2h_secret);
+ if (ret)
+ return ret;
+
+ ret = nxp_hkdf_expand_label(keys->d2h_secret,
+ NXP_TLS_KEYING_KEY_LABEL, NULL, 0,
+ keys->d2h_key, AES_KEYSIZE_128);
+ if (ret)
+ return ret;
+
+ ret = nxp_hkdf_expand_label(keys->d2h_secret,
+ NXP_TLS_KEYING_IV_LABEL, NULL, 0,
+ keys->d2h_iv, GCM_AES_IV_SIZE);
+ if (ret)
+ return ret;
+
+ ret = nxp_hkdf_derive_secret(nxpdev->crypto.master_secret,
+ NXP_TLS_H_AP_TS_LABEL, hash, keys->h2d_secret);
+ if (ret)
+ return ret;
+
+ ret = nxp_hkdf_expand_label(keys->h2d_secret,
+ NXP_TLS_KEYING_KEY_LABEL, NULL, 0,
+ keys->h2d_key, AES_KEYSIZE_128);
+ if (ret)
+ return ret;
+
+ ret = nxp_hkdf_expand_label(keys->h2d_secret,
+ NXP_TLS_KEYING_IV_LABEL, NULL, 0,
+ keys->h2d_iv, GCM_AES_IV_SIZE);
+ if (ret)
+ return ret;
+
+ memset(hash, 0, sizeof(hash));
+ return ret;
+}
+
static int nxp_authenticate_device(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
@@ -2579,10 +2659,10 @@ static int nxp_authenticate_device(struct hci_dev *hdev)
if (ret)
goto free_skb;
- /* TODO: Implement actual TLS handshake protocol
- * This will include:
- * 1. Master secret and traffic key derivation
- */
+ nxp_handshake_derive_master_secret(nxpdev->crypto.master_secret,
+ nxpdev->crypto.handshake_secret);
+
+ nxp_handshake_derive_traffic_keys(hdev);
free_skb:
kfree_skb(skb);
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
` (7 preceding siblings ...)
2025-11-18 14:20 ` [PATCH v1 08/11] Bluetooth: btnxpuart: Derive traffic keys from TLS 1.3 handshake Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-20 8:40 ` kernel test robot
2025-11-18 14:20 ` [PATCH v1 10/11] Bluetooth: btnxpuart: Add encrypted event handling Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 11/11] Bluetooth: btnxpuart: Select crypto algorithms for secure interface Neeraj Sanjay Kale
10 siblings, 1 reply; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
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
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands
2025-11-18 14:20 ` [PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands Neeraj Sanjay Kale
@ 2025-11-20 8:40 ` kernel test robot
0 siblings, 0 replies; 20+ messages in thread
From: kernel test robot @ 2025-11-20 8:40 UTC (permalink / raw)
To: Neeraj Sanjay Kale, marcel, luiz.dentz
Cc: oe-kbuild-all, linux-bluetooth, linux-kernel, amitkumar.karwar,
sherry.sun, dmitrii.lebed, neeraj.sanjaykale
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
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v1 10/11] Bluetooth: btnxpuart: Add encrypted event handling
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
` (8 preceding siblings ...)
2025-11-18 14:20 ` [PATCH v1 09/11] Bluetooth: btnxpuart: Add command encryption for sensitive HCI commands Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
2025-11-18 14:20 ` [PATCH v1 11/11] Bluetooth: btnxpuart: Select crypto algorithms for secure interface Neeraj Sanjay Kale
10 siblings, 0 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This adds support for receiving and decrypting vendor events from secure
NXP chip and forwarding the decrypted sensitive HCI events to the BT
stack.
The NXP BT chip encrypts the Link Key Notification event that is usually
sent in plaintext over UART lines.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 99 ++++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 452fff651d82..72b14cbe03f2 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -228,6 +228,7 @@ struct btnxpuart_crypto {
u8 handshake_secret[SHA256_DIGEST_SIZE];
u8 master_secret[SHA256_DIGEST_SIZE];
u64 enc_seq_no;
+ u64 dec_seq_no;
struct completion completion;
int decrypt_result;
struct nxp_tls_traffic_keys keys;
@@ -2749,6 +2750,102 @@ static struct sk_buff *nxp_crypto_encrypt_cmd(struct hci_dev *hdev,
return skb;
}
+static int nxp_crypto_event(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ int ciphertext_size;
+ u8 *ciphertext;
+ u8 aes_gcm_tag[NXP_ENC_AUTH_TAG_SIZE];
+ u8 nonce[GCM_AES_IV_SIZE];
+ int ret;
+ struct sk_buff *event_skb;
+ struct nxp_tls_traffic_keys *keys = &nxpdev->crypto.keys;
+
+ if (skb->len < NXP_ENC_AUTH_TAG_SIZE) {
+ bt_dev_err(hdev, "Encrypted event too short: %d", skb->len);
+ return -EINVAL;
+ }
+ ciphertext_size = skb->len - NXP_ENC_AUTH_TAG_SIZE;
+ ciphertext = kzalloc(ciphertext_size, GFP_KERNEL);
+ if (!ciphertext)
+ return -ENOMEM;
+
+ memcpy(ciphertext, skb->data, ciphertext_size);
+ memcpy(aes_gcm_tag, skb->data + ciphertext_size, NXP_ENC_AUTH_TAG_SIZE);
+
+ nxp_data_calc_nonce(keys->d2h_iv, nxpdev->crypto.dec_seq_no, nonce);
+
+ ret = nxp_aes_gcm_decrypt(hdev, ciphertext, ciphertext_size,
+ aes_gcm_tag, keys->d2h_key, nonce);
+ if (ret) {
+ kfree(ciphertext);
+ return ret;
+ }
+
+ event_skb = bt_skb_alloc(ciphertext_size, GFP_ATOMIC);
+ if (!event_skb) {
+ kfree(ciphertext);
+ return -ENOMEM;
+ }
+
+ hci_skb_pkt_type(event_skb) = HCI_EVENT_PKT;
+ skb_put_data(event_skb, ciphertext, ciphertext_size);
+
+ nxpdev->crypto.dec_seq_no++;
+
+ kfree(ciphertext);
+
+ /* Inject Decrypted Event to upper stack */
+ return hci_recv_frame(hdev, event_skb);
+}
+
+static int nxp_process_vendor_event(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct hci_event_hdr *vendor_event_hdr;
+ u8 *vendor_sub_event;
+
+ vendor_event_hdr = (struct hci_event_hdr *)skb_pull_data(skb,
+ sizeof(*vendor_event_hdr));
+ if (!vendor_event_hdr)
+ goto free_skb;
+
+ if (!vendor_event_hdr->plen)
+ goto free_skb;
+
+ vendor_sub_event = skb_pull_data(skb, 1);
+ if (!vendor_sub_event)
+ goto free_skb;
+
+ switch (*vendor_sub_event) {
+ case 0x23:
+ break; // Power Save Enable/Disable vendor response. Can be ignored.
+ case 0xe3:
+ if (nxpdev->secure_interface)
+ nxp_crypto_event(hdev, skb);
+ else
+ bt_dev_warn(hdev, "Unexpected encrypted event");
+ break;
+ default:
+ bt_dev_err(hdev, "Unknown vendor event subtype: %d", *vendor_sub_event);
+ break;
+ }
+
+free_skb:
+ kfree_skb(skb);
+ return 0;
+}
+
+static int nxp_recv_event_frame(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ u8 event = hci_event_hdr(skb)->evt;
+
+ if (event == 0xff)
+ return nxp_process_vendor_event(hdev, skb);
+ else
+ return hci_recv_frame(hdev, skb);
+}
+
/* NXP protocol */
static int nxp_setup(struct hci_dev *hdev)
{
@@ -3076,7 +3173,7 @@ static int btnxpuart_flush(struct hci_dev *hdev)
static const struct h4_recv_pkt nxp_recv_pkts[] = {
{ H4_RECV_ACL, .recv = nxp_recv_acl_pkt },
{ H4_RECV_SCO, .recv = hci_recv_frame },
- { H4_RECV_EVENT, .recv = hci_recv_frame },
+ { H4_RECV_EVENT, .recv = nxp_recv_event_frame },
{ H4_RECV_ISO, .recv = hci_recv_frame },
{ NXP_RECV_CHIP_VER_V1, .recv = nxp_recv_chip_ver_v1 },
{ NXP_RECV_FW_REQ_V1, .recv = nxp_recv_fw_req_v1 },
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 11/11] Bluetooth: btnxpuart: Select crypto algorithms for secure interface
2025-11-18 14:20 [PATCH v1 00/11] Bluetooth: btnxpuart: Add secure interface support for NXP chipsets Neeraj Sanjay Kale
` (9 preceding siblings ...)
2025-11-18 14:20 ` [PATCH v1 10/11] Bluetooth: btnxpuart: Add encrypted event handling Neeraj Sanjay Kale
@ 2025-11-18 14:20 ` Neeraj Sanjay Kale
10 siblings, 0 replies; 20+ messages in thread
From: Neeraj Sanjay Kale @ 2025-11-18 14:20 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar, sherry.sun,
dmitrii.lebed, neeraj.sanjaykale
This adds crypto dependencies (ECDSA, ECDH, AES-GCM, SHA256, HMAC)
needed for TLS-based secure host interface authentication and
encryption.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
drivers/bluetooth/Kconfig | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index c5d45cf91f88..ccbd2e13977e 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -493,6 +493,13 @@ config BT_NXPUART
select BT_HCIUART_H4
select CRC32
select CRC8
+ select CRYPTO
+ select CRYPTO_ECDSA
+ select CRYPTO_ECDH
+ select CRYPTO_AES
+ select CRYPTO_GCM
+ select CRYPTO_SHA256
+ select CRYPTO_HMAC
help
NXP is serial driver required for NXP Bluetooth
devices with UART interface.
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread