rustls / tokio-rustls

Async TLS for the Tokio runtime
Apache License 2.0
125 stars 70 forks source link

TlsAcceptor reads invalid data #88

Closed tidely closed 3 weeks ago

tidely commented 3 weeks ago

I was testing tokio-rustls on my own project, but it didn't let me accept connections using the TlsAcceptor.accept method. In search for a minimal reproducible example, I tried running the server example from this repo. After generating a cert and a key and running the example as instructed by README.md and visiting the page in my browser, the connection would fail during the TlsAcceptor.accept call with the error:

Custom { kind: InvalidData, error: InvalidMessage(InvalidContentType) }

I tried multiple configurations, all failing.

MacOS Safari MacOS Chrome Linux Firefox

cpu commented 3 weeks ago

@tidely Are you accessing your server with http:// or https:// ? I'd expect the error you describe to happen if you try to access an HTTPS server using plain HTTP.

FWIW I'm not able to reproduce with cargo run --example server -- 127.0.0.1:8000 --cert tests/certs/chain.pem --key tests/certs/end.key and using https://localhost:8000 in Chrome (after skipping the unknown certificate interstitial of course).

tidely commented 3 weeks ago

When accessing with the https:// scheme I get:

Custom { kind: InvalidData, error: PeerIncompatible(NoSignatureSchemesInCommon) }

I haven't messed with any of my supported signature schemes in my browsers, so I feel like this could still stem from some type of parsing bug.

cpu commented 3 weeks ago

The example server doesn't customize the supported signature schemes and uses a default set with broad compatibility.

Are you accessing the example server through some kind of proxy? Or on a machine that has some sort of corporate policy applied to it? I think a parsing bug is unlikely and instead suspect there's something interesting about the configuration of the machine you're testing on, or the way in which you're testing. :thinking:

tidely commented 3 weeks ago

The example server doesn't customize the supported signature schemes and uses a default set with broad compatibility.

Exactly why this seems like a very weird bug.

Are you accessing the example server through some kind of proxy? Or on a machine that has some sort of corporate policy applied to it? I think a parsing bug is unlikely and instead suspect there's something interesting about the configuration of the machine you're testing on, or the way in which you're testing. 🤔

I have no corporate policy or any proxy and I'm testing it on 127.0.0.1:8080. It's very likely on my end, but I have the same issue on two devices and on different browsers.

ctz commented 3 weeks ago

After generating a cert and a key

Could you share the method you used for this?

tidely commented 3 weeks ago

I use the rcgen crate to generate the certificate and key.

use rcgen::{CertificateParams, KeyPair, PKCS_ED25519};
use std::{fs::File, io::Write};

fn main() -> Result<(), Box<dyn core::error::Error>> {
    let key_pair = KeyPair::generate_for(&PKCS_ED25519)?;

    let params = CertificateParams::new(vec!["127.0.0.1".into(), "localhost".into()])?;
    let cert = params.self_signed(&key_pair)?;

    let pem_cert = cert.pem();
    File::create("./cert.pem")?.write_all(pem_cert.as_bytes())?;

    let pem_key = key_pair.serialize_pem();
    File::create("./key.pem")?.write_all(pem_key.as_bytes())?;

    println!("Certificate and private key were saved as: cert.pem & key.pem");
    Ok(())
}

I've successfully used this self-signed cert generation method before with the tonic crate.

ctz commented 3 weeks ago

Aha, that is very revealing. AFAIK there is no current browser support for ED25519 keys in TLS; which is a great shame because AIUI they all have implementations of it for webcrypto.

tidely commented 3 weeks ago

Well that explains it then, did not know that. Very interesting decision indeed... I assume my best bet is ECDSA then, I'll retry and close the issue once it works, thanks for the quick replies.

cpu commented 3 weeks ago

I assume my best bet is ECDSA then, I'll retry and close the issue once it works, thanks for the quick replies.

Agreed, something like KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256) should work better for you.