Skip to content

fix: use wall-clock time for the WireGuard handshake timestamp - #13

Merged
fudio101 merged 1 commit into
mainfrom
fix/tai64n-wall-clock
Aug 18, 2026
Merged

fix: use wall-clock time for the WireGuard handshake timestamp#13
fudio101 merged 1 commit into
mainfrom
fix/tai64n-wall-clock

Conversation

@fudio101

Copy link
Copy Markdown

Summary

wireguard_tai64n_now() in src/wireguard-platform-esp32.c used esp_timer_get_time() (device
uptime) for the TAI64N handshake-initiation timestamp. Per WireGuard's replay protection (spec
5.1), a peer keeps the greatest timestamp it has seen from us and rejects any handshake initiation
whose timestamp is not greater. With uptime as the source, every reboot restarts the counter near
zero — so a device that ran for hours cannot reconnect at all after a reboot, until its new uptime
happens to exceed the previous session's.

Fix: use gettimeofday() (wall-clock time, expected to be SNTP-synced before connecting) instead.
Also drops the now-unused esp_timer.h include (confirmed esp_timer_get_time() was its only use
in this file — wireguard_sys_now() uses lwIP's sys_now(), unaffected).

Attribution

Adapted from CamM2325/microlink@6a4447c5
and CamM2325/microlink@a8d769e3 — this
fix originated in the microlink monorepo before wireguard_lwip was split out into this
standalone repo/submodule, as part of absorbing the bugfix/hardening subset of upstream
CamM2325/microlink#22
(see fugo101/microlink#44, already merged).

Test plan

  • No build environment available in the sandbox this PR was written in — please build/flash
    before merging.
  • Manual diff review: pure timestamp-source swap, wireguard_sys_now() untouched, confirmed no
    other use of esp_timer_get_time() in this file.
  • Hardware re-test recommended specifically for reconnect-after-reboot, since that's the exact
    scenario this fix targets — a fresh boot needs the system clock set (SNTP) before the WG
    handshake for the fix to take effect as intended.

🤖 Generated with Claude Code

wireguard_tai64n_now() used esp_timer_get_time() (uptime) for the
TAI64N handshake-initiation timestamp. A peer keeps the greatest
timestamp it has seen from us and rejects any handshake initiation
whose timestamp is not greater (replay protection, WireGuard spec
5.1). With uptime, every reboot restarts the counter near zero, so a
device that ran for hours cannot reconnect after a reboot until its
new uptime passes the previous session's.

Switch to gettimeofday() (wall-clock, expected to be set e.g. by SNTP
before connecting). Also drops the now-unused esp_timer.h include.

Adapted from CamM2325/microlink@6a4447c5 and
CamM2325/microlink@a8d769e3 (this fix originated in the microlink
monorepo before wireguard_lwip was split into its own submodule/repo).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@fudio101
fudio101 merged commit dd5e921 into main Aug 18, 2026
4 checks passed
fudio101 added a commit to fugo101/microlink that referenced this pull request Aug 18, 2026
Picks up the TAI64N wall-clock handshake-timestamp fix
(fugo101/wireguard-lwip#13, released as v1.0.1) for local/submodule
builds. Registry-based builds already resolve it automatically via
idf_component.yml's existing "^1.0.0" pin — no change needed there.

Refs fugo101/wireguard-lwip#13

Co-authored-by: Adrian.Nguyen-Qualgo <nguyen.ndt@qualgo.net>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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.

2 participants