Project 6: The BLE Keyboard Attack (nRF52840)
Build a BLE HID keyboard on XIAO nRF52840 that pairs with a phone or laptop and types a predefined macro.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Intermediate |
| Time Estimate | 1-2 weeks |
| Main Programming Language | C (nRF Connect SDK) |
| Alternative Programming Languages | Arduino C++ (Bluefruit, ZMK) |
| Coolness Level | High |
| Business Potential | Medium (HID devices) |
| Prerequisites | BLE basics, GATT concepts, HID familiarity |
| Key Topics | BLE advertising, HID report descriptors, pairing/bonding |
1. Learning Objectives
By completing this project, you will:
- Explain BLE roles, advertising, and GATT services.
- Build a HID report descriptor for a keyboard.
- Implement key press and release reports correctly.
- Enable pairing and bonding for smooth reconnection.
- Debug connection and notification issues using logs.
2. All Theory Needed (Per-Concept Breakdown)
2.1 Concept 1: BLE Advertising, Connection, and GATT
Fundamentals
BLE is designed for low-power, short-range communication. Devices advertise their presence, and a central (phone or PC) connects. Once connected, the device exposes services and characteristics via the GATT (Generic Attribute Profile). A BLE keyboard is a peripheral that advertises a HID service. The central connects, discovers the HID service, and subscribes to notifications for key reports. Understanding advertising, connection parameters, and GATT is essential to making the keyboard appear and behave correctly.
Deep Dive into the Concept
BLE advertising is a periodic broadcast that includes the device name, UUIDs, and flags. The advertising interval affects power and connection speed; shorter intervals connect faster but consume more power. For a keyboard, you want relatively fast connections, but you can increase the interval after bonding to save power. When a central connects, it negotiates connection parameters (interval, latency, supervision timeout). These parameters determine how often the peripheral can send notifications. If the interval is too long, typing feels laggy. If too short, battery drain increases.
GATT is the attribute-based protocol for services and characteristics. The HID over GATT profile (HOGP) defines standard services: HID service, Battery service, and Device Information service. The HID service includes characteristics like HID Information, HID Control Point, and Report characteristics. Each report characteristic is associated with a report ID and a report type (input, output, feature). For a keyboard, the input report is used to send key presses to the host. The host subscribes to notifications on the input report characteristic. If you do not set the correct permissions or CCCD (Client Characteristic Configuration Descriptor), notifications will not work.
BLE security and pairing are separate from GATT but interact with it. Some characteristics require encryption to read or write. If you require encryption, the device must pair and bond. Otherwise, the host may fail to read the report map. For a keyboard, you usually want at least “Just Works” pairing with bonding so the device reconnects automatically without re-pairing. This is especially important for a smooth UX.
Finally, BLE uses a layered stack. The application defines services and sends notifications. The SoftDevice (or controller) handles radio scheduling. If you send notifications too quickly, they will be dropped or queued. Proper rate limiting and connection parameter selection are part of a robust design. This project gives you a practical understanding of how the BLE stack behaves in real devices.
How this fits on projects
You will set up advertising, implement the HID GATT service, and manage connections. This knowledge applies to any BLE device, including sensors and beacons.
Definitions & Key Terms
- Advertising: Periodic broadcasts that announce a BLE device.
- Central/Peripheral: Roles in BLE; central connects, peripheral advertises.
- GATT: Attribute protocol for services/characteristics.
- HOGP: HID over GATT profile.
- CCCD: Descriptor that enables notifications.
Mental Model Diagram (ASCII)
Peripheral (Keyboard) --advertise--> Central (Phone/PC)
Peripheral --GATT services--> Central
Central --subscribe--> Input Report
Peripheral --notify--> Key report
How It Works (Step-by-Step)
- Start advertising with HID service UUID.
- Central connects and discovers services.
- Central enables notifications on input report.
- Peripheral sends reports when keys change.
- Central interprets reports as keystrokes.
Minimal Concrete Example
// Notify key report
bt_gatt_notify(conn, &hid_input_report, report, sizeof(report));
Common Misconceptions
- “Advertising automatically means connected.” It only announces.
- “GATT is optional.” All BLE data transfer uses GATT.
- “Notifications always work.” CCCD must be enabled.
Check-Your-Understanding Questions
- Why do you need CCCD for notifications?
- How do connection parameters affect latency?
- What service does a BLE keyboard advertise?
Check-Your-Understanding Answers
- CCCD tells the peripheral the client wants notifications.
- Longer intervals mean higher latency but lower power.
- HID service (HOGP), plus optional battery and device info.
Real-World Applications
- Wireless keyboards, mice, and remote controls.
- BLE sensors with GATT characteristics.
Where You’ll Apply It
- See Section 3.2 Functional Requirements and Section 5.10 Phase 1.
- Also used in: P03 ESP-NOW Remote for wireless design tradeoffs.
References
- Bluetooth SIG HOGP specification
- Nordic nRF52840 BLE documentation
Key Insights
A BLE keyboard is mostly a GATT service with correct notifications.
Summary
BLE advertising and GATT services form the backbone of the keyboard. Without correct advertising, services, and CCCD configuration, nothing works.
Homework/Exercises to Practice the Concept
- List the standard services in a HID device profile.
- Explain why a longer connection interval saves power.
Solutions to the Homework/Exercises
- HID service, Battery service, Device Information service.
- Fewer connection events per second reduce radio usage.
2.2 Concept 2: HID Report Descriptors and Keycodes
Fundamentals
HID report descriptors define the format of data sent between a HID device and host. For a keyboard, the report includes modifier keys (Ctrl, Shift, etc.) and a list of keycodes. The host uses the descriptor to parse incoming reports. If the descriptor is wrong, the host will ignore or misinterpret the data. Understanding the report format is essential for sending correct keypress events.
Deep Dive into the Concept
The HID report descriptor is a small byte array that describes how to interpret reports. It defines usage pages (e.g., Generic Desktop, Keyboard), usage IDs (e.g., keycodes), report sizes, and report counts. A typical keyboard report is 8 bytes: one byte for modifier bits, one byte reserved, and six bytes for keycodes (allowing up to six simultaneous key presses). The host uses this descriptor to map bytes to key events. If you send a report that does not match the descriptor, the host may ignore it or interpret it incorrectly.
Keycodes are defined by the HID Usage Tables. For example, the keycode for ‘a’ is 0x04. Modifier keys are bit flags in the modifier byte; e.g., left control is bit 0. To send “Ctrl+L”, you set the modifier bit and include the keycode for ‘l’. You must also send a release report (all zeros) to indicate key release. If you do not, the host will think the key is held down. This is a common beginner bug that leads to stuck keys.
Report IDs allow multiple report types on the same device. For a keyboard with media keys, you might have two report IDs: one for keyboard input and one for consumer control. The report descriptor defines each report separately. If you include report IDs, you must include the ID as the first byte in each report. If you forget, the host will mis-parse the data.
HID also includes output reports (e.g., LED status for Caps Lock). The host can write these to the device. If you want to support Caps Lock LED, you must implement the output report and handle write events. This is optional for a basic keyboard, but understanding it shows the full HID flow.
How this fits on projects
You will implement a keyboard report descriptor and send reports that match it. You will also send press and release events for each key in your macro.
Definitions & Key Terms
- HID report descriptor: Defines the structure of HID reports.
- Usage page: Category of HID usages (e.g., keyboard).
- Usage ID: Specific key or control within a usage page.
- Report ID: Identifier for multiple report types.
- Modifier byte: Bitfield for Ctrl/Shift/Alt/GUI keys.
Mental Model Diagram (ASCII)
Descriptor -> Report format
|
v
[mod][res][key1][key2][key3][key4][key5][key6]
How It Works (Step-by-Step)
- Define HID report descriptor.
- Host reads descriptor and configures parser.
- Device sends key press report.
- Device sends key release report.
- Host generates key events.
Minimal Concrete Example
uint8_t report[8] = {0};
report[0] = 0x01; // left ctrl
report[2] = 0x0F; // 'l'
notify(report, 8);
report[0] = 0; report[2] = 0; // release
notify(report, 8);
Common Misconceptions
- “One report is enough.” You need a press and a release.
- “Any keycode works.” Must use HID usage table values.
- “Report IDs are optional.” If used, they must be in every report.
Check-Your-Understanding Questions
- Why do you need a key release report?
- What happens if your report size does not match the descriptor?
- How do you represent Shift+A?
Check-Your-Understanding Answers
- Otherwise the host thinks the key is held down.
- The host mis-parses or ignores the report.
- Set the Shift modifier bit and send keycode for ‘a’.
Real-World Applications
- HID keyboards, media controls, and game controllers.
Where You’ll Apply It
- See Section 3.2 Functional Requirements and Section 5.10 Phase 2.
- Also used in: P10 Web Oscilloscope for data format discipline.
References
- HID Usage Tables (USB HID spec)
- Bluetooth SIG HOGP profile
Key Insights
The report descriptor is the contract between your device and the OS.
Summary
Correct HID descriptors and keycodes are essential. If the descriptor and report do not match, the OS cannot interpret your keystrokes.
Homework/Exercises to Practice the Concept
- Look up the HID keycode for “Enter” and “Space”.
- Design a report to send “Ctrl+Alt+Del”.
Solutions to the Homework/Exercises
- Enter = 0x28, Space = 0x2C.
- Set Ctrl and Alt modifiers, include keycode for Delete (0x4C).
2.3 Concept 3: Pairing, Bonding, and Security
Fundamentals
Pairing establishes a secure relationship between the device and the host, while bonding stores the keys for future reconnections. BLE supports different security levels, from “Just Works” (no MITM protection) to passkey or numeric comparison. For a keyboard, bonding is important because users expect reconnection without repeated pairing. Security also determines whether sensitive characteristics can be read or written.
Deep Dive into the Concept
BLE pairing uses the Security Manager Protocol (SMP). During pairing, the device and host exchange information about supported security features. If both support it, they may use passkey or numeric comparison. For a keyboard without input/output, “Just Works” is typical. Once pairing is complete, keys are generated (LTK for encryption, IRK for identity). Bonding means these keys are stored in non-volatile memory so that future connections can be encrypted without repeating the pairing process.
If you do not enable bonding, the host may forget the device after a reboot. This leads to repeated pairing prompts and a poor UX. Some operating systems refuse to accept HID reports unless the connection is encrypted. Therefore, you should ensure that the HID service requires encryption and that pairing occurs automatically when needed. This is especially true for keyboards, which are considered input devices with security implications.
Security level also affects the HID report map. If the report map characteristic is not readable without encryption, the host will initiate pairing. If you require encryption for the input report, the host will also enforce pairing. This is a practical way to ensure that only bonded devices can receive keystrokes. In a “keyboard attack” scenario (for learning), you might use open pairing, but you should still understand the security implications.
The bonding storage is limited; devices can usually store a finite number of bonded peers. You must decide how to handle a new bond when storage is full: reject it or delete the oldest. This policy impacts UX. In this project, you can limit to one bonded peer for simplicity.
How this fits on projects
You will enable bonding and configure security so that your keyboard reconnects automatically and only sends keystrokes to bonded devices.
Definitions & Key Terms
- Pairing: Establishing a secure connection and exchanging keys.
- Bonding: Storing keys for future connections.
- SMP: Security Manager Protocol.
- LTK: Long-Term Key used for encryption.
- IRK: Identity Resolving Key.
Mental Model Diagram (ASCII)
Device <-> Pairing (SMP) <-> Host
keys stored (bonding)
future connection encrypted
How It Works (Step-by-Step)
- Device advertises with security requirements.
- Host connects and reads HID service.
- Pairing is initiated via SMP.
- Keys are generated and stored.
- Future connections use stored keys.
Minimal Concrete Example
// Enable bonding in Zephyr
bt_conn_set_security(conn, BT_SECURITY_L2);
Common Misconceptions
- “Pairing once is enough.” Without bonding, keys are lost on reboot.
- “Security slows everything down.” The overhead is minimal for HID.
- “Any security level is fine.” Some hosts require encryption for HID.
Check-Your-Understanding Questions
- Why is bonding important for a keyboard?
- What is the difference between pairing and bonding?
- What happens if the device runs out of bond slots?
Check-Your-Understanding Answers
- It allows automatic reconnection without user prompts.
- Pairing creates keys; bonding stores them.
- You must reject new bonds or delete old ones.
Real-World Applications
- Wireless keyboards and mice in consumer devices.
- Medical input devices requiring secure pairing.
Where You’ll Apply It
- See Section 5.11 Key Decisions and Section 6.2 Critical Test Cases.
- Also used in: P02 Deep Sleep Champion when considering reconnection energy.
References
- Bluetooth Core Specification (SMP)
- Nordic nRF Connect SDK BLE security docs
Key Insights
Bonding is the difference between a one-off demo and a real product.
Summary
Pairing and bonding are essential for HID devices. They enable secure, frictionless reconnection and protect input devices from unauthorized use.
Homework/Exercises to Practice the Concept
- List the security modes supported by BLE and their tradeoffs.
- Define a policy for handling a new bond when memory is full.
Solutions to the Homework/Exercises
- Just Works (no MITM), Passkey (MITM), Numeric Comparison (MITM).
- Keep one bond; delete the oldest on new pairing.
3. Project Specification
3.1 What You Will Build
A BLE HID keyboard that pairs with a phone or laptop and types a predefined macro (e.g., Ctrl+L, a URL, Enter). The device must reconnect without re-pairing and send correct press/release reports.
3.2 Functional Requirements
- Advertising: Advertise HID service UUID.
- HID Descriptor: Provide a correct keyboard report descriptor.
- Key Reports: Send press and release reports for each key.
- Pairing/Bonding: Enable bonding and store keys.
- Macro: Send a multi-key macro on button press.
3.3 Non-Functional Requirements
- Latency: Keystrokes appear within 100 ms of button press.
- Reliability: Reconnects without re-pairing after reboot.
- Security: Encrypted connection for HID reports.
3.4 Example Usage / Output
[BLE] Advertising started
[BLE] Connected
[HID] Sending Ctrl+L
[HID] Sending URL
[HID] Sending Enter
3.5 Data Formats / Schemas / Protocols
- HID report format: 8-byte keyboard report
- Report descriptor according to HID Usage Tables
3.6 Edge Cases
- Host rejects pairing due to missing security.
- Key release report missing, causing stuck keys.
- Report ID mismatch with descriptor.
3.7 Real World Outcome
A device that appears as a keyboard and types a macro reliably.
3.7.1 How to Run (Copy/Paste)
west build -b xiao_nrf52840 .
west flash
3.7.2 Golden Path Demo (Deterministic)
- Use a fixed macro string.
- Send each key with 50 ms spacing.
Expected log:
[HID] Macro: Ctrl+L -> https://example.com -> Enter
3.7.3 Failure Demo (Missing Release)
[HID] Sent key 'a' without release
[HOST] Key appears stuck, repeated 'a'
3.7.4 If CLI
No standalone CLI. Exit codes not applicable.
3.7.5 If Web App
Not applicable.
3.7.6 If API
No API is exposed. Error JSON shape not applicable.
3.7.7 If GUI / Desktop / Mobile
Host UI is provided by OS when pairing; device appears as keyboard.
3.7.8 If TUI
Not applicable.
4. Solution Architecture
4.1 High-Level Design
[Button] -> [HID report] -> BLE -> Host -> Keystrokes
4.2 Key Components
| Component | Responsibility | Key Decisions | |———-|—————-|—————| | Advertising | Announce HID service | Fast interval for pairing | | HID descriptor | Define report format | Standard 8-byte keyboard | | Report sender | Send key press/release | Timing and sequencing | | Security | Pairing and bonding | Just Works + bonding |
4.3 Data Structures (No Full Code)
struct hid_report {
uint8_t modifiers;
uint8_t reserved;
uint8_t keycodes[6];
};
4.4 Algorithm Overview
Key Algorithm: Macro Send
- On button press, connect (if needed).
- Send press report for each key.
- Send release report after each key.
- Disconnect or stay connected.
Complexity Analysis:
- Time: O(keys in macro)
- Space: O(1)
5. Implementation Guide
5.1 Development Environment Setup
west build -b xiao_nrf52840 .
5.2 Project Structure
p06_ble_keyboard/
+-- src/
| +-- main.c
| +-- hid_desc.c
| +-- keymap.c
+-- prj.conf
5.3 The Core Question You’re Answering
“How does an OS recognize a wireless keyboard?”
5.4 Concepts You Must Understand First
- BLE advertising and GATT services
- HID report descriptor and keycodes
- Pairing and bonding
5.5 Questions to Guide Your Design
- What macro will you send and how many reports does it require?
- What security level is required for HID on your OS?
- How will you handle reconnection after reboot?
5.6 Thinking Exercise
Design a report sequence that sends Ctrl+L, types a URL, and presses Enter.
5.7 The Interview Questions They’ll Ask
- What is the HID report map used for?
- Why must you send key release reports?
- What is the difference between pairing and bonding?
5.8 Hints in Layers
Hint 1: Start with a known HID descriptor from Nordic or Zephyr examples.
Hint 2: Send press and release for every key.
Hint 3: Enable bonding for smooth reconnect.
Hint 4: Use a button to trigger the macro safely.
5.9 Books That Will Help
| Topic | Book | Chapter | |——|——|———| | BLE fundamentals | Getting Started with BLE | GATT chapters | | USB/HID | USB Complete | HID chapters |
5.10 Implementation Phases
Phase 1: BLE + HID Service (2 days)
Goals:
- Advertise HID service.
- Provide report descriptor.
Tasks:
- Configure GATT services.
- Add HID report map.
Checkpoint: Host sees device as keyboard.
Phase 2: Macro Reports (2 days)
Goals:
- Send press/release sequence.
- Verify correct keystrokes.
Tasks:
- Implement key report sending.
- Test with a simple macro.
Checkpoint: Macro types correctly.
Phase 3: Security and UX (1-2 days)
Goals:
- Enable bonding.
- Handle reconnection.
Tasks:
- Enable SMP pairing.
- Store bonds and reconnect.
Checkpoint: Reboot and reconnect without re-pair.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale | |———-|———|—————-|———–| | Security | None vs Just Works | Just Works + bonding | Good UX and security | | Report format | Custom vs standard | Standard 8-byte | Compatibility | | Connection interval | Fast vs slow | Moderate | Balance latency and power |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples | |———-|———|———-| | Unit Tests | Validate report bytes | Check keycodes | | Integration Tests | Pair and type | OS keyboard input | | Edge Case Tests | Missing release | Stuck key detection |
6.2 Critical Test Cases
- Pairing: Device pairs and bonds.
- Macro: Macro types correctly.
- Reconnect: Reboot device, reconnect without pairing.
6.3 Test Data
macro = "Ctrl+L https://example.com Enter"
7. Common Pitfalls & Debugging
7.1 Frequent Mistakes
| Pitfall | Symptom | Solution | |——–|———|———-| | Bad descriptor | Host ignores input | Use known-good descriptor | | No release | Stuck key | Send release report | | No bonding | Re-pair every time | Enable bonding |
7.2 Debugging Strategies
- Use BLE logs to check CCCD and notification status.
- Test on two different OSes to verify compatibility.
7.3 Performance Traps
- Sending reports too fast can drop notifications.
8. Extensions & Challenges
8.1 Beginner Extensions
- Add media keys (volume up/down).
- Add a battery service with fake level.
8.2 Intermediate Extensions
- Support multiple macros via different buttons.
- Implement Caps Lock LED output report.
8.3 Advanced Extensions
- Add passkey pairing for higher security.
- Implement a composite HID device (keyboard + mouse).
9. Real-World Connections
9.1 Industry Applications
- Wireless peripherals and remote controllers.
- Accessibility devices using BLE HID.
9.2 Related Open Source Projects
- ZMK Firmware - open-source keyboard firmware.
- Adafruit Bluefruit - BLE HID library.
9.3 Interview Relevance
- BLE GATT and HID report questions are common in embedded interviews.
10. Resources
10.1 Essential Reading
- Bluetooth HOGP specification
- HID Usage Tables
10.2 Video Resources
- “BLE HID Keyboard” (tutorial)
- “Understanding HID Reports” (lecture)
10.3 Tools & Documentation
- nRF Connect SDK
- Bluetooth SIG documentation
10.4 Related Projects in This Series
- P03 ESP-NOW Remote - wireless protocol design
- P02 Deep Sleep Champion - power considerations for always-on devices
11. Self-Assessment Checklist
11.1 Understanding
- I can explain BLE advertising and GATT.
- I can read and write HID report descriptors.
- I can explain pairing vs bonding.
11.2 Implementation
- Device appears as a keyboard.
- Macro types correctly with press/release.
- Reconnects without re-pairing.
11.3 Growth
- I can describe security tradeoffs for HID devices.
- I can extend the HID report for media keys.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Device pairs and sends keystrokes.
Full Completion:
- Bonding enabled and reconnects automatically.
- Macro sends correctly every time.
Excellence (Going Above & Beyond):
- Composite HID device or enhanced security.
- Documentation of report descriptor and keycodes.