A Bluetooth vulnerability was released this week for devices using up to version 5.1 of the Bluetooth specification allowing an attacker to influence the key length of the encryption key needed to setup a secure connection between to devices. According to the Bluetooth SIG (Special Interest Group), an attacker can attempt to perform this attack if two vulnerable devices are within range and are establishing a BR/EDR connection between each device. Not to be confused with the attacking device, that is a third party in this scenario. The attack works in a very short time window where an encrypted connection is being setup between two vulnerable devices and the attacking device intercepts and re-transmits a shortened key size to one of the vulnerable devices and blocks the transmission from the other. If this transmission is successful the vulnerable device can be open for a brute force attack on the encryption key. The attacking device could set the key size to 1 byte of entropy in the 2 octets returned to vulnerable device and then attempt to crack the key by brute forcing the vulnerable device since 1 byte is expected. This attack window is only open for a short period as a vulnerable device will most likely ask to re-negotiate the encrypted connection after a specific time window.
How to Prevent this from Happening
The easiest way to prevent this attack, in my opinion, is to always require a minimum encryption key length when pairing or an authenticated connection is taking place. For example, make sure when the secure connection goes up, that your device's application code checks the length of the encryption key before proceeding. If the length is below what you would expect, close the connection. To test this out, clone the BlueZ project on a Linux machine and follow the instructions in HACKING file to run a local copy of BlueZ to see the signal and pairing data being passed back and forth.
From the HACKING file:
# Clone the BlueZ repository $ git clone git://git.kernel.org/pub/scm/bluetooth/bluez.git $ cd bluez # Configure and build $ ./configure --enable-maintainer-mode $ make # Copy configuration file which specifies the required security policies $ sudo cp ./src/bluetooth.conf /etc/dbus-1/system.d/ # Run daemon in foreground with debugging $ sudo ./src/bluetoothd -n -d -f ./src/main.conf
For testing devices connected in mesh that could potentially receive a shortened key, validate the mesh encryption method from crypto.c. If the psmg and key variable do not meet a specific length then close the file descriptor and return false.
bool mesh_crypto_aes_ccm_encrypt(const uint8_t nonce[13], const uint8_t key[16], const uint8_t *aad, uint16_t aad_len, const uint8_t *msg, uint16_t msg_len, uint8_t *out_msg, void *out_mic, size_t mic_size) { uint8_t pmsg[16], cmic[16], cmsg[16]; uint8_t mic[16], Xn[16]; uint16_t blk_cnt, last_blk; bool result; size_t i, j; int fd; /* Mesh limits AAD length to 16 */ if (aad_len > 16) return false; fd = aes_ecb_setup(key); if (fd < 0) return false; /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */ pmsg[0] = 0x01; memcpy(pmsg + 1, nonce, 13); l_put_be16(0x0000, pmsg + 14); printf("\n Key and message length failure \n"); // Validate that pmsg (plaintext message meets a specific length) // and the key meet a specific length here. // A minimum encryption key length of 7 octets for BR/EDR connections. // // If not, close the file descriptor and return fals // aes_ecb_destroy(fd); // return false; result = aes_ecb(fd, pmsg, cmic); if (!result) goto done; // ... }
For devices authenticating between one another, try examining the authentication requests that are taking place in the hcitool.c file in the /tools directory of BlueZ. This is a good place to examine the requests going back and forth between BlueZ and the desired device. Through this chain of methods you can really examine how is being passed back and forth as well.
int hci_authenticate_link(int dd, uint16_t handle, int to) { auth_requested_cp cp; evt_auth_complete rp; struct hci_request rq; cp.handle = handle; rq.ogf = OGF_LINK_CTL; rq.ocf = OCF_AUTH_REQUESTED; rq.event = EVT_AUTH_COMPLETE; rq.cparam = &cp; rq.clen = AUTH_REQUESTED_CP_SIZE; rq.rparam = &rp; rq.rlen = EVT_AUTH_COMPLETE_SIZE; if (hci_send_req(dd, &rq, to) < 0) return -1; if (rp.status) { errno = EIO; return -1; } return 0; }
If both of these results turn up fine and you are still wanting to block against the vulnerability, try going to the actual application code and validating that a minimum encryption key length of 7 octets for BR/EDR connections. This could potentially be done on whatever application code your device runs. If this is mobile, try looking at the iOS CoreBluetooth APIs, and the Android Bluetooth APIs.
References:
For more information on this CVE and the Bluetooth SIG's security announcement, please see these references below:
- CVE-2019-9506: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9506
- Key Negotiation of Bluetooth: https://www.bluetooth.com/security/statement-key-negotiation-of-bluetooth/
- Apple-SA-2019-8-1 (Bluetooth): https://seclists.org/fulldisclosure/2019/Aug/11
- NIST: https://nvd.nist.gov/vuln/detail/CVE-2019-9506
- Mesh Crypto.c: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/mesh/crypto.c?id=8994b7f2bf817a7fea677ebe18f690a426088367#n244