Re: [PATCH 2/3] AF_ALG: Drop support for off-CPU cryptography

From: Simon Richter

Date: Sat Jul 25 2026 - 06:24:00 EST


Hi,

On 7/25/26 16:37, Dominique Martinet wrote:

So being selfish I'd very much appreciate some effort to have a standard
API everyone could use to simplify my userspace, but given vendors will
never spend this kind of time I guess it's a pipe dream and I'll be
stuck with custom drivers and/or framework for the forseeable future...

The thing is: such an API would have to look completely different from the API we have now, and all the existing drivers would need to be ported to it.

The current API is designed around the assumption that the hardware can be interfaced with minimal overhead. This assumption is no longer true for any hardware built in the last ten years at least.

One example for this assumption is the "import" and "export" functions in ahash: these are synchronous even though the hash is supposed to be asynchronous. That is not a problem for the old hardware, since we can just grab the hash state via direct register access, but it makes it close to impossible to write a conforming implementation on anything more modern.

I've tried on an FPGA, but even with full control over the hardware implementation, I need to either serialize all requests and reduce performance, or implement an elaborate system where each request context goes into a separate virtual queue that can be synchronized without affecting other in-flight requests. On the other hand, I need that mechanism anyway, because ahash is not expected to return the result via DMA -- instead, we are supposed to use an interrupt that collects the result and starts the next queued request if there is any.

I don't believe ahash/acomp/acrypt is salvageable, because it is not only a problem on the hardware side, but also on the client side. The words "if there is any" are doing a lot of heavy lifting here, because most clients submit requests sequentially because the context cannot be reused until it is idle, except for queuing more data for streaming -- so you'd also need a request pool.

We need to both hide that complexity from the clients, and make it also optional and subject to negotiation, because the majority of machines out there simply do not have crypto hardware, so we want to skip the extra overhead there and just use the CPU.

So, for a new common API, a napkin design would look like

- merged sync and async interfaces
(completion through a callback, which can be a tail call)
- same for user API
- context switches optional
- CPU implementation runs in userspace via vDSO
- hardware that supports user virtual addresses (OpenCAPI, IBM NX) is programmed from userspace
- negotiation of DMA requirements
- CPU: none
- most engines: 64 bit
- some engines: 32 bit
- cheap batch submission
- cancellation of in-flight requests
- submission of additional requests while a batch is under way
- negotiated fallback to single-request submission (for CPU algs)
- lightweight contexts with asynchronous creation
- different keys or IVs
- copies of other contexts

So, the (normal) CPU fallback case would have the client code get a (heavyweight) context for the chosen algorithm, which has a flag that says "batch submission is not beneficial", the client code would call into a function inside this context, submitting a single request and a completion callback, the handler function would call into the crypto library and subsequently tail call into the completion function

If the callback code is the only processing needed, then the call into the function provided by the context could be a tail call already (so the return type of the callback and of the crypto function would have to be the same, and the callback would have to pinky promise to always return success).

The offload case would have different implementations depending on whether the hardware supports on-device queues or not, but it would likely ask clients to submit a large batch if possible (so if we have an 1 MB request for file system data, we see more than 4 kB of it).

It may even be possible to make the entry points lightweight enough that submission of batches does not even need a separate interface, just calling the entry for a single request repeatedly (and maybe another "flush" function at the end) may turn out to be sufficient.

That is pretty much the only approach I can come up with that can abstract away the hardware differences and still be somewhat usable on the client side. As I said, this is a napkin design, and it would need a lot of thoughts on the security aspects -- I've been looking at it from a "how to keep the pipeline fed" point of view.

Simon

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature