Open tarcieri opened 4 years ago
I would really love to find some solution for allowing an embedded cryptographic accelerator to process work in the background while the primary processor/MCU is performing other operations.
Down-the-road I think async
would be great here: you could submit work asynchronously to a cryptographic accelerator, receiving a Future
you can poll for completion. Unfortunately async-trait
seems like a nonstarter in the embedded space, so perhaps it's worth investigating some sort of stopgap API which lets you submit work and then poll/busywait for completion.
This would be quite helpful for algorithms like AES-GCM and AES-GCM-SIV (decryption, at least), by allowing encryption to happen in parallel on an accelerator/coprocessor while authentication is handled on the main processor/MCU.
In nightly it is already possible to have async traits with feature(generic_associated_types)
. (example). This does fully static dispatch and no heap allocations. You can even implement the traits with async
blocks (instead of manually-written futures) with feature(type_alias_impl_trait)
(example)
IMO it's not worth it to stand up an async traits ecosystem with the current async_trait crate or other workarounds that require alloc/dyn, only to break them later when switching to "real" async traits with generic_associated_types
.
Another potential use-case is using Web Crypto API as a backend for some algorithms. But I also don't think we should depend on the async-trait
crate. Having an unstable feature is a better option in my opinion, plus it can help with the feature development.
Another question is what to do with the software implementations? Should we in future add a wrapper which would use a thread pool to emulate async API?
Having an unstable feature is a better option in my opinion.
Sounds good to me! As noted above, the async-trait
is a showstopper for the use cases I'm really interested in solving, so starting with a nightly-only option which can actually be used in embedded environments would be preferable to me.
Another question is what to do with the software implementations? Should we in future add a wrapper which would use a thread pool to emulate async API?
Seems pretty context-dependent to me. I think it's a problem worth leaving open-ended initially, letting people define the sync-vs-async relationships as they see fit, and then perhaps seeing if there are common patterns we could wrap up with things like blanket impls (perhaps gated with marker traits) or failing that, proc macros.
FYI, I spiked out an async-signature
crate which uses async-trait
(for now): #320
That said, I did it with the caveat that the longer-term goal is to move those traits into the signature
crate proper, and when that happens, we'll use GATs. Once we have a stable GAT solution for signature
, we can simply retire the async-signature
crate.
Another potential use-case is using Web Crypto API as a backend for some algorithms. But I also don't think we should depend on the
async-trait
crate. Having an unstable feature is a better option in my opinion, plus it can help with the feature development.
I have this use case where I want to construct aead::stream using AES-GCM in Web Crypto (async api) when targetting wasm32. What would currently be the best workaround?
There's presently no async support for aead
, or for that matter in the cipher
crate.
As it seems GATs may soon be stable, I would suggest holding off explorations of how to asyncify those crates until GATs land.
I agree there are many uses for async aead
and cipher
: beyond just WebCrypto, they would be helpful for supporting cryptographic accelerators/coprocessors which can compute cryptographic functions in parallel and either be polled to completion or send an interrupt when done. This would be very helpful for pipelining work between e.g. a UHF functioning as a MAC which is executed on an MCU and e.g. AES as executed by an accelerator/coprocessor.
Hi,
Async traits are now available since 1.75. Is there anything blocking this endeavor now?
Nope, and in fact the async-signature
crate now makes use of AFIT with a 1.75 MSRV (I've updated the description above).
What would be helpful now that AFIT is stable is to have some concrete use cases for async traits to drive their design. An example would be embedded async
users who are handling interrupts from a cryptographic coprocessor/accelerator using async
.
We already have those for signatures, in that there are many external signers (e.g. KMS) where async
is needed to communicate with them, but it would be helpful to have those for e.g. cipher
use cases.
What a coincidence, or maybe not! :)
I'm currently writing an DTLS 1.3 implementation for embedded (Cortex-M mainly) and for accelerating the AES128-GCM and SHA256 I was planning to use the crypto accelerator and the hash accelerator of the MCU.
This is why I was looking for async
traits so I can simply make the implementation work with sync implementations and interrupt driven via async
.
Generally most MCUs that are communication oriented have acceleration for at least the symmetric encryption, but some also has hash accelerators.
Both which generally support interrupts on completion (or error).
E.g. the STM32 CRYPTO
(symmetric cryptography accelerator) and HASH
(MD5, SHA-1, SHA224, SHA256 accelerator) peripherals allows for fully interrupt driven operation and has async
HAL support in embassy-stm32
.
How could I help give some insight?
@korken89 perhaps you could open a PR with the traits you'd like to see?
Additionally, are there any reason the async-signature
crate is not #![no_std]
? or is it just an oversight?
@MathiasKoch I think it might be leftover from before AFIT when it was using async-trait
, anyway yes it's an oversight and we should make it no_std
I can indeed have a look at the traits!
I'm getting close to finalizing the DTLS 1.3 implementation and when I'm there I'll start looking into async
-ifying the APIs and seeing where one would need to add async traits.
Several crates in this repo could benefit from having
async
equivalents. There are several use cases forasync
, such as communicating with network services which implement a particular cryptographic primitive (Cloud KMS, NetHSM), or things like cryptographic tokens, SmartCards, non-networked HSMs (e.g. PCI cards, USB devices), or embedded cryptographic accelerators.Unfortunately Rust doesn't natively support async traits yet. The most commonly used solution at the moment is @dtolnay's async-trait crate. This provides an ergonomic syntax which should hopefully be easy to transition to hypothetical future natively supported async traits, however at the moment it requires
std
and usesBox
to storeFuture
s. There's some discussion about improving this happening on rust-internals right now.I think it'd be useful to start defining some async traits, even if they presently depend on
std
. Here's a tracking list of crates that could benefit from async traits:aead
: embedded cryptographic acceleratorscipher
: embedded cryptographic acceleratorsasync-signature
: Cloud KMS/NetHSM services and embedded cryptographic acceleratorsOthers? (please leave a note in the comments if you have a use case and I'll update)