Bluetooth: hci_nxp: Improve MAC address uniqueness using CRC-32 hash
The previous method of deriving the local MAC address from the MCU's
Unique ID (UID) by slicing the last 3 bytes had two issues:
1. **Low Entropy:** Risk of address collision because only a small
portion of the UID was used, and this portion may not vary much.
2. **Offset Error:** An incorrect offset calculation could copy
non-intended bytes.
This commit resolves both issues by replacing the slice operation
with a **CRC-32 hash** over the **entire 16-byte UID**.
The lower 3 bytes (24 bits) of the resulting CRC-32 are used as the
local part of the MAC address, maximizing randomization and ensuring
a high probability of uniqueness across all devices.
Signed-off-by: Badr Bacem KAABIA <badrbacemkaabia@gmail.com>
diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig
index ad9ae6b..f07d35f 100644
--- a/drivers/bluetooth/hci/Kconfig
+++ b/drivers/bluetooth/hci/Kconfig
@@ -255,6 +255,7 @@
default y
depends on DT_HAS_NXP_HCI_BLE_ENABLED
select BT_HCI_SETUP
+ select CRC if BT_HCI_SET_PUBLIC_ADDR
help
NXP HCI bluetooth interface
diff --git a/drivers/bluetooth/hci/hci_nxp.c b/drivers/bluetooth/hci/hci_nxp.c
index 8d91fb1..727f834 100644
--- a/drivers/bluetooth/hci/hci_nxp.c
+++ b/drivers/bluetooth/hci/hci_nxp.c
@@ -12,6 +12,7 @@
#include <zephyr/drivers/bluetooth.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/byteorder.h>
+#include <zephyr/sys/crc.h>
#include <zephyr/device.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/bluetooth/hci_types.h>
@@ -50,6 +51,7 @@
#define HCI_CMD_BT_HOST_SLEEP_CONFIG_OCF 0x59U
#define HCI_CMD_BT_HOST_SLEEP_CONFIG_PARAM_LENGTH 2U
#define HCI_CMD_BT_HOST_SET_MAC_ADDR_PARAM_LENGTH 8U
+#define HCI_BT_MAC_ADDR_CRC_SEED 0xFFFFFFFFU
#define HCI_SET_MAC_ADDR_CMD 0x0022U
#define BT_USER_BD 254
#define BD_ADDR_OUI 0x37U, 0x60U, 0x00U
@@ -178,6 +180,7 @@
uint8_t addrOUI[BD_ADDR_OUI_PART_SIZE] = {BD_ADDR_OUI};
uint8_t uid[16] = {0};
uint8_t uuidLen;
+ uint32_t unique_val_crc = 0;
uint8_t params[HCI_CMD_BT_HOST_SET_MAC_ADDR_PARAM_LENGTH] = {
BT_USER_BD,
0x06U
@@ -188,12 +191,20 @@
*/
if (bt_addr_eq(public_addr, BT_ADDR_ANY) || bt_addr_eq(public_addr, BT_ADDR_NONE)) {
PLATFORM_GetMCUUid(uid, &uuidLen);
- /* Set 3 LSB of MAC address from UUID */
- if (uuidLen > BD_ADDR_UUID_PART_SIZE) {
- memcpy((void *)bleDeviceAddress,
- (void *)(uid + uuidLen - (BD_ADDR_UUID_PART_SIZE + 1)),
- BD_ADDR_UUID_PART_SIZE);
+
+ if (uuidLen > 0) {
+ /* Calculate a 32-bit IEEE CRC over the entire unique ID (uid)
+ * Initial CRC value is 0xFFFFFFFFU for maximum randomization
+ */
+ unique_val_crc = crc32_ieee_update(HCI_BT_MAC_ADDR_CRC_SEED, uid, uuidLen);
+ /* Copy the lower 3 bytes (24 bits) of the CRC result */
+ memcpy((void *)bleDeviceAddress, (const void *)&unique_val_crc,
+ BD_ADDR_UUID_PART_SIZE);
+ } else {
+ LOG_ERR("UUID is empty, cannot generate address.");
+ return -EFAULT;
}
+
/* Set 3 MSB of MAC address from OUI */
memcpy((void *)(bleDeviceAddress + BD_ADDR_UUID_PART_SIZE), (void *)addrOUI,
BD_ADDR_OUI_PART_SIZE);