BLE Device Identity Address definition

1. STM32WB-WBA - Bluetooth® Low Energy Device Identity Address definition

Bluetooth® Low Energy devices have an Identity address associated with each device.
A Bluetooth® Low Energy address is a 48-bit value that uniquely identifies a Bluetooth® Low Energy device.

There are two main types of Bluetooth® Low Energy addresses: Public and Random addresses.

Bluetooth® Low Energy Address Types
Connectivity Privacy BLE addr types.png


The four Bluetooth® address types are:
- Public Address
- Random Static Address
- Random Private Resolvable Address
- Random Private Non-Resolvable Address
Random Address and Private Address, as shown in the diagram, are simply classifications.

1.1. Public Address

Bluetooth’s LE public address is a constant worldwide address; that is, it never changes and is registered with IEEE. The public device address must conform with the IEEE 802-2001 standard, using a valid organization unique identifier (OUI) obtained from the IEEE registration authority. It abides by the same guidelines as MAC addresses, and is an extended unique identifier (EUI-48).
The following diagram represents the simplified format of a public Bluetooth® Low Energy address (LSB first):

Bluetooth® Low Energy public address
Company assigned Company ID
24 bits 24 bits


- Company ID: The publicly assigned portion of the address by the IEEE (MSB)
- Company assigned: The internally assigned ID as part of the allocated block (LSB)

1.2. Random Address

Random Addresses do not require any registration with the IEEE.

A random address is an identifier that is either programmed into the device or generated at runtime. The latter depends on the subtype.
The two subtypes of random addresses are:
- Random Static Address
- Random Private Address

1.2.1. Random Static Address

This specific type of Bluetooth® Low Energy address is a popular alternative to public addresses, as there are no fees involved with its use.

Random Static Addresses can be used in one of two ways:

- Assigned and fixed for the lifetime of the device.
- Changed at bootup.
However, they cannot be changed during runtime.

The format of Random Static Addresses is as follows (LSB first):

Bluetooth® Low Energy random static address
Random part - 46 bits 1 1


- The two most significant bits (MSB) must be set to 1.
- The remaining 46 bits are chosen randomly by the developer or manufacturer and must meet the following requirements:

  • At least one bit of the random part of the address must be 0.
  • At least one bit of the random part of the address must be 1.

1.2.2. Random Private Address

There are two types of Random Private Addresses:

  • Resolvable
  • Non-Resolvable

Random Private Addresses are specifically used to protect the privacy of a Bluetooth® Low Energy device by hiding its identity and preventing tracking of the device.

1.2.3. Resolvable Random Private Address

The purpose of a Resolvable Random Private Address is to prevent malicious third-parties from tracking a Bluetooth device while still allowing one or more trusted parties to identify the Bluetooth® Low Energy device of interest.

A Resolvable Random Private address is “'resolvable”' by using a key shared with a trusted device.
This key is referred to as the identity resolving key (IRK).

The address is originally generated using this IRK and a random number.

So, what makes a device “trusted” by another device?

In this case, a trusted device is a bonded device. Bonding is the optional step that takes place after the pairing of two Bluetooth® Low Energy devices.
The bonding process involves the storage of keys inside the devices that are bonded with each other.
One of the keys exchanged by the two bonded Bluetooth® Low Energy devices is the IRK.

This type of address changes periodically. The recommendation per the Bluetooth specification is to have it change every 15 minutes.

The format of resolvable private addresses looks like this (LSB first):

Bluetooth® Low Energy resolvable private address
Hash Random part 1 0
24 bits prand (24 bits)


- 0 and 1 are fixed in the most significant bits (MSB).
- The next 22 bits are randomly generated.
- The prand constitutes most of the significant 24 bits
- The lower 24 bits represent a hash value, which is generated using the prand and the IRK.

1.2.4. Non-Resolvable Random Private Address

The other type of random private address is the Non-Resolvable Random Private address.

This type of address also changes periodically. However, unlike resolvable addresses, it is Not resolvable by any other device.
The only purpose of this type of address is to prevent tracking by any other Bluetooth® Low Energy device.

This type is not very common, but it is sometimes used in beacon applications.

The format of Non-Resolvable Random Private Addresses is as follows:

Bluetooth® Low Energy Non-Resolvable private address
Random part - 46 bits 0 0


- Bits 0 and 0 are fixed in the most significant bits (MSB). - The remaining 46 bits are chosen at random.

2. Selection of device address type using CubeMX (for WBA)

2.1. Public Address Selection

In the CubeMX configuration tab:

Bluetooth® Low Energy public address selection
Connectivity BLE CMX PublicAddress.png

If CFG_BD_ADDRESS is defined as 0x000000000000, then device address is built using UDN, company ID and device ID.

In app_ble.c:

p_bd_addr = BleGenerateBdAddress();

static const uint8_t* BleGenerateBdAddress(void)
{
  OTP_Data_s *p_otp_addr = NULL;
  const uint8_t *p_bd_addr;
  uint32_t udn;
  uint32_t company_id;
  uint32_t device_id;
  uint8_t a_BdAddrDefault[BD_ADDR_SIZE] ={0x65, 0x43, 0x21, 0x1E, 0x08, 0x00};
  uint8_t a_BDAddrNull[BD_ADDR_SIZE];
  memset(&a_BDAddrNull[0], 0x00, sizeof(a_BDAddrNull));

  a_BdAddr[0] = (uint8_t)(CFG_BD_ADDRESS & 0x0000000000FF);
  a_BdAddr[1] = (uint8_t)((CFG_BD_ADDRESS & 0x00000000FF00) >> 8);
  a_BdAddr[2] = (uint8_t)((CFG_BD_ADDRESS & 0x000000FF0000) >> 16);
  a_BdAddr[3] = (uint8_t)((CFG_BD_ADDRESS & 0x0000FF000000) >> 24);
  a_BdAddr[4] = (uint8_t)((CFG_BD_ADDRESS & 0x00FF00000000) >> 32);
  a_BdAddr[5] = (uint8_t)((CFG_BD_ADDRESS & 0xFF0000000000) >> 40);

  if(memcmp(&a_BdAddr[0], &a_BDAddrNull[0], BD_ADDR_SIZE) != 0)
  {
    p_bd_addr = (const uint8_t *)a_BdAddr;
  }
  else
  {
    udn = LL_FLASH_GetUDN();

    /* USER CODE BEGIN BleGenerateBdAddress */

    /* USER CODE END BleGenerateBdAddress */

    if (udn != 0xFFFFFFFF)
    {
      company_id = LL_FLASH_GetSTCompanyID();
      device_id = LL_FLASH_GetDeviceID();

    /**
     * Public Address with the ST company ID
     * bit[47:24]: 24 bits (OUI) equal to the company ID
     * bit[23:16]: Device ID.
     * bit[15:0]: The last 16 bits from the UDN
     * Note: To use the Public Address in a final product, a dedicated
     * 24-bit company ID (OUI) must be bought.
     */
      a_BdAddr[0] = (uint8_t)(udn & 0x000000FF);
      a_BdAddr[1] = (uint8_t)((udn & 0x0000FF00) >> 8);
      a_BdAddr[2] = (uint8_t)device_id;
      a_BdAddr[3] = (uint8_t)(company_id & 0x000000FF);
      a_BdAddr[4] = (uint8_t)((company_id & 0x0000FF00) >> 8);
      a_BdAddr[5] = (uint8_t)((company_id & 0x00FF0000) >> 16);
      p_bd_addr = (const uint8_t *)a_BdAddr;
    }
    else
    {
      if (OTP_Read(0, &p_otp_addr) == HAL_OK)
      {
        a_BdAddr[0] = p_otp_addr->bd_address[0];
        a_BdAddr[1] = p_otp_addr->bd_address[1];
        a_BdAddr[2] = p_otp_addr->bd_address[2];
        a_BdAddr[3] = p_otp_addr->bd_address[3];
        a_BdAddr[4] = p_otp_addr->bd_address[4];
        a_BdAddr[5] = p_otp_addr->bd_address[5];
        p_bd_addr = (const uint8_t *)a_BdAddr;
      }
      else
      {
        memcpy(&a_BdAddr[0], a_BdAddrDefault,BD_ADDR_SIZE);
        p_bd_addr = (const uint8_t *)a_BdAddr;
      }
    }
  }

  return p_bd_addr;
}

2.2. Static Random Address Selection

In CubeMX configuration tab:

Bluetooth® Low Energy static random address selection
Connectivity BLE CMX StaticRandomAddress.png

CFG_BD_ADDRESS is not used in this case.
STATIC_RANDOM_ADDRESS is selected through CubeMX interface. The two upper bits are set to 1, which corresponds to static random address type).
This address remains unchanged and is not board dependent.

In app_ble.c:

/* The two upper bits shall be set to 1 */
uint32_t p_bd_addr[2];
  p_bd_addr[0] = CFG_STATIC_RANDOM_ADDRESS & 0xFFFFFFFF;
  p_bd_addr[1] = (uint32_t)((uint64_t)CFG_STATIC_RANDOM_ADDRESS >> 32);
  p_bd_addr[1] |= 0xC000; /* The two upper bits shall be set to 1 */

2.3. Static Random Address Selection (static unique type)

In CubeMX configuration tab:

Bluetooth® Low Energy Static Random Address Selection (static unique type)
Connectivity BLE CMX StaticRandomAddressUnique 2.png

CFG_BD_ADDRESS is not used in this case.
Device ID, UDN and Random_id number are used to build the address.
Company ID must not be used.
Random_id number can be modified in User Section.

In app_ble.c:

  /**
   * Static random Address
   * The two upper bits shall be set to 1
   * The lowest 32bits is read from the UDN to differentiate between devices
   * The RNG may be used to provide a random number on each power on
   */
  uint32_t random_id = 0x223344;
  uint32_t device_id;
  uint32_t udn;
  udn = LL_FLASH_GetUDN();

  device_id = LL_FLASH_GetDeviceID();

  a_BdAddr[0] = (uint8_t)(udn & 0x000000FF);
  a_BdAddr[1] = (uint8_t)((udn & 0x0000FF00) >> 8);
  a_BdAddr[2] = (uint8_t)device_id;

  /* USER CODE BEGIN Random ID */

  /* USER CODE END Random ID */

  a_BdAddr[3] = (uint8_t)(random_id & 0x000000FF);

  p_bd_addr [0] = (a_BdAddr[3] << 24 | a_BdAddr[2] << 16 | a_BdAddr[1] << 8 | a_BdAddr[0]);
  a_BdAddr[4] = (uint8_t)((random_id & 0x0000FF00) >> 8);
  a_BdAddr[5] = (uint8_t)((random_id & 0x00FF0000) >> 16);

  p_bd_addr [1] = (a_BdAddr[5] << 8) | (a_BdAddr[4]);
  p_bd_addr [1] |= 0xC000; /* The two upper bits shall be set to 1 */

  ret = aci_hal_write_config_data(CONFIG_DATA_RANDOM_ADDRESS_OFFSET, CONFIG_DATA_RANDOM_ADDRESS_LEN, (uint8_t*)p_bd_addr);
  if (ret != BLE_STATUS_SUCCESS)
  {
    LOG_INFO_APP("  Fail   : aci_hal_write_config_data command - CONFIG_DATA_RANDOM_ADDRESS_OFFSET, result: 0x%02X\n", ret);
  }
  else
  {
    LOG_INFO_APP("  Success: aci_hal_write_config_data command - CONFIG_DATA_RANDOM_ADDRESS_OFFSET\n");
    LOG_INFO_APP("  Random Bluetooth Address: %02x:%02x:%02x:%02x:%02x:%02x\n", (uint8_t)(p_bd_addr[1] >> 8),
                                                                               (uint8_t)(p_bd_addr[1]),
                                                                               (uint8_t)(p_bd_addr[0] >> 24),
                                                                               (uint8_t)(p_bd_addr[0] >> 16),
                                                                               (uint8_t)(p_bd_addr[0] >> 8),
                                                                               (uint8_t)(p_bd_addr[0]));
     memcpy(&a_BdAddr[0], (uint8_t*)p_bd_addr, 6);
  }

2.4. Static Random Address Selection (static dynamic type): changed at bootup

In CubeMX configuration tab:

Bluetooth® Low Energy Static Random Address Selection (static unique type)
Connectivity BLE CMX StaticRandomAddressDynamic.png

CFG_BD_ADDRESS is not used in this case.

In app_ble.c:

/* The two upper bits shall be set to 1 */
/* The RNG may be used to provide a random number on each power on */
/* Random address generation */

 uint32_t p_bd_addr[2];
  HW_RNG_Get(1, &p_bd_addr[1]);
  HW_RNG_Get(1, &p_bd_addr[0]);
  p_bd_addr[1] |= 0xC000; /* The two upper bits shall be set to 1 */