Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async traits #304

Open
1 of 3 tasks
tarcieri opened this issue Sep 13, 2020 · 14 comments
Open
1 of 3 tasks

Async traits #304

tarcieri opened this issue Sep 13, 2020 · 14 comments
Labels
cipher Block and stream cipher crate signature Digital signature crate

Comments

@tarcieri
Copy link
Member

tarcieri commented Sep 13, 2020

Several crates in this repo could benefit from having async equivalents. There are several use cases for async, 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 uses Box to store Futures. 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 accelerators
  • cipher: embedded cryptographic accelerators
  • async-signature: Cloud KMS/NetHSM services and embedded cryptographic accelerators

Others? (please leave a note in the comments if you have a use case and I'll update)

@tarcieri tarcieri added signature Digital signature crate cipher Block and stream cipher crate labels Sep 13, 2020
@tarcieri
Copy link
Member Author

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.

@Dirbaio
Copy link

Dirbaio commented Sep 13, 2020

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.

@newpavlov
Copy link
Member

newpavlov commented Sep 13, 2020

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?

@tarcieri
Copy link
Member Author

tarcieri commented Sep 13, 2020

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.

tarcieri added a commit that referenced this issue Oct 5, 2020
Adds an `async-signature` crate with `AsyncSigner` and
`AsyncDigestSigner` traits, based on the `async-trait` crate.

Though we'd discussed not using an `async-trait`-based approach (#304),
there are some immediate needs for these traits for `std` users, namely
providing a common `async` API to things like Cloud KMS services and
NetHSMs.

I think we can still pursue nightly-only versions of these traits in the
`signature` crate itself (ones which will work in `no_std`
environments).

In the meantime, these traits are self-contained within their own,
relatively small crate to unblock making some initial progress with
things like Cloud KMS abstractions.
@tarcieri
Copy link
Member Author

tarcieri commented Oct 5, 2020

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.

tarcieri added a commit that referenced this issue Oct 5, 2020
Adds an `async-signature` crate with `AsyncSigner` and
`AsyncDigestSigner` traits, based on the `async-trait` crate.

Though we'd discussed not using an `async-trait`-based approach (#304),
there are some immediate needs for these traits for `std` users, namely
providing a common `async` API to things like Cloud KMS services and
NetHSMs.

I think we can still pursue nightly-only versions of these traits in the
`signature` crate itself (ones which will work in `no_std`
environments).

In the meantime, these traits are self-contained within their own,
relatively small crate to unblock making some initial progress with
things like Cloud KMS abstractions.
tarcieri added a commit that referenced this issue Oct 5, 2020
Adds an `async-signature` crate with `AsyncSigner` and
`AsyncDigestSigner` traits, based on the `async-trait` crate.

Though we'd discussed not using an `async-trait`-based approach (#304),
there are some immediate needs for these traits for `std` users, namely
providing a common `async` API to things like Cloud KMS services and
NetHSMs.

I think we can still pursue nightly-only versions of these traits in the
`signature` crate itself (ones which will work in `no_std`
environments).

In the meantime, these traits are self-contained within their own,
relatively small crate to unblock making some initial progress with
things like Cloud KMS abstractions.
tarcieri added a commit that referenced this issue Oct 5, 2020
Adds an `async-signature` crate with `AsyncSigner` and
`AsyncDigestSigner` traits, based on the `async-trait` crate.

Though we'd discussed not using an `async-trait`-based approach (#304),
there are some immediate needs for these traits for `std` users, namely
providing a common `async` API to things like Cloud KMS services and
NetHSMs.

I think we can still pursue nightly-only versions of these traits in the
`signature` crate itself (ones which will work in `no_std`
environments).

In the meantime, these traits are self-contained within their own,
relatively small crate to unblock making some initial progress with
things like Cloud KMS abstractions.
tarcieri added a commit that referenced this issue Oct 5, 2020
Adds an `async-signature` crate with `AsyncSigner` and
`AsyncDigestSigner` traits, based on the `async-trait` crate.

Though we'd discussed not using an `async-trait`-based approach (#304),
there are some immediate needs for these traits for `std` users, namely
providing a common `async` API to things like Cloud KMS services and
NetHSMs.

I think we can still pursue nightly-only versions of these traits in the
`signature` crate itself (ones which will work in `no_std`
environments).

In the meantime, these traits are self-contained within their own,
relatively small crate to unblock making some initial progress with
things like Cloud KMS abstractions.
tarcieri added a commit that referenced this issue Oct 6, 2020
Adds an `async-signature` crate with `AsyncSigner` and
`AsyncDigestSigner` traits, based on the `async-trait` crate.

Though we'd discussed not using an `async-trait`-based approach (#304),
there are some immediate needs for these traits for `std` users, namely
providing a common `async` API to things like Cloud KMS services and
NetHSMs.

I think we can still pursue nightly-only versions of these traits in the
`signature` crate itself (ones which will work in `no_std`
environments).

In the meantime, these traits are self-contained within their own,
relatively small crate to unblock making some initial progress with
things like Cloud KMS abstractions.
@leonbotros
Copy link

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?

@tarcieri
Copy link
Member Author

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.

dns2utf8 pushed a commit to dns2utf8/traits that referenced this issue Jan 24, 2023
Bumps [crypto-bigint](https://github.com/RustCrypto/crypto-bigint) from 0.4.2 to 0.4.3.
- [Release notes](https://github.com/RustCrypto/crypto-bigint/releases)
- [Changelog](https://github.com/RustCrypto/crypto-bigint/blob/master/CHANGELOG.md)
- [Commits](RustCrypto/crypto-bigint@v0.4.2...v0.4.3)

---
updated-dependencies:
- dependency-name: crypto-bigint
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@korken89
Copy link

Hi,

Async traits are now available since 1.75.
Is there anything blocking this endeavor now?

@tarcieri
Copy link
Member Author

tarcieri commented Mar 17, 2024

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.

@korken89
Copy link

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?

@tarcieri
Copy link
Member Author

@korken89 perhaps you could open a PR with the traits you'd like to see?

@MathiasKoch
Copy link

Additionally, are there any reason the async-signature crate is not #![no_std]? or is it just an oversight?

@tarcieri
Copy link
Member Author

@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

@korken89
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cipher Block and stream cipher crate signature Digital signature crate
Projects
None yet
Development

No branches or pull requests

6 participants