penguin/homekey-go

homekey-go

ha-app/NFC.md

raw ยท 4712 bytes

NFC STANDARD authentication

This release connects the HomeKit provisioning store to the ESP32 reader. Go runs SELECT, AUTH0 and STANDARD AUTH1; the ESP32 keeps the PN532 target active and relays APDUs. A verified, active enrolled endpoint unlocks the virtual HomeKit lock and updates its target/current state to unlocked. There is no physical actuator integration in this release.

Deploy both sides

  1. Apply the matching homekey-relay changes and build/flash its ESP32 project:

    cd esp32
    idf.py build flash monitor
    

    The PN532 UART remains TX GPIO3 / RX GPIO4 at 115200 baud. The firmware preserves the startup wake prefix on firmware and SAM commands and their existing initialization order. NFC runs in its own task with an 8192-byte stack; there is no need to edit an existing sdkconfig's main-task stack.

  2. Build and publish your usual homekey-go, then stage the HA app metadata using the existing repository workflow. Update the installed app and restart it. Keep its existing persistent /data/state.

  3. Discover readers and assign them to locks in Open Web UI as described in DOCS.md, then save the configuration. The app needs host D-Bus, host networking, and one TCP HomeKit port per lock. Open Web UI for pairing.

  4. Hold the phone at the reader with its existing Home Key installed. ECP should select the key; Express Mode can authenticate without opening Wallet. If Express Mode is disabled, approve the presented Home Key. Remove it between attempts. Set the virtual lock to locked first if you want to see the successful transition in Home.

Expected Go milestones:

BLE gateway: connected to ...; APDU write_size=...
BLE gateway: Home Key ECP configured reader=... enabled=true
Home Key SELECT accepted; protocol=2.0
Home Key AUTH0 key exchange complete
Home Key authenticated reader=... session=... endpoint=... lock=...; virtual lock unlocked

An ordinary card can be detected without having the Home Key applet. SELECT status 6a82 means the applet was unavailable for that attempt. It does not mean that UID detection or BLE is broken. AUTH1: unknown, inactive or invalid endpoint does not grant access; check that the phone has an enrolled key.

If the app reports missing relay characteristics after flashing, BlueZ may still have the old GATT services cached. Disconnect/reconnect first. If they remain missing, remove only this reader's BlueZ device entry on the host and let the gateway rediscover it. There is no need to remove the HomeKit lock or its provisioned keys.

Scope

Home Key ECP routing is implemented in the matching firmware. It requires both updates: Go supplies the public Home group ID, and the ESP32 broadcasts it before card activation. No private key is sent over BLE. Firmware waits with RF off until configured and clears the configuration on reconnect. Go updates the group when provisioning changes. ECP itself does not authenticate a device.

FAST authentication and NFC attestation for previously unknown/shared devices are not implemented yet. The stored persistent key is preparation for FAST; this release still performs STANDARD on every tap.

The NFC session expires after 15 seconds. Go allows 12 seconds for authentication, 5 seconds per APDU and 2 seconds for completion UX. APDUs are bounded to 240 bytes; extended/chained PN532 APDUs and ISO18013 attestation transfers are not supported. An error, removal, timeout or disconnect never authenticates a key.

Verification

Go tests cover an end-to-end simulated phone, response tampering, unknown and inactive endpoints, revocation and reader changes, BER-TLV failures and stale BLE responses. Independent Python cryptography vectors verify X9.63/HKDF and secure-response decryption; RFC 4493 vectors verify AES-CMAC.

The firmware host tests exercise UART frame parsing and the BLE mailbox with AddressSanitizer/UndefinedBehaviorSanitizer:

./tests/run.sh

These host tests do not replace an ESP-IDF build or an actual phone tap. This patch was not tested on ESP32/PN532 hardware.