FREE “INTRO TO BLE” BOOK [HARDCOVER] →

A Practical Guide to Debugging BLE Communication on iOS

Debugging Bluetooth LE is tricky, and on mobile devices, it can be even more so!

In this guide, I lay out the different steps in detail on how you can debug and sniff Bluetooth LE communication on iOS devices. Specifically, we’ll be capturing the HCI commands and events between the Host and Controller on the iOS device.

Host Controller Interface (HCI)

Before we dive into the details of how to achieve this, let’s go over a few essential concepts.

The Host Controller Interface (HCI) layer is a communication interface defined in the Bluetooth Core Specification document. It standardizes the way that a Bluetooth Host communicates with a Bluetooth Controller.

Host Controller Interface (HCI)
Host Controller Interface (HCI)

It is an optional interface that is needed in cases where the controller and host are present on separate hardware components. If it is omitted, it means in such a device, the same processor will implement the functionality of a host and a controller. Here’s an example:

Host and Controller on the same microcontroller

If it is included, then it allows a device to implement the Bluetooth LE functionality using a host from one vendor and a controller from another vendor (on different chipsets). Physically, the HCI may run on top of an interface like UART, RS-232, USB, or SD. The set of packets that can be exchanged on this interface is defined by the Bluetooth specification.

Examples of where the Host and Controller are separated across different microcontrollers/processors, and HCI is implemented include:

A. Bluetooth USB dongle connected to a PC:

Bluetooth USB Dongle HCI

B. Smartwatch

Smartwatch HCI

The different aspects of HCI include:

  • HCI Commands: these are sent from the Host to the Controller to request an operation. Examples include creating a connection, starting advertising, stopping advertising, starting scanning, stopping scanning, creating CIS, creating BIS, etc.
  • HCI Events: these are sent from the Controller to the Host, reporting back with important information such as the status of a command. Examples include connection complete, advertising report, scan request received, etc.

Different operations in Bluetooth LE are split across the Host and Controller. Some are the Host’s responsibility, while others are the Controller’s. If we can get a peek at the commands and events that are being passed between the two subsystems, this gives us developers a lot more insight into what’s happening in a Bluetooth LE device (or app).

Many might not know that both Android and iOS actually expose the HCI layer to us (I certainly didn’t realize this until later in my Bluetooth LE development journey!). This is a powerful feature that can be very useful in many debugging scenarios.

For example, did you know that:

  • You can capture the GATT operations being triggered by any mobile app?
  • Or, that you can capture the advertising reports from the smartphone’s Controller when scanning for Bluetooth LE devices?
  • Or, that you can capture the security keys used to secure communication between the smartphone and another Bluetooth LE device? and then use that to decrypt the encrypted data exchanged between the two devices?!

All of these are possible on both iOS and Android. In this post, we’ll cover how to do this on iOS. In a follow-up article, we’ll cover the Android case.

Requirements

To be able to do this on iOS, we need the following:

  • A macOS laptop/desktop
  • An Apple Developer Account
  • An iOS device running iOS 13 or later
  • A cable for connecting the iOS device to the Mac

HCI Capture Steps on iOS

Here are the steps to take to capture HCI communication on iOS:

Step 1: Download and install Apple’s Bluetooth Profile on an iOS device. You can do this in two ways:

Here’s a short screen recording detailing this step:

Downloading Apple’s Bluetooth for iOS Profile

Once installed, you’ll be able to find it under SettingsGeneralVPN & Device Management:

Bluetooth for iOS Profile installed

Step #2: Now that we have the Profile installed on our iOS device, we can move on to the next step, which is to download and run a tool from Apple called the Packet Logger. You can download the Packet Logger tool from the Additional Tools for Xcode package here [simply download the latest version].

Packet Logger Tool

Step #3: Now, let’s run the Packet Logger tool (you can also drag and drop it to your local Applications folder so you can quickly run it next time).

Packet Logger Tool Window

Step #4: Next, connect your iOS device to your Mac (and accept any dialogs asking to allow access to your device).

Step #5: Click on the FileNew iOS Trace menu item:

New iOS Trace in the Packet Logger Tool

Step #6: After starting the iOS Trace, you should start seeing some Bluetooth traffic, and the iOS device should show a “signal” status at the top of the screen:

Bluetooth for iOS Profile running on iOS device

Step #7: As an advanced tip, you can actually export the log file to a BTSnoop format, which can be opened in Wireshark for additional analysis.

Exporting HCI data in BTSnoop format

Step #8: So, what do you do from here now that you have access to the HCI logs?
At this point, you can view all the HCI traffic between the Bluetooth Host and Controller on your iOS device.

In order to understand the different HCI commands and events, I recommend referring to the Bluetooth Core Specification document Vol 4, Part E, Section 7. Here are examples of some common Bluetooth LE HCI Commands on the Central side (the most common role for a smartphone):

  • LE Set Scan Parameters command
  • LE Set Scan Enable command
  • LE Create Connection command
  • LE Enable Encryption command

Capturing BLE Security Keys (LTK)

One handy use case for the Packet Logger tool is to extract the LTK for a secure connection between two BLE devices (utilizing the LE Secure Connections pairing method).

To demonstrate this, I am going to use the following:

  • A Nordic nRF52840 board running the nRF Connect SDK (Zephyr-based) peripheral_sc_only example (this one runs in LE Secure Connections only mode)
  • nRF Connect mobile app on an iPhone 14 Pro Max (running iOS 17)
  • Ellisys Bluetooth Tracker (Bluetooth LE Sniffer tool)
    [Used for sniffing over the air traffic and inputting the LTK for traffic decryption. Alternatively, you can use Wireshark in combination with nRF Sniffer on one of the Nordic dev boards]

Exercise Steps

Make sure the nRF DK is not bonded with the iOS device. If it already is, then remove it from the Bluetooth Settings menu by clicking on the (i) icon and then clicking “Forget This Device”:

“Forget This Device” to remove Bluetooth LE Bond

Now navigate to the nRF Connect mobile app and discover the device:

Discovering the Bluetooth LE Peripheral

Note: Make sure the Packet Logger Tool is running an iOS Trace before continuing with the next step.

Click “Connect.” then, you’ll be presented with a Passkey entry form:

Pairing Passkey entry on the smartphone

You’ll find the passkey displayed in the serial terminal from the nRF DK:

Passkey from the board shown in the serial terminal

Make sure you enter the passkey reasonably quickly. Otherwise, the pairing process will time out. Once paired, the device serial terminal output will indicate a successful pairing:

Pairing complete

Once this is completed, you can now stop the Packet Logger trace and filter for HCI Commands:

Filtering for HCI Commands in Packet Logger

Now, look for the HCI Command “LE Start Encryption” and expand the command for more information. In there, you will find the LTK for the bond. Voila!

Capturing the LTK in Packet Logger during Pairing/Bonding

Even if you miss capturing the pairing process using the Packet Logger, you can disconnect the nRF DK (or any other device you’re looking to capture) and capture the reconnection operation to the DK.

From there, you can again look for the same HCI command: “LE Start Encryption” (you can also verify this is the same LTK used when first establishing the pairing between the two devices):

Capturing the LTK in Packet Logger upon reconnection between bonded devices

After extracting the LTK from the Packet Logger tool, you can now fully decrypt the traffic between the two BLE devices (the nRF DK and the iOS device)!

Summary

In this post, we covered a very practical technique that we can use when debugging Bluetooth LE communication with a smartphone, whether that’s from an app that you’ve developed or even any other app on your phone!

Credits

“Learn The Basics of Bluetooth Low Energy EVEN If You Have No Coding Or Wireless Experience!"

Don't miss out on the latest articles & tutorials. Sign-up for our newsletter today!

Take your BLE knowledge to the next level.

If you’re looking to get access to full video courses covering more topics, then check out the Bluetooth Developer Academy.

As part of all the courses within the Academy, you’ll also be able to download the full source code to use as a reference or use within your own application.

By joining the Bluetooth Developer Academy, you will get access to a growing library of video courses.

The Academy also features access to a private community of Bluetooth experts, developers, and innovators. You’ll get to connect and interact with me and other experts in the Bluetooth space, learn from others’ experiences and knowledge, and share yours as well.

So, what are you waiting for?? Join today!

Get the new "Intro to Bluetooth Low Energy" hardcover book for FREE

This new & updated edition of my best-selling book is specially crafted to help you learn everything you need to get started with BLE development.

Grab your copy for FREE today!