UltraWideLock: an Apple UWB digital key lock that an iPhone or Apple Watch unlocks on approach over UWB or on tap over NFC

Portable firmware for NFC and UWB smart locks.

v0.4.0 · ISC license · Zephyr, ESP-IDF and FreeRTOS ports · 9,608 host tests

UltraWideLock implements Aliro, the CSA door-lock credential standard, over BLE, NFC and UWB on real hardware. One portable core behind five HAL seams drives four lock applications, a second UWB anchor and standalone reader, initiator, anchor and witness examples, across Zephyr, ESP-IDF and FreeRTOS.

Features

Feature Description Command
Credential AUTH0, AUTH1, EXCHANGE, key ladder, provisioning and step-up over BLE make build
UWB ranging DS-TWR inside a CCC STS session, channels 5 and 9, FiRa session control make build
NFC tap ECP over an ST25R or PN532 reader on the nRF5340 DK make nrf-build
Matter node Hand-written Door Lock cluster, Approach Direction, UWB presence, five fabrics make build
Matter client Opens a second Matter lock over CASE through the Binding cluster make build CLIENT=1
Thread OpenThread MTD on the nRF parts make build
Wi-Fi Matter over Wi-Fi on ESP32-S3, C5 and C6 make esp-build APP=matter-lock
Second anchor A satellite joins the phone's own ranging round and returns a sealed distance make anchorlink
BLE witnesses Two dongles resolve inside from outside and latch the answer across a crossing make witness-build
Obstruction classifier Depth-2 decision tree over the DW3000 receive diagnostics, 776 B of flash make mlgate
Delta updates Signed P-256 deltas over BLE or USB through MCUboot make dfu
Whole-image updates Signed images over native GATT on ESP32 make esp-ota
Serial recovery A whole signed image over USB CDC-ACM, needing no starting image make ota-recovery
FreeRTOS port The same stack on the nRF52833 without Zephyr make freertos-build
SDK CMake package, umbrella header and per-role headers make sdk-export
Digital twin The ranging engine compiled to WebAssembly and replayed in a browser make test-twin
Website Guides, flasher, twin and subsystem graph, generated from this tree make docs-serve
Host suite 9,608 checks across 18 suites, no hardware make check

Quick start

The host suite needs a C compiler and python3.

git clone https://github.com/ultrawidelock/ultrawidelock.git
cd ultrawidelock
make check

Bare targets build for the Qorvo DWM3001CDK.

make dfu-key                # once per clone   · the image-signing key
make bootstrap              # once per machine · NCS v3.3.0
make build                  # -> build/cdk-matter
make flash
make monitor

Adding the key needs an iPhone with UWB on iOS 26 or later, a home hub and a Thread border router: add the key.

make help lists every target. make tools reports what this machine is missing.

Unlock sequence

Boards

Application Hardware Connectivity
apps/dwm3001cdk-lock/ DWM3001CDK UWB, Matter over Thread
apps/dwm3001cdk-lock-freertos/ DWM3001CDK, no Zephyr UWB, Matter over Thread
apps/nrf5340dk-lock/ nRF5340 DK, DWM3000EVB, NFC12A1 UWB and NFC, Matter over Thread
apps/esp32-matter-lock/ ESP32-S3 / C5 / C6 with DWM3000EVB UWB, Matter over Wi-Fi
apps/satellite/ CDK, nRF5340 DK, or the ESP32 tier UWB responder, sealed link to the lock
make nrf-build && make nrf-flash && make nrf-term    # nRF5340 DK
make esp-bootstrap && make esp-go APP=matter-lock TARGET=esp32s3
make freertos-build && make freertos-flash           # the Zephyr-free port
make sat-build && make sat-flash                     # the satellite
make hitl                                            # unattended end-to-end bench
Example Role Build
examples/zephyr/anchor/ Two-board anchor-to-anchor DS-TWR bench make anchor-pair
examples/zephyr/ble-witness/ The inside/outside dongle make witness-build
examples/zephyr/nrf5340dk-initiator/ A DK standing in for the phone make nrf-init-build
examples/esp32/reader/ The credential reader alone make esp-build APP=reader
examples/esp32/initiator/ An ESP32 BLE initiator peer make esp-build APP=initiator
examples/esp32/satellite/ The satellite on the ESP32 tier make esp-build APP=satellite
examples/cmake/consumer/ An out-of-tree C consumer of the SDK make sdk-check

Apple Home and Home Assistant share one CDK and one Thread network: the multi-admin guide.

Home Key setup, Approach Direction, provisioning, NFC tap, and lock-state notifications on live hardware
Home Key · Approach Direction · provisioning · NFC tap · live lock state

Updates

ultrawidelock.com/flash finds the board, reads what it is running and sends the one update that applies. Chrome or Edge on a computer, Chrome on Android.

DWM3001CDK ESP32-S3 / C5 / C6
Transport mcumgr, over BLE or USB Native GATT frames
Payload Signed delta, ~11 KB Signed whole image, ~2 MB
Slots One MCUboot slot in 512 KB Two full OTA slots
Time Seconds Several minutes over BLE

Writing starts once the update window is open on the board: SW2 on the CDK, a double-click on the ESP32's button. Authenticity is a P-256 signature, checked before the first byte is written and again by the bootloader.

The CDK also reinstalls whole over that cable through MCUboot serial recovery, which runs from the bootloader alone.

make fota                   # CDK: one file a phone can install
make fota-done              # after every phone push, to record what the board runs
make ota-fan  PREV_HEXES=…  # the delta fan and the index the web page reads
make release  RELEASE_KEY=… # the published bundle

make fota-done is required: a CDK delta is cut against the exact bytes on the part, and only the build host keeps that record.

In a browser

ultrawidelock.com is generated from this tree by stdlib Python. make docs-serve serves it on localhost:8080.

Page Contents
Guides Every file in docs/, with search, a contents rail and a reading order
Digital twin The ranging engine in WebAssembly: walk a phantom phone, add noise, fire a Ghost-Peak spoof, single-step a DS-TWR round
Flash Install an ESP32 over the cable, or update either chip over the air
Graph The subsystem graph, generated from the source tree

The twin compiles the untouched modules/ultrawidelock_uwb sources against the host shim the test suite links, so every block is a real CCM*-encrypted exchange decoded by the firmware's own RX state machine.

Verification

make check                  # 18 host suites, 9,608 checks, no hardware
make ci                     # every pull-request gate, in CI's order
make regress                # everything a machine can check without a board
make regress-hil            # and then on air, against a live reader
Gate Enforces
make seam Every call to the radio passes the CCC STS seam
make scope Vendor radio APIs are named only in the DW3000 engine file set
make purity modules/ names no OS, and each port tree names only its own
make drift Constants and integration patch sets match the C they are copied from
make cdk-size-check The image keeps its flash and RAM headroom
make lint / make sca cppcheck and Clang Static Analyzer over the portable tree
make cbmc The wire parsers are proved memory-safe
make test-san The host suite passes again under ASan and UBSan
make coverage Line coverage, with 0% rows for what no suite reaches
make docs-check Every internal link resolves, and three constant tables match their C

make sdk-check builds an out-of-tree C consumer against the installed CMake package. make app-diff diffs this tree's door-lock app against pinned upstream. make instrument serves a latency dashboard captured from a real board.

SDK

#include <ultrawidelock/reader.h>     // the lock side
#include <ultrawidelock/device.h>     // the initiator side
#include <ultrawidelock/tlv.h>        // the codec alone

Ports implement the five seams in <ultrawidelock/ultrawidelock_hal.h>: DW3000 GPIO/IRQ, DW3000 SPI, reader BLE, central BLE and credential storage. New board or chipset: PORTING.md. Consuming the CMake package directly: reference.

Documentation

Start configuring · add the key · troubleshooting
Boards ESP32 bring-up · ESP32 gotchas · nRF5340 bring-up · nRF5340 wiring · DWM3001CDK surgery · hardware validation
Porting porting · porting to ESP32 · chipset memory
Protocol notes · research · range integrity · approach direction · UWB MAC login · Door Lock events · Matter binding · binding bench · BodyCal
Side of door inside latch · second anchor · bench runbook
Reference reference · changelog · contributing · coding agents

Repository layout

ultrawidelock/
├── apps/           complete lock products
├── examples/       independently buildable role and bench examples
├── modules/        the portable protocol, with no OS in it
│   ├── ultrawidelock_cred/       credential sessions, TLV, key ladder
│   ├── ultrawidelock_cred_stack/ that stack, adapted into the Nordic app
│   ├── ultrawidelock_uwb/        ranging engine behind the STS seam
│   ├── ultrawidelock_dw3000/     DW3000 driver integration
│   ├── ultrawidelock_anchor/     side of door: fusion, latch, witnesses, seal
│   ├── ultrawidelock_matter/     the hand-written Matter node
│   ├── ultrawidelock_ml/         on-device classifiers
│   ├── ultrawidelock_nfc/        ECP and reader transports
│   ├── ultrawidelock_dfu/        signed delta updates
│   └── ultrawidelock_port/       the OS, flash, log and byte-order contracts
├── ports/          zephyr · esp32 · freertos-nrf52833
├── integrations/   patches for external upstream applications
├── tests/          host, shared, port, tooling, sdk, on-target
├── include/        SDK umbrella and public-API ownership
├── cmake/          shared CMake helpers
├── mk/             what sits behind each Make target
├── scripts/        setup, release, DFU, sizing, device utilities
├── docs/           the guides, read on GitHub and published to the site
├── web/            the site, the flasher, the WASM twin, the graph
└── release/        templates and scripts for release bundles
A Wallet home key unlocking the lock on approach, recorded on real hardware

A Wallet home key, on approach, recorded on hardware.

FAQ

What is needed to add the key? An iPhone with UWB on iOS 26 or later, a home hub such as a HomePod or Apple TV, and the network the target joins: a Thread border router for the nRF boards, 2.4 GHz Wi-Fi for ESP32. The image ships no credential; Apple Home mints the Aliro key during Matter commissioning.

Which board should come first? The Qorvo DWM3001CDK. It carries the nRF52833, the DW3110 radio and a J-Link on one module, and every bare make target builds for it.

Can it be tried without hardware? Yes. make check runs the whole host suite, and the digital twin runs the firmware's own ranging engine in a browser.

Does the phone have to be awake? No. An NFC tap is validated in Express Mode with the screen off (HV-5).

Where does the console come from? RTT, not UART. make monitor attaches with the ELF that was flashed. The ring survives reset, so the first block belongs to the previous run.

What does make flash-erase cost? The commissioning. Apple Home has to add the lock again, and Home Assistant has to be shared again afterward.

Can one lock open another? Yes. make build CLIENT=1 compiles the Matter client role, which opens a bound lock over CASE through the Binding cluster.

[!WARNING] These are bench defaults. Do not secure valuables with them, and never lock APPROTECT: recovery needs a mass erase, which takes the reader's private key and every phone key on it. scripts/check-approtect.sh checks a part.