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

Delegating crypto to a RustCrypto traits implementation #390

Closed
hug-dev opened this issue Aug 3, 2020 · 13 comments
Closed

Delegating crypto to a RustCrypto traits implementation #390

hug-dev opened this issue Aug 3, 2020 · 13 comments

Comments

@hug-dev
Copy link

hug-dev commented Aug 3, 2020

Hello 👋

As stated in the repository's README.md file, Rustls uses ring for cryptography. The RustCrypto team has also published a set of traits describing the functionality of crypto primitives. There is an implementation of some of those traits for ring.

The idea put forward by this issue would be for Rustls to perform cryptography through the RustCrypto traits instead of doing it directly through ring. A configuration option would be there to choose between RustCrypto traits implementors.

Apart from the ring implementation, we were also thinking of implementing those traits for our projects: the Parsec Rust Client and PSA Crypto wrapper.

The advantages for Rustls would be to have the flexibility of choosing the crypto implementation that fits the best the use-case.
In the case of the Parsec Rust Client, that would allow Rustls to perform its crypto on a real hardware (such as a TPM or HSM) abstracted by the trait implementation.
In the case of the PSA Wrapper crate, it would open the way to any PSA Crypto implementation such as Mbed Crypto or the crypto service of Trusted Firmware-M (for microcontrollers, assuming Rustls could be no-std).

We would be very interested in knowing your opinion about this, and if it would be feasable at all.

cc @raw-bin

@raw-bin
Copy link

raw-bin commented Aug 4, 2020

A few additional points:

  • There is growing interest in using Rust on AArch64 systems, for safety and security sensitive software layers, such as firmware.
  • This is especially so for bare-metal deployments on AArch64 systems.
  • Rustls has evidently gained a lot of momentum as a good TLS library.
  • At present, the perception is that Rustls doesn't have a clear and standardised path to using secure hardware elements for crypto ops.
  • One good way ahead would be adopting the RustCrypto traits within Rustls. Given that Rustls already works with Ring and given that Ring has already broken ground to start using the RustCrypto traits, it bodes well for Rustls to do so too.
  • That would then enable Rustls to benefit from software crypto implementations as is the case today but have a wider set of options (Ring today, PSA Crypto services tomorrow).
  • Ultimately, what would be a neat outcome is for Rustls to be able to work seamlessly with options such as Parsec.

It would be great if we can brain-storm on these options and then work out a feasible path to implementation ahead.

@Darkspirit
Copy link

(Sorry for some naive questions, I'm just a user who plans to use rustls+webpki+ring additionally on Raspberry Pi.)
I thought ring is already the one relevant and carefully designed API and not just some crypto backend?
As webpki depends on ring, could you as ARM sponsor improvements to the aarch64 target of ring? Ring also needs AArch64 Win10 CI testing capability (briansmith/ring#960). Thanks! My concern is that if ring was circumvented, its ecosystem might be divided and its users might not profit from better hardware support.
@briansmith: Would it make sense for webpki to use external traits or is enhancing ring the desired way forward? Didn't you plan to found a Rust crypto working group and work out such hardware interfaces for ring? Couldn't ARM contract you and @ctz in this regard?

@raw-bin
Copy link

raw-bin commented Aug 5, 2020

Hey @Darkspirit! Those are good questions and not naive ones at all! :)

I think it should be possible to find good and reasonable ways in which both Ring's AArch64 support improves as well as Rustls gains the ability to work with secure hardware elements.

More choice for folks wanting to use Rust on AArch64 can never be a bad thing! :)

Completely take your point that there is a balance to be maintained though.

More than happy to discuss options!

@newpavlov
Copy link

newpavlov commented Aug 25, 2020

As a representative of the RustCrypto project, I am really interested in adding a pure-Rust backend to rustls and ready to contribute to it. In my understanding the required primitives are already mostly implemented (though I am not 100% sure about elliptic curves, @tarcieri is more knowledgeable about them) and the main blocker right now is webpki, which unconditionally depends on ring in the following 3 places:

  • src/time.rs: trivial change of the error type
  • src/der.rs: it's easy to refactor relevant bits into a separate crate, but unfortunately Brian has responded negatively to such request.
  • src/signed_data.rs: the signature crate aims to provide an abstraction layer which can be used here, but APIs slightly differ (1, 2), so changes will be a bit more involved than in the previous two cases.

Ring has already broken ground to start using the RustCrypto traits

Note that ring wrappers are implemented as part of the RustCrypto project, i.e. they are not part of the ring project.

@tarcieri
Copy link

I am not 100% sure about elliptic curves, @tarcieri is more knowledgeable about them

The p256 crate implements NIST P-256 curve/field arithmetic, namely complete projective formulas with constant-time scalar multiplication. It also provides high-level implementations of Elliptic Curve Diffie-Hellman and ECDSA signing and verification.

That said we've done practically no optimization work so I expect it will be significantly slower than ring.

@DemiMarie
Copy link

Hardware cryptographic implementations are generally asynchronous, so rustls will need asynchronous signing support. For hardware cryptographic accelerators, asynchronous bulk encryption will be needed as well, but that is a much lower priority.

@ctz
Copy link
Member

ctz commented Aug 26, 2020

I'm really not sold on this, I'm afraid. A few points I want to make:

a. rustls has an existing extension point for using long-term server and client authentication keys. I'm aware of several uses already of this extension point to make use of keys held elsewhere: HSMs, TPMs, etc. I assert that -- in practice -- nobody stores other keys used in TLS in a HSM/TPM, because they tend to have terrible performance and scalability, and because those keys are of similar value to the application data. Docs for that feature are here: https://docs.rs/rustls/0.18.1/rustls/manual/_03_howto/index.html#customising-private-key-usage

b. I feel that supporting "bring your own AES" is of no benefit to 99% of users, but costs all users in terms of complexity. I can see the argument for embedded users, where you really need to be using a proprietary hardware crypto peripherals for performance/power reasons; but rustls does not target embedded workloads.

c. I really have little interest in maintaining and testing rustls on top of the entire power set of rustcrypto trait implementations. It seems like a really thankless task to ensure that rustls is tested with this sha256, and that aes-gcm, and while one would expect them to be orthogonal, that's certainly not guaranteed.

d. the number of traits implementation would be absolutely wild to parameterise a given rustls session as the API currently stands. At a rough count, the top-level rustls ClientSession/ServerSession types would need 19 type parameters.

e. I'm quite unsure that the shape of the rustcrypto traits are right for rustls to depend on -- rustls's TLS13_AES_128_GCM_SHA256 ciphersuite type would be quite broken if generic over aead::AeadInPlace and digest::Digest -- it would want to be generic over a specific implementation of AES-128-GCM and SHA256, but not merely any aead and any hash function.

So I'm always willing to listen to the arguments here, but I want to maintain a high bar for far-reaching and foundational changes.

@newpavlov
Copy link

newpavlov commented Aug 26, 2020

I really have little interest in maintaining and testing rustls on top of the entire power set of rustcrypto trait implementations.

Nobody expects you to. rustls just have to introduce an extension interface and make ring dependency optional. Default and the only one "guaranteed to work correctly" mode can still be the one using ring backend.

At a rough count, the top-level rustls ClientSession/ServerSession types would need 19 type parameters.

rustls's TLS13_AES_128_GCM_SHA256 ciphersuite type would be quite broken if generic over aead::AeadInPlace and digest::Digest -- it would want to be generic over a specific implementation of AES-128-GCM and SHA256, but not merely any aead and any hash function.

We don't have to be so fine-grained. rustls can introduce it's own high-level (and probably object-safe) traits. We can handle plumbing of RustCrypto implementations on our side. Such approach will be also useful from versioning PoV, since most of the RustCrypto trait crates still haven't reached 1.0.

Another use-case is an ability to extend rustls with custom ciphersuits. For example, in a private project on which I work we have to implement TLS with GOST cryptography support and we are seriously considering forking webpki and rustls because of that. I think you can understand that it would be really far from ideal.

UPD: BTW support of custom ciphersuits was also proposed here as a way to allow experimentation with new algorithms.

@hug-dev
Copy link
Author

hug-dev commented Aug 27, 2020

Thanks for your honest response.

Your point a. makes total sense: the only keys which seem useful from a security perspective to be stored in hardware are the authentication keys. Now if you already have traits to implement to offload the signing operation to an external hardware where the private key is stored, that's excellent. We could implement those traits and test that with Parsec immediately. That pretty much answers my original issue which was how to combie rustls with our projects.

Concerning the other subject, if there might be value in defining an interface (in the end it could be something closer to rustls as @newpavlov said and does not have to be RustCrypto traits), it depends on the possible use-case that could benefit from that. I agree on @newpavlov point that the default (and only tested option) should always be using ring but there could be configuration steps that would allow people to implement the traits themselves (outside the tree) and try rustls with that.

@tarcieri
Copy link

The signature traits were designed with HSM use cases in mind, and are being used in practice to enable code which is generic over both software and hardware signers (including ring, in the case of the former).

@djc
Copy link
Member

djc commented Oct 7, 2020

One good way ahead would be adopting the RustCrypto traits within Rustls. Given that Rustls already works with Ring and given that Ring has already broken ground to start using the RustCrypto traits, it bodes well for Rustls to do so too.

Note that this point is somewhat misleading: the trait implementations of RustCrypto traits for ring implementations seem to be implemented by RustCrypto authors, not by the ring maintainer.

@briansmith
Copy link
Contributor

I don't want to get all into this, except to note that in general I am working on making ring work on more targets, with the goal of working on all Rust Tier 1 and Tier 2 targets by EoY. In the case of embedded applications, that was the original goal for creating ring that's mentioned even in its README.md; things got side-tracked because I couldn't find other people interested in embedded who were willing to do open source, while people were more interested in traditional platforms. If you are interested in adding open source support for your hardware elements then please feel free to work with me on the ring project on it.

@djc
Copy link
Member

djc commented May 5, 2022

In order to keep this discussion in one place, let's continue in #521.

@djc djc closed this as completed May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants