Breadboard
docs
Example project · ESP32

Bluetooth LE: pair & encrypt

Two ESP32-C6 boards secure a real LE link end-to-end: one advertises connectably, the other connects as central and calls gap_pair. The SMP Just-Works handshake runs over the link (watch the SMP frames in the Sniffer), the controllers derive the key and run the LL encryption-start procedure, and BOTH boards report _IRQ_ENCRYPTION_UPDATE with a 16-byte key — the peripheral’s report rides the emulator’s post-encryption receive path through the controller’s own buffer allocator. One script on both boards; roles derive from each board’s MAC.

The Bluetooth LE: pair & encrypt circuit as rendered by the simulator

What's on the bench

  • 2× Battery
  • 2× ESP32-C6

The code

This MicroPython script runs on the emulated board every boot; edit it in the Code tab.

import bluetooth, time
b = bluetooth.BLE()
b.active(1)
b.config(bond=False, mitm=False, le_secure=False)
S = {}
server = b.config('mac')[1][-1] % 2 == 0
tag = 'SRV' if server else 'CLI'
tgt = []
cn = []
def cb(e, d):
    if e == 29:
        t, i, k = d
        return None if k is None else S.get((t, bytes(k)), None)
    if e == 30:
        t, k, v = d
        k = (t, bytes(k))
        if v is None:
            S.pop(k, None)
        else:
            S[k] = bytes(v)
        return True
    if e == 28:
        print(tag + ' encrypted, key size ' + str(d[4]))
    elif e == 5 and not tgt:
        tgt.append((d[0], bytes(d[1])))
        print('CLI found advertiser')
    elif e == 7:
        cn.append(d[0])
        print('CLI connected, pairing soon')
    elif e == 1:
        print('SRV central connected')
b.irq(cb)
if server:
    b.gap_advertise(50000, b'\x02\x01\x06\x05\xffCAFE', connectable=True)
    print('SRV advertising, ready to pair')
else:
    b.gap_scan(0, 30000, 30000)
    while not tgt:
        time.sleep_ms(50)
    b.gap_scan(None)
    time.sleep_ms(50)
    b.gap_connect(tgt[0][0], tgt[0][1])
    while not cn:
        time.sleep_ms(50)
    time.sleep_ms(2000)
    b.gap_pair(cn[0])
    print('CLI pairing...')