From 95461d90eede1995409248c456c2d056ff34e4cc Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Sun, 31 May 2026 15:11:24 +0200 Subject: [PATCH] Increment signature counter by a random number As defined in Requirement 2.3.2 of the Security Requirements v1.5, we have to use a random (positive) increment for a global signature counter. This patch uses a random u8 + 1. As the signature counter is a u32, this still gives us more than 16 million operations until the counter can potentially overflow. --- CHANGELOG.md | 1 + src/state.rs | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f58040..eb783b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix signature counter to improve spec compliance: - Set the initial signature counter to 1. - Correctly handle signature counter overflows by returning 0. + - Increment the signature counter by a positive random number per assertion. ## [v0.4.0-rc.1](https://github.com/trussed-dev/fido-authenticator/releases/tag/v0.4.0-rc.1) (2026-05-29) diff --git a/src/state.rs b/src/state.rs index 480412d..dc751bd 100644 --- a/src/state.rs +++ b/src/state.rs @@ -395,13 +395,21 @@ impl PersistentState { } } - pub fn signature_counter(&mut self, trussed: &mut T) -> Result { + pub fn signature_counter( + &mut self, + trussed: &mut T, + ) -> Result { let now = self.timestamp; // 0 indicates a counter overflow. If this is the case, we can no longer increment the // counter and have to always return 0, see Requirement 2.3.2 in the Security Requirements // v1.5. if now > 0 { - if let Some(timestamp) = self.timestamp.checked_add(1) { + // As we use a global signature counter, we have to increment it by a random (positive) + // number to ensure that it cannot be used to correlate authenticators. + // The signature counter is a u32, so incrementing it by at most 256 still gives us plenty + // of time until the counter overflows. + let increment = syscall!(trussed.random_bytes(1)).bytes[0]; + if let Some(timestamp) = self.timestamp.checked_add(u32::from(increment) + 1) { self.timestamp = timestamp; } else { // Indicate an overflow by setting the counter to 0.