embedded-tls
embedded-tls copied to clipboard
Introduce a way to resolve certificates on the fly
This is a follow-up to https://github.com/drogue-iot/embedded-tls/pull/135
Currently, the TlsConfig
holds CA, Device Certificate and Private Key in memory, basically for the full lifetime of the TLS connection, even though they are only used during the handshake.
This can be very costly on the RAM usage for no reason at all.
I would like to introduce some sort of resolver, that can load the certificates on the fly in the handshake, and then drop them again when no longer needed.
It could be something along the lines of rustls's resolves traits:
- https://docs.rs/rustls/latest/rustls/client/trait.ResolvesClientCert.html
- https://docs.rs/rustls/latest/rustls/server/trait.ResolvesServerCert.html
I am not quite sure if these should be part of the TlsConfig
or if it would make more sense to have them as part of the provider implementation somehow:
pub trait CryptoProvider {
type CipherSuite: TlsCipherSuite;
type Signature: AsRef<[u8]>;
fn rng(&mut self) -> impl CryptoRngCore;
fn verifier(
&mut self,
) -> Result<&mut impl TlsVerifier<'_, Self::CipherSuite>, crate::TlsError> {
Err::<&mut NoVerify, _>(crate::TlsError::Unimplemented)
}
/// Decode and validate a private signing key from `key_der`.
fn signer(
&mut self,
_key_der: &[u8], <-- REMOVE THIS
) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
{
// Resolve private key here. This could be as simple as self.priv_key, which would be the same as today.
// It could also be I/O or flash read using self.
// Return a signer impl based on above private key
}
}
Similarly, the Verifier
could resolve the CA
, left is only something to resolve the ClientCertificate
?
Not sure if i am missing something obvious here though?
Sounds like a great idea to me!
Sounds like a great idea to me!
Do you have any preferences whether it ends up being rustls'like with a new trait in the TlsConfig
, or an implied part of CryptoProvider
?
Another option is to add additional functions to the provider, along the lines of resolve_ca()
, etc.? That would make it less implied, than requiring the signer()
fn to also resolve a private key as part of the impl, on the other hand it might make lifetimes etc. much more tricky, at no other win than what could just as well be solved by proper docs?
I think I am leaning towards the implied resolution in verifier
, signer
and then a new fn client_cert()
or similar? Solely because I would like to avoid introducing the additional generic in the config, as i this a config should be as lean as possible?
Sounds like a great idea to me!
Do you have any preferences whether it ends up being rustls'like with a new trait in the
TlsConfig
, or an implied part ofCryptoProvider
?
I don't, I think you're in a better position to make that judgement really.
Another option is to add additional functions to the provider, along the lines of
resolve_ca()
, etc.? That would make it less implied, than requiring thesigner()
fn to also resolve a private key as part of the impl, on the other hand it might make lifetimes etc. much more tricky, at no other win than what could just as well be solved by proper docs?I think I am leaning towards the implied resolution in
verifier
,signer
and then a newfn client_cert()
or similar? Solely because I would like to avoid introducing the additional generic in the config, as i this a config should be as lean as possible?
Yeah, I think that approach is the best path forward. If it turns out not to be, we can always change it.