pccs: report a missing rustls crypto provider instead of panicking - #80
Merged
ameba23 merged 1 commit intoAug 13, 2026
Merged
Conversation
The workspace pins reqwest with rustls-no-provider, so building a reqwest::Client requires the application to have installed a process-level rustls crypto provider. That requirement was documented nowhere and enforced only by the #[cfg(test)] install helpers, and the one client pccs builds itself lives in fetch_fmspcs — called from the pre-warm task Pccs::new spawns in its constructor. An application that never installed a provider therefore got a panic inside a detached task it cannot catch, dumping a full backtrace on every Pccs construction. That panic was worse than log noise: - Pccs::ready() deadlocked: the task died before finish_prewarm, so the outcome channel never resolved — and it cannot even close, because the Pccs instance being awaited holds the sender alive. An application doing the responsible thing and waiting for the cache before serving hung forever, with no error and no timeout. - Under panic = "abort" the same code killed the whole process, so the library's failure mode ranged from invisible to fatal depending on the consumer's build profile. The blast radius was otherwise confined to the pre-warm: on-demand collateral fetches and background refreshes go through dcap-qvl, whose client bundles its own TLS provider, so verification kept working while the FMSPC-discovery step died silently. Check for the provider before building the client and return a new PccsError::MissingCryptoProvider naming the fix. The pre-warm then degrades through its existing failed-fetch path — one warning line stating the consequence (no warm cache, collateral fetched on demand) and the remedy — and ready() surfaces the same error immediately, so applications that consider a warm cache mandatory get fail-fast semantics. The precondition is now documented on Pccs. Deliberately not chosen: installing aws-lc-rs as a silent fallback when no provider is set. That would force the aws-lc-rs build dependency on every consumer — the choice rustls-no-provider exists to leave with the application — and an application installing its own provider late with install_default().unwrap() could lose the race against the pre-warm task. The rustls dependency added here carries no provider feature: only the process-default lookup is used.
samlaf
added a commit
to SeismicSystems/enclave
that referenced
this pull request
Aug 12, 2026
…#246) Fixes SEI-201 Quote verification's collateral fetching (attested-tls) builds rustls-backed HTTP clients. rustls 0.23 requires the application to install a process-level default crypto provider; without one, the first verification panics with "no process-level CryptoProvider available". Install the aws-lc-rs provider at service start, before anything verifies evidence. The install is best-effort: a provider installed earlier by an embedding process wins, and any provider serves. Related to, but orthogonal to, our upstream PR flashbots/attested-tls#80.
ameba23
approved these changes
Aug 13, 2026
ameba23
left a comment
Collaborator
There was a problem hiding this comment.
Good catch and sorry for not documenting. Ideally we want to not lock in to either aws-lc or ring but let users of the library choose. But it does cause issues like this.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Human Summary
Forgot to setup a rustls provider in our code, and hence the collateral prefetcher was just panicing in the background and cluttering our logs with huge stack traces (see this for example):
LLM Summary
The workspace pins reqwest with rustls-no-provider, so building a
reqwest::Client requires the application to have installed a
process-level rustls crypto provider. That requirement was documented
nowhere and enforced only by the #[cfg(test)] install helpers, and the
one client pccs builds itself lives in fetch_fmspcs — called from the
pre-warm task Pccs::new spawns in its constructor. An application that
never installed a provider therefore got a panic inside a detached
task it cannot catch, dumping a full backtrace on every Pccs
construction.
That panic was worse than log noise:
the outcome channel never resolved — and it cannot even close,
because the Pccs instance being awaited holds the sender alive. An
application doing the responsible thing and waiting for the cache
before serving hung forever, with no error and no timeout.
the library's failure mode ranged from invisible to fatal depending
on the consumer's build profile.
The blast radius was otherwise confined to the pre-warm: on-demand
collateral fetches and background refreshes go through dcap-qvl, whose
client bundles its own TLS provider, so verification kept working
while the FMSPC-discovery step died silently.
Check for the provider before building the client and return a new
PccsError::MissingCryptoProvider naming the fix. The pre-warm then
degrades through its existing failed-fetch path — one warning line
stating the consequence (no warm cache, collateral fetched on demand)
and the remedy — and ready() surfaces the same error immediately, so
applications that consider a warm cache mandatory get fail-fast
semantics. The precondition is now documented on Pccs.
Deliberately not chosen: installing aws-lc-rs as a silent fallback
when no provider is set. That would force the aws-lc-rs build
dependency on every consumer — the choice rustls-no-provider exists to
leave with the application — and an application installing its own
provider late with install_default().unwrap() could lose the race
against the pre-warm task. The rustls dependency added here carries no
provider feature: only the process-default lookup is used.