Repository navigation
crypto: add direct SG2002 transport for OpenSSL - #507
dormancygrace wants to merge 9 commits into
Conversation
Build outputsCompared with the build of main at 2571baa; codex/openssl-chacha20 is at 6ce28df, so outputs changed since then are listed too. 4 changed, 159 added, 145 removed of 584 outputs.
|
dormancygrace
left a comment
There was a problem hiding this comment.
I found no memory-safety or crypto-correctness issue in the transport.
- The ABI header is a byte-exact copy of the kernel one.
- The struct sizes match.
- The host transport test and its negative control pass.
- Mutating
transaction()shows the test catches real failure-path bugs.
One more point, beyond the inline comments: once the module is loaded, every root process using this libcrypto offloads by default. The only switch is NANOKVM_OPENSSL_DMA=off in each process's environment. CryptoDMA running next to the H.265 encoder used to hang the SoC. Write burst 4 in the kernel module fixed that, but this new userspace path has no measurement with concurrent video yet. Until it does, please consider a system-wide switch (for example honouring /etc/kvm/disable_hardware_aes) or default-off.
A question: sg2002_aes_probe.c still describes itself as an "Experimental" diagnostic backend and says it is not a production driver. Now that libcrypto depends on /dev/sg2002-aes-probe, is its ioctl ABI a stable userspace contract? If so, the module description should say so.
| + || !CRYPTO_THREAD_run_once(&once, init_options) || disabled | ||
| + || atomic_load_explicit(&failed, memory_order_relaxed)) | ||
| + return -1; | ||
| + fd = open("/dev/sg2002-aes-probe", O_RDWR | O_CLOEXEC); |
There was a problem hiding this comment.
Every operation does open + fstat + SG2002_CRYPTO_INFO + close before RUN. In the driver, INFO takes the same global mutex as an in-flight DMA request, which SRTP and the kernel GCM path also hold. So even an attempt that ends in software fallback queues behind video-call traffic.
Negative results are not remembered either. The device is mode 0600, so every non-root operation repeats a failing open, as does every operation in a system without the module.
Capabilities and ABI never change while the module is loaded, and RUN already reports poison as EIO. Could the INFO result and permanent failures (ENOENT, EACCES, ABI mismatch) be cached process-wide, keeping only the fd per operation? Otherwise, please include this cost when the per-algorithm thresholds are measured.
There was a problem hiding this comment.
Implemented positive capability/ABI caching and permanent negative caching in f5c9efe. Steady-state operations no longer issue INFO or acquire the driver mutex for that query. ENOENT/EACCES/protocol failures are remembered; EMFILE/EINTR remain retryable. Each operation still owns its close-on-exec descriptor, so no shared descriptor or new userspace lock crosses fork/provider unload. Concurrent first probes may repeat INFO; subsequent calls use the atomic capability mask. The sanitizer/fault suite verifies these cache transitions and descriptor closure.
There was a problem hiding this comment.
With INFO cached, the remaining per-operation work is open + fstat + RUN + close. The later PRs measured a large fixed cost per call, at heads that predate f5c9efe. Converting their MiB/CPU-s figures into time per call:
- SHA-1 (crypto: offload OpenSSL SHA-1 compression to SG2002 #509): 92 / 115 / 169 µs at 4 / 8 / 16 KiB, so about 66 µs fixed plus about 26 µs per 4 KiB request.
- DES-CBC (crypto: offload OpenSSL DES ECB and CBC to SG2002 #512): an intercept of about 96 µs.
- EDE3-CBC (crypto: offload OpenSSL Triple DES ECB and CBC to SG2002 #513): about 105 µs.
The driver comment puts one spinning 1216-byte RUN at about 19 µs. f5c9efe removed one ioctl and its mutex wait, which cannot account for tens of microseconds. So most of the fixed cost should remain: open/close plus EVP and provider setup. Please measure begin/end alone (10k iterations, plus strace -T on a 4 KiB hash) to split the two.
If open/close dominates, the structural fix is one O_CLOEXEC fd per library image. That is a real decision for you: it pins the module against rmmod, and it brings back the fork/unload handling you avoided on purpose. If the fixed part falls substantially, the SHA-1 crossover and the 2–2.5 KiB AES cutoffs should drop accordingly (my estimate).
dormancygrace
left a comment
There was a problem hiding this comment.
Thanks for f5c9efe. It addresses most of my earlier points: secure_getenv is now in 0002, INFO is cached after the first successful probe, and permanent failures (ENOENT/EACCES/ENOTTY/EINVAL/EMSGSIZE, among others) are latched. I resolved those threads.
What remains per operation is open + fstat + RUN + close; details in the reply on the open/INFO thread.
Two smaller questions:
- Latched ENOENT and EACCES last for the library image. A long-lived process that starts before the sg2002 module is loaded never uses DMA. Is the module guaranteed to be loaded before such daemons start, or should an ENOENT latch expire after some time?
- System-wide switch. One is still missing. INFO already carries the algorithm mask that this transport honours, so a module parameter that masks bits of that field would give an admin-controlled off switch for new processes, with no file read in userspace.
# Conflicts: # .github/workflows/ci.yml
Add a shared direct SG2002 ioctl client for the separate OpenSSL algorithm patches. It uses the existing
/dev/sg2002-aes-probeversion-1 ABI, without cryptodev or ENGINE. This transport-only patch enables no hardware algorithm by itself.Each bulk operation owns its descriptor and capability check. Requests use private state/output until successful completion, so late copy failures cannot corrupt in-place input before software fallback. There is no cached descriptor or userspace mutex to inherit across fork/provider unload. Controller errors disable further hardware use in the process; interruptions and temporary failures permit later attempts. Hashes avoid the cipher/Base64 output-scratch frame.
Validation: clean OpenSSL 3.5.9 RISC-V cross-build without warnings; host ASan/UBSan fault tests exercise 56 submissions across all seven hardware algorithms, capability/ABI/poison checks, fd lifecycle and retry/disable behavior. A negative control proves the tests reject direct writes to caller output. CI runs these tests and the ChaCha assembly reproducibility check.
Stacked on #506 for the patch application infrastructure. Draft pending physical device integration tests in the per-algorithm PRs. Each algorithm gets its own OpenSSL patch, correctness/threshold/RAM evidence and PR.