HCI whitelisting tutorial – ble HCI whitelisting

 

HCI Auth, Encryption, Testing & White List Usage
Chapter 9 Sections 9.2.11–9.2.14 | Link Info wrap-up · Encryption · P-256 DHKey · RF Testing · White List Filter Policies
LTK
128-bit
Auth Timeout
Per connection
P-256 4.2
Elliptic curve
White List
3 filter params
Keywords:

BLE HCI_LE_Encrypt AES-128 BLE LE_Long_Term_Key_Requested_Event BLE HCI_LE_Start_Encryption BLE Authenticated_Payload_Timeout 4.1 BLE P-256 DHKey Secure Connections 4.2 BLE HCI_LE_Receiver_Test BLE white list filter policy Figure 9.7 passive scanning

9.2.11 Link Information — Final Commands

HCI_Read_Transmit_Power_Level

Returns the current TX power (dBm) for a connection. Two modes: current power or maximum power. Useful for detecting power reduction due to proximity.

HCI_Read_RSSI

Returns received signal strength (dBm) from the peer device. Useful for proximity detection and connection quality monitoring.

HCI_LE_Read_Advertising_Channel_Tx_Power

Returns the fixed TX power used during advertising. Embed this in your advertising data “TX Power Level” AD type so scanners can estimate distance.

HCI_LE_Read_Channel_Map

Returns the current 37-bit channel bitmap for a connection — shows which data channels are enabled and which are avoided due to interference.

9.2.12 — Authentication and Encryption

Core Encryption Commands — The Complete Set

The host never does the actual cryptographic work — the controller hardware does. The host orchestrates the process by issuing the right commands in the right sequence.

HCI_LE_Rand

Asks the controller’s hardware RNG to generate 8 bytes of cryptographically random data and return it. Used by the Security Manager as nonce inputs during pairing. The controller’s hardware RNG is higher quality than a software PRNG on the host.

HCI_LE_Encrypt

A utility command: host provides a 16-byte key and 16 bytes of plaintext, controller runs AES-128 and returns the ciphertext. Used by the Security Manager for pairing calculations (confirm values, key derivation). Not used to encrypt the actual BLE link — that is HCI_LE_Start_Encryption’s job.

HCI_LE_Start_Encryption

Tells the controller to start the LLCP Encryption Start procedure. The host provides the connection handle, random number, EDIV, and 16-byte LTK. The controller handles the LL_ENC_REQ / LL_ENC_RSP / LL_START_ENC handshake with the peer autonomously. Only the Master’s host calls this.

LE_Long_Term_Key_Requested_Event

Fired on the Slave side when the link layer receives LL_ENC_REQ. The link layer does not know the LTK — the host does. This event delivers the EDIV and random number so the host can look up the matching LTK from its security database and reply.

HCI_LE_Long_Term_Key_Request_Reply

The Slave host’s positive response — provides the 16-byte LTK. The controller derives the session key and completes the encryption handshake.

HCI_LE_Long_Term_Key_Request_Negative_Reply

The Slave host’s rejection — used when no matching LTK is found (device was un-paired). The controller responds with LL_REJECT_IND and the encryption attempt fails.

Encryption_Change_Event

Fired when the encryption state changes. 0x00 = off, 0x01 = AES-128 CCM on. The host waits for this before sending sensitive data.

Encryption_Key_Refresh_Complete_Event

Fired after the Encryption Pause and Restart procedure swaps in a new LTK. The host knows the new key is active and data transfer can safely resume.

BLE 4.1 — Authenticated Payload Timeout

A maximum time window in which an authenticated (MIC-carrying) packet must arrive from the peer. If the timer expires, the link layer fires the expired event and the host should trigger an LE Ping to force the peer to send an authenticated response.

HCI_Write_Authenticated_Payload_Timeout 4.1

Sets the timeout in 10 ms units per connection. Default is 30 seconds (3000). Lower = stricter security. Higher = more tolerant.

HCI_Read_Authenticated_Payload_Timeout 4.1

Reads back the currently active timeout for a connection.

Authenticated_Payload_Timeout_Expired_Event 4.1

No authenticated packet arrived in time. Host should send LL_PING or terminate the connection.

LTK Exchange — Slave Side Flow
Master host
HCI_LE_Start_Encryption (handle + rand + EDIV + LTK)
Master controller sends LL_ENC_REQ to Slave controller
Slave host
LE_Long_Term_Key_Requested_Event (EDIV + random)
Slave host
HCI_LE_Long_Term_Key_Request_Reply (LTK 16 bytes)
Controllers complete LL_START_ENC handshake
Encryption_Change_Event (encrypt=1) → both hosts
/* Encryption monitoring with BlueZ btmon */
/* sudo btmon | grep -A 5 "Encryption Change" */

/* HCI_LE_Start_Encryption parameters: */
typedef struct {
    uint16_t handle;    /* connection handle       */
    uint64_t random;    /* from pairing exchange   */
    uint16_t ediv;      /* encrypted diversifier   */
    uint8_t  ltk[16];   /* 128-bit Long Term Key   */
} __attribute__((packed)) le_start_enc_cp;

/* After Encryption_Change_Event with encrypt=0x01: */
/* connection is fully encrypted with AES-128 CCM   */

/* Set authenticated payload timeout (30s default): */
/* OGF=0x08, OCF=0x0023, params: handle(2)+timeout(2) */
/* timeout in 10ms units: 3000 = 30 seconds         */
BLE 4.2 — P-256 Elliptic Curve and Diffie-Hellman Key Exchange

BLE 4.2 upgraded pairing security to use FIPS-approved algorithms. P-256 elliptic curve and AES-CMAC replace the custom 4.0 algorithms. Four new HCI items enable this. The controller performs the expensive elliptic curve computations in hardware so the host CPU does not have to.

4.2

HCI_LE_Read_Local_P-256_Public_Key

Asks the controller to generate a new P-256 key pair. The private key stays in the controller — the host only gets the 64-byte public key via the completion event. This public key is shared with the peer during Secure Connections pairing.

4.2

HCI_LE_Read_Local_P-256_Public_Key_Complete_Event

Asynchronous response delivering the 64-byte public key (two 32-byte curve coordinates) once computation finishes.

4.2

LE_Generate_DHKey

Host passes the peer’s 64-byte P-256 public key. Controller computes the 32-byte Diffie-Hellman shared secret using the peer’s public key and the previously generated local private key. Both sides independently compute the same DHKey — this shared secret seeds all subsequent key derivation.

4.2

LE_Generate_DHKey_Complete_Event

Delivers the 32-byte DHKey to the host once the controller finishes computing it. The host feeds this into AES-CMAC to derive the LTK and other session keys.

/* BLE 4.2 Secure Connections key exchange via HCI */

/* Step 1: Generate P-256 key pair */
/* OGF=0x08, OCF=0x0025 */
hcitool cmd 0x08 0x0025
/* Wait for LE Meta subevent 0x08 = P-256 Key Complete */
/* Returns: status(1) + local_p256_public_key(64 bytes) */

/* Step 2: After receiving peer public key during pairing, */
/* compute DHKey */
/* OGF=0x08, OCF=0x0026 */
/* Parameter: remote_p256_public_key (64 bytes) */
/* Wait for LE Meta subevent 0x09 = DHKey Complete */
/* Returns: status(1) + DHKey(32 bytes) */

/* The 32-byte DHKey then goes into AES-CMAC to derive: */
/* - LTK (Long Term Key) */
/* - IRK (Identity Resolving Key) */
/* - CSRK (Connection Signature Resolving Key) */

9.2.13 — Testing

RF Compliance Test Commands — For the Test Bench Only

These three commands are only used during Bluetooth RF certification testing. They place the controller into dedicated test modes. Never used in production.

HCI_LE_Receiver_Test

Puts the receiver into test mode on a specified RF channel. Test equipment transmits reference packets. The controller counts correctly received packets — provides a BER (Bit Error Rate) measurement.

HCI_LE_Transmitter_Test

Puts the transmitter into continuous test mode on a specified channel. Test equipment measures frequency accuracy, modulation quality, TX power, and spurious emissions.

HCI_LE_Test_End

Stops the running test and returns the received packet count (for receiver tests). Controller returns to normal standby.

/* RF test commands — test bench only */

/* Receiver test on channel 20 (2440 MHz): */
/* OGF=0x08, OCF=0x001D, param: channel (0-39) */
hcitool cmd 0x08 0x001d 14

/* Transmitter test on channel 20, 37-byte PRBS9 packets: */
/* OGF=0x08, OCF=0x001E */
/* Params: TX_channel(1) + Data_Length(1) + Packet_Payload(1) */
/* Payload types: 0x00=PRBS9, 0x01=all 1s, 0x02=all 0s */
hcitool cmd 0x08 0x001e 14 25 00

/* Stop test: */
hcitool cmd 0x08 0x001f
/* Returns: status(1) + num_packets_received(2) */

9.2.14 — Usage of White Lists

How the White List Is Activated Through Three Filter Policy Parameters

The white list is not enabled by a separate command. Instead, three existing commands each have a filter policy parameter that engages it:

HCI_LE_Set_Advertising_Parameters — Advertising_Filter_Policy

0x00 = all devices can scan and connect. 0x01 = only white list. 0x02 = scan from all but connect only from white list. 0x03 = scan only from white list, connect from all.

HCI_LE_Set_Scan_Parameters — Scanning_Filter_Policy

0x00 = report all. 0x01 = only from white list. 0x02 = white list + resolve directed RPAs (4.2). 0x03 = all + resolve directed RPAs (4.2). Using 0x01 dramatically reduces advertising reports in a crowded environment.

HCI_LE_Create_Connection — Initiator_Filter_Policy

0x00 = connect to the specific address named in Peer_Address. 0x01 = connect to whichever white list device advertises first. The LE_Connection_Complete_Event Peer_Address field tells the host which device it connected to.

Figure 9.7 — Passive Scanning Sequence
Device A
Advertiser
Air
Device B
Scanner
LL State: Standby
LL State: Standby
HCI_LE_Set_Advertising_Parameters
(Connectable_Undirected)
HCI_LE_Set_Scan_Parameters
(LE_Scan_Type=0x00 passive)
HCI_LE_Set_Advertising_Data
LE_Set_Scan_Enable → Scanning
Set_Advertise_Enable → Advertising
ADV_IND →
ADV_IND →
ADV_IND →
← LE_Advertising_Report_Event
Scanner never transmits — TX is off throughout
/* White list workflow */
/* 1. Clear and populate */
hcitool cmd 0x08 0x0010                       /* clear     */
hcitool cmd 0x08 0x0011 00 FF EE DD CC BB AA  /* add addr  */

/* 2. Use in advertising (only WL devices can connect) */
/* Set advertising_filter_policy=0x01 in adv params   */

/* 3. Use in scanning (only report WL devices) */
le_set_scan_parameters_cp sp;
sp.filter = 0x01; /* white list only */

/* 4. Use in connection (connect to first WL advertiser) */
le_create_connection_cp cc;
cc.filter_policy = 0x01; /* white list */
/* Peer_Address in LE_Connection_Complete tells you who */

Chapter 9 HCI — All Files
PDF 13

Table 9.1, Reset, Flow Control

PDF 46

White List, Resolving List, Controller Info

PDF 79

Controller Config, Discovery, Conn Setup
PDF 1012 ✅

Auth, Encryption, P-256, Testing, WL Usage

PDF 1315

Practical Sequences & Chapter 9 Summary

Next — Practical Sequence Diagrams

PDF 1315 puts all these commands together into four real-world sequence diagrams showing exactly what fires on both devices.

Next: Practical Sequences & Chapter 9 Summary → ← PDF 79

Leave a Reply

Your email address will not be published. Required fields are marked *