Skip to content

Time point parsing bounds#7648

Open
eddyashton wants to merge 18 commits intomicrosoft:mainfrom
eddyashton:time_point_parsing_bounds
Open

Time point parsing bounds#7648
eddyashton wants to merge 18 commits intomicrosoft:mainfrom
eddyashton:time_point_parsing_bounds

Conversation

@eddyashton
Copy link
Member

@eddyashton eddyashton commented Feb 6, 2026

Spotted some wraparound issues with our time-point parsing code. We use std::system_clock, which uses int64 to store nanoseconds from 1970. As such, the range of representable time points is surprisingly perceivable:

Duration min: 1677-09-21 00:12:43.145224192
Duration max: 2262-04-11 23:47:16.854775807

This specifically causes problems for certs with Not-Before or Not-After timestamps a few hundred years away - if they're after 2262, they wrap around and we get bugs.

This includes some new tests, in both crypto unit test and e2e cert auth, that exhibit these bugs.

There's also a proposed fix, shifting to tracking seconds rather than std::system_clock::time_points. This has a little more churn on the implementation than I'd like, so I'll also explore just defining our own clock type.

We fix this with minimal churn by defining a new clock type - ccf::ds::EpochClock, tracking seconds rather than nanoseconds. Note that we still use system_clock in many places, primarily for ::now(). I say that's fine - we can correctly convert between system_clock and EpochClock for every time within system_clock's bounds, which should include every value returned from now(). We only use EpochClock when we're consuming cert validity times, that are externally sourced and may well be hundreds of years in the future.

@eddyashton eddyashton added 6.x-todo PRs which should be backported to 6.x labels Feb 9, 2026
@eddyashton eddyashton marked this pull request as ready for review February 9, 2026 13:15
@eddyashton eddyashton requested a review from a team as a code owner February 9, 2026 13:15
Copilot AI review requested due to automatic review settings February 9, 2026 13:15
@achamayou achamayou added the auto-backport Automatically backport this PR to LTS branch label Feb 9, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses wraparound/overflow in X.509 certificate validity time handling by introducing a custom clock type (ccf::ds::EpochClock) which tracks seconds since epoch, avoiding std::chrono::system_clock’s nanosecond-range limits when parsing externally-sourced cert timestamps.

Changes:

  • Add ccf::ds::EpochClock and switch X.509 time parsing/formatting helpers to use it for parsed time points.
  • Update verifier APIs and OpenSSL wrappers to accept/use EpochClock::time_point for validity calculations.
  • Add unit and e2e tests covering long-lived and far-future certificate validity periods.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/js-custom-authorization/custom_authorization.py Adds e2e coverage for long-lived and far-future cert validity handling.
src/crypto/test/crypto.cpp Adds bounds-focused unit tests and migrates relevant tests to EpochClock.
src/crypto/openssl/verifier.h Updates verifier method signatures to take EpochClock::time_point.
src/crypto/openssl/verifier.cpp Updates implementations to match the new EpochClock-based API.
include/ccf/ds/x509_time_fmt.h Changes parsed time-point type to EpochClock and adds formatting overloads.
include/ccf/ds/epoch_clock.h Introduces the new seconds-based clock abstraction.
include/ccf/crypto/verifier.h Updates public verifier interface to use EpochClock for time-based queries.
include/ccf/crypto/openssl/openssl_wrappers.h Updates Unique_X509_TIME constructor to accept EpochClock::time_point.
Comments suppressed due to low confidence (1)

src/crypto/openssl/verifier.cpp:216

  • remaining_seconds() returns size_t but duration_cast<seconds>(tp_to - now).count() can be negative for expired certs; converting that to size_t will underflow to a huge value. Consider clamping at 0 (or returning a signed type) before converting to size_t.
  size_t Verifier_OpenSSL::remaining_seconds(
    const ccf::ds::EpochClock::time_point& now) const
  {
    auto [from, to] = validity_period();
    auto tp_to = ccf::ds::time_point_from_string(to);
    return std::chrono::duration_cast<std::chrono::seconds>(tp_to - now)
             .count() +
      1;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.x-todo PRs which should be backported to 6.x auto-backport Automatically backport this PR to LTS branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants