In this part, we cover how to simulate the KNOB attack on ESP32. We will modify the open-source Bluetooth Low Energy stack NimBLE to modify the maximum key size and force the use of a low entropy Long Term Key.
First, let's explore how NimBLE is implemented in ESP IoT Development Framework. Go to /home/cyberinsophia/esp/esp-idf/components/bt
:
cyberinsophia@vm:~$ cd ~/esp/esp-idf/components/bt
cyberinsophia@vm:~/esp/esp-idf/components/bt$ ls
CMakeLists.txt common component.mk controller esp_ble_mesh host include Kconfig linker.lf sdkconfig.rename test
As we mentioned earlier, the controller is implemented directly into a specific hardware component. As a result, NimBLE only implements the Host part of the stack. Let's explore the host implementations availables:
cyberinsophia@vm:~/esp/esp-idf/components/bt$ cd host
cyberinsophia@vm:~/esp/esp-idf/components/bt/host$ ls
bluedroid nimble
As we can see, ESP32 provides two different stacks to implement the Host component: NimBLE and Bluedroid (initially designed for Android). Let's dive deeper into NimBLE stack:
cyberinsophia@vm:~/esp/esp-idf/components/bt/host$ cd nimble/nimble/nimble/host/src
cyberinsophia@vm:~/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/src$ ls
ble_att.c ble_gap.c ble_hs_adv_priv.h ble_hs_flow.c ble_hs_id.c ble_hs_periodic_sync.c ble_hs_shutdown.c ble_l2cap_coc_priv.h ble_sm_alg.c ble_store_util.c
ble_att_clt.c ble_gap_priv.h ble_hs_atomic.c ble_hs_flow_priv.h ble_hs_id_priv.h ble_hs_periodic_sync_priv.h ble_hs_startup.c ble_l2cap_priv.h ble_sm.c ble_uuid.c
ble_att_cmd.c ble_gattc.c ble_hs_atomic_priv.h ble_hs_hci.c ble_hs_log.c ble_hs_priv.h ble_hs_startup_priv.h ble_l2cap_sig.c ble_sm_cmd.c ble_uuid_priv.h
ble_att_cmd_priv.h ble_gatt_priv.h ble_hs.c ble_hs_hci_cmd.c ble_hs_mbuf.c ble_hs_pvcy.c ble_hs_stop.c ble_l2cap_sig_cmd.c ble_sm_lgcy.c
ble_att_priv.h ble_gatts.c ble_hs_cfg.c ble_hs_hci_evt.c ble_hs_mbuf_priv.h ble_hs_pvcy_priv.h ble_ibeacon.c ble_l2cap_sig_priv.h ble_sm_priv.h
ble_att_svr.c ble_gatts_lcl.c ble_hs_conn.c ble_hs_hci_priv.h ble_hs_misc.c ble_hs_resolv.c ble_l2cap.c ble_monitor.c ble_sm_sc.c
ble_eddystone.c ble_hs_adv.c ble_hs_conn_priv.h ble_hs_hci_util.c ble_hs_mqueue.c ble_hs_resolv_priv.h ble_l2cap_coc.c ble_monitor_priv.h ble_store.c
In this folder, we can observe the C implementations of upper layers. We want to edit the Security Manager: open ble_sm.c
with a Text editor. Identify the function ble_sm_gen_ltk
, and observe the source code:
Identify the parameter indicating the key size used to compute the Long Term Key. Identify where this parameter is computed in the source code, and how :
To influence this value, we need to find where the maximum encryption key size transmitted over the air is configured. Find the functions allowing to fill the Pairing Request and the Pairing Response:
Edit the function where cmd->max_enc_key_size
is filled, and replace the provided constant by value 7.
Save the file, then recompile bleprph example and flash the new version on the board.
Once the ESP32 has been reflashed with the modified NimBLE stack, we can observe the effect of KNOB attack in Wireshark. Initiate a new connection from your laptop and observe the Pairing Response transmitted in Wireshark. Check if the behaviour is consistent with the modification we just performed.
Now, observe the key distribution phase, and identify the Long Term Key transmitted by ESP32 peripheral. How our modification influenced the Long Term Key generation ? How did it affect the security of the communication ?
KNOB attack is typically used in a context of Man-in-the-Middle attack:
To implement such an attack, an attacker needs to be able to spoof the BD address of its victim. In this part, we cover how to perform such a spoofing attack on ESP32 chip.
For this exercise, you will have to work in pair with another group.
First, flash an unmodified version of NimBLE (with max encryption key size equals to 16) on the first ESP32. Check that the device is advertising, and identify the associated BD address. It will be our victim device for this exercise.
Now, modify the bleprph example to spoof the victim BD address. This operation can't be performed using the legitimate ESP32 API: we will have to import a function from the proprietary controller, which is not documented but can be called from user code. The signature of this function is:
int r_lld_util_set_bd_address(uint8_t *p_bd_addr, uint32_t addr_type);
We also need to modify the address at the Host level: we will use the following function:
void ble_hs_id_set_pub(const uint8_t *addr);
Note that these functions must be called together and only work if they are called after the advertising configuration. Identify where it occurs in main.c
, and use them to spoof the target BD address.
Now, flash the code with the modified version of NimBLE, and perform several consecutive connections. You should observe that the connection is sometimes initiated with the victim, and sometimes with the attacker. Monitor the traffic in wireshark, and note the effect of KNOB attack on the pairing when the connection is established with attacker device.