ble mesh tutorial – Security Encryption Keys

🔐 Bluetooth Mesh — Part 3

ble mesh tutorial –  Security, Encryption Keys, Obfuscation & Key Identifiers Explained

📖 Topic
Security & Keys
⏱ Read Time
~12 minutes
🎯 Level
Intermediate

Key Terms in This Post

NetKey AppKey DevKey Key Binding Relay Node Configuration Client Obfuscation Privacy Key Key Identifier Trash-can Attack

Why is Mesh Security Complex?

In a Bluetooth Mesh network, messages are relayed by intermediate nodes — a message may pass through several bulbs and switches before reaching its destination. This creates a challenge: how do you allow relaying without letting relay nodes read or modify the data? The answer is Bluetooth Mesh’s two-layer key system. There are no unencrypted or unauthenticated messages in a mesh network — everything is secured.

🗝️ The Three Keys — DevKey, AppKey, NetKey

Bluetooth Mesh security is built around three distinct key types. Each protects a different layer of communication.

🔵 Network Key
NetKey
🟢 Application Key
AppKey
🔴 Device Key
DevKey
Shared by ALL nodes
Secures the network layer. Allows messages to be relayed through the mesh.
One NetKey = one mesh network
A node can know multiple NetKeys
Shared by specific nodes
Secures application data. Only nodes with the AppKey can read the payload.
Lighting AppKey ≠ Door AppKey
Up to 251 AppKeys per model
Only Config Client + one node
Secures key distribution. Used to safely send keys to a specific node.
Config Client knows all DevKeys
Protects against “trash-can attack”

🏗️ Two-Layer Encryption — Network vs Application

Think of a mesh message like a sealed envelope inside another sealed envelope:

🔵 Outer Envelope — Network Layer (encrypted with NetKey)
Visible to ALL nodes (for routing):
DST: 0xC001 SRC: 0x0011 TTL: 5 [obfuscated]
🟢 Inner Envelope — Application Layer (encrypted with AppKey)
Only nodes with the AppKey can read this:
Generic OnOff Set: value=0x01 (ON)

Why two layers? A relay node only needs to open the outer envelope to forward the message. It cannot open the inner envelope (no AppKey). So:

A smart bulb acting as a Relay node CAN forward door lock messages — but it CANNOT unlock or read the door lock data.

🔄 How Relay Nodes Stay Secure

Relay nodes increase the range of a mesh network by forwarding messages they receive. But how do we make sure they cannot tamper with or read application data?

💡
Light Switch
Has: NetKey + AppKey
Net-encrypted
message

💡
Relay Bulb
Has: NetKey only
❌ No AppKey
Cannot read payload
forwarded
(TTL–1)

🔒
Door Lock
Has: NetKey + AppKey
✅ Can decrypt
and act

Network keys are widely distributed (every node in the network has them) to maximise the number of relay nodes. Application keys are shared only with nodes that need to act on the data.

🏠 Real world example: Your door lock’s AppKey is separate from your lighting AppKey. Even if someone hacks your smart bulb, they still cannot unlock your door — the bulb never had the door AppKey.

🎯 Device Key (DevKey) — Node-to-Node Secure Channel

The DevKey is unique to each node. It is known only by the Configuration Client (the provisioning tool/app) and the node itself. It is used to securely deliver keys to individual nodes.

🖥️
Config Client
Knows DevKey
of ALL nodes
AppKey encrypted
with DevKey(Node1)

🔒
Door Lock
(Node 1)
Receives: new
AppKey (door)
|
AppKey encrypted
with DevKey(Node2)

💡
Smart Bulb
(Node 2)
Receives: new
AppKey (light)
🗑️ Trash-can Attack: Someone digs a disposed smart device out of the bin and tries to use it to attack the network. Since the Config Client distributes new AppKeys/NetKeys using DevKeys — and it only sends to trusted, still-active nodes — the old device never gets the new keys. It becomes useless to the attacker.

🔗 Key Binding — AppKey ↔ NetKey

An AppKey can only work with one specific NetKey. This link is called the key binding.

NetKey Index AppKey Index Bound Application
0 (Main Network) 0 💡 Lighting control
0 (Main Network) 1 🔒 Door security
0 (Main Network) 2 📊 Sensor reporting

At the model level, each server model has a set of AppKeys bound to it. This means the model will only accept messages encrypted with those specific keys. Up to 251 AppKeys can be bound to a single model.

📌 Example: A Light Lightness Server might have 3 AppKeys bound to it (admin, user, guest — all can switch the light). But the Configuration Server only has 1 AppKey bound (admin only — only admin can configure the device).

🕵️ Obfuscation — Hiding Who Is Talking

Even though messages are encrypted, an attacker monitoring the radio could still track devices by watching which source address (SRC) sends messages over time. Bluetooth Mesh prevents this with obfuscation.

Without Obfuscation With Obfuscation
Packet 1: SRC=0x0023, SEQ=0100
Packet 2: SRC=0x0023, SEQ=0101
Packet 3: SRC=0x0023, SEQ=0102
⚠️ Attacker can track: “Device 0x0023 is active at these times and locations”
Packet 1: SRC=[AES encrypted]
Packet 2: SRC=[AES encrypted]
Packet 3: SRC=[AES encrypted]
✅ Attacker cannot correlate packets to a specific node

Obfuscation uses AES encryption to encrypt the source address, sequence numbers, and other header fields with a derived Privacy Key (derived from the NetKey). The receiving node knows the Privacy Key so it can reverse the obfuscation and read the actual header.

💡 Note: Obfuscation is not the same as encryption. Encryption hides the application data. Obfuscation hides the header metadata (who is sending). Both happen simultaneously.

🏷️ Key Identifiers — Efficient Key Lookup

A node may have many AppKeys and NetKeys. When a message arrives, the node needs to know which key to use to decrypt it. Trying all keys would be wasteful. Enter Key Identifiers.

A Key Identifier (Key ID) is a short value derived from the key itself using a key derivation function. It is included in the message header. The node checks the Key ID first to narrow down candidates, then tries only those matching keys.

📩 Incoming Message
KeyID: 0x2A
DST: 0xC001
Payload: [encrypted]

Node’s AppKey Table
AppKey Idx Key ID bits Match?
AppKey 0 0x15 ❌ skip
AppKey 1 0x2A ✅ try!
AppKey 2 0x3F ❌ skip
→ Try AppKey 1 → decryption succeeds!

If a message arrives with an unknown Key ID, the node immediately discards it without spending time trying to decrypt. This is efficient and also a first line of defence against unknown/rogue messages.

💻 BlueZ in Action — Managing Keys

Here is how you manage NetKeys, AppKeys, and model bindings using mesh-cfgclient in BlueZ.

Step 1: Add a new Application Key to the network (provisioner side)

# The primary NetKey (index 0) is created during provisioning.
# Add a new AppKey bound to NetKey 0
[mesh-cfgclient]# appkey-add 0

# Output: Added AppKey: index=1, bound to NetKey index=0

Step 2: Distribute the AppKey to a node using its Device Key

# Target node with unicast address 0x0001
[mesh-cfgclient]# target 0x0001

# Send AppKey Add message — internally uses the node's DevKey for security
# Command: appkey-add <net_key_index> <app_key_index>
[mesh-cfgclient]# appkey-add 0 1

# Output: AppKey Add Status: success
# The node 0x0001 now has AppKey index=1 in its key store

Step 3: Bind the AppKey to a specific model on the node

# Bind AppKey index=1 to Generic Power Level Server (0x1306) on element 0x0001
# Command: bind <element_addr> <app_key_index> <model_id>
[mesh-cfgclient]# bind 0x0001 1 0x1306

# Output: Model App Bind Status: success
# Now the Generic Power Level Server on Socket 1 ONLY accepts
# messages encrypted with AppKey index=1

Step 4: Verify key bindings — get model app status

# Check which AppKeys are bound to the model
[mesh-cfgclient]# model-app-get 0x0001 0x0001 0x1306

# Output:
# Model App Get: element=0x0001, model=0x1306
# Bound AppKeys: [1]   <--- only AppKey index 1 is bound

Step 5: Add a separate AppKey for door security (isolated from lighting)

# Add AppKey index=2 for door security — bound to the same NetKey 0
[mesh-cfgclient]# appkey-add 0   # creates index=2

# Distribute to door lock node at 0x0050
[mesh-cfgclient]# target 0x0050
[mesh-cfgclient]# appkey-add 0 2

# Bind to the door model on the lock
[mesh-cfgclient]# bind 0x0050 2 0x1000   # Generic OnOff Server on door

# The light bulb (0x0001) was NEVER given AppKey index=2
# So it can NEVER decrypt or act on door control messages

📝 Quick Summary

Concept Protects Known By
NetKey Network layer (routing + relay) All nodes in the network
AppKey Application data payload Only nodes for that application
DevKey Key distribution to each node Config Client + that node only
Key Binding Ties AppKey to a NetKey One AppKey → one NetKey only
Obfuscation Source address, SEQ (privacy) Uses Privacy Key from NetKey
Key Identifier Efficient key selection Derived from key via KDF

🎉 You’ve Completed the Bluetooth Mesh Foundations Series!

You now understand how mesh devices are structured (Elements & Models), how they communicate (Pub-Sub), and how everything stays secure (Keys & Obfuscation).

◀ Part 2: Publish-Subscribe 🏠 Back to BLE Series

Leave a Reply

Your email address will not be published. Required fields are marked *