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

bug?: cannot extract client key from pem file if it encoded by SEC1 EC #1143

Closed
YuJuncen opened this issue Nov 9, 2022 · 0 comments · Fixed by #1145 or #1337
Closed

bug?: cannot extract client key from pem file if it encoded by SEC1 EC #1143

YuJuncen opened this issue Nov 9, 2022 · 0 comments · Fixed by #1145 or #1337

Comments

@YuJuncen
Copy link
Contributor

YuJuncen commented Nov 9, 2022

Bug Report

Version

│   │   │   │   └── tonic v0.5.2
│   │   │   ├── tonic v0.5.2 (*)
│   │   │   └── tonic-build v0.5.2
│   │   ├── tonic v0.5.2 (*)

Platform

Linux 3.10.0-1160.36.2.el7.x86_64 #1 SMP Wed Jul 21 11:57:15 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Crates

tonic, with feature tls enabled.

Description

I tried this code:

Generally, I have wrote a client looks like this:

Usage: tls-test [OPTIONS] --ca-path <CA_PATH> --cert-path <CERT_PATH> --key-path <KEY_PATH>

Options:
  -e, --endpoints <ENDPOINTS>  
      --ca-path <CA_PATH>      
      --cert-path <CERT_PATH>  
      --key-path <KEY_PATH>    
  -h, --help                   Print help information

Which fills the tls config like:

pub fn tonic_tls_config(&self) -> Option<ClientTlsConfig> {
        // This function loads the content from files at `{ca,cert,key}_path`.
        let (ca, cert, key) = self.cfg.load_certs().unwrap_or_default();
        if ca.is_empty() && cert.is_empty() && key.is_empty() {
            return None;
        }
        let mut cfg = ClientTlsConfig::new();
        if !ca.is_empty() {
            cfg = cfg.ca_certificate(Certificate::from_pem(ca));
        }
        if !cert.is_empty() && !key.is_empty() {
            cfg = cfg.identity(Identity::from_pem(cert, key));
        }
        Some(cfg)
    }

With a client key file generated by:

openssl ecparam -out "$TEST_DIR/certs/$cluster.key" -name prime256v1 -genkey

I expected to see this happen:
We should be able to connect to the server via the key, or return some error like DNSNameError which hints the key is invalid.

Instead, this happened:
It returns a error like:

tonic::transport::Error(Transport, PrivateKeyParseError)

Some notes:
By reading the code, I have noticed that we are going to extract key via applying pkcs8_private_keys and rsa_private_keys. It seems rustls-pemfile supports SEC1 EC keys however doesn't provide something like ec_private_keys (!).

Perhaps we can use read_once direcly, so we only need to iterate the key file once and can extract the EC keys:

    fn load_rustls_private_key(
        mut cursor: std::io::Cursor<&[u8]>,
    ) -> Result<PrivateKey, crate::Error> {
        while let Ok(Some(item)) = rustls_pemfile::read_one(&mut cursor) {
            match item {
                rustls_pemfile::Item::RSAKey(key)
                | rustls_pemfile::Item::PKCS8Key(key)
                | rustls_pemfile::Item::ECKey(key) => return Ok(PrivateKey(key)),
                _ => continue,
            }
        }

        // Otherwise we have a Private Key parsing problem
        Err(Box::new(TlsError::PrivateKeyParseError))
    }

-->

YuJuncen added a commit to YuJuncen/tonic that referenced this issue Nov 9, 2022
Fixes: hyperium#1143
Signed-off-by: Yu Juncen <yu745514916@live.com>
LucioFranco pushed a commit that referenced this issue Feb 13, 2023
* tonic: allow TLS to read ECKeys.

Fixes: #1143
Signed-off-by: Yu Juncen <yu745514916@live.com>

* tonic: minimize the scope of published function.

Signed-off-by: Yu Juncen <yu745514916@live.com>

---------

Signed-off-by: Yu Juncen <yu745514916@live.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant