rustls icon indicating copy to clipboard operation
rustls copied to clipboard

Use monotonic time for ticket refresh/lifetimes

Open ctz opened this issue 2 years ago • 5 comments

I think the ticketer code should be relying only on monotonic time so tickets have the desired lifetime irrespective of system clock jumps.

ctz avatar Sep 13 '23 10:09 ctz

@japaric this might be relevant for #1399.

djc avatar Sep 13 '23 11:09 djc

Yeah, though a first pass of no-std for that would be to avoid providing the standard ticketer at all.

ctz avatar Sep 13 '23 11:09 ctz

One issue I thought about: this pretty much only works for a single process run, right? If the machine persists tickets across reboots or if tickets are shared via a network cache, there would still be no monotonicity guarantee (and it might even be worse than using a SystemTime)?

djc avatar Sep 13 '23 12:09 djc

implementing a monotonic timer, that is relative time (Instant & Duration in libstd), on bare metal (no OS) systems is easier than implementing a real time clock, that is absolute time (date and time) (+), so this would actually make no-std usage easier.

as far as the no-std RFC is concerned, the TimeProvider would become an InstantProvider and get_current_time would return an opaque Instant type that implements Sub<Rhs=Self, Output=core::time::Duration>. the conversions to std::time::SystemTime would no longer be needed.

if support for making rustls dump and reuse session tickets is implemented at some point in time (and I think that feature should use something like SystemTime as djc pointed out), that should be done as an optional extension -- ideally configurable via the Config structs rather than a more coarse mechanism like a Cargo feature -- so that no-std users are not forced to provide a SystemTime implementation to use rustls but can opt into reusable session tickets if they do have a SystemTime implementation.

(+) properly implementing a real time clock (RTC) requires a battery to keep the clock running while the system / CPU is powered off. embedded systems (including embedded Linux systems) that lack a battery sometimes implement RTC functionality by relying on an external NTP server so before the NTP server is contacted there's no absolute SystemTime, only Instants that are basically a Duration relative to the boot time.

EDIT: summary of the above, I'd be in favor of rustls, in std mode, relying on Instant instead of on SystemTime because that makes no-std usage / adoption easier

japaric avatar Sep 14 '23 11:09 japaric

summary of the above, I'd be in favor of rustls, in std mode, relying on Instant instead of on SystemTime because that makes no-std usage / adoption easier

circling back to this: while working on the no-std PR, I realized that even if the ticketer uses something like Instant, other components will still have to rely on UnixTime (SystemTime). for example, the server cert verification that the client does needs to get the current time, as a non-opaque UnixTime, to check if the the certificate is valid; as far as I see, the certificate stores this information as DER-encoded UnixTime values.

so, here we are talking about only using opaque Instant-like values in the ticketer while other components continue to use UnixTime, correct? in that case, the change does not make no-std usage easier because everyone would still need to provide a source of UnixTimes and, if they want to use the ticketer, then they would on top of that provide a source of Instants. To the contrary, that makes no-std usage a bit harder ~~but since the ticketer / resumption is an optional component it does not seem like much of a big deal.~~ actually the Instant provider may end up being required for everyone because Resumption is a feature that's enabled at runtime. this probably would need to become Instant::now, right?

https://github.com/rustls/rustls/blob/ac10422a898335230f64104b169461a50e9d61db/rustls/src/client/hs.rs#L71

japaric avatar Oct 16 '23 13:10 japaric