sfackler / rust-native-tls

Apache License 2.0
468 stars 196 forks source link

Support cipher suite selection #4

Open sfackler opened 7 years ago

sfackler commented 7 years ago

OpenSSL's the most flexible here, and SChannel is the least. The cross-platform solution will probably look something like an SChannel style enum of algorithms that will be unioned:

pub enum Algorithm {
    Sha256,
    Aes,
    Dhe,
    Rsa,
    ...
}

If you then call

client_builder.supported_algorithms(&[Algorithm::Rsa, Algorithm::Aes, Algorithm::Sha256, Algorithm::Dhe])

would mean all ciphers that use RSA or DHE for key exchange, AES as a bulk cipher, and SHA256 as a hash algorithm would be enabled. That'd translate in SChannel to

cred_builder.supported_algorithms(&[Algorithm::Rsa, Algorithm::Aes, Algorithm::Sha256. Algorithm::Dhe])

and in OpenSSL to (note that we have to generate the cartesian product of key exchange, bulk cipher and hash algorithms)

ctx.set_cipher_suite("RSA+AES+SHA256:DHE+AES+SHA256:@STRENGTH")

and in Secure Transport to a somewhat complicated dance where we load supported ciphers and filter them through the provided algorithms:

let supported = ctx.supported_ciphers();
let enabled = supported.into_iter().filter(|c| suite_supported(c, algorithms)).collect();
ctx.set_enabled_ciphers(&enabled);

One interesting question is what to do if no algorithm in a category is specified (e.g. just &[Algorithm::Aes, Algorithm::Dhe] is passed). Should that mean that no suites match and no connections will work, or that all algorithms of that type can be used?

An alternative design would be to have separate enums for each algorithm type:

client_builder.supported_algorithms(&[KeyExchange::Rsa, KeyExchange::Dhe], &[BulkCipher::Aes], &[Hash::Sha256]);

It would be a bit more clear, but more verbose as well.

sfackler commented 7 years ago

We'll also probably want to disable unauthenticated and anonymous suites entirely.

cyang1 commented 4 years ago

I'm interested in this. I took a stab at the security-framework and schannel-rs implementations, and the public API in https://github.com/cyang1/rust-native-tls/commit/a82bfbe245b76d0aa0d44366f157cb4d6ced3f93. I think the OpenSSL implementation would be simple as you mentioned above.

I don't think my change is necessarily production ready yet, as it's not necessarily maintainable in its current state.

In my change, the questions I still have are: