From 73fcc444e5a3b1f44e92b8cf768f44ad75d235cb Mon Sep 17 00:00:00 2001 From: Dario Gonzalez Date: Wed, 10 Jul 2019 10:19:01 -0700 Subject: [PATCH 01/14] Implement PKCS8 certificate support for all three backends. --- Cargo.toml | 2 +- README.md | 4 +- examples/simple-server-pkcs8.rs | 43 +++++++++++ src/imp/openssl.rs | 26 ++++++- src/imp/schannel.rs | 116 ++++++++++++++++++++++++++++- src/imp/security_framework.rs | 29 ++++++++ src/lib.rs | 13 ++++ src/test.rs | 126 ++++++++++++++++++++++++++++++++ test/cert.pem | 20 +++++ test/cert2.pem | 32 ++++++++ test/chain.pem | 48 ++++++++++++ test/key.pem | 28 +++++++ test/key2.pem | 52 +++++++++++++ test/root-ca.der | Bin 0 -> 865 bytes test/root-ca.pem | 21 ++++++ 15 files changed, 552 insertions(+), 8 deletions(-) create mode 100644 examples/simple-server-pkcs8.rs create mode 100644 test/cert.pem create mode 100644 test/cert2.pem create mode 100644 test/chain.pem create mode 100644 test/key.pem create mode 100644 test/key2.pem create mode 100644 test/root-ca.der create mode 100644 test/root-ca.pem diff --git a/Cargo.toml b/Cargo.toml index 042b14e2..32d11f65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ libc = "0.2" tempfile = "3.1.0" [target.'cfg(target_os = "windows")'.dependencies] -schannel = "0.1.16" +schannel = "0.1.17" [target.'cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))'.dependencies] log = "0.4.5" diff --git a/README.md b/README.md index 22bd1fde..fe5d04b8 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ native-tls = "0.2" An example client looks like: -```rust +```rust,ignore extern crate native_tls; use native_tls::TlsConnector; @@ -46,7 +46,7 @@ fn main() { To accept connections as a server from remote clients: -```rust,no_run +```rust,ignore extern crate native_tls; use native_tls::{Identity, TlsAcceptor, TlsStream}; diff --git a/examples/simple-server-pkcs8.rs b/examples/simple-server-pkcs8.rs new file mode 100644 index 00000000..8e1b1b81 --- /dev/null +++ b/examples/simple-server-pkcs8.rs @@ -0,0 +1,43 @@ +extern crate native_tls; + +use native_tls::{Identity, TlsAcceptor, TlsStream}; +use std::fs::File; +use std::io::{Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::sync::Arc; +use std::thread; + +fn main() { + let mut cert_file = File::open("test/cert.pem").unwrap(); + let mut certs = vec![]; + cert_file.read_to_end(&mut certs).unwrap(); + let mut key_file = File::open("test/key.pem").unwrap(); + let mut key = vec![]; + key_file.read_to_end(&mut key).unwrap(); + let pkcs8 = Identity::from_pkcs8(&certs, &key).unwrap(); + + let acceptor = TlsAcceptor::new(pkcs8).unwrap(); + let acceptor = Arc::new(acceptor); + + let listener = TcpListener::bind("0.0.0.0:8443").unwrap(); + + fn handle_client(mut stream: TlsStream) { + let mut buf = [0; 1024]; + let read = stream.read(&mut buf).unwrap(); + let received = std::str::from_utf8(&buf[0..read]).unwrap(); + stream.write_all(format!("received '{}'", received).as_bytes()).unwrap(); + } + + for stream in listener.incoming() { + match stream { + Ok(stream) => { + let acceptor = acceptor.clone(); + thread::spawn(move || { + let stream = acceptor.accept(stream).unwrap(); + handle_client(stream); + }); + } + Err(_e) => { /* connection failed */ } + } + } +} diff --git a/src/imp/openssl.rs b/src/imp/openssl.rs index ef254a3e..7afdd596 100644 --- a/src/imp/openssl.rs +++ b/src/imp/openssl.rs @@ -5,7 +5,7 @@ use self::openssl::error::ErrorStack; use self::openssl::hash::MessageDigest; use self::openssl::nid::Nid; use self::openssl::pkcs12::Pkcs12; -use self::openssl::pkey::PKey; +use self::openssl::pkey::{PKey, Private}; use self::openssl::ssl::{ self, MidHandshakeSslStream, SslAcceptor, SslConnector, SslContextBuilder, SslMethod, SslVerifyMode, @@ -16,7 +16,6 @@ use std::fmt; use std::io; use std::sync::Once; -use self::openssl::pkey::Private; use {Protocol, TlsAcceptorBuilder, TlsConnectorBuilder}; #[cfg(have_min_max_version)] @@ -161,6 +160,19 @@ impl Identity { chain: parsed.chain.into_iter().flatten().collect(), }) } + + pub fn from_pkcs8(buf: &[u8], key: &[u8]) -> Result { + let pkey = PKey::private_key_from_pem(key)?; + let mut cert_chain = X509::stack_from_pem(buf)?.into_iter(); + let cert = cert_chain.next(); + let chain = cert_chain.collect(); + Ok(Identity { + pkey, + // an identity must have at least one certificate, the leaf cert + cert: cert.expect("at least one certificate must be provided to create an identity"), + chain, + }) + } } #[derive(Clone)] @@ -258,7 +270,10 @@ impl TlsConnector { if let Some(ref identity) = builder.identity { connector.set_certificate(&identity.0.cert)?; connector.set_private_key(&identity.0.pkey)?; - for cert in identity.0.chain.iter().rev() { + for cert in identity.0.chain.iter() { + // https://www.openssl.org/docs/manmaster/man3/SSL_CTX_add_extra_chain_cert.html + // specifies that "When sending a certificate chain, extra chain certificates are + // sent in order following the end entity certificate." connector.add_extra_chain_cert(cert.to_owned())?; } } @@ -342,7 +357,10 @@ impl TlsAcceptor { let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?; acceptor.set_private_key(&builder.identity.0.pkey)?; acceptor.set_certificate(&builder.identity.0.cert)?; - for cert in builder.identity.0.chain.iter().rev() { + for cert in builder.identity.0.chain.iter() { + // https://www.openssl.org/docs/manmaster/man3/SSL_CTX_add_extra_chain_cert.html + // specifies that "When sending a certificate chain, extra chain certificates are + // sent in order following the end entity certificate." acceptor.add_extra_chain_cert(cert.to_owned())?; } supported_protocols(builder.min_protocol, builder.max_protocol, &mut acceptor)?; diff --git a/src/imp/schannel.rs b/src/imp/schannel.rs index 58ec0636..78747f95 100644 --- a/src/imp/schannel.rs +++ b/src/imp/schannel.rs @@ -1,8 +1,9 @@ extern crate schannel; -use self::schannel::cert_context::{CertContext, HashAlgorithm}; +use self::schannel::cert_context::{CertContext, HashAlgorithm, KeySpec}; use self::schannel::cert_store::{CertAdd, CertStore, Memory, PfxImportOptions}; use self::schannel::schannel_cred::{Direction, Protocol, SchannelCred}; +use self::schannel::crypt_prov::{AcquireOptions, ProviderType}; use self::schannel::tls_stream; use std::error; use std::fmt; @@ -93,6 +94,38 @@ impl Identity { Ok(Identity { cert: identity }) } + + pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result { + let mut store = Memory::new()?.into_store(); + let mut cert_iter = pem::PemBlock::new(pem).into_iter(); + let leaf = cert_iter.next().expect("at least one certificate must be provided to create an identity"); + let cert = CertContext::from_pem(std::str::from_utf8(leaf).map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "leaf cert contains invalid utf8"))?)?; + + let mut options = AcquireOptions::new(); + options.container("schannel"); + let type_ = ProviderType::rsa_full(); + + let mut container = match options.acquire(type_) { + Ok(container) => container, + Err(_) => options.new_keyset(true).acquire(type_)?, + }; + container.import() + .import_pkcs8_pem(&key)?; + + cert.set_key_prov_info() + .container("schannel") + .type_(type_) + .keep_open(true) + .key_spec(KeySpec::key_exchange()) + .set()?; + let mut context = store.add_cert(&cert, CertAdd::Always)?; + + for int_cert in cert_iter { + let certificate = Certificate::from_pem(int_cert)?; + context = store.add_cert(&certificate.0, schannel::cert_store::CertAdd::Always)?; + } + Ok(Identity{cert: context}) + } } #[derive(Clone)] @@ -384,3 +417,84 @@ impl io::Write for TlsStream { self.0.flush() } } + + +mod pem { + /// Split data by PEM guard lines + pub struct PemBlock<'a> { + pem_block: &'a str, + cur_end: usize, + } + + impl<'a> PemBlock<'a> { + pub fn new(data: &'a [u8]) -> PemBlock<'a> { + let s = ::std::str::from_utf8(data).unwrap(); + PemBlock { + pem_block: s, + cur_end: s.find("-----BEGIN").unwrap_or(s.len()), + } + } + } + + impl<'a> Iterator for PemBlock<'a> { + type Item = &'a [u8]; + fn next(&mut self) -> Option { + let last = self.pem_block.len(); + if self.cur_end >= last { + return None; + } + let begin = self.cur_end; + let pos = self.pem_block[begin + 1..].find("-----BEGIN"); + self.cur_end = match pos { + Some(end) => end + begin + 1, + None => last, + }; + return Some(&self.pem_block[begin..self.cur_end].as_bytes()); + } + } + + #[test] + fn test_split() { + // Split three certs, CRLF line terminators. + assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n\ + -----BEGIN SECOND-----\r\n-----END SECOND\r\n\ + -----BEGIN THIRD-----\r\n-----END THIRD\r\n").collect::>(), + vec![b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n" as &[u8], + b"-----BEGIN SECOND-----\r\n-----END SECOND\r\n", + b"-----BEGIN THIRD-----\r\n-----END THIRD\r\n"]); + // Split three certs, CRLF line terminators except at EOF. + assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n\ + -----BEGIN SECOND-----\r\n-----END SECOND-----\r\n\ + -----BEGIN THIRD-----\r\n-----END THIRD-----").collect::>(), + vec![b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n" as &[u8], + b"-----BEGIN SECOND-----\r\n-----END SECOND-----\r\n", + b"-----BEGIN THIRD-----\r\n-----END THIRD-----"]); + // Split two certs, LF line terminators. + assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----\n\ + -----BEGIN SECOND-----\n-----END SECOND\n").collect::>(), + vec![b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8], + b"-----BEGIN SECOND-----\n-----END SECOND\n"]); + // Split two certs, CR line terminators. + assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\r-----END FIRST-----\r\ + -----BEGIN SECOND-----\r-----END SECOND\r").collect::>(), + vec![b"-----BEGIN FIRST-----\r-----END FIRST-----\r" as &[u8], + b"-----BEGIN SECOND-----\r-----END SECOND\r"]); + // Split two certs, LF line terminators except at EOF. + assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----\n\ + -----BEGIN SECOND-----\n-----END SECOND").collect::>(), + vec![b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8], + b"-----BEGIN SECOND-----\n-----END SECOND"]); + // Split a single cert, LF line terminators. + assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----\n").collect::>(), + vec![b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8]]); + // Split a single cert, LF line terminators except at EOF. + assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----").collect::>(), + vec![b"-----BEGIN FIRST-----\n-----END FIRST-----" as &[u8]]); + // (Don't) split garbage. + assert_eq!(PemBlock::new(b"junk").collect::>(), + Vec::<&[u8]>::new()); + assert_eq!(PemBlock::new(b"junk-----BEGIN garbage").collect::>(), + vec![b"-----BEGIN garbage" as &[u8]]); + } +} + diff --git a/src/imp/security_framework.rs b/src/imp/security_framework.rs index c14b2fb0..65dd0711 100644 --- a/src/imp/security_framework.rs +++ b/src/imp/security_framework.rs @@ -24,6 +24,8 @@ use self::security_framework::os::macos::certificate::{PropertyType, SecCertific #[cfg(not(target_os = "ios"))] use self::security_framework::os::macos::certificate_oids::CertificateOid; #[cfg(not(target_os = "ios"))] +use self::security_framework::os::macos::identity::SecIdentityExt; +#[cfg(not(target_os = "ios"))] use self::security_framework::os::macos::import_export::{ ImportOptions, Pkcs12ImportOptionsExt, SecItems, }; @@ -82,6 +84,33 @@ pub struct Identity { } impl Identity { + pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result { + let dir = TempDir::new().unwrap(); + let keychain = keychain::CreateOptions::new() + .password("password") + .create(dir.path().join("identity.keychain"))?; + + let mut items = SecItems::default(); + + ImportOptions::new() + .filename("key.pem") + .items(&mut items) + .keychain(&keychain) + .import(&key)?; + + ImportOptions::new() + .filename("chain.pem") + .items(&mut items) + .keychain(&keychain) + .import(&pem)?; + + let ident = SecIdentity::with_certificate(&[keychain], &items.certificates[0])?; + Ok(Identity { + identity: ident, + chain: items.certificates + }) + } + pub fn from_pkcs12(buf: &[u8], pass: &str) -> Result { let mut imports = Identity::import_options(buf, pass)?; let import = imports.pop().unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 171e8c7e..14dabb7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ //! * TLS/SSL client communication //! * TLS/SSL server communication //! * PKCS#12 encoded identities +//! * X.509/PKCS#8 encoded identities //! * Secure-by-default for client and server //! * Includes hostname verification for clients //! * Supports asynchronous I/O for both the server and the client @@ -177,6 +178,18 @@ impl Identity { let identity = imp::Identity::from_pkcs12(der, password)?; Ok(Identity(identity)) } + + /// Parses a chain of PEM encoded X509 certificates, with the leaf certificate first. + /// `key` is a PEM encoded PKCS #8 formatted private key for the leaf certificate. + /// + /// The certificate chain should contain any intermediate cerficates that should be sent to + /// clients to allow them to build a chain to a trusted root. + /// + /// A certificate chain here means a series of PEM encoded certificates concatenated together. + pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result { + let identity = imp::Identity::from_pkcs8(pem, key)?; + Ok(Identity(identity)) + } } /// An X509 certificate. diff --git a/src/test.rs b/src/test.rs index 940ff21f..a26ca67e 100644 --- a/src/test.rs +++ b/src/test.rs @@ -346,6 +346,11 @@ fn import_same_identity_multiple_times() { &keys.server.pkcs12, &keys.server.pkcs12_password )); + + let p8buf = include_bytes!("../test/chain.pem"); + let key = include_bytes!("../test/key.pem"); + let _ = p!(Identity::from_pkcs8(p8buf, key)); + let _ = p!(Identity::from_pkcs8(p8buf, key)); } #[test] @@ -416,3 +421,124 @@ fn alpn_google_none() { let alpn = p!(socket.negotiated_alpn()); assert_eq!(alpn, None); } + +#[test] +fn server_pkcs8() { + let key = include_bytes!("../test/key.pem"); + let cert = include_bytes!("../test/cert.pem"); + + let ident = Identity::from_pkcs8(cert, key).unwrap(); + let ident2 = ident.clone(); + let builder = p!(TlsAcceptor::new(ident)); + + let listener = p!(TcpListener::bind("0.0.0.0:0")); + let port = p!(listener.local_addr()).port(); + + let j = thread::spawn(move || { + let socket = p!(listener.accept()).0; + let mut socket = p!(builder.accept(socket)); + + let mut buf = [0; 5]; + p!(socket.read_exact(&mut buf)); + assert_eq!(&buf, b"hello"); + + p!(socket.write_all(b"world")); + }); + + let root_ca = include_bytes!("../test/root-ca.der"); + let root_ca = Certificate::from_der(root_ca).unwrap(); + + let socket = p!(TcpStream::connect(("localhost", port))); + let mut builder = TlsConnector::builder(); + // FIXME + // This checks that we can successfully add a certificate on the client side. + // Unfortunately, we can not request client certificates through the API of this library, + // otherwise we could check in the server thread that + // socket.peer_certificate().unwrap().is_some() + builder.identity(ident2); + + builder.add_root_certificate(root_ca); + let builder = p!(builder.build()); + let mut socket = p!(builder.connect("foobar.com", socket)); + + p!(socket.write_all(b"hello")); + let mut buf = vec![]; + p!(socket.read_to_end(&mut buf)); + assert_eq!(buf, b"world"); + + p!(j.join()); +} + +#[test] +fn two_servers() { + let key = include_bytes!("../test/key.pem"); + let cert = include_bytes!("../test/cert.pem"); + let identity = p!(Identity::from_pkcs8(cert, key)); + let builder = TlsAcceptor::builder(identity); + let builder = p!(builder.build()); + + let listener = p!(TcpListener::bind("0.0.0.0:0")); + let port = p!(listener.local_addr()).port(); + + let j = thread::spawn(move || { + let socket = p!(listener.accept()).0; + let mut socket = p!(builder.accept(socket)); + + let mut buf = [0; 5]; + p!(socket.read_exact(&mut buf)); + assert_eq!(&buf, b"hello"); + + p!(socket.write_all(b"world")); + }); + + let key = include_bytes!("../test/key2.pem"); + let cert = include_bytes!("../test/cert2.pem"); + let identity = p!(Identity::from_pkcs8(cert, key)); + let builder = TlsAcceptor::builder(identity); + let builder = p!(builder.build()); + + let listener = p!(TcpListener::bind("0.0.0.0:0")); + let port2 = p!(listener.local_addr()).port(); + + let j2 = thread::spawn(move || { + let socket = p!(listener.accept()).0; + let mut socket = p!(builder.accept(socket)); + + let mut buf = [0; 5]; + p!(socket.read_exact(&mut buf)); + assert_eq!(&buf, b"hello"); + + p!(socket.write_all(b"world")); + }); + + let root_ca = include_bytes!("../test/root-ca.pem"); + let root_ca = p!(Certificate::from_pem(root_ca)); + + let socket = p!(TcpStream::connect(("localhost", port))); + let mut builder = TlsConnector::builder(); + builder.add_root_certificate(root_ca); + let builder = p!(builder.build()); + let mut socket = p!(builder.connect("foobar.com", socket)); + + p!(socket.write_all(b"hello")); + let mut buf = vec![]; + p!(socket.read_to_end(&mut buf)); + assert_eq!(buf, b"world"); + + let root_ca = include_bytes!("../test/cert2.pem"); + let root_ca = p!(Certificate::from_pem(root_ca)); + + let socket = p!(TcpStream::connect(("localhost", port2))); + let mut builder = TlsConnector::builder(); + builder.add_root_certificate(root_ca); + let builder = p!(builder.build()); + let mut socket = p!(builder.connect("foobar.com", socket)); + + p!(socket.write_all(b"hello")); + let mut buf = vec![]; + p!(socket.read_to_end(&mut buf)); + assert_eq!(buf, b"world"); + + p!(j.join()); + p!(j2.join()); +} diff --git a/test/cert.pem b/test/cert.pem new file mode 100644 index 00000000..ce447144 --- /dev/null +++ b/test/cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub +3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ +mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6 +TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI +ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y +euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq +hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM +6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE +wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY +oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9 +dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp +HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA== +-----END CERTIFICATE----- + diff --git a/test/cert2.pem b/test/cert2.pem new file mode 100644 index 00000000..d9fbcd57 --- /dev/null +++ b/test/cert2.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIJAOFl3cFizu8kMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmZvb2Jhci5jb20wHhcNMTcwNjI0MTYw +NzEwWhcNMjcwNjIyMTYwNzEwWjBaMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29t +ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYD +VQQDDApmb29iYXIuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +2TfYpOOpb1HigFQOHq756Hr/wE2YvTGRRmFOuI/7TEzZnG4TcYGqbS8UTNIvxaeU +GtQdRLFV6QWtIQhArHOU22D0EWxj88MYE7O3h5csZOUKfI0s4IRA/u3VP2mfk/VT +AbikUJH370tTpxltcpMoOgOWkxraF6LDCnSSGALU6MN23OySUjadd4jtv5BmqdQL +t5+VDOsgEK8Gq0Kvw4noyADPAWRj/7L/OyJ2nk9Krlof/FYb+c7lK27LUqEM3yjZ +nARO+zCFj0cWqd0uYY3Uz+My73CLLu8NeHtl0Qv9a23jtol76j7wUXjrIR5VBs0o +hhP1/zcOfuXu2NYzHa6gbefJqnUtqMgnibimQyMZaLxoVOryJKkEHj/D/U3OgbkW +3q4sWZ2xGp6FlVU8smgPcq5KMQ/BQzPcGciVYKbHl+H6TUgSdABga8yMxURK058t +TZnv/GaSKEVjM8VNLuiZAlmRtzBbd5cbRMIb/8SV6m5xwK4jQ0pdDtKbY8I0poku +YbT/B8Rs/x50LgCk/sEjWCEdoxZ/KY4nuYpGzs5B79LZn4ofmHRG1IfiQBPxuR4S +ChW5V+HaICXsL2oKhxIhpDQjtownj9PF85ew6IODNzk/oHDZgFCJwHK23Acr+kTt +AsI/Oht3W0eG34DHS2UPuVc1jGE5TaNK3F/AN8ICANUCAwEAAaNTMFEwHQYDVR0O +BBYEFNlnR/6xSAyj2shdqYPPRbOpFj9AMB8GA1UdIwQYMBaAFNlnR/6xSAyj2shd +qYPPRbOpFj9AMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAAd/ +RYi40if/HiOLjVWeu4ETpZLut6p4NnFY2ueRF7O3cNSH3ugQ0Ucc4S8rDrTGHryz +jTVHC1p0783u7VkOiJNFKT+y5RmGVSRLnXfbWY4Vwpz5Dqz6sZtZlVO22VqhfT0K +Cwzbu6Mgr/rhPow3tCWUDzDVoKPnJCFmDwHWcXlDCjnuU/0DdgO+q3anj1x3Zt7x +1cXG+2O2PO8474A1ESujTYduCnQRzEOeud4beGhLeW6wcuq2tNRwbxQzBdCzb4/f +INSDsqk6lpimpokxVh9Q8yUSbORvPyXMLb0F2I670CBfsQ27U/+xqBPU7rmz63vL +J70fee+QQQ9KF9O1LWeIaPkRyKzU0kovwLTsTVXV6xQUeH1PLdgAkhh5KTnWReUq +n7Iu8EGIHNRQFGp/qgo7bww+g2aWiqyCquCCe5zyt13j5Ev9naRJzROna39BocsG +t2/NHSNMJ6ru4mPunPrP25J5V2qT7sN9RrKEPaANAV3dWuUOhvlrHQBVXKACckTJ +K+mKXP0pXrnLhQc6RP4ep8JuDY7qlRnJwr3+WxeTb52wcjmz0RusdbiEeBhgMcnF +ZDpZmLeTTPH/50TVvRTXgYGFmlgzVEqqGwpJsnEISuhgI/x58FqiXFCEaz9zr+xi +QWt2BCQJnE0G1UV9msEybRE4toiCHdOpojJjHFi8 +-----END CERTIFICATE----- diff --git a/test/chain.pem b/test/chain.pem new file mode 100644 index 00000000..6b171293 --- /dev/null +++ b/test/chain.pem @@ -0,0 +1,48 @@ +Bag Attributes + friendlyName: foobar.com + localKeyID: 59 17 2D 93 13 E8 44 59 BC FF 27 F9 67 E7 9E 6E 92 17 E5 84 +subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=foobar.com +issuer=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd +-----BEGIN CERTIFICATE----- +MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub +3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ +mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6 +TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI +ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y +euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq +hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM +6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE +wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY +oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9 +dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp +HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA== +-----END CERTIFICATE----- +Bag Attributes: +subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd +issuer=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G +ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV +eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr +7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92 +aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc +klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN +XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn +BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv +Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3 +AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy +OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3 +mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9 +GA== +-----END CERTIFICATE----- diff --git a/test/key.pem b/test/key.pem new file mode 100644 index 00000000..d381795d --- /dev/null +++ b/test/key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCo9CWMRLMXo1CF +/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErplxfLkt0pJqcoiZG8g9NU0 +kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10uSDk6V9aJSX1vKwONVNS +wiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1VfOugka7UktYnk9mrBbAM +jmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1GbN4AtDuhs252eqE9E4iT +Hk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U3KTfhO/mTlAUWVyg9tCt +OzboKgs1AgMBAAECggEBAKLj6IOJBKXolczpzb8UkyAjAkGBektcseV07gelJ/fk +3z0LuWPv5p12E/HlXB24vU2x/ikUbbP3eMsawRzDEahQqmNmPEkYAYUAy/Qpi9GN +DYvn3LqDec4jVgeQKS+p9H2DzUpTogp8zR2//yzbuWBg2+F//xh7vU0S0RQCziPM +x7RSBgbhxSfChfEJbS2sDnzfh0jRQmoY95iFv7puet1FJtzdZ4fgCd1RqmC2lFM5 +H0eZtN/Cz19lieVs0b996DErdEBqClVZO00eYbRozCDaBzRU3ybB/dMrGJxhkkXm +wb3kWMtziH9qOYsostuHIFu8eKFLloKxFnq2R4DGxOECgYEA2KUIZISOeGJSBcLJ +JAUK2gvgXPNo4HHWIwOA9xeN3ZJlsnPlffXQNnm6t1st1V2gfMm9I2n0m/F0y2B/ +n/XGSa8bghfPA9l0c2h58lkL3JQJR/paa8ycTz+YZPrznEyN7Qa0RrJXUvZv9lQL +Hc3+FHcSHgMqDV2f2bHAEu9YGi0CgYEAx6VEIPNvrHFgjo/jk1RTuk+m0xEWQsZL +Cs+izQMr2TaeJn8LG+93AvFuYn0J0nT3WuStLPrUg8i4IhSS6lf1tId5ivIZPm4r +YwMyblBJXhnHbk7Uqodjfw/3s6V2HAu++B7hTdyVr9DFuST9uv4m8bkPV8rfX1jE +I2rAPVWvgikCgYB+wNAQP547wQrMZBLbCDg5KwmyWJfb+b6X7czexOEz6humNTjo +YZHYzY/5B1fhpk3ntQD8X1nGg5caBvOk21+QbOtjShrM3cXMYCw5JvBRtitX+Zo9 +yBEMLOE0877ki8XeEDYZxu5gk98d+D4oygUGZEQtWxyXhVepPt5qNa8OYQKBgQDH +RVgZI6KFlqzv3wMh3PutbS9wYQ+9GrtwUQuIYe/0YSW9+vSVr5E0qNKrD28sV39F +hBauXLady0yvB6YUrjMbPFW+sCMuQzyfGWPO4+g3OrfqjFiM1ZIkE0YEU9Tt7XNx +qTDtTI1D7bhNMnTnniI1B6ge0und+3XafAThs5L48QKBgQCTTpfqMt8kU3tcI9sf +0MK03y7kA76d5uw0pZbWFy7KI4qnzWutCzb+FMPWWsoFtLJLPZy//u/ZCUVFVa4d +0Y/ASNQIESVPXFLAltlLo4MSmsg1vCBsbviEEaPeEjvMrgki93pYtd/aOSgkYC1T +mEq154s5rmqh+h+XRIf7Au0SLw== +-----END PRIVATE KEY----- diff --git a/test/key2.pem b/test/key2.pem new file mode 100644 index 00000000..3d21e448 --- /dev/null +++ b/test/key2.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +QYXuzBi7LlSFYIOmdDy+5XZ6N4hTXtE= +-----END PRIVATE KEY----- diff --git a/test/root-ca.der b/test/root-ca.der new file mode 100644 index 0000000000000000000000000000000000000000..a9335c6fc2c81c3802c3d9ce20b0a83b124328a6 GIT binary patch literal 865 zcmXqLVvaRvVsc%;%*4pV#L4hTpHDUV`thj-ylk9WZ60mkc^MhGSs4sm4Y>_C*_cCF z*o2uJLk)!u1VJ1Q9qfVU#$p5r}I94=}PaFgG#sGZ-{6axpbA zGBT_Uye3vxrn|Fr`uw<~w`b0~8kDYZW4Xau{wLdX-T7XAaf}kJzq01V@waVhv!iz$ zTvpTjh^g!gN63#Ix=+|#1g2K0OR!uDS8MeNsq0(+wAiKp_l4NE3gMlPL@QdKCWpMA z&ZOU8oO}4r^SmZY2wonMv_e*dnN*PZxl z${CvXmX@9>anO4GZ0^CPI~(37ewVpC)WBZoOK(E!7oks&l};#1b{l$O8;Hdek0>8u>x zOGKuduVOfQ;lrys{_U*0xNYWU@XuNMqU*)>4?-sv)w*A(zW&eu$w9B_9!Zz=(-XgK zvviF=n%(P|Z@2sT)3bZH9-X-Oi?Oj^TvAi;X0ycE9J8K}T6Zn#HO@I@-TclFxjiRo zn$g96_wIk+-4zAyDxY1TrrMGn>QTG**|xWvo95U0ZhSXAmid`SU)!m2BMas$n?4_! z5__We(bsJW8C$a^N!7+A3%&TUM|pB?!#BD0y@vzb)m(1|UEOy_V$D_a*-TXuN^f+k w3ZnlkKK1iYhiC4b*#}RYzgH=FKQ?X}&$CaRvswPtH6Lm5TzJJ;Y|UN?0B@CI7XSbN literal 0 HcmV?d00001 diff --git a/test/root-ca.pem b/test/root-ca.pem new file mode 100644 index 00000000..4ec2f538 --- /dev/null +++ b/test/root-ca.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G +ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV +eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr +7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92 +aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc +klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN +XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn +BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv +Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3 +AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy +OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3 +mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9 +GA== +-----END CERTIFICATE----- From f5e5e6d6be8b66e16da4efcb2c614f835dfd2849 Mon Sep 17 00:00:00 2001 From: kazk Date: Sun, 7 Nov 2021 02:09:28 -0800 Subject: [PATCH 02/14] Update test-cert-gen to 0.7 --- Cargo.toml | 2 +- src/test.rs | 58 ++++++++++++++++++++++++++--------------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 32d11f65..105ad6c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,4 +36,4 @@ openssl-src = { version = "300.0.3", optional = true } [dev-dependencies] tempfile = "3.0" -test-cert-gen = "0.1" +test-cert-gen = "0.7" diff --git a/src/test.rs b/src/test.rs index a26ca67e..eb3e5f3e 100644 --- a/src/test.rs +++ b/src/test.rs @@ -59,8 +59,8 @@ fn server_no_root_certs() { let keys = test_cert_gen::keys(); let identity = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let builder = p!(TlsAcceptor::new(identity)); @@ -78,7 +78,7 @@ fn server_no_root_certs() { p!(socket.write_all(b"world")); }); - let root_ca = Certificate::from_der(&keys.client.cert_der).unwrap(); + let root_ca = Certificate::from_der(keys.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port))); let builder = p!(TlsConnector::builder() @@ -100,8 +100,8 @@ fn server() { let keys = test_cert_gen::keys(); let identity = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let builder = p!(TlsAcceptor::new(identity)); @@ -119,7 +119,7 @@ fn server() { p!(socket.write_all(b"world")); }); - let root_ca = Certificate::from_der(&keys.client.cert_der).unwrap(); + let root_ca = Certificate::from_der(keys.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port))); let builder = p!(TlsConnector::builder() @@ -141,7 +141,7 @@ fn certificate_from_pem() { let keys = test_cert_gen::keys(); let der_path = dir.path().join("cert.der"); - fs::write(&der_path, &keys.client.cert_der).unwrap(); + fs::write(&der_path, &keys.client.ca.get_der()).unwrap(); let output = Command::new("openssl") .arg("x509") .arg("-in") @@ -155,7 +155,7 @@ fn certificate_from_pem() { assert!(output.status.success()); let cert = Certificate::from_pem(&output.stdout).unwrap(); - assert_eq!(cert.to_der().unwrap(), keys.client.cert_der); + assert_eq!(cert.to_der().unwrap(), keys.client.ca.get_der()); } #[test] @@ -163,8 +163,8 @@ fn peer_certificate() { let keys = test_cert_gen::keys(); let identity = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let builder = p!(TlsAcceptor::new(identity)); @@ -177,7 +177,7 @@ fn peer_certificate() { assert!(socket.peer_certificate().unwrap().is_none()); }); - let root_ca = Certificate::from_der(&keys.client.cert_der).unwrap(); + let root_ca = Certificate::from_der(keys.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port))); let builder = p!(TlsConnector::builder() @@ -186,7 +186,7 @@ fn peer_certificate() { let socket = p!(builder.connect("localhost", socket)); let cert = socket.peer_certificate().unwrap().unwrap(); - assert_eq!(cert.to_der().unwrap(), keys.client.cert_der); + assert_eq!(cert.to_der().unwrap(), keys.client.ca.get_der()); p!(j.join()); } @@ -196,8 +196,8 @@ fn server_tls11_only() { let keys = test_cert_gen::keys(); let identity = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let builder = p!(TlsAcceptor::builder(identity) .min_protocol_version(Some(Protocol::Tlsv12)) @@ -218,7 +218,7 @@ fn server_tls11_only() { p!(socket.write_all(b"world")); }); - let root_ca = Certificate::from_der(&keys.client.cert_der).unwrap(); + let root_ca = Certificate::from_der(keys.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port))); let builder = p!(TlsConnector::builder() @@ -241,8 +241,8 @@ fn server_no_shared_protocol() { let keys = test_cert_gen::keys(); let identity = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let builder = p!(TlsAcceptor::builder(identity) .min_protocol_version(Some(Protocol::Tlsv12)) @@ -256,7 +256,7 @@ fn server_no_shared_protocol() { assert!(builder.accept(socket).is_err()); }); - let root_ca = Certificate::from_der(&keys.client.cert_der).unwrap(); + let root_ca = Certificate::from_der(keys.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port))); let builder = p!(TlsConnector::builder() @@ -274,8 +274,8 @@ fn server_untrusted() { let keys = test_cert_gen::keys(); let identity = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let builder = p!(TlsAcceptor::new(identity)); @@ -301,8 +301,8 @@ fn server_untrusted_unverified() { let keys = test_cert_gen::keys(); let identity = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let builder = p!(TlsAcceptor::new(identity)); @@ -339,12 +339,12 @@ fn import_same_identity_multiple_times() { let keys = test_cert_gen::keys(); let _ = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let _ = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let p8buf = include_bytes!("../test/chain.pem"); @@ -358,8 +358,8 @@ fn shutdown() { let keys = test_cert_gen::keys(); let identity = p!(Identity::from_pkcs12( - &keys.server.pkcs12, - &keys.server.pkcs12_password + &keys.server.cert_and_key_pkcs12.pkcs12.0, + &keys.server.cert_and_key_pkcs12.password )); let builder = p!(TlsAcceptor::new(identity)); @@ -378,7 +378,7 @@ fn shutdown() { p!(socket.shutdown()); }); - let root_ca = Certificate::from_der(&keys.client.cert_der).unwrap(); + let root_ca = Certificate::from_der(keys.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port))); let builder = p!(TlsConnector::builder() From eb7fef5b26dbb6249e52b06247b0525267e3231e Mon Sep 17 00:00:00 2001 From: kazk Date: Sun, 7 Nov 2021 03:15:09 -0800 Subject: [PATCH 03/14] Update tests to use test-cert-gen --- Cargo.toml | 1 + src/test.rs | 51 ++++++++++++++++++++++++++-------------------- test/cert.pem | 20 ------------------ test/cert2.pem | 32 ----------------------------- test/chain.pem | 48 ------------------------------------------- test/key.pem | 28 ------------------------- test/key2.pem | 52 ----------------------------------------------- test/root-ca.der | Bin 865 -> 0 bytes test/root-ca.pem | 21 ------------------- 9 files changed, 30 insertions(+), 223 deletions(-) delete mode 100644 test/cert.pem delete mode 100644 test/cert2.pem delete mode 100644 test/chain.pem delete mode 100644 test/key.pem delete mode 100644 test/key2.pem delete mode 100644 test/root-ca.der delete mode 100644 test/root-ca.pem diff --git a/Cargo.toml b/Cargo.toml index 105ad6c7..e5650638 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,5 +35,6 @@ openssl-probe = "0.1" openssl-src = { version = "300.0.3", optional = true } [dev-dependencies] +pem = "1.0" tempfile = "3.0" test-cert-gen = "0.7" diff --git a/src/test.rs b/src/test.rs index eb3e5f3e..a260f266 100644 --- a/src/test.rs +++ b/src/test.rs @@ -347,10 +347,10 @@ fn import_same_identity_multiple_times() { &keys.server.cert_and_key_pkcs12.password )); - let p8buf = include_bytes!("../test/chain.pem"); - let key = include_bytes!("../test/key.pem"); - let _ = p!(Identity::from_pkcs8(p8buf, key)); - let _ = p!(Identity::from_pkcs8(p8buf, key)); + let cert = keys.server.cert_and_key.cert.to_pem().into_bytes(); + let key = key_to_pem(keys.server.cert_and_key.key.get_der()).into_bytes(); + let _ = p!(Identity::from_pkcs8(&cert, &key)); + let _ = p!(Identity::from_pkcs8(&cert, &key)); } #[test] @@ -424,10 +424,11 @@ fn alpn_google_none() { #[test] fn server_pkcs8() { - let key = include_bytes!("../test/key.pem"); - let cert = include_bytes!("../test/cert.pem"); + let keys = test_cert_gen::keys(); + let cert = keys.server.cert_and_key.cert.to_pem().into_bytes(); + let key = key_to_pem(keys.server.cert_and_key.key.get_der()).into_bytes(); - let ident = Identity::from_pkcs8(cert, key).unwrap(); + let ident = Identity::from_pkcs8(&cert, &key).unwrap(); let ident2 = ident.clone(); let builder = p!(TlsAcceptor::new(ident)); @@ -445,8 +446,7 @@ fn server_pkcs8() { p!(socket.write_all(b"world")); }); - let root_ca = include_bytes!("../test/root-ca.der"); - let root_ca = Certificate::from_der(root_ca).unwrap(); + let root_ca = Certificate::from_der(keys.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port))); let mut builder = TlsConnector::builder(); @@ -459,7 +459,7 @@ fn server_pkcs8() { builder.add_root_certificate(root_ca); let builder = p!(builder.build()); - let mut socket = p!(builder.connect("foobar.com", socket)); + let mut socket = p!(builder.connect("localhost", socket)); p!(socket.write_all(b"hello")); let mut buf = vec![]; @@ -471,9 +471,10 @@ fn server_pkcs8() { #[test] fn two_servers() { - let key = include_bytes!("../test/key.pem"); - let cert = include_bytes!("../test/cert.pem"); - let identity = p!(Identity::from_pkcs8(cert, key)); + let keys1 = test_cert_gen::gen_keys(); + let cert = keys1.server.cert_and_key.cert.to_pem().into_bytes(); + let key = key_to_pem(keys1.server.cert_and_key.key.get_der()).into_bytes(); + let identity = p!(Identity::from_pkcs8(&cert, &key)); let builder = TlsAcceptor::builder(identity); let builder = p!(builder.build()); @@ -491,9 +492,10 @@ fn two_servers() { p!(socket.write_all(b"world")); }); - let key = include_bytes!("../test/key2.pem"); - let cert = include_bytes!("../test/cert2.pem"); - let identity = p!(Identity::from_pkcs8(cert, key)); + let keys2 = test_cert_gen::gen_keys(); + let cert = keys2.server.cert_and_key.cert.to_pem().into_bytes(); + let key = key_to_pem(keys2.server.cert_and_key.key.get_der()).into_bytes(); + let identity = p!(Identity::from_pkcs8(&cert, &key)); let builder = TlsAcceptor::builder(identity); let builder = p!(builder.build()); @@ -511,28 +513,26 @@ fn two_servers() { p!(socket.write_all(b"world")); }); - let root_ca = include_bytes!("../test/root-ca.pem"); - let root_ca = p!(Certificate::from_pem(root_ca)); + let root_ca = Certificate::from_der(keys1.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port))); let mut builder = TlsConnector::builder(); builder.add_root_certificate(root_ca); let builder = p!(builder.build()); - let mut socket = p!(builder.connect("foobar.com", socket)); + let mut socket = p!(builder.connect("localhost", socket)); p!(socket.write_all(b"hello")); let mut buf = vec![]; p!(socket.read_to_end(&mut buf)); assert_eq!(buf, b"world"); - let root_ca = include_bytes!("../test/cert2.pem"); - let root_ca = p!(Certificate::from_pem(root_ca)); + let root_ca = Certificate::from_der(keys2.client.ca.get_der()).unwrap(); let socket = p!(TcpStream::connect(("localhost", port2))); let mut builder = TlsConnector::builder(); builder.add_root_certificate(root_ca); let builder = p!(builder.build()); - let mut socket = p!(builder.connect("foobar.com", socket)); + let mut socket = p!(builder.connect("localhost", socket)); p!(socket.write_all(b"hello")); let mut buf = vec![]; @@ -542,3 +542,10 @@ fn two_servers() { p!(j.join()); p!(j2.join()); } + +fn key_to_pem(der: &[u8]) -> String { + pem::encode(&pem::Pem { + tag: "RSA PRIVATE KEY".to_owned(), + contents: der.to_owned(), + }) +} diff --git a/test/cert.pem b/test/cert.pem deleted file mode 100644 index ce447144..00000000 --- a/test/cert.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub -3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ -mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6 -TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI -ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y -euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq -hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM -6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE -wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY -oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9 -dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp -HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA== ------END CERTIFICATE----- - diff --git a/test/cert2.pem b/test/cert2.pem deleted file mode 100644 index d9fbcd57..00000000 --- a/test/cert2.pem +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFijCCA3KgAwIBAgIJAOFl3cFizu8kMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmZvb2Jhci5jb20wHhcNMTcwNjI0MTYw -NzEwWhcNMjcwNjIyMTYwNzEwWjBaMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29t -ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYD -VQQDDApmb29iYXIuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA -2TfYpOOpb1HigFQOHq756Hr/wE2YvTGRRmFOuI/7TEzZnG4TcYGqbS8UTNIvxaeU -GtQdRLFV6QWtIQhArHOU22D0EWxj88MYE7O3h5csZOUKfI0s4IRA/u3VP2mfk/VT -AbikUJH370tTpxltcpMoOgOWkxraF6LDCnSSGALU6MN23OySUjadd4jtv5BmqdQL -t5+VDOsgEK8Gq0Kvw4noyADPAWRj/7L/OyJ2nk9Krlof/FYb+c7lK27LUqEM3yjZ -nARO+zCFj0cWqd0uYY3Uz+My73CLLu8NeHtl0Qv9a23jtol76j7wUXjrIR5VBs0o -hhP1/zcOfuXu2NYzHa6gbefJqnUtqMgnibimQyMZaLxoVOryJKkEHj/D/U3OgbkW -3q4sWZ2xGp6FlVU8smgPcq5KMQ/BQzPcGciVYKbHl+H6TUgSdABga8yMxURK058t -TZnv/GaSKEVjM8VNLuiZAlmRtzBbd5cbRMIb/8SV6m5xwK4jQ0pdDtKbY8I0poku -YbT/B8Rs/x50LgCk/sEjWCEdoxZ/KY4nuYpGzs5B79LZn4ofmHRG1IfiQBPxuR4S -ChW5V+HaICXsL2oKhxIhpDQjtownj9PF85ew6IODNzk/oHDZgFCJwHK23Acr+kTt -AsI/Oht3W0eG34DHS2UPuVc1jGE5TaNK3F/AN8ICANUCAwEAAaNTMFEwHQYDVR0O -BBYEFNlnR/6xSAyj2shdqYPPRbOpFj9AMB8GA1UdIwQYMBaAFNlnR/6xSAyj2shd -qYPPRbOpFj9AMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAAd/ -RYi40if/HiOLjVWeu4ETpZLut6p4NnFY2ueRF7O3cNSH3ugQ0Ucc4S8rDrTGHryz -jTVHC1p0783u7VkOiJNFKT+y5RmGVSRLnXfbWY4Vwpz5Dqz6sZtZlVO22VqhfT0K -Cwzbu6Mgr/rhPow3tCWUDzDVoKPnJCFmDwHWcXlDCjnuU/0DdgO+q3anj1x3Zt7x -1cXG+2O2PO8474A1ESujTYduCnQRzEOeud4beGhLeW6wcuq2tNRwbxQzBdCzb4/f -INSDsqk6lpimpokxVh9Q8yUSbORvPyXMLb0F2I670CBfsQ27U/+xqBPU7rmz63vL -J70fee+QQQ9KF9O1LWeIaPkRyKzU0kovwLTsTVXV6xQUeH1PLdgAkhh5KTnWReUq -n7Iu8EGIHNRQFGp/qgo7bww+g2aWiqyCquCCe5zyt13j5Ev9naRJzROna39BocsG -t2/NHSNMJ6ru4mPunPrP25J5V2qT7sN9RrKEPaANAV3dWuUOhvlrHQBVXKACckTJ -K+mKXP0pXrnLhQc6RP4ep8JuDY7qlRnJwr3+WxeTb52wcjmz0RusdbiEeBhgMcnF -ZDpZmLeTTPH/50TVvRTXgYGFmlgzVEqqGwpJsnEISuhgI/x58FqiXFCEaz9zr+xi -QWt2BCQJnE0G1UV9msEybRE4toiCHdOpojJjHFi8 ------END CERTIFICATE----- diff --git a/test/chain.pem b/test/chain.pem deleted file mode 100644 index 6b171293..00000000 --- a/test/chain.pem +++ /dev/null @@ -1,48 +0,0 @@ -Bag Attributes - friendlyName: foobar.com - localKeyID: 59 17 2D 93 13 E8 44 59 BC FF 27 F9 67 E7 9E 6E 92 17 E5 84 -subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=foobar.com -issuer=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd ------BEGIN CERTIFICATE----- -MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub -3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ -mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6 -TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI -ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y -euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq -hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM -6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE -wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY -oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9 -dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp -HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA== ------END CERTIFICATE----- -Bag Attributes: -subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd -issuer=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd ------BEGIN CERTIFICATE----- -MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF -MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 -ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G -ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV -eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr -7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92 -aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc -klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN -XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow -DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn -BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv -Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3 -AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy -OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3 -mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9 -GA== ------END CERTIFICATE----- diff --git a/test/key.pem b/test/key.pem deleted file mode 100644 index d381795d..00000000 --- a/test/key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCo9CWMRLMXo1CF -/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErplxfLkt0pJqcoiZG8g9NU0 -kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10uSDk6V9aJSX1vKwONVNS -wiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1VfOugka7UktYnk9mrBbAM -jmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1GbN4AtDuhs252eqE9E4iT -Hk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U3KTfhO/mTlAUWVyg9tCt -OzboKgs1AgMBAAECggEBAKLj6IOJBKXolczpzb8UkyAjAkGBektcseV07gelJ/fk -3z0LuWPv5p12E/HlXB24vU2x/ikUbbP3eMsawRzDEahQqmNmPEkYAYUAy/Qpi9GN -DYvn3LqDec4jVgeQKS+p9H2DzUpTogp8zR2//yzbuWBg2+F//xh7vU0S0RQCziPM -x7RSBgbhxSfChfEJbS2sDnzfh0jRQmoY95iFv7puet1FJtzdZ4fgCd1RqmC2lFM5 -H0eZtN/Cz19lieVs0b996DErdEBqClVZO00eYbRozCDaBzRU3ybB/dMrGJxhkkXm -wb3kWMtziH9qOYsostuHIFu8eKFLloKxFnq2R4DGxOECgYEA2KUIZISOeGJSBcLJ -JAUK2gvgXPNo4HHWIwOA9xeN3ZJlsnPlffXQNnm6t1st1V2gfMm9I2n0m/F0y2B/ -n/XGSa8bghfPA9l0c2h58lkL3JQJR/paa8ycTz+YZPrznEyN7Qa0RrJXUvZv9lQL -Hc3+FHcSHgMqDV2f2bHAEu9YGi0CgYEAx6VEIPNvrHFgjo/jk1RTuk+m0xEWQsZL -Cs+izQMr2TaeJn8LG+93AvFuYn0J0nT3WuStLPrUg8i4IhSS6lf1tId5ivIZPm4r -YwMyblBJXhnHbk7Uqodjfw/3s6V2HAu++B7hTdyVr9DFuST9uv4m8bkPV8rfX1jE -I2rAPVWvgikCgYB+wNAQP547wQrMZBLbCDg5KwmyWJfb+b6X7czexOEz6humNTjo -YZHYzY/5B1fhpk3ntQD8X1nGg5caBvOk21+QbOtjShrM3cXMYCw5JvBRtitX+Zo9 -yBEMLOE0877ki8XeEDYZxu5gk98d+D4oygUGZEQtWxyXhVepPt5qNa8OYQKBgQDH -RVgZI6KFlqzv3wMh3PutbS9wYQ+9GrtwUQuIYe/0YSW9+vSVr5E0qNKrD28sV39F -hBauXLady0yvB6YUrjMbPFW+sCMuQzyfGWPO4+g3OrfqjFiM1ZIkE0YEU9Tt7XNx -qTDtTI1D7bhNMnTnniI1B6ge0und+3XafAThs5L48QKBgQCTTpfqMt8kU3tcI9sf -0MK03y7kA76d5uw0pZbWFy7KI4qnzWutCzb+FMPWWsoFtLJLPZy//u/ZCUVFVa4d -0Y/ASNQIESVPXFLAltlLo4MSmsg1vCBsbviEEaPeEjvMrgki93pYtd/aOSgkYC1T -mEq154s5rmqh+h+XRIf7Au0SLw== ------END PRIVATE KEY----- diff --git a/test/key2.pem b/test/key2.pem deleted file mode 100644 index 3d21e448..00000000 --- a/test/key2.pem +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -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 -QYXuzBi7LlSFYIOmdDy+5XZ6N4hTXtE= ------END PRIVATE KEY----- diff --git a/test/root-ca.der b/test/root-ca.der deleted file mode 100644 index a9335c6fc2c81c3802c3d9ce20b0a83b124328a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 865 zcmXqLVvaRvVsc%;%*4pV#L4hTpHDUV`thj-ylk9WZ60mkc^MhGSs4sm4Y>_C*_cCF z*o2uJLk)!u1VJ1Q9qfVU#$p5r}I94=}PaFgG#sGZ-{6axpbA zGBT_Uye3vxrn|Fr`uw<~w`b0~8kDYZW4Xau{wLdX-T7XAaf}kJzq01V@waVhv!iz$ zTvpTjh^g!gN63#Ix=+|#1g2K0OR!uDS8MeNsq0(+wAiKp_l4NE3gMlPL@QdKCWpMA z&ZOU8oO}4r^SmZY2wonMv_e*dnN*PZxl z${CvXmX@9>anO4GZ0^CPI~(37ewVpC)WBZoOK(E!7oks&l};#1b{l$O8;Hdek0>8u>x zOGKuduVOfQ;lrys{_U*0xNYWU@XuNMqU*)>4?-sv)w*A(zW&eu$w9B_9!Zz=(-XgK zvviF=n%(P|Z@2sT)3bZH9-X-Oi?Oj^TvAi;X0ycE9J8K}T6Zn#HO@I@-TclFxjiRo zn$g96_wIk+-4zAyDxY1TrrMGn>QTG**|xWvo95U0ZhSXAmid`SU)!m2BMas$n?4_! z5__We(bsJW8C$a^N!7+A3%&TUM|pB?!#BD0y@vzb)m(1|UEOy_V$D_a*-TXuN^f+k w3ZnlkKK1iYhiC4b*#}RYzgH=FKQ?X}&$CaRvswPtH6Lm5TzJJ;Y|UN?0B@CI7XSbN diff --git a/test/root-ca.pem b/test/root-ca.pem deleted file mode 100644 index 4ec2f538..00000000 --- a/test/root-ca.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF -MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 -ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G -ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV -eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr -7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92 -aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc -klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN -XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow -DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn -BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv -Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3 -AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy -OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3 -mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9 -GA== ------END CERTIFICATE----- From de0fc42d6953c248df50b369b62a9cee004a6cda Mon Sep 17 00:00:00 2001 From: kazk Date: Sun, 7 Nov 2021 19:56:17 -0800 Subject: [PATCH 04/14] Use `CertAdd::Always` --- src/imp/schannel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imp/schannel.rs b/src/imp/schannel.rs index 78747f95..f952b92b 100644 --- a/src/imp/schannel.rs +++ b/src/imp/schannel.rs @@ -122,7 +122,7 @@ impl Identity { for int_cert in cert_iter { let certificate = Certificate::from_pem(int_cert)?; - context = store.add_cert(&certificate.0, schannel::cert_store::CertAdd::Always)?; + context = store.add_cert(&certificate.0, CertAdd::Always)?; } Ok(Identity{cert: context}) } From 14f49650e6cf6f4926279ef6ca68f70195824967 Mon Sep 17 00:00:00 2001 From: kazk Date: Sun, 7 Nov 2021 19:59:04 -0800 Subject: [PATCH 05/14] Don't panic when `TempDir::new()` fails --- src/imp/security_framework.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imp/security_framework.rs b/src/imp/security_framework.rs index 65dd0711..84e7ee48 100644 --- a/src/imp/security_framework.rs +++ b/src/imp/security_framework.rs @@ -85,7 +85,7 @@ pub struct Identity { impl Identity { pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result { - let dir = TempDir::new().unwrap(); + let dir = TempDir::new().map_err(|_| Error(base::Error::from(errSecIO)))?; let keychain = keychain::CreateOptions::new() .password("password") .create(dir.path().join("identity.keychain"))?; From 59688ef7e4ebf0e32513f30a8185fd9c89850895 Mon Sep 17 00:00:00 2001 From: kazk Date: Sun, 7 Nov 2021 20:17:48 -0800 Subject: [PATCH 06/14] Don't panic on empty chain --- src/imp/openssl.rs | 15 ++++++++------- src/imp/schannel.rs | 14 ++++++++++++-- src/imp/security_framework.rs | 8 ++++++-- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/imp/openssl.rs b/src/imp/openssl.rs index 7afdd596..16c321c0 100644 --- a/src/imp/openssl.rs +++ b/src/imp/openssl.rs @@ -116,6 +116,7 @@ fn load_android_root_certs(connector: &mut SslContextBuilder) -> Result<(), Erro pub enum Error { Normal(ErrorStack), Ssl(ssl::Error, X509VerifyResult), + EmptyChain, } impl error::Error for Error { @@ -123,6 +124,7 @@ impl error::Error for Error { match *self { Error::Normal(ref e) => error::Error::source(e), Error::Ssl(ref e, _) => error::Error::source(e), + Error::EmptyChain => None, } } } @@ -133,6 +135,10 @@ impl fmt::Display for Error { Error::Normal(ref e) => fmt::Display::fmt(e, fmt), Error::Ssl(ref e, X509VerifyResult::OK) => fmt::Display::fmt(e, fmt), Error::Ssl(ref e, v) => write!(fmt, "{} ({})", e, v), + Error::EmptyChain => write!( + fmt, + "at least one certificate must be provided to create an identity" + ), } } } @@ -164,14 +170,9 @@ impl Identity { pub fn from_pkcs8(buf: &[u8], key: &[u8]) -> Result { let pkey = PKey::private_key_from_pem(key)?; let mut cert_chain = X509::stack_from_pem(buf)?.into_iter(); - let cert = cert_chain.next(); + let cert = cert_chain.next().ok_or(Error::EmptyChain)?; let chain = cert_chain.collect(); - Ok(Identity { - pkey, - // an identity must have at least one certificate, the leaf cert - cert: cert.expect("at least one certificate must be provided to create an identity"), - chain, - }) + Ok(Identity { pkey, cert, chain }) } } diff --git a/src/imp/schannel.rs b/src/imp/schannel.rs index f952b92b..1b281566 100644 --- a/src/imp/schannel.rs +++ b/src/imp/schannel.rs @@ -98,8 +98,18 @@ impl Identity { pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result { let mut store = Memory::new()?.into_store(); let mut cert_iter = pem::PemBlock::new(pem).into_iter(); - let leaf = cert_iter.next().expect("at least one certificate must be provided to create an identity"); - let cert = CertContext::from_pem(std::str::from_utf8(leaf).map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "leaf cert contains invalid utf8"))?)?; + let leaf = cert_iter.next().ok_or_else(|| { + io::Error::new( + io::ErrorKind::InvalidInput, + "at least one certificate must be provided to create an identity", + ) + })?; + let cert = CertContext::from_pem(std::str::from_utf8(leaf).map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidInput, + "leaf cert contains invalid utf8", + ) + })?)?; let mut options = AcquireOptions::new(); options.container("schannel"); diff --git a/src/imp/security_framework.rs b/src/imp/security_framework.rs index 84e7ee48..04fe7a74 100644 --- a/src/imp/security_framework.rs +++ b/src/imp/security_framework.rs @@ -104,10 +104,14 @@ impl Identity { .keychain(&keychain) .import(&pem)?; - let ident = SecIdentity::with_certificate(&[keychain], &items.certificates[0])?; + let cert = items + .certificates + .get(0) + .ok_or_else(|| Error(base::Error::from(errSecParam)))?; + let ident = SecIdentity::with_certificate(&[keychain], cert)?; Ok(Identity { identity: ident, - chain: items.certificates + chain: items.certificates, }) } From a512918cfc050fac00011aec84874311d6a2ea08 Mon Sep 17 00:00:00 2001 From: kazk Date: Sun, 7 Nov 2021 20:31:28 -0800 Subject: [PATCH 07/14] Format code --- examples/simple-server-pkcs8.rs | 4 +- src/imp/schannel.rs | 112 ++++++++++++++++++++++---------- src/imp/security_framework.rs | 4 +- 3 files changed, 81 insertions(+), 39 deletions(-) diff --git a/examples/simple-server-pkcs8.rs b/examples/simple-server-pkcs8.rs index 8e1b1b81..df9c95da 100644 --- a/examples/simple-server-pkcs8.rs +++ b/examples/simple-server-pkcs8.rs @@ -25,7 +25,9 @@ fn main() { let mut buf = [0; 1024]; let read = stream.read(&mut buf).unwrap(); let received = std::str::from_utf8(&buf[0..read]).unwrap(); - stream.write_all(format!("received '{}'", received).as_bytes()).unwrap(); + stream + .write_all(format!("received '{}'", received).as_bytes()) + .unwrap(); } for stream in listener.incoming() { diff --git a/src/imp/schannel.rs b/src/imp/schannel.rs index 1b281566..d3f214cc 100644 --- a/src/imp/schannel.rs +++ b/src/imp/schannel.rs @@ -2,8 +2,8 @@ extern crate schannel; use self::schannel::cert_context::{CertContext, HashAlgorithm, KeySpec}; use self::schannel::cert_store::{CertAdd, CertStore, Memory, PfxImportOptions}; -use self::schannel::schannel_cred::{Direction, Protocol, SchannelCred}; use self::schannel::crypt_prov::{AcquireOptions, ProviderType}; +use self::schannel::schannel_cred::{Direction, Protocol, SchannelCred}; use self::schannel::tls_stream; use std::error; use std::fmt; @@ -119,8 +119,7 @@ impl Identity { Ok(container) => container, Err(_) => options.new_keyset(true).acquire(type_)?, }; - container.import() - .import_pkcs8_pem(&key)?; + container.import().import_pkcs8_pem(&key)?; cert.set_key_prov_info() .container("schannel") @@ -134,7 +133,7 @@ impl Identity { let certificate = Certificate::from_pem(int_cert)?; context = store.add_cert(&certificate.0, CertAdd::Always)?; } - Ok(Identity{cert: context}) + Ok(Identity { cert: context }) } } @@ -428,7 +427,6 @@ impl io::Write for TlsStream { } } - mod pem { /// Split data by PEM guard lines pub struct PemBlock<'a> { @@ -466,45 +464,87 @@ mod pem { #[test] fn test_split() { // Split three certs, CRLF line terminators. - assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n\ + assert_eq!( + PemBlock::new( + b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n\ -----BEGIN SECOND-----\r\n-----END SECOND\r\n\ - -----BEGIN THIRD-----\r\n-----END THIRD\r\n").collect::>(), - vec![b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n" as &[u8], - b"-----BEGIN SECOND-----\r\n-----END SECOND\r\n", - b"-----BEGIN THIRD-----\r\n-----END THIRD\r\n"]); + -----BEGIN THIRD-----\r\n-----END THIRD\r\n" + ) + .collect::>(), + vec![ + b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n" as &[u8], + b"-----BEGIN SECOND-----\r\n-----END SECOND\r\n", + b"-----BEGIN THIRD-----\r\n-----END THIRD\r\n" + ] + ); // Split three certs, CRLF line terminators except at EOF. - assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n\ + assert_eq!( + PemBlock::new( + b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n\ -----BEGIN SECOND-----\r\n-----END SECOND-----\r\n\ - -----BEGIN THIRD-----\r\n-----END THIRD-----").collect::>(), - vec![b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n" as &[u8], - b"-----BEGIN SECOND-----\r\n-----END SECOND-----\r\n", - b"-----BEGIN THIRD-----\r\n-----END THIRD-----"]); + -----BEGIN THIRD-----\r\n-----END THIRD-----" + ) + .collect::>(), + vec![ + b"-----BEGIN FIRST-----\r\n-----END FIRST-----\r\n" as &[u8], + b"-----BEGIN SECOND-----\r\n-----END SECOND-----\r\n", + b"-----BEGIN THIRD-----\r\n-----END THIRD-----" + ] + ); // Split two certs, LF line terminators. - assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----\n\ - -----BEGIN SECOND-----\n-----END SECOND\n").collect::>(), - vec![b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8], - b"-----BEGIN SECOND-----\n-----END SECOND\n"]); + assert_eq!( + PemBlock::new( + b"-----BEGIN FIRST-----\n-----END FIRST-----\n\ + -----BEGIN SECOND-----\n-----END SECOND\n" + ) + .collect::>(), + vec![ + b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8], + b"-----BEGIN SECOND-----\n-----END SECOND\n" + ] + ); // Split two certs, CR line terminators. - assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\r-----END FIRST-----\r\ - -----BEGIN SECOND-----\r-----END SECOND\r").collect::>(), - vec![b"-----BEGIN FIRST-----\r-----END FIRST-----\r" as &[u8], - b"-----BEGIN SECOND-----\r-----END SECOND\r"]); + assert_eq!( + PemBlock::new( + b"-----BEGIN FIRST-----\r-----END FIRST-----\r\ + -----BEGIN SECOND-----\r-----END SECOND\r" + ) + .collect::>(), + vec![ + b"-----BEGIN FIRST-----\r-----END FIRST-----\r" as &[u8], + b"-----BEGIN SECOND-----\r-----END SECOND\r" + ] + ); // Split two certs, LF line terminators except at EOF. - assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----\n\ - -----BEGIN SECOND-----\n-----END SECOND").collect::>(), - vec![b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8], - b"-----BEGIN SECOND-----\n-----END SECOND"]); + assert_eq!( + PemBlock::new( + b"-----BEGIN FIRST-----\n-----END FIRST-----\n\ + -----BEGIN SECOND-----\n-----END SECOND" + ) + .collect::>(), + vec![ + b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8], + b"-----BEGIN SECOND-----\n-----END SECOND" + ] + ); // Split a single cert, LF line terminators. - assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----\n").collect::>(), - vec![b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8]]); + assert_eq!( + PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----\n").collect::>(), + vec![b"-----BEGIN FIRST-----\n-----END FIRST-----\n" as &[u8]] + ); // Split a single cert, LF line terminators except at EOF. - assert_eq!(PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----").collect::>(), - vec![b"-----BEGIN FIRST-----\n-----END FIRST-----" as &[u8]]); + assert_eq!( + PemBlock::new(b"-----BEGIN FIRST-----\n-----END FIRST-----").collect::>(), + vec![b"-----BEGIN FIRST-----\n-----END FIRST-----" as &[u8]] + ); // (Don't) split garbage. - assert_eq!(PemBlock::new(b"junk").collect::>(), - Vec::<&[u8]>::new()); - assert_eq!(PemBlock::new(b"junk-----BEGIN garbage").collect::>(), - vec![b"-----BEGIN garbage" as &[u8]]); + assert_eq!( + PemBlock::new(b"junk").collect::>(), + Vec::<&[u8]>::new() + ); + assert_eq!( + PemBlock::new(b"junk-----BEGIN garbage").collect::>(), + vec![b"-----BEGIN garbage" as &[u8]] + ); } } - diff --git a/src/imp/security_framework.rs b/src/imp/security_framework.rs index 04fe7a74..f133903f 100644 --- a/src/imp/security_framework.rs +++ b/src/imp/security_framework.rs @@ -87,8 +87,8 @@ impl Identity { pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result { let dir = TempDir::new().map_err(|_| Error(base::Error::from(errSecIO)))?; let keychain = keychain::CreateOptions::new() - .password("password") - .create(dir.path().join("identity.keychain"))?; + .password("password") + .create(dir.path().join("identity.keychain"))?; let mut items = SecItems::default(); From 0f91cd7baab2cc220480e92be63e7acfecb1855b Mon Sep 17 00:00:00 2001 From: kazk Date: Sun, 7 Nov 2021 20:56:06 -0800 Subject: [PATCH 08/14] Revert the order of the chain in Identity from PKCS12 --- src/imp/openssl.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/imp/openssl.rs b/src/imp/openssl.rs index 16c321c0..22fbb249 100644 --- a/src/imp/openssl.rs +++ b/src/imp/openssl.rs @@ -163,7 +163,10 @@ impl Identity { Ok(Identity { pkey: parsed.pkey, cert: parsed.cert, - chain: parsed.chain.into_iter().flatten().collect(), + // > The stack is the reverse of what you might expect due to the way + // > PKCS12_parse is implemented, so we need to load it backwards. + // > https://github.com/sfackler/rust-native-tls/commit/05fb5e583be589ab63d9f83d986d095639f8ec44 + chain: parsed.chain.into_iter().flatten().rev().collect(), }) } From 7493a48efe60b05d2caa7995e865da291059f06b Mon Sep 17 00:00:00 2001 From: kazk Date: Tue, 7 Dec 2021 18:11:51 -0800 Subject: [PATCH 09/14] Fix macOS build --- src/test.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test.rs b/src/test.rs index a260f266..dcb9e416 100644 --- a/src/test.rs +++ b/src/test.rs @@ -186,7 +186,10 @@ fn peer_certificate() { let socket = p!(builder.connect("localhost", socket)); let cert = socket.peer_certificate().unwrap().unwrap(); - assert_eq!(cert.to_der().unwrap(), keys.client.ca.get_der()); + assert_eq!( + cert.to_der().unwrap(), + keys.server.cert_and_key.cert.get_der() + ); p!(j.join()); } From f0201c9ae96d80e9f0832dcbd76285851387f700 Mon Sep 17 00:00:00 2001 From: kazk Date: Fri, 10 Dec 2021 20:56:09 -0800 Subject: [PATCH 10/14] Use unique container name --- src/imp/schannel.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/imp/schannel.rs b/src/imp/schannel.rs index d3f214cc..285b2b6d 100644 --- a/src/imp/schannel.rs +++ b/src/imp/schannel.rs @@ -111,8 +111,9 @@ impl Identity { ) })?)?; + let name = gen_container_name(); let mut options = AcquireOptions::new(); - options.container("schannel"); + options.container(&name); let type_ = ProviderType::rsa_full(); let mut container = match options.acquire(type_) { @@ -122,7 +123,7 @@ impl Identity { container.import().import_pkcs8_pem(&key)?; cert.set_key_prov_info() - .container("schannel") + .container(&name) .type_(type_) .keep_open(true) .key_spec(KeySpec::key_exchange()) @@ -137,6 +138,13 @@ impl Identity { } } +// The name of the container must be unique to have multiple active keys. +fn gen_container_name() -> String { + use std::sync::atomic::{AtomicUsize, Ordering}; + static COUNTER: AtomicUsize = AtomicUsize::new(0); + format!("native-tls-{}", COUNTER.fetch_add(1, Ordering::Relaxed)) +} + #[derive(Clone)] pub struct Certificate(CertContext); From 01337348b5edcd4ab3cc156e5186e5bdc1a5a8d2 Mon Sep 17 00:00:00 2001 From: kazk Date: Fri, 10 Dec 2021 21:30:44 -0800 Subject: [PATCH 11/14] Test with PKCS#8 keys --- Cargo.toml | 1 + src/lib.rs | 2 ++ src/test.rs | 16 ++++++++++++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e5650638..b3d7ddb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,5 +36,6 @@ openssl-src = { version = "300.0.3", optional = true } [dev-dependencies] pem = "1.0" +rsa = { version = "0.5.0", features = ["alloc", "pem", "std"] } tempfile = "3.0" test-cert-gen = "0.7" diff --git a/src/lib.rs b/src/lib.rs index 14dabb7b..13c70b54 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,6 +123,8 @@ mod imp; #[cfg(test)] mod test; +#[cfg(test)] +extern crate rsa; /// A typedef of the result-type returned by many methods. pub type Result = result::Result; diff --git a/src/test.rs b/src/test.rs index dcb9e416..96d7316d 100644 --- a/src/test.rs +++ b/src/test.rs @@ -351,7 +351,7 @@ fn import_same_identity_multiple_times() { )); let cert = keys.server.cert_and_key.cert.to_pem().into_bytes(); - let key = key_to_pem(keys.server.cert_and_key.key.get_der()).into_bytes(); + let key = rsa_to_pkcs8(&key_to_pem(keys.server.cert_and_key.key.get_der())).into_bytes(); let _ = p!(Identity::from_pkcs8(&cert, &key)); let _ = p!(Identity::from_pkcs8(&cert, &key)); } @@ -429,7 +429,7 @@ fn alpn_google_none() { fn server_pkcs8() { let keys = test_cert_gen::keys(); let cert = keys.server.cert_and_key.cert.to_pem().into_bytes(); - let key = key_to_pem(keys.server.cert_and_key.key.get_der()).into_bytes(); + let key = rsa_to_pkcs8(&key_to_pem(keys.server.cert_and_key.key.get_der())).into_bytes(); let ident = Identity::from_pkcs8(&cert, &key).unwrap(); let ident2 = ident.clone(); @@ -476,7 +476,7 @@ fn server_pkcs8() { fn two_servers() { let keys1 = test_cert_gen::gen_keys(); let cert = keys1.server.cert_and_key.cert.to_pem().into_bytes(); - let key = key_to_pem(keys1.server.cert_and_key.key.get_der()).into_bytes(); + let key = rsa_to_pkcs8(&key_to_pem(keys1.server.cert_and_key.key.get_der())).into_bytes(); let identity = p!(Identity::from_pkcs8(&cert, &key)); let builder = TlsAcceptor::builder(identity); let builder = p!(builder.build()); @@ -497,7 +497,7 @@ fn two_servers() { let keys2 = test_cert_gen::gen_keys(); let cert = keys2.server.cert_and_key.cert.to_pem().into_bytes(); - let key = key_to_pem(keys2.server.cert_and_key.key.get_der()).into_bytes(); + let key = rsa_to_pkcs8(&key_to_pem(keys2.server.cert_and_key.key.get_der())).into_bytes(); let identity = p!(Identity::from_pkcs8(&cert, &key)); let builder = TlsAcceptor::builder(identity); let builder = p!(builder.build()); @@ -552,3 +552,11 @@ fn key_to_pem(der: &[u8]) -> String { contents: der.to_owned(), }) } + +fn rsa_to_pkcs8(pem: &str) -> String { + use rsa::{pkcs1::FromRsaPrivateKey, pkcs8::ToPrivateKey, RsaPrivateKey}; + let pkey = RsaPrivateKey::from_pkcs1_pem(pem).unwrap(); + let pkcs8_pem = pkey.to_pkcs8_pem().unwrap(); + let pkcs8_pem: &str = pkcs8_pem.as_ref(); + pkcs8_pem.to_owned() +} From 93bf66e4f881dd9be8a7af42f9d4c256973bf1de Mon Sep 17 00:00:00 2001 From: kazk Date: Fri, 10 Dec 2021 21:54:35 -0800 Subject: [PATCH 12/14] Only accept PKCS#8 keys --- src/imp/openssl.rs | 7 +++++++ src/imp/schannel.rs | 4 ++++ src/imp/security_framework.rs | 4 ++++ src/test.rs | 10 ++++++++++ 4 files changed, 25 insertions(+) diff --git a/src/imp/openssl.rs b/src/imp/openssl.rs index 22fbb249..389caa5e 100644 --- a/src/imp/openssl.rs +++ b/src/imp/openssl.rs @@ -117,6 +117,7 @@ pub enum Error { Normal(ErrorStack), Ssl(ssl::Error, X509VerifyResult), EmptyChain, + NotPkcs8, } impl error::Error for Error { @@ -125,6 +126,7 @@ impl error::Error for Error { Error::Normal(ref e) => error::Error::source(e), Error::Ssl(ref e, _) => error::Error::source(e), Error::EmptyChain => None, + Error::NotPkcs8 => None, } } } @@ -139,6 +141,7 @@ impl fmt::Display for Error { fmt, "at least one certificate must be provided to create an identity" ), + Error::NotPkcs8 => write!(fmt, "expected PKCS#8 PEM"), } } } @@ -171,6 +174,10 @@ impl Identity { } pub fn from_pkcs8(buf: &[u8], key: &[u8]) -> Result { + if !key.starts_with(b"-----BEGIN PRIVATE KEY-----") { + return Err(Error::NotPkcs8); + } + let pkey = PKey::private_key_from_pem(key)?; let mut cert_chain = X509::stack_from_pem(buf)?.into_iter(); let cert = cert_chain.next().ok_or(Error::EmptyChain)?; diff --git a/src/imp/schannel.rs b/src/imp/schannel.rs index 285b2b6d..62e5042f 100644 --- a/src/imp/schannel.rs +++ b/src/imp/schannel.rs @@ -96,6 +96,10 @@ impl Identity { } pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result { + if !key.starts_with(b"-----BEGIN PRIVATE KEY-----") { + return Err(io::Error::new(io::ErrorKind::InvalidInput, "not a PKCS#8 key").into()); + } + let mut store = Memory::new()?.into_store(); let mut cert_iter = pem::PemBlock::new(pem).into_iter(); let leaf = cert_iter.next().ok_or_else(|| { diff --git a/src/imp/security_framework.rs b/src/imp/security_framework.rs index f133903f..6dba7a85 100644 --- a/src/imp/security_framework.rs +++ b/src/imp/security_framework.rs @@ -85,6 +85,10 @@ pub struct Identity { impl Identity { pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result { + if !key.starts_with(b"-----BEGIN PRIVATE KEY-----") { + return Err(Error(base::Error::from(errSecParam))); + } + let dir = TempDir::new().map_err(|_| Error(base::Error::from(errSecIO)))?; let keychain = keychain::CreateOptions::new() .password("password") diff --git a/src/test.rs b/src/test.rs index 96d7316d..f8b4c9f5 100644 --- a/src/test.rs +++ b/src/test.rs @@ -356,6 +356,16 @@ fn import_same_identity_multiple_times() { let _ = p!(Identity::from_pkcs8(&cert, &key)); } +#[test] +fn from_pkcs8_rejects_rsa_key() { + let keys = test_cert_gen::keys(); + let cert = keys.server.cert_and_key.cert.to_pem().into_bytes(); + let rsa_key = key_to_pem(keys.server.cert_and_key.key.get_der()); + assert!(Identity::from_pkcs8(&cert, rsa_key.as_bytes()).is_err()); + let pkcs8_key = rsa_to_pkcs8(&rsa_key); + assert!(Identity::from_pkcs8(&cert, pkcs8_key.as_bytes()).is_ok()); +} + #[test] fn shutdown() { let keys = test_cert_gen::keys(); From 2a720f6c360489c60a34e1bcfba7d50497a8ba33 Mon Sep 17 00:00:00 2001 From: kazk Date: Sat, 11 Dec 2021 01:57:53 -0800 Subject: [PATCH 13/14] Test `from_pkcs8` without new dev dependencies --- Cargo.toml | 2 -- src/lib.rs | 2 -- src/test.rs | 35 ++++++++++++++++++----------------- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b3d7ddb5..105ad6c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,5 @@ openssl-probe = "0.1" openssl-src = { version = "300.0.3", optional = true } [dev-dependencies] -pem = "1.0" -rsa = { version = "0.5.0", features = ["alloc", "pem", "std"] } tempfile = "3.0" test-cert-gen = "0.7" diff --git a/src/lib.rs b/src/lib.rs index 13c70b54..14dabb7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,8 +123,6 @@ mod imp; #[cfg(test)] mod test; -#[cfg(test)] -extern crate rsa; /// A typedef of the result-type returned by many methods. pub type Result = result::Result; diff --git a/src/test.rs b/src/test.rs index f8b4c9f5..d29f0d26 100644 --- a/src/test.rs +++ b/src/test.rs @@ -351,7 +351,7 @@ fn import_same_identity_multiple_times() { )); let cert = keys.server.cert_and_key.cert.to_pem().into_bytes(); - let key = rsa_to_pkcs8(&key_to_pem(keys.server.cert_and_key.key.get_der())).into_bytes(); + let key = rsa_to_pkcs8(&keys.server.cert_and_key.key.to_pem_incorrect()).into_bytes(); let _ = p!(Identity::from_pkcs8(&cert, &key)); let _ = p!(Identity::from_pkcs8(&cert, &key)); } @@ -360,7 +360,7 @@ fn import_same_identity_multiple_times() { fn from_pkcs8_rejects_rsa_key() { let keys = test_cert_gen::keys(); let cert = keys.server.cert_and_key.cert.to_pem().into_bytes(); - let rsa_key = key_to_pem(keys.server.cert_and_key.key.get_der()); + let rsa_key = keys.server.cert_and_key.key.to_pem_incorrect(); assert!(Identity::from_pkcs8(&cert, rsa_key.as_bytes()).is_err()); let pkcs8_key = rsa_to_pkcs8(&rsa_key); assert!(Identity::from_pkcs8(&cert, pkcs8_key.as_bytes()).is_ok()); @@ -439,7 +439,7 @@ fn alpn_google_none() { fn server_pkcs8() { let keys = test_cert_gen::keys(); let cert = keys.server.cert_and_key.cert.to_pem().into_bytes(); - let key = rsa_to_pkcs8(&key_to_pem(keys.server.cert_and_key.key.get_der())).into_bytes(); + let key = rsa_to_pkcs8(&keys.server.cert_and_key.key.to_pem_incorrect()).into_bytes(); let ident = Identity::from_pkcs8(&cert, &key).unwrap(); let ident2 = ident.clone(); @@ -486,7 +486,7 @@ fn server_pkcs8() { fn two_servers() { let keys1 = test_cert_gen::gen_keys(); let cert = keys1.server.cert_and_key.cert.to_pem().into_bytes(); - let key = rsa_to_pkcs8(&key_to_pem(keys1.server.cert_and_key.key.get_der())).into_bytes(); + let key = rsa_to_pkcs8(&keys1.server.cert_and_key.key.to_pem_incorrect()).into_bytes(); let identity = p!(Identity::from_pkcs8(&cert, &key)); let builder = TlsAcceptor::builder(identity); let builder = p!(builder.build()); @@ -507,7 +507,7 @@ fn two_servers() { let keys2 = test_cert_gen::gen_keys(); let cert = keys2.server.cert_and_key.cert.to_pem().into_bytes(); - let key = rsa_to_pkcs8(&key_to_pem(keys2.server.cert_and_key.key.get_der())).into_bytes(); + let key = rsa_to_pkcs8(&keys2.server.cert_and_key.key.to_pem_incorrect()).into_bytes(); let identity = p!(Identity::from_pkcs8(&cert, &key)); let builder = TlsAcceptor::builder(identity); let builder = p!(builder.build()); @@ -556,17 +556,18 @@ fn two_servers() { p!(j2.join()); } -fn key_to_pem(der: &[u8]) -> String { - pem::encode(&pem::Pem { - tag: "RSA PRIVATE KEY".to_owned(), - contents: der.to_owned(), - }) -} - fn rsa_to_pkcs8(pem: &str) -> String { - use rsa::{pkcs1::FromRsaPrivateKey, pkcs8::ToPrivateKey, RsaPrivateKey}; - let pkey = RsaPrivateKey::from_pkcs1_pem(pem).unwrap(); - let pkcs8_pem = pkey.to_pkcs8_pem().unwrap(); - let pkcs8_pem: &str = pkcs8_pem.as_ref(); - pkcs8_pem.to_owned() + let mut child = Command::new("openssl") + .arg("pkcs8") + .arg("-topk8") + .arg("-nocrypt") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .unwrap(); + { + let child_stdin = child.stdin.as_mut().unwrap(); + child_stdin.write_all(pem.as_bytes()).unwrap(); + } + String::from_utf8(child.wait_with_output().unwrap().stdout).unwrap() } From 658800ee8ea2e0ece153a56d603c85a07d5a6149 Mon Sep 17 00:00:00 2001 From: kazk Date: Sun, 12 Dec 2021 19:41:09 -0800 Subject: [PATCH 14/14] Use random password --- src/imp/security_framework.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/imp/security_framework.rs b/src/imp/security_framework.rs index 6dba7a85..5a89dfa8 100644 --- a/src/imp/security_framework.rs +++ b/src/imp/security_framework.rs @@ -7,6 +7,7 @@ use self::security_framework::base; use self::security_framework::certificate::SecCertificate; use self::security_framework::identity::SecIdentity; use self::security_framework::import_export::{ImportedIdentity, Pkcs12ImportOptions}; +use self::security_framework::random::SecRandom; use self::security_framework::secure_transport::{ self, ClientBuilder, SslConnectionType, SslContext, SslProtocol, SslProtocolSide, }; @@ -91,7 +92,7 @@ impl Identity { let dir = TempDir::new().map_err(|_| Error(base::Error::from(errSecIO)))?; let keychain = keychain::CreateOptions::new() - .password("password") + .password(&random_password()?) .create(dir.path().join("identity.keychain"))?; let mut items = SecItems::default(); @@ -180,6 +181,19 @@ impl Identity { } } +fn random_password() -> Result { + use std::fmt::Write; + let mut bytes = [0_u8; 10]; + SecRandom::default() + .copy_bytes(&mut bytes) + .map_err(|_| Error(base::Error::from(errSecIO)))?; + let mut s = String::with_capacity(2 * bytes.len()); + for byte in bytes { + write!(s, "{:02X}", byte).map_err(|_| Error(base::Error::from(errSecIO)))?; + } + Ok(s) +} + #[derive(Clone)] pub struct Certificate(SecCertificate);