Skip to content

Proposal: non-blocking signing via OpenSSL's ASYNC_JOB API #35

Description

@venkatesh6911

rustls-openssl's Signer::sign() is synchronous and blocks the calling thread until OpenSSL returns. That's fine for CPU-bound signing, but it's not a suitable fit when the underlying key is backed by a hardware/optimized-software offload engine (e.g. Intel QAT via qatengine) or any other OpenSSL provider that can pause a long-running operation instead of blocking.

In that case, blocking the handshake thread for the duration of the round-trip defeats the purpose of using an event-driven/async server (one OS thread ends up parked per in-flight handshake instead of being free to drive other connections).

OpenSSL already has a mechanism for this: the ASYNC_JOB API (ASYNC_start_job/ASYNC_pause_job, stackful coroutines). Engines that support it call ASYNC_pause_job() internally when an operation is offloaded to hardware/optimized software library, and register a wait descriptor via ASYNC_WAIT_CTX_get_all_fds() so the caller can poll/select on it instead of blocking.

My proposal:

An opt-in async-jobs Cargo feature (Linux-only) that lets rustls-openssl drive Signer::sign()-equivalent operations as ASYNC_JOB`s instead of always blocking:

  • A PendingSign type wraps a single in-flight ASYNC_JOB. It's thread-affine (OpenSSL's ASYNC_JOBs can only be resumed from the OS thread that started/last resumed them), so PendingSign records its home_thread and returns an error rather than causing UB if polled from the wrong thread.
  • Per-thread ASYNC_init_thread job-pool sizing
  • If the engine pauses the job with a wait descriptor registered, that fd is exposed so callers can poll()/epoll on it instead of busy-looping.
  • Falls back to synchronous signing when the feature is disabled (the default) — this is purely additive.

This depends on a corresponding non-blocking signing API on the rustls side (a SignOperation/pending-result type, since rustls::sign::Signer is currently synchronous-only). I'm working on that as a separate proposal to rustls and happy to link it here once it's posted, and the two would need to land roughly together.

Given the size of the changes, I wanted to check with you on the next steps. I will be happy to raise a draft PR for you to take a look.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions