128-bit
Per connection
Elliptic curve
3 filter params
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
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.
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.1Sets 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.1Reads back the currently active timeout for a connection.
Authenticated_Payload_Timeout_Expired_Event 4.1No authenticated packet arrived in time. Host should send LL_PING or terminate the connection.
/* 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 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.
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.
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.
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.
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
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
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.
Advertiser
Scanner
(Connectable_Undirected)
(LE_Scan_Type=0x00 passive)
/* 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 */
Next — Practical Sequence Diagrams
PDF 1315 puts all these commands together into four real-world sequence diagrams showing exactly what fires on both devices.
