Skip to content

Firmware: Google Find Hub (FMDN) advertising for nRF5x (#3) - #4

Merged
dzianisv merged 3 commits into
mainfrom
issue-3-findhub-fmdn
Oct 2, 2026
Merged

dzianisv merged 3 commits into
mainfrom
issue-3-findhub-fmdn

Conversation

@dzianisv

@dzianisv dzianisv commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Closes #3 (phase 1).

  • FIND_NETWORK=APPLE (default, unchanged) | GOOGLE_FMDN | DUAL
  • FEAA service-data advert, frame 0x41, 20-byte SECP160R1 EID from a precomputed table
  • tools/fmdn_keys.py + tests/test_fmdn_keys.py

Testing: .venv/bin/python -m unittest discover -s tests -> Ran 86 tests, OK (skipped=2).
Caveats: Google publishes no numeric EID test vector; tests are FIPS-197 AES + curve/composition self-consistency. Firmware NOT compiled (no arm-none-eabi-gcc locally). Not flashed / not live-verified on Android. Find Hub account registration not addressed.

APPLE stays the default. GOOGLE_FMDN and DUAL advertise a precomputed SECP160R1 EID table as FEAA service data.
@dzianisv

dzianisv commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

Independent review of exact head 2e9f805 — REQUEST CHANGES (comment-only: the configured GitHub identity is also the PR author, so GitHub cannot record a formal self-review).

  1. Blocking — firmware/src/ble_stack.c:36, :50, :58 and :258-292: The frame is unconditionally 0x41, but the hashed clear flags have UTP bit 7 = 0 and the NRPA changes on every EID rotation. The FHN spec defines 0x41 as unwanted-tracking-protection mode, requiring that bit set and a fixed FHN address (up to a 24-hour rotation); normal mode is 0x40. This advert makes contradictory mode claims and can be classified as an unwanted tracker. Use 0x40 for the implemented normal mode; only advertise 0x41 if the UTP state, flag and MAC behavior are actually implemented together. Source: https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn (Advertised frames; Unwanted tracking protection mode).

  2. Blocking for a resolvable FHN tag — firmware/src/main.c:215-217, :435-440, :506-512 and fmdn_eid_table.h:14-18: The firmware treats the EID table as a circular list, beginning at time-counter zero on every boot. With the committed eight slots and the documented 1024-second interval, after 8192 seconds it repeats EID/time-counter 0 while the owner resolver expects the advancing beacon clock. Power cycling resets to slot 0 as well. Moreover, the build default interval remains 3600 seconds, so FIND_NETWORK=GOOGLE_FMDN without a separate override diverges from the table at the first rotation. Tie EID selection to a persistent/synchronized counter or explicitly bound and reject the usable lifetime, and enforce/validate K=10 rotation for this mode. Otherwise the broadcast is syntactically FEAA but not reliably locatable in Find Hub. The README acknowledges the clock/reset limitation; it does not make this acceptance path work.

  3. Required verification absent — issue Firmware: Google Find Hub (FMDN) support for nRF5x tags #3 asks for an nrf52832 GOOGLE_FMDN build and a live Android scan. The passing firmware CI Build job runs make all with FIND_NETWORK=APPLE only (.github/workflows/build-firmware.yml:35-37); my local checkout has neither the Nordic SDK nor arm-none-eabi-gcc, so I cannot establish that the new firmware path compiles. No flashed Android FEAA scan evidence is supplied. The PR also has a red Lockfile in sync check: run 36967943522/job/110715660357 reports Pipfile.lock out-of-date. Please provide the named build/scan evidence and resolve the red check before merge.

Verified: the Python timestamp block is FF11 || 0A || masked uint32 BE || 0011 || 0A || masked uint32 BE; r = AES-256-ECB(block) mod SECP160R1 n; the x-coordinate matched independent OpenSSL secp160r1 public-key derivation for timestamps 0, 1024, 0x84d000 and 1700000000 using the public placeholder EIK. FEAA AD length 0x19, UUID byte order AA FE, EID bytes 8..27 and hashed flags byte 28 match Table 15. Local .venv/bin/python -m unittest discover -s tests -v: Ran 86 tests, OK (2 skipped). The APPLE default branch keeps the prior key choice/advertising call and the CI default APPLE build passed; no hardware regression test was performed. Google publishes no numeric EID reference vector, so the Python suite cannot meet issue #3s vector criterion literally.

Use frame type 0x40. 0x41 is unwanted-tracking-protection mode and this
build does not implement the UTP flag or a fixed address.

GOOGLE_FMDN and DUAL require a 1024-second rotation. The beacon counter
is stored in the last flash page and restored after reset. The table is
not circular: advertising stops when the counter leaves the precomputed
windows instead of repeating slot 0.
@dzianisv

dzianisv commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

Independent re-review of exact head 3514f92 against my comment 5946035986 — REQUEST CHANGES (comment-only: this GitHub identity is the PR author, so GitHub cannot record a formal self-review).

Fixed / verified:

  • Frame type is now 0x40 in firmware/src/ble_stack.c; Python advert layout agrees. The implemented clear UTP flag and rotating NRPA no longer contradict the advertised mode.
  • GOOGLE_FMDN/DUAL force K=10 / 1024 seconds in both Makefiles; the C static assertions and generator reject mismatches. make -C firmware/src -n nrf52832_xxaa FIND_NETWORK=GOOGLE_FMDN KEY_ROTATION_INTERVAL=3600 rejects the override; the default dry run passes 1024.
  • Slot selection rejects pre-table and exhausted counters rather than wrapping. fmdn_state.c journals the beacon counter to a reserved flash page and restores it across ordinary resets; main.c stops FMDN advertising on exhaustion (DUAL continues Apple). This fixes the former deterministic slot-zero reboot and table-wrap behavior, though elapsed time while unpowered remains unsynchronized, as documented; no on-device persistence test was provided.
  • Firmware CI job 110721472949 completed successfully: its log shows the nrf52832 GOOGLE_FMDN step actually compiled main.c, ble_stack.c, and fmdn_state.c, linked _build/nrf52832_xxaa.out, and produced the merged S132 binary with FIND_NETWORK=GOOGLE_FMDN and KEY_ROTATION_INTERVAL=1024. The prior missing-build finding is resolved.

Still blocking:

  1. Lockfile in sync fails on both current-head CI runs (jobs 110721473038 and 110721461988): pipenv verify says Pipfile.lock is out-of-date. My local /opt/homebrew/bin/pipenv verify says up-to-date, so this is an environment-dependent lock-hash discrepancy, not proof that CI is wrong. Make the lock verify on the workflow's Linux/Python 3.12/pipenv installation and get the checks green; do not waive the red checks.
  2. Unit tests (Linux) fails on both runs (e.g. job 110721472788): test_fmdn_make_forces_k10_and_rejects_3600 assumes make -n succeeds without the Nordic SDK. The CI Python job does not download the SDK, so the nested make exits 2 with missing nRF5_SDK_15.3.0_59ac345/.../Makefile.common. This test passes locally only because the SDK exists in that checkout. Make the test independent of a local SDK or provide the required fixture/dependency to that job, then verify the whole suite green.
  3. Issue Firmware: Google Find Hub (FMDN) support for nRF5x tags #3's named live acceptance — a flashed tag seen as FEAA by an Android scan — still has no evidence. The compile and Python tests do not exercise radio output or the flash journal on hardware. Supply the scan evidence before claiming that acceptance path complete.

No merge performed.

make -n still runs recipes that call $(MAKE), so a dry-run of
nrf52832_xxaa entered the chip makefile and failed when the SDK was
not downloaded. The interval is now resolved by check-fmdn-interval
before that include, and the chip makefiles reject a non-1024
interval before they include the SDK.

CI installs pipenv 2026.8.0, which hashes Pipfile names in PEP 503
form (FindMy becomes findmy). The lock still had the older plette
hash, so pipenv verify said it was out of date even though the pins
match main. Rehashed with 2026.8.0 and left the pins alone: a macOS
pipenv lock would strip the darwin markers Linux sync depends on.
@dzianisv

dzianisv commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

Independent re-review of exact head 02fbece against comments 5946035986 and 5946269925 — APPROVE (code-review verdict, comment-only: the configured GitHub identity is the PR author and cannot submit a formal approving self-review).

Previously blocking CI issues are resolved: both current-head push and PR runs completed successfully. The Linux unit-test log explicitly reports OK (skipped=2), the lockfile verification says Pipfile.lock is up-to-date, and the firmware build log shows fmdn_state.c compiled, nrf52832_xxaa.out linked, DONE nrf52832_xxaa, and the S132 image merged in the GOOGLE_FMDN step. The Makefile guard now has an SDK-free check target; locally, the 16 FMDN tests passed and the 3600-second override was rejected. The complete local suite could not run in my isolated checkout (findmy is not installed there); the CI Linux suite is the full-suite evidence.

The earlier 0x41 mode and table-wrap/reset findings remain addressed in the reviewed diff (0x40 normal mode, K=10 enforcement, bounded slot selection and flash journal). No additional evidenced code-review blocker found. The flashed-tag Android FEAA scan and on-device journal behavior are not verified by CI and remain separate hardware acceptance; this verdict does not claim those steps passed or that Find Hub registration is implemented. No merge performed.

@dzianisv
dzianisv merged commit 65e765a into main Oct 2, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Firmware: Google Find Hub (FMDN) support for nRF5x tags

1 participant