diff --git a/Cargo.toml b/Cargo.toml index 9a742d24e4b..e6449b64283 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,20 @@ ring = { version = "0.13.2", features = ["rsa_signing"] } webpki = "0.18.1" sct = "0.4" +[patch.crates-io] +webpki = { git = "https://github.com/mesalock-linux/webpki", branch = "develop", default-features = true } +sct = { git = "https://github.com/mesalock-linux/sct.rs", branch = "develop", default-features = false } + [features] -default = ["logging"] +default=["logging", "aesgcm", "chachapoly", "tls13", "x25519", "ecdh", "ecdsa"] logging = ["log"] dangerous_configuration = [] +aesgcm = [] +chachapoly = [] +tls13 = [] +x25519 = [] +ecdh = [] +ecdsa = ["sct/ecdsa"] quic = [] [dev-dependencies] @@ -35,6 +45,11 @@ ct-logs = "0.4" regex = "1.0" vecio = "0.1" +[profile.release] +opt-level = "z" +lto = true +panic = "abort" + [[example]] name = "bogo_shim" path = "examples/internal/bogo_shim.rs" diff --git a/src/cipher.rs b/src/cipher.rs index d18b57e527e..0c6fd401235 100644 --- a/src/cipher.rs +++ b/src/cipher.rs @@ -88,6 +88,7 @@ pub fn new_tls12(scs: &'static SupportedCipherSuite, let aead_alg = scs.get_aead_alg(); match scs.bulk { + #[cfg(feature = "aesgcm")] BulkAlgorithm::AES_128_GCM | BulkAlgorithm::AES_256_GCM => { (Box::new(GCMMessageDecrypter::new(aead_alg, @@ -98,7 +99,7 @@ pub fn new_tls12(scs: &'static SupportedCipherSuite, write_iv, explicit_nonce_offs))) } - + #[cfg(feature = "chachapoly")] BulkAlgorithm::CHACHA20_POLY1305 => { (Box::new(ChaCha20Poly1305MessageDecrypter::new(aead_alg, read_key, @@ -110,6 +111,7 @@ pub fn new_tls12(scs: &'static SupportedCipherSuite, } } +#[cfg(feature = "tls13")] pub fn new_tls13_read(scs: &'static SupportedCipherSuite, secret: &[u8]) -> Box { let hash = scs.get_hash(); @@ -120,6 +122,7 @@ pub fn new_tls13_read(scs: &'static SupportedCipherSuite, Box::new(TLS13MessageDecrypter::new(aead_alg, &key, &iv)) } +#[cfg(feature = "tls13")] pub fn new_tls13_write(scs: &'static SupportedCipherSuite, secret: &[u8]) -> Box { let hash = scs.get_hash(); @@ -131,6 +134,7 @@ pub fn new_tls13_write(scs: &'static SupportedCipherSuite, } /// A `MessageEncrypter` for AES-GCM AEAD ciphersuites. TLS 1.2 only. +#[cfg(feature = "aesgcm")] pub struct GCMMessageEncrypter { alg: &'static ring::aead::Algorithm, enc_key: ring::aead::SealingKey, @@ -139,14 +143,18 @@ pub struct GCMMessageEncrypter { } /// A `MessageDecrypter` for AES-GCM AEAD ciphersuites. TLS1.2 only. +#[cfg(feature = "aesgcm")] pub struct GCMMessageDecrypter { dec_key: ring::aead::OpeningKey, dec_salt: [u8; 4], } +#[cfg(feature = "aesgcm")] const GCM_EXPLICIT_NONCE_LEN: usize = 8; +#[cfg(feature = "aesgcm")] const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16; +#[cfg(feature = "aesgcm")] impl MessageDecrypter for GCMMessageDecrypter { fn decrypt(&self, mut msg: Message, seq: u64) -> Result { let payload = msg.take_opaque_payload() @@ -186,6 +194,7 @@ impl MessageDecrypter for GCMMessageDecrypter { } } +#[cfg(feature = "aesgcm")] impl MessageEncrypter for GCMMessageEncrypter { fn encrypt(&self, msg: BorrowMessage, seq: u64) -> Result { // The GCM nonce is constructed from a 32-bit 'salt' derived @@ -223,6 +232,7 @@ impl MessageEncrypter for GCMMessageEncrypter { } } +#[cfg(feature = "aesgcm")] impl GCMMessageEncrypter { fn new(alg: &'static ring::aead::Algorithm, enc_key: &[u8], @@ -245,6 +255,7 @@ impl GCMMessageEncrypter { } } +#[cfg(feature = "aesgcm")] impl GCMMessageDecrypter { fn new(alg: &'static ring::aead::Algorithm, dec_key: &[u8], @@ -260,18 +271,21 @@ impl GCMMessageDecrypter { } } +#[cfg(feature = "tls13")] struct TLS13MessageEncrypter { alg: &'static ring::aead::Algorithm, enc_key: ring::aead::SealingKey, enc_offset: [u8; 12], } +#[cfg(feature = "tls13")] struct TLS13MessageDecrypter { alg: &'static ring::aead::Algorithm, dec_key: ring::aead::OpeningKey, dec_offset: [u8; 12], } +#[cfg(feature = "tls13")] fn unpad_tls13(v: &mut Vec) -> ContentType { loop { match v.pop() { @@ -284,6 +298,7 @@ fn unpad_tls13(v: &mut Vec) -> ContentType { } } +#[cfg(feature = "tls13")] const TLS13_AAD_SIZE: usize = 1 + 2 + 2; fn make_tls13_aad(len: usize, out: &mut [u8]) { out[0] = 0x17; // ContentType::ApplicationData @@ -293,6 +308,7 @@ fn make_tls13_aad(len: usize, out: &mut [u8]) { out[4] = len as u8; } +#[cfg(feature = "tls13")] impl MessageEncrypter for TLS13MessageEncrypter { fn encrypt(&self, msg: BorrowMessage, seq: u64) -> Result { let mut nonce = [0u8; 12]; @@ -320,6 +336,7 @@ impl MessageEncrypter for TLS13MessageEncrypter { } } +#[cfg(feature = "tls13")] impl MessageDecrypter for TLS13MessageDecrypter { fn decrypt(&self, mut msg: Message, seq: u64) -> Result { let mut nonce = [0u8; 12]; @@ -364,6 +381,7 @@ impl MessageDecrypter for TLS13MessageDecrypter { } } +#[cfg(feature = "tls13")] impl TLS13MessageEncrypter { fn new(alg: &'static ring::aead::Algorithm, enc_key: &[u8], @@ -379,6 +397,7 @@ impl TLS13MessageEncrypter { } } +#[cfg(feature = "tls13")] impl TLS13MessageDecrypter { fn new(alg: &'static ring::aead::Algorithm, dec_key: &[u8], @@ -397,6 +416,7 @@ impl TLS13MessageDecrypter { /// The RFC7905/RFC7539 ChaCha20Poly1305 construction. /// This implementation does the AAD construction required in TLS1.2. /// TLS1.3 uses `TLS13MessageEncrypter`. +#[cfg(feature = "chachapoly")] pub struct ChaCha20Poly1305MessageEncrypter { alg: &'static ring::aead::Algorithm, enc_key: ring::aead::SealingKey, @@ -406,11 +426,13 @@ pub struct ChaCha20Poly1305MessageEncrypter { /// The RFC7905/RFC7539 ChaCha20Poly1305 construction. /// This implementation does the AAD construction required in TLS1.2. /// TLS1.3 uses `TLS13MessageDecrypter`. +#[cfg(feature = "chachapoly")] pub struct ChaCha20Poly1305MessageDecrypter { dec_key: ring::aead::OpeningKey, dec_offset: [u8; 12], } +#[cfg(feature = "chachapoly")] impl ChaCha20Poly1305MessageEncrypter { fn new(alg: &'static ring::aead::Algorithm, enc_key: &[u8], @@ -426,6 +448,7 @@ impl ChaCha20Poly1305MessageEncrypter { } } +#[cfg(feature = "chachapoly")] impl ChaCha20Poly1305MessageDecrypter { fn new(alg: &'static ring::aead::Algorithm, dec_key: &[u8], @@ -440,8 +463,10 @@ impl ChaCha20Poly1305MessageDecrypter { } } +#[cfg(feature = "chachapoly")] const CHACHAPOLY1305_OVERHEAD: usize = 16; +#[cfg(feature = "chachapoly")] impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter { fn decrypt(&self, mut msg: Message, seq: u64) -> Result { let payload = msg.take_opaque_payload() @@ -478,6 +503,7 @@ impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter { } } +#[cfg(feature = "chachapoly")] impl MessageEncrypter for ChaCha20Poly1305MessageEncrypter { fn encrypt(&self, msg: BorrowMessage, seq: u64) -> Result { let mut nonce = [0u8; 12]; diff --git a/src/client/common.rs b/src/client/common.rs index 7d9cf3c86cf..4bb69c422d0 100644 --- a/src/client/common.rs +++ b/src/client/common.rs @@ -29,6 +29,7 @@ impl ServerCertDetails { } } + #[cfg(feature = "tls13")] pub fn take_chain(&mut self) -> CertificatePayload { mem::replace(&mut self.cert_chain, Vec::new()) } @@ -99,6 +100,7 @@ impl ClientHelloDetails { .map(|idx| self.offered_key_shares.remove(idx)) } + #[cfg(feature = "tls13")] pub fn find_key_share_and_discard_others(&mut self, group: NamedGroup) -> Option { match self.find_key_share(group) { diff --git a/src/client/hs.rs b/src/client/hs.rs index f16fde83940..2b26375c6c0 100644 --- a/src/client/hs.rs +++ b/src/client/hs.rs @@ -76,6 +76,7 @@ fn illegal_param(sess: &mut ClientSessionImpl, why: &str) -> TLSError { TLSError::PeerMisbehavedError(why.to_string()) } +#[cfg(feature = "tls13")] fn check_aligned_handshake(sess: &mut ClientSessionImpl) -> Result<(), TLSError> { if !sess.common.handshake_joiner.is_empty() { Err(illegal_param(sess, "keys changed with pending hs fragment")) @@ -116,6 +117,7 @@ fn find_kx_hint(sess: &mut ClientSessionImpl, dns_name: webpki::DNSNameRef) -> O maybe_value.and_then(|enc| NamedGroup::read_bytes(&enc)) } +#[cfg(feature = "tls13")] fn save_kx_hint(sess: &mut ClientSessionImpl, dns_name: webpki::DNSNameRef, group: NamedGroup) { let key = persist::ClientSessionKey::hint_for_dns_name(dns_name); @@ -248,7 +250,10 @@ fn emit_client_hello_for_retry(sess: &mut ClientSessionImpl, }; let support_tls12 = sess.config.supports_version(ProtocolVersion::TLSv1_2); + #[cfg(feature = "tls13")] let support_tls13 = sess.config.supports_version(ProtocolVersion::TLSv1_3); + #[cfg(not(feature = "tls13"))] + let support_tls13 = false; let mut supported_versions = Vec::new(); if support_tls13 { @@ -467,6 +472,7 @@ fn emit_client_hello_for_retry(sess: &mut ClientSessionImpl, } // Extensions we expect in plaintext in the ServerHello. +#[cfg(feature = "tls13")] static ALLOWED_PLAINTEXT_EXTS: &'static [ExtensionType] = &[ ExtensionType::KeyShare, ExtensionType::PreSharedKey, @@ -475,6 +481,7 @@ static ALLOWED_PLAINTEXT_EXTS: &'static [ExtensionType] = &[ // Only the intersection of things we offer, and those disallowed // in TLS1.3 +#[cfg(feature = "tls13")] static DISALLOWED_TLS13_EXTS: &'static [ExtensionType] = &[ ExtensionType::ECPointFormats, ExtensionType::SessionTicket, @@ -482,6 +489,7 @@ static DISALLOWED_TLS13_EXTS: &'static [ExtensionType] = &[ ExtensionType::ExtendedMasterSecret, ]; +#[cfg(feature = "tls13")] fn validate_server_hello_tls13(sess: &mut ClientSessionImpl, server_hello: &ServerHelloPayload) -> Result<(), TLSError> { @@ -509,6 +517,7 @@ fn process_alpn_protocol(sess: &mut ClientSessionImpl, } impl ExpectServerHello { + #[cfg(feature = "tls13")] fn start_handshake_traffic(&mut self, sess: &mut ClientSessionImpl, server_hello: &ServerHelloPayload) @@ -591,6 +600,7 @@ impl ExpectServerHello { Ok(()) } + #[cfg(feature = "tls13")] fn into_expect_tls13_encrypted_extensions(self) -> NextState { Box::new(ExpectTLS13EncryptedExtensions { handshake: self.handshake, @@ -739,10 +749,13 @@ impl State for ExpectServerHello { // For TLS1.3, start message encryption using // handshake_traffic_secret. if sess.common.is_tls13() { - validate_server_hello_tls13(sess, server_hello)?; - self.start_handshake_traffic(sess, server_hello)?; - emit_fake_ccs(&mut self.handshake, sess); - return Ok(self.into_expect_tls13_encrypted_extensions()); + #[cfg(feature = "tls13")] + { + validate_server_hello_tls13(sess, server_hello)?; + self.start_handshake_traffic(sess, server_hello)?; + emit_fake_ccs(&mut self.handshake, sess); + return Ok(self.into_expect_tls13_encrypted_extensions()); + } } // TLS1.2 only from here-on @@ -938,6 +951,7 @@ impl State for ExpectServerHelloOrHelloRetryRequest { } } +#[cfg(feature = "tls13")] fn validate_encrypted_extensions(sess: &mut ClientSessionImpl, hello: &ClientHelloDetails, exts: &EncryptedExtensions) -> Result<(), TLSError> { @@ -965,12 +979,14 @@ fn validate_encrypted_extensions(sess: &mut ClientSessionImpl, Ok(()) } +#[cfg(feature = "tls13")] struct ExpectTLS13EncryptedExtensions { handshake: HandshakeDetails, server_cert: ServerCertDetails, hello: ClientHelloDetails, } +#[cfg(feature = "tls13")] impl ExpectTLS13EncryptedExtensions { fn into_expect_tls13_finished_resume(self, certv: verify::ServerCertVerified, @@ -991,6 +1007,7 @@ impl ExpectTLS13EncryptedExtensions { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13EncryptedExtensions { fn check_message(&self, m: &Message) -> Result<(), TLSError> { check_handshake_message(m, &[HandshakeType::EncryptedExtensions]) @@ -1052,12 +1069,14 @@ fn sct_list_is_invalid(scts: &SCTList) -> bool { scts.iter().any(|sct| sct.0.is_empty()) } +#[cfg(feature = "tls13")] struct ExpectTLS13Certificate { handshake: HandshakeDetails, server_cert: ServerCertDetails, client_auth: Option, } +#[cfg(feature = "tls13")] impl ExpectTLS13Certificate { fn into_expect_tls13_certificate_verify(self) -> NextState { Box::new(ExpectTLS13CertificateVerify { @@ -1068,6 +1087,7 @@ impl ExpectTLS13Certificate { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13Certificate { fn check_message(&self, m: &Message) -> Result<(), TLSError> { check_handshake_message(m, &[HandshakeType::Certificate]) @@ -1226,11 +1246,13 @@ impl State for ExpectTLS12CertificateStatusOrServerKX { } } +#[cfg(feature = "tls13")] struct ExpectTLS13CertificateOrCertReq { handshake: HandshakeDetails, server_cert: ServerCertDetails, } +#[cfg(feature = "tls13")] impl ExpectTLS13CertificateOrCertReq { fn into_expect_tls13_certificate(self) -> NextState { Box::new(ExpectTLS13Certificate { @@ -1248,6 +1270,7 @@ impl ExpectTLS13CertificateOrCertReq { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13CertificateOrCertReq { fn check_message(&self, m: &Message) -> Result<(), TLSError> { check_handshake_message(m, @@ -1312,12 +1335,14 @@ impl State for ExpectTLS12ServerKX { } // --- TLS1.3 CertificateVerify --- +#[cfg(feature = "tls13")] struct ExpectTLS13CertificateVerify { handshake: HandshakeDetails, server_cert: ServerCertDetails, client_auth: Option, } +#[cfg(feature = "tls13")] impl ExpectTLS13CertificateVerify { fn into_expect_tls13_finished(self, certv: verify::ServerCertVerified, @@ -1347,6 +1372,7 @@ fn send_cert_error_alert(sess: &mut ClientSessionImpl, err: TLSError) -> TLSErro err } +#[cfg(feature = "tls13")] impl State for ExpectTLS13CertificateVerify { fn check_message(&self, m: &Message) -> Result<(), TLSError> { check_handshake_message(m, &[HandshakeType::CertificateVerify]) @@ -1558,11 +1584,13 @@ impl State for ExpectTLS12CertificateRequest { // TLS1.3 version of the above. We then move to expecting the server Certificate. // Unfortunately the CertificateRequest type changed in an annoying way in TLS1.3. +#[cfg(feature = "tls13")] struct ExpectTLS13CertificateRequest { handshake: HandshakeDetails, server_cert: ServerCertDetails, } +#[cfg(feature = "tls13")] impl ExpectTLS13CertificateRequest { fn into_expect_tls13_certificate(self, client_auth: ClientAuthDetails) -> NextState { Box::new(ExpectTLS13Certificate { @@ -1573,6 +1601,7 @@ impl ExpectTLS13CertificateRequest { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13CertificateRequest { fn check_message(&self, m: &Message) -> Result<(), TLSError> { check_handshake_message(m, &[HandshakeType::CertificateRequest]) @@ -1770,9 +1799,13 @@ impl State for ExpectTLS12ServerDone { let sig = &st.server_kx.kx_sig; let scs = sess.common.get_suite_assert(); if scs.sign != sig.scheme.sign() { + #[cfg(feature = "logging")] let error_message = format!("peer signed kx with wrong algorithm (got {:?} expect {:?})", sig.scheme.sign(), scs.sign); + #[cfg(not(feature = "logging"))] + let error_message = + format!("peer signed kx with wrong algorithm"); return Err(TLSError::PeerMisbehavedError(error_message)); } @@ -1956,6 +1989,7 @@ fn save_session(handshake: &mut HandshakeDetails, } } +#[cfg(feature = "tls13")] fn emit_certificate_tls13(client_auth: &mut ClientAuthDetails, sess: &mut ClientSessionImpl) { let context = client_auth.auth_context @@ -1985,6 +2019,7 @@ fn emit_certificate_tls13(client_auth: &mut ClientAuthDetails, sess.common.send_msg(m, true); } +#[cfg(feature = "tls13")] fn emit_certverify_tls13(client_auth: &mut ClientAuthDetails, sess: &mut ClientSessionImpl) -> Result<(), TLSError> { if client_auth.signer.is_none() { @@ -2016,6 +2051,7 @@ fn emit_certverify_tls13(client_auth: &mut ClientAuthDetails, Ok(()) } +#[cfg(feature = "tls13")] fn emit_finished_tls13(sess: &mut ClientSessionImpl) { let handshake_hash = sess.common.hs_transcript.get_current_hash(); let verify_data = sess.common @@ -2036,6 +2072,7 @@ fn emit_finished_tls13(sess: &mut ClientSessionImpl) { sess.common.send_msg(m, true); } +#[cfg(feature = "tls13")] fn emit_end_of_early_data_tls13(sess: &mut ClientSessionImpl) { let m = Message { typ: ContentType::Handshake, @@ -2050,6 +2087,7 @@ fn emit_end_of_early_data_tls13(sess: &mut ClientSessionImpl) { sess.common.send_msg(m, true); } +#[cfg(feature = "tls13")] struct ExpectTLS13Finished { handshake: HandshakeDetails, client_auth: Option, @@ -2057,6 +2095,7 @@ struct ExpectTLS13Finished { sig_verified: verify::HandshakeSignatureValid, } +#[cfg(feature = "tls13")] impl ExpectTLS13Finished { fn into_expect_tls13_traffic(self, fin: verify::FinishedMessageVerified) -> NextState { @@ -2069,6 +2108,7 @@ impl ExpectTLS13Finished { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13Finished { fn check_message(&self, m: &Message) -> CheckResult { check_handshake_message(m, &[HandshakeType::Finished]) @@ -2254,6 +2294,7 @@ impl State for ExpectTLS12Traffic { // -- Traffic transit state (TLS1.3) -- // In this state we can be sent tickets, keyupdates, // and application data. +#[cfg(feature = "tls13")] struct ExpectTLS13Traffic { handshake: HandshakeDetails, _cert_verified: verify::ServerCertVerified, @@ -2261,6 +2302,7 @@ struct ExpectTLS13Traffic { _fin_verified: verify::FinishedMessageVerified, } +#[cfg(feature = "tls13")] impl ExpectTLS13Traffic { fn handle_new_ticket_tls13(&mut self, sess: &mut ClientSessionImpl, m: Message) -> Result<(), TLSError> { let nst = extract_handshake!(m, HandshakePayload::NewSessionTicketTLS13).unwrap(); @@ -2304,6 +2346,7 @@ impl ExpectTLS13Traffic { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13Traffic { fn check_message(&self, m: &Message) -> Result<(), TLSError> { check_message(m, diff --git a/src/error.rs b/src/error.rs index dda0a8092fb..432efdd637d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,7 +5,8 @@ use webpki; use sct; /// rustls reports protocol errors using this type. -#[derive(Debug, PartialEq, Clone)] +#[derive(PartialEq, Clone)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum TLSError { /// We received a TLS message that isn't valid right now. /// `expect_types` lists the message types we can expect right now. @@ -75,6 +76,21 @@ pub enum TLSError { PeerSentOversizedRecord, } +#[cfg(not(feature = "logging"))] +impl fmt::Debug for TLSError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Error string not enabled") + } +} + +#[cfg(not(feature = "logging"))] +impl fmt::Display for TLSError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Error string not enabled") + } +} + +#[cfg(feature = "logging")] fn join(items: &[T]) -> String { items.iter() .map(|x| format!("{:?}", x)) @@ -82,6 +98,7 @@ fn join(items: &[T]) -> String { .join(" or ") } +#[cfg(feature = "logging")] impl fmt::Display for TLSError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/msgs/alert.rs b/src/msgs/alert.rs index dd24bf4b03a..7bc3cf54c95 100644 --- a/src/msgs/alert.rs +++ b/src/msgs/alert.rs @@ -1,7 +1,7 @@ use msgs::enums::{AlertLevel, AlertDescription}; use msgs::codec::{Codec, Reader}; -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct AlertMessagePayload { pub level: AlertLevel, pub description: AlertDescription, diff --git a/src/msgs/base.rs b/src/msgs/base.rs index 52b288f0fb1..adb918aaa29 100644 --- a/src/msgs/base.rs +++ b/src/msgs/base.rs @@ -2,7 +2,8 @@ use msgs::codec; use msgs::codec::{Codec, Reader}; use key; /// An externally length'd payload -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, PartialEq)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct Payload(pub Vec); impl Codec for Payload { @@ -46,7 +47,8 @@ impl Codec for key::Certificate { } /// An arbitrary, unknown-content, u24-length-prefixed payload -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, PartialEq)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct PayloadU24(pub Vec); impl PayloadU24 { @@ -74,7 +76,8 @@ impl Codec for PayloadU24 { } /// An arbitrary, unknown-content, u16-length-prefixed payload -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, PartialEq)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct PayloadU16(pub Vec); impl PayloadU16 { @@ -102,7 +105,8 @@ impl Codec for PayloadU16 { } /// An arbitrary, unknown-content, u8-length-prefixed payload -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, PartialEq)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct PayloadU8(pub Vec); impl PayloadU8 { diff --git a/src/msgs/ccs.rs b/src/msgs/ccs.rs index 57c125fdf6f..f70be427875 100644 --- a/src/msgs/ccs.rs +++ b/src/msgs/ccs.rs @@ -1,6 +1,6 @@ use msgs::codec::{Codec, Reader}; -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ChangeCipherSpecPayload; impl Codec for ChangeCipherSpecPayload { diff --git a/src/msgs/codec.rs b/src/msgs/codec.rs index 97ab59d7573..d03a9269367 100644 --- a/src/msgs/codec.rs +++ b/src/msgs/codec.rs @@ -48,6 +48,7 @@ impl<'a> Reader<'a> { } /// Things we can encode and read from a Reader. +#[cfg(feature = "logging")] pub trait Codec: Debug + Sized { /// Encode yourself by appending onto `bytes`. fn encode(&self, bytes: &mut Vec); @@ -71,6 +72,30 @@ pub trait Codec: Debug + Sized { } } +#[cfg(not(feature = "logging"))] +pub trait Codec: Sized { + /// Encode yourself by appending onto `bytes`. + fn encode(&self, bytes: &mut Vec); + + /// Decode yourself by fiddling with the `Reader`. + /// Return Some if it worked, None if not. + fn read(&mut Reader) -> Option; + + /// Convenience function to get the results of `encode()`. + fn get_encoding(&self) -> Vec { + let mut ret = Vec::new(); + self.encode(&mut ret); + ret + } + + /// Read one of these from the front of `bytes` and + /// return it. + fn read_bytes(bytes: &[u8]) -> Option { + let mut rd = Reader::init(bytes); + Self::read(&mut rd) + } +} + // Encoding functions. pub fn decode_u8(bytes: &[u8]) -> Option { Some(bytes[0]) diff --git a/src/msgs/handshake.rs b/src/msgs/handshake.rs index 665cea89d47..2384f65473c 100644 --- a/src/msgs/handshake.rs +++ b/src/msgs/handshake.rs @@ -52,7 +52,8 @@ macro_rules! declare_u16_vec( declare_u16_vec!(VecU16OfPayloadU8, PayloadU8); declare_u16_vec!(VecU16OfPayloadU16, PayloadU16); -#[derive(Debug, PartialEq, Clone)] +#[derive(PartialEq, Clone)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct Random([u8; 32]); static HELLO_RETRY_REQUEST_RANDOM: Random = Random([ @@ -96,6 +97,7 @@ pub struct SessionID { data: [u8; 32], } +#[cfg(feature = "logging")] impl fmt::Debug for SessionID { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut t = f.debug_tuple("SessionID"); @@ -173,7 +175,8 @@ impl SessionID { } } -#[derive(Clone, Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] +#[derive(Clone)] pub struct UnknownExtension { pub typ: ExtensionType, pub payload: Payload, @@ -212,9 +215,25 @@ pub trait SupportedGroups { } impl SupportedGroups for NamedGroups { + #[cfg(all(feature = "x25519", feature = "ecdh"))] fn supported() -> NamedGroups { vec![ NamedGroup::X25519, NamedGroup::secp384r1, NamedGroup::secp256r1 ] } + + #[cfg(all(not(feature = "x25519"), feature = "ecdh"))] + fn supported() -> NamedGroups { + vec![ NamedGroup::secp384r1, NamedGroup::secp256r1 ] + } + + #[cfg(all(feature = "x25519", not(feature = "ecdh")))] + fn supported() -> NamedGroups { + vec![ NamedGroup::X25519 ] + } + + #[cfg(all(not(feature = "x25519"), not(feature = "ecdh")))] + fn supported() -> NamedGroups { + vec![] + } } declare_u16_vec!(SupportedSignatureSchemes, SignatureScheme); @@ -234,6 +253,7 @@ impl DecomposedSignatureScheme for SignatureScheme { SignatureScheme::RSA_PSS_SHA256 | SignatureScheme::RSA_PSS_SHA384 | SignatureScheme::RSA_PSS_SHA512 => SignatureAlgorithm::RSA, + #[cfg(feature = "ecdsa")] SignatureScheme::ECDSA_NISTP256_SHA256 | SignatureScheme::ECDSA_NISTP384_SHA384 | SignatureScheme::ECDSA_NISTP521_SHA512 => SignatureAlgorithm::ECDSA, @@ -242,7 +262,9 @@ impl DecomposedSignatureScheme for SignatureScheme { } fn make(alg: SignatureAlgorithm, hash: HashAlgorithm) -> SignatureScheme { - use msgs::enums::SignatureAlgorithm::{RSA, ECDSA}; + use msgs::enums::SignatureAlgorithm::RSA; + #[cfg(feature = "ecdsa")] + use msgs::enums::SignatureAlgorithm::ECDSA; use msgs::enums::HashAlgorithm::{SHA1, SHA256, SHA384, SHA512}; match (alg, hash) { @@ -250,8 +272,11 @@ impl DecomposedSignatureScheme for SignatureScheme { (RSA, SHA256) => SignatureScheme::RSA_PKCS1_SHA256, (RSA, SHA384) => SignatureScheme::RSA_PKCS1_SHA384, (RSA, SHA512) => SignatureScheme::RSA_PKCS1_SHA512, + #[cfg(feature = "ecdsa")] (ECDSA, SHA256) => SignatureScheme::ECDSA_NISTP256_SHA256, + #[cfg(feature = "ecdsa")] (ECDSA, SHA384) => SignatureScheme::ECDSA_NISTP384_SHA384, + #[cfg(feature = "ecdsa")] (ECDSA, SHA512) => SignatureScheme::ECDSA_NISTP521_SHA512, (_, _) => unreachable!(), } @@ -268,7 +293,9 @@ impl SupportedMandatedSignatureSchemes for SupportedSignatureSchemes { fn supported_verify() -> SupportedSignatureSchemes { vec![ /* FIXME: ECDSA-P521-SHA512 */ + #[cfg(feature = "ecdsa")] SignatureScheme::ECDSA_NISTP384_SHA384, + #[cfg(feature = "ecdsa")] SignatureScheme::ECDSA_NISTP256_SHA256, SignatureScheme::RSA_PSS_SHA512, @@ -285,7 +312,9 @@ impl SupportedMandatedSignatureSchemes for SupportedSignatureSchemes { fn supported_sign_tls13() -> SupportedSignatureSchemes { vec![ + #[cfg(feature = "ecdsa")] SignatureScheme::ECDSA_NISTP384_SHA384, + #[cfg(feature = "ecdsa")] SignatureScheme::ECDSA_NISTP256_SHA256, SignatureScheme::RSA_PSS_SHA512, @@ -295,7 +324,8 @@ impl SupportedMandatedSignatureSchemes for SupportedSignatureSchemes { } } -#[derive(Clone, Debug)] +#[derive(Clone)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum ServerNamePayload { HostName(webpki::DNSName), Unknown(Payload), @@ -324,7 +354,8 @@ impl ServerNamePayload { } } -#[derive(Clone, Debug)] +#[derive(Clone)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ServerName { pub typ: ServerNameType, pub payload: ServerNamePayload, @@ -408,7 +439,8 @@ impl ConvertProtocolNameList for ProtocolNameList { } // --- TLS 1.3 Key shares --- -#[derive(Clone, Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] +#[derive(Clone)] pub struct KeyShareEntry { pub group: NamedGroup, pub payload: PayloadU16, @@ -441,7 +473,8 @@ impl Codec for KeyShareEntry { } // --- TLS 1.3 PresharedKey offers --- -#[derive(Clone, Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] +#[derive(Clone)] pub struct PresharedKeyIdentity { pub identity: PayloadU16, pub obfuscated_ticket_age: u32, @@ -474,7 +507,8 @@ declare_u16_vec!(PresharedKeyIdentities, PresharedKeyIdentity); pub type PresharedKeyBinder = PayloadU8; pub type PresharedKeyBinders = VecU16OfPayloadU8; -#[derive(Clone, Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] +#[derive(Clone)] pub struct PresharedKeyOffer { pub identities: PresharedKeyIdentities, pub binders: PresharedKeyBinders, @@ -507,7 +541,8 @@ impl Codec for PresharedKeyOffer { // --- RFC6066 certificate status request --- type ResponderIDs = VecU16OfPayloadU16; -#[derive(Clone, Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] +#[derive(Clone)] pub struct OCSPCertificateStatusRequest { pub responder_ids: ResponderIDs, pub extensions: PayloadU16, @@ -528,7 +563,8 @@ impl Codec for OCSPCertificateStatusRequest { } } -#[derive(Clone, Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] +#[derive(Clone)] pub enum CertificateStatusRequest { OCSP(OCSPCertificateStatusRequest), Unknown((CertificateStatusType, Payload)) @@ -582,7 +618,8 @@ declare_u8_vec!(PSKKeyExchangeModes, PSKKeyExchangeMode); declare_u16_vec!(KeyShareEntries, KeyShareEntry); declare_u8_vec!(ProtocolVersions, ProtocolVersion); -#[derive(Clone, Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] +#[derive(Clone)] pub enum ClientExtension { ECPointFormats(ECPointFormatList), NamedGroups(NamedGroups), @@ -734,7 +771,119 @@ impl ClientExtension { } } -#[derive(Clone, Debug)] +#[test] +fn can_roundtrip_unknown_client_ext() { + let bytes = [0x12u8, 0x34u8, 0, 3, 1, 2, 3]; + let mut rd = Reader::init(&bytes); + let ext = ClientExtension::read(&mut rd) + .unwrap(); + + println!("{:?}", ext); + assert_eq!(ext.get_type(), ExtensionType::Unknown(0x1234)); + assert_eq!(bytes.to_vec(), ext.get_encoding()); +} + +#[test] +fn can_roundtrip_single_sni() { + let bytes = [ + 0, 0, + 0, 7, + 0, 5, + 0, 0, 2, 0x6c, 0x6f + ]; + let mut rd = Reader::init(&bytes); + let ext = ClientExtension::read(&mut rd) + .unwrap(); + println!("{:?}", ext); + + assert_eq!(ext.get_type(), ExtensionType::ServerName); + assert_eq!(bytes.to_vec(), ext.get_encoding()); +} + +#[test] +fn can_roundtrip_multiname_sni() { + let bytes = [ + 0, 0, + 0, 12, + 0, 10, + 0, 0, 2, 0x68, 0x69, + 0, 0, 2, 0x6c, 0x6f + ]; + let mut rd = Reader::init(&bytes); + let ext = ClientExtension::read(&mut rd) + .unwrap(); + println!("{:?}", ext); + + assert_eq!(ext.get_type(), ExtensionType::ServerName); + assert_eq!(bytes.to_vec(), ext.get_encoding()); + match ext { + ClientExtension::ServerName(req) => { + assert_eq!(2, req.len()); + + let dns_name_str: &str = req.get_hostname().unwrap().into(); + assert_eq!(dns_name_str, "hi"); + + assert_eq!(req[0].typ, ServerNameType::HostName); + assert_eq!(req[1].typ, ServerNameType::HostName); + } + _ => unreachable!() + } +} + +#[test] +fn can_roundtrip_multi_proto() { + let bytes = [ + 0, 16, + 0, 8, + 0, 6, + 2, 0x68, 0x69, + 2, 0x6c, 0x6f + ]; + let mut rd = Reader::init(&bytes); + let ext = ClientExtension::read(&mut rd) + .unwrap(); + println!("{:?}", ext); + + assert_eq!(ext.get_type(), ExtensionType::ALProtocolNegotiation); + assert_eq!(bytes.to_vec(), ext.get_encoding()); + match ext { + ClientExtension::Protocols(prot) => { + assert_eq!(2, prot.len()); + assert_eq!(vec!["hi".to_string(), "lo".to_string()], + prot.to_strings()); + assert_eq!(prot.as_single_string(), None); + } + _ => unreachable!() + } +} + +#[test] +fn can_roundtrip_single_proto() { + let bytes = [ + 0, 16, + 0, 5, + 0, 3, + 2, 0x68, 0x69, + ]; + let mut rd = Reader::init(&bytes); + let ext = ClientExtension::read(&mut rd) + .unwrap(); + println!("{:?}", ext); + + assert_eq!(ext.get_type(), ExtensionType::ALProtocolNegotiation); + assert_eq!(bytes.to_vec(), ext.get_encoding()); + match ext { + ClientExtension::Protocols(prot) => { + assert_eq!(1, prot.len()); + assert_eq!(vec!["hi".to_string()], prot.to_strings()); + assert_eq!(prot.as_single_string(), Some("hi")); + } + _ => unreachable!() + } +} + +#[cfg_attr(feature = "logging", derive(Debug))] +#[derive(Clone)] pub enum ServerExtension { ECPointFormats(ECPointFormatList), ServerNameAck, @@ -857,7 +1006,7 @@ impl ServerExtension { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ClientHelloPayload { pub client_version: ProtocolVersion, pub random: Random, @@ -1057,7 +1206,7 @@ impl ClientHelloPayload { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum HelloRetryExtension { KeyShare(NamedGroup), Cookie(PayloadU16), @@ -1112,7 +1261,7 @@ impl Codec for HelloRetryExtension { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct HelloRetryRequest { pub legacy_version: ProtocolVersion, pub session_id: SessionID, @@ -1205,7 +1354,7 @@ impl HelloRetryRequest { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ServerHelloPayload { pub legacy_version: ProtocolVersion, pub random: Random, @@ -1322,7 +1471,7 @@ impl Codec for CertificatePayload { // That's annoying. It means the parsing is not // context-free any more. -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum CertificateExtension { CertificateStatus(CertificateStatus), SignedCertificateTimestamp(SCTList), @@ -1395,7 +1544,7 @@ impl Codec for CertificateExtension { declare_u16_vec!(CertificateExtensions, CertificateExtension); -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct CertificateEntry { pub cert: key::Certificate, pub exts: CertificateExtensions, @@ -1462,7 +1611,7 @@ impl CertificateEntry { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct CertificatePayloadTLS13 { pub context: PayloadU8, pub list: Vec, @@ -1542,7 +1691,7 @@ impl CertificatePayloadTLS13 { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum KeyExchangeAlgorithm { BulkOnly, DH, @@ -1555,7 +1704,7 @@ pub enum KeyExchangeAlgorithm { // We don't support arbitrary curves. It's a terrible // idea and unnecessary attack surface. Please, // get a grip. -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ECParameters { pub curve_type: ECCurveType, pub named_group: NamedGroup, @@ -1583,7 +1732,8 @@ impl Codec for ECParameters { } } -#[derive(Debug, Clone)] +#[derive(Clone)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct DigitallySignedStruct { pub scheme: SignatureScheme, pub sig: PayloadU16, @@ -1615,7 +1765,7 @@ impl Codec for DigitallySignedStruct { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ClientECDHParams { pub public: PayloadU8, } @@ -1631,7 +1781,7 @@ impl Codec for ClientECDHParams { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ServerECDHParams { pub curve_params: ECParameters, pub public: PayloadU8, @@ -1666,7 +1816,7 @@ impl Codec for ServerECDHParams { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ECDHEServerKeyExchange { pub params: ServerECDHParams, pub dss: DigitallySignedStruct, @@ -1689,7 +1839,7 @@ impl Codec for ECDHEServerKeyExchange { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum ServerKeyExchangePayload { ECDHE(ECDHEServerKeyExchange), Unknown(Payload), @@ -1806,7 +1956,7 @@ declare_u8_vec!(ClientCertificateTypes, ClientCertificateType); pub type DistinguishedName = PayloadU16; pub type DistinguishedNames = VecU16OfPayloadU16; -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct CertificateRequestPayload { pub certtypes: ClientCertificateTypes, pub sigschemes: SupportedSignatureSchemes, @@ -1833,7 +1983,7 @@ impl Codec for CertificateRequestPayload { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum CertReqExtension { SignatureAlgorithms(SupportedSignatureSchemes), AuthorityNames(DistinguishedNames), @@ -1889,7 +2039,7 @@ impl Codec for CertReqExtension { declare_u16_vec!(CertReqExtensions, CertReqExtension); -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct CertificateRequestPayloadTLS13 { pub context: PayloadU8, pub extensions: CertReqExtensions, @@ -1935,7 +2085,7 @@ impl CertificateRequestPayloadTLS13 { } // -- NewSessionTicket -- -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct NewSessionTicketPayload { pub lifetime_hint: u32, pub ticket: PayloadU16, @@ -1968,7 +2118,7 @@ impl Codec for NewSessionTicketPayload { } // -- NewSessionTicket electric boogaloo -- -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum NewSessionTicketExtension { EarlyData(u32), Unknown(UnknownExtension), @@ -2013,7 +2163,7 @@ impl Codec for NewSessionTicketExtension { declare_u16_vec!(NewSessionTicketExtensions, NewSessionTicketExtension); -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct NewSessionTicketPayloadTLS13 { pub lifetime: u32, pub age_add: u32, @@ -2078,7 +2228,7 @@ impl Codec for NewSessionTicketPayloadTLS13 { // -- RFC6066 certificate status types /// Only supports OCSP -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct CertificateStatus { pub ocsp_response: PayloadU24 } @@ -2114,7 +2264,7 @@ impl CertificateStatus { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum HandshakePayload { HelloRequest, ClientHello(ClientHelloPayload), @@ -2169,7 +2319,7 @@ impl HandshakePayload { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct HandshakeMessagePayload { pub typ: HandshakeType, pub payload: HandshakePayload, diff --git a/src/msgs/macros.rs b/src/msgs/macros.rs index c64dda9542c..d092b5a58ae 100644 --- a/src/msgs/macros.rs +++ b/src/msgs/macros.rs @@ -4,7 +4,8 @@ macro_rules! enum_builder { EnumName: $enum_name: ident; EnumVal { $( $enum_var: ident => $enum_val: expr ),* } ) => { - #[derive(Debug, PartialEq, Eq, Clone, Copy)] + #[derive(PartialEq, Eq, Clone, Copy)] + #[cfg_attr(feature = "logging", derive(Debug))] pub enum $enum_name { $( $enum_var),* ,Unknown(u8) @@ -36,7 +37,8 @@ macro_rules! enum_builder { EnumName: $enum_name: ident; EnumVal { $( $enum_var: ident => $enum_val: expr ),* } ) => { - #[derive(Debug, PartialEq, Eq, Clone, Copy)] + #[derive(PartialEq, Eq, Clone, Copy)] + #[cfg_attr(feature = "logging", derive(Debug))] pub enum $enum_name { $( $enum_var),* ,Unknown(u16) diff --git a/src/msgs/message.rs b/src/msgs/message.rs index a917cf7e4de..6b667f3738e 100644 --- a/src/msgs/message.rs +++ b/src/msgs/message.rs @@ -10,7 +10,7 @@ use msgs::enums::HandshakeType; use std::mem; -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum MessagePayload { Alert(AlertMessagePayload), Handshake(HandshakeMessagePayload), @@ -71,7 +71,7 @@ impl MessagePayload { /// A TLS frame, named TLSPlaintext in the standard. /// This type owns all memory for its interior parts. -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct Message { pub typ: ContentType, pub version: ProtocolVersion, @@ -230,7 +230,7 @@ impl<'a> Message { /// /// This type also cannot decode its internals and /// is not a `Codec` type, only `Message` can do that. -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct BorrowMessage<'a> { pub typ: ContentType, pub version: ProtocolVersion, diff --git a/src/msgs/persist.rs b/src/msgs/persist.rs index 03249992193..15e630ad180 100644 --- a/src/msgs/persist.rs +++ b/src/msgs/persist.rs @@ -15,7 +15,7 @@ use std::cmp; // --- Client types --- /// Keys for session resumption and tickets. /// Matching value is a `ClientSessionValue`. -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ClientSessionKey { kind: &'static [u8], dns_name: PayloadU8, @@ -51,7 +51,7 @@ impl ClientSessionKey { } } -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ClientSessionValue { pub version: ProtocolVersion, pub cipher_suite: CipherSuite, @@ -164,7 +164,7 @@ impl ClientSessionValue { // --- Server types --- pub type ServerSessionKey = SessionID; -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct ServerSessionValue { pub sni: Option, pub version: ProtocolVersion, diff --git a/src/server/hs.rs b/src/server/hs.rs index f76ff4d361e..d944bdeed9c 100644 --- a/src/server/hs.rs +++ b/src/server/hs.rs @@ -114,6 +114,7 @@ fn same_dns_name_or_both_none(a: Option<&webpki::DNSName>, // messages. Otherwise the defragmented messages will have // been protected with two different record layer protections, // which is illegal. Not mentioned in RFC. +#[cfg(feature = "tls13")] fn check_aligned_handshake(sess: &mut ServerSessionImpl) -> Result<(), TLSError> { if !sess.common.handshake_joiner.is_empty() { Err(illegal_param(sess, "keys changed with pending hs fragment")) @@ -149,6 +150,7 @@ impl ExpectClientHello { }) } + #[cfg(feature = "tls13")] fn into_expect_retried_client_hello(self) -> NextState { Box::new(ExpectClientHello { handshake: self.handshake, @@ -159,6 +161,7 @@ impl ExpectClientHello { }) } + #[cfg(feature = "tls13")] fn into_expect_tls13_certificate(self) -> NextState { Box::new(ExpectTLS13Certificate { handshake: self.handshake, @@ -166,6 +169,7 @@ impl ExpectClientHello { }) } + #[cfg(feature = "tls13")] fn into_expect_tls13_finished(self) -> NextState { Box::new(ExpectTLS13Finished { handshake: self.handshake, @@ -288,6 +292,7 @@ impl ExpectClientHello { Ok(ret) } + #[cfg(feature = "tls13")] fn check_binder(&self, sess: &mut ServerSessionImpl, client_hello: &Message, @@ -311,6 +316,7 @@ impl ExpectClientHello { constant_time::verify_slices_are_equal(&real_binder, binder).is_ok() } + #[cfg(feature = "tls13")] fn emit_server_hello_tls13(&mut self, sess: &mut ServerSessionImpl, session_id: &SessionID, @@ -383,6 +389,7 @@ impl ExpectClientHello { Ok(()) } + #[cfg(feature = "tls13")] fn emit_fake_ccs(&mut self, sess: &mut ServerSessionImpl) { let m = Message { @@ -393,6 +400,7 @@ impl ExpectClientHello { sess.common.send_msg(m, false); } + #[cfg(feature = "tls13")] fn emit_hello_retry_request(&mut self, sess: &mut ServerSessionImpl, group: NamedGroup) { @@ -421,6 +429,7 @@ impl ExpectClientHello { sess.common.send_msg(m, false); } + #[cfg(feature = "tls13")] fn emit_encrypted_extensions(&mut self, sess: &mut ServerSessionImpl, server_key: &mut sign::CertifiedKey, @@ -443,6 +452,7 @@ impl ExpectClientHello { Ok(()) } + #[cfg(feature = "tls13")] fn emit_certificate_req_tls13(&mut self, sess: &mut ServerSessionImpl) -> bool { if !sess.config.verifier.offer_client_auth() { return false; @@ -476,6 +486,7 @@ impl ExpectClientHello { true } + #[cfg(feature = "tls13")] fn emit_certificate_tls13(&mut self, sess: &mut ServerSessionImpl, server_key: &mut sign::CertifiedKey) { @@ -522,6 +533,7 @@ impl ExpectClientHello { sess.common.send_msg(c, true); } + #[cfg(feature = "tls13")] fn emit_certificate_verify_tls13(&mut self, sess: &mut ServerSessionImpl, server_key: &mut sign::CertifiedKey, @@ -556,6 +568,7 @@ impl ExpectClientHello { Ok(()) } + #[cfg(feature = "tls13")] fn emit_finished_tls13(&mut self, sess: &mut ServerSessionImpl) { let handshake_hash = sess.common.hs_transcript.get_current_hash(); let verify_data = sess.common @@ -815,6 +828,7 @@ impl ExpectClientHello { Ok(self.into_expect_tls12_ccs()) } + #[cfg(feature = "tls13")] fn handle_client_hello_tls13(mut self, sess: &mut ServerSessionImpl, sni: Option, @@ -1069,6 +1083,7 @@ impl State for ExpectClientHello { client_hello.random.write_slice(&mut self.handshake.randoms.client); if sess.common.is_tls13() { + #[cfg(feature = "tls13")] return self.handle_client_hello_tls13(sess, sni, certkey, &m); } @@ -1173,6 +1188,7 @@ impl State for ExpectClientHello { ecpoints_ext.as_slice()) .ok_or_else(|| incompatible(sess, "no supported point format"))?; + #[cfg(feature = "logging")] debug_assert_eq!(ecpoint, ECPointFormat::Uncompressed); self.emit_server_hello(sess, Some(&mut certkey), client_hello, false)?; @@ -1237,11 +1253,13 @@ impl State for ExpectTLS12Certificate { } } +#[cfg(feature = "tls13")] pub struct ExpectTLS13Certificate { handshake: HandshakeDetails, send_ticket: bool, } +#[cfg(feature = "tls13")] impl ExpectTLS13Certificate { fn into_expect_tls13_finished(self) -> NextState { Box::new(ExpectTLS13Finished { @@ -1260,6 +1278,7 @@ impl ExpectTLS13Certificate { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13Certificate { fn check_message(&self, m: &Message) -> CheckResult { check_handshake_message(m, &[HandshakeType::Certificate]) @@ -1416,12 +1435,14 @@ impl State for ExpectTLS12CertificateVerify { } } +#[cfg(feature = "tls13")] pub struct ExpectTLS13CertificateVerify { handshake: HandshakeDetails, client_cert: ClientCertDetails, send_ticket: bool, } +#[cfg(feature = "tls13")] impl ExpectTLS13CertificateVerify { fn into_expect_tls13_finished(self) -> NextState { Box::new(ExpectTLS13Finished { @@ -1431,6 +1452,7 @@ impl ExpectTLS13CertificateVerify { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13CertificateVerify { fn check_message(&self, m: &Message) -> CheckResult { check_handshake_message(m, &[HandshakeType::CertificateVerify]) @@ -1521,6 +1543,7 @@ fn get_server_session_value_tls12(handshake: &HandshakeDetails, v } +#[cfg(feature = "tls13")] fn get_server_session_value_tls13(sess: &ServerSessionImpl, nonce: &[u8]) -> persist::ServerSessionValue { let scs = sess.common.get_suite_assert(); @@ -1665,11 +1688,13 @@ impl State for ExpectTLS12Finished { } } +#[cfg(feature = "tls13")] pub struct ExpectTLS13Finished { handshake: HandshakeDetails, send_ticket: bool, } +#[cfg(feature = "tls13")] impl ExpectTLS13Finished { fn into_expect_tls13_traffic(self, fin: verify::FinishedMessageVerified) -> NextState { Box::new(ExpectTLS13Traffic { @@ -1737,6 +1762,7 @@ impl ExpectTLS13Finished { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13Finished { fn check_message(&self, m: &Message) -> CheckResult { check_handshake_message(m, &[HandshakeType::Finished]) @@ -1812,10 +1838,12 @@ impl State for ExpectTLS12Traffic { } } +#[cfg(feature = "tls13")] pub struct ExpectTLS13Traffic { _fin_verified: verify::FinishedMessageVerified, } +#[cfg(feature = "tls13")] impl ExpectTLS13Traffic { fn handle_traffic(&self, sess: &mut ServerSessionImpl, mut m: Message) -> Result<(), TLSError> { sess.common.take_received_plaintext(m.take_opaque_payload().unwrap()); @@ -1828,6 +1856,7 @@ impl ExpectTLS13Traffic { } } +#[cfg(feature = "tls13")] impl State for ExpectTLS13Traffic { fn check_message(&self, m: &Message) -> CheckResult { check_message(m, diff --git a/src/server/mod.rs b/src/server/mod.rs index 9f42450db57..b75780a9e11 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -136,7 +136,7 @@ pub struct ServerConfig { pub versions: Vec, /// How to verify client certificates. - verifier: Arc, + pub verifier: Arc, /// How to output key material for debugging. The default /// does nothing. diff --git a/src/session.rs b/src/session.rs index f3dab93ee9e..42b685db7f2 100644 --- a/src/session.rs +++ b/src/session.rs @@ -444,6 +444,7 @@ impl SessionCommon { pub fn is_tls13(&self) -> bool { match self.negotiated_version { + #[cfg(feature = "tls13")] Some(ProtocolVersion::TLSv1_3) => true, _ => false } @@ -562,6 +563,7 @@ impl SessionCommon { } } + #[cfg(feature = "tls13")] fn do_write_key_update(&mut self) { // TLS1.3 putting key update triggering here breaks layering // between the handshake and record layer. @@ -589,6 +591,7 @@ impl SessionCommon { /// the encrypted fragments for sending. pub fn send_msg_encrypt(&mut self, m: Message) { if self.want_write_key_update { + #[cfg(feature = "tls13")] self.do_write_key_update(); } @@ -605,6 +608,7 @@ impl SessionCommon { payload: &[u8], limit: Limit) -> usize { if self.want_write_key_update { + #[cfg(feature = "tls13")] self.do_write_key_update(); } @@ -795,6 +799,7 @@ impl SessionCommon { self.send_warning_alert_no_log(AlertDescription::CloseNotify); } + #[cfg(feature = "tls13")] pub fn process_key_update(&mut self, kur: &KeyUpdateRequest, read_kind: SecretKind) diff --git a/src/suites.rs b/src/suites.rs index 5fbca79d691..185ef7f2721 100644 --- a/src/suites.rs +++ b/src/suites.rs @@ -10,15 +10,18 @@ use untrusted; /// Bulk symmetric encryption scheme used by a cipher suite. #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq)] +#[cfg_attr(feature = "logging", derive(Debug))] pub enum BulkAlgorithm { /// AES with 128-bit keys in Galois counter mode. + #[cfg(feature = "aesgcm")] AES_128_GCM, /// AES with 256-bit keys in Galois counter mode. + #[cfg(feature = "aesgcm")] AES_256_GCM, /// Chacha20 for confidentiality with poly1305 for authenticity. + #[cfg(feature = "chachapoly")] CHACHA20_POLY1305, } @@ -42,8 +45,11 @@ impl KeyExchange { pub fn named_group_to_ecdh_alg(group: NamedGroup) -> Option<&'static ring::agreement::Algorithm> { match group { + #[cfg(feature = "x25519")] NamedGroup::X25519 => Some(&ring::agreement::X25519), + #[cfg(feature = "ecdh")] NamedGroup::secp256r1 => Some(&ring::agreement::ECDH_P256), + #[cfg(feature = "ecdh")] NamedGroup::secp384r1 => Some(&ring::agreement::ECDH_P384), _ => None, } @@ -119,7 +125,7 @@ impl KeyExchange { /// /// All possible instances of this class are provided by the library in /// the `ALL_CIPHERSUITES` array. -#[derive(Debug)] +#[cfg_attr(feature = "logging", derive(Debug))] pub struct SupportedCipherSuite { /// The TLS enumeration naming this cipher suite. pub suite: CipherSuite, @@ -221,8 +227,11 @@ impl SupportedCipherSuite { /// Which AEAD algorithm to use for this suite. pub fn get_aead_alg(&self) -> &'static ring::aead::Algorithm { match self.bulk { + #[cfg(feature = "aesgcm")] BulkAlgorithm::AES_128_GCM => &ring::aead::AES_128_GCM, + #[cfg(feature = "aesgcm")] BulkAlgorithm::AES_256_GCM => &ring::aead::AES_256_GCM, + #[cfg(feature = "chachapoly")] BulkAlgorithm::CHACHA20_POLY1305 => &ring::aead::CHACHA20_POLY1305, } } @@ -236,6 +245,7 @@ impl SupportedCipherSuite { /// Return true if this suite is usable for TLS `version`. pub fn usable_for_version(&self, version: ProtocolVersion) -> bool { match version { + #[cfg(feature = "tls13")] ProtocolVersion::TLSv1_3 => self.sign == SignatureAlgorithm::Anonymous, ProtocolVersion::TLSv1_2 => self.sign != SignatureAlgorithm::Anonymous, _ => false, @@ -261,6 +271,7 @@ impl SupportedCipherSuite { } } +#[cfg(all(feature = "chachapoly", feature = "ecdsa"))] pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, @@ -273,6 +284,7 @@ pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = explicit_nonce_len: 0, }; +#[cfg(feature = "chachapoly")] pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, @@ -285,6 +297,7 @@ pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = explicit_nonce_len: 0, }; +#[cfg(feature = "aesgcm")] pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, kx: KeyExchangeAlgorithm::ECDHE, @@ -296,6 +309,7 @@ pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = Support explicit_nonce_len: 8, }; +#[cfg(feature = "aesgcm")] pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, kx: KeyExchangeAlgorithm::ECDHE, @@ -307,6 +321,7 @@ pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = Support explicit_nonce_len: 8, }; +#[cfg(all(feature = "aesgcm", feature = "ecdsa"))] pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, kx: KeyExchangeAlgorithm::ECDHE, @@ -318,6 +333,7 @@ pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = Suppo explicit_nonce_len: 8, }; +#[cfg(all(feature = "aesgcm", feature = "ecdsa"))] pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, kx: KeyExchangeAlgorithm::ECDHE, @@ -329,6 +345,7 @@ pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = Suppo explicit_nonce_len: 8, }; +#[cfg(all(feature = "chachapoly", feature = "tls13"))] pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, kx: KeyExchangeAlgorithm::BulkOnly, @@ -340,6 +357,7 @@ pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = SupportedCiphe explicit_nonce_len: 0, }; +#[cfg(all(feature = "aesgcm", feature = "tls13"))] pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS13_AES_256_GCM_SHA384, kx: KeyExchangeAlgorithm::BulkOnly, @@ -351,6 +369,7 @@ pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite explicit_nonce_len: 0, }; +#[cfg(all(feature = "aesgcm", feature = "tls13"))] pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite { suite: CipherSuite::TLS13_AES_128_GCM_SHA256, kx: KeyExchangeAlgorithm::BulkOnly, @@ -363,6 +382,7 @@ pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite }; /// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "aesgcm", feature = "chachapoly", feature = "tls13", feature = "ecdsa"))] pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 9] = [// TLS1.3 suites &TLS13_CHACHA20_POLY1305_SHA256, @@ -377,6 +397,110 @@ pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 9] = &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]; +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "aesgcm", feature = "chachapoly", feature = "tls13", not(feature = "ecdsa")))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 6] = + [// TLS1.3 suites + &TLS13_CHACHA20_POLY1305_SHA256, + &TLS13_AES_256_GCM_SHA384, + &TLS13_AES_128_GCM_SHA256, + + // TLS1.2 suites + &TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "aesgcm", feature = "chachapoly", not(feature = "tls13"), feature = "ecdsa"))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 6] = + [// TLS1.2 suites + &TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + &TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + &TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "aesgcm", feature = "chachapoly", not(feature = "tls13"), not(feature = "ecdsa")))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 3] = + [// TLS1.2 suites + &TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "aesgcm", not(feature = "chachapoly"), feature = "tls13", feature = "ecdsa"))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 6] = + [// TLS1.3 suites + &TLS13_AES_256_GCM_SHA384, + &TLS13_AES_128_GCM_SHA256, + + // TLS1.2 suites + &TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "aesgcm", not(feature = "chachapoly"), feature = "tls13", not(feature = "ecdsa")))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 4] = + [// TLS1.3 suites + &TLS13_AES_256_GCM_SHA384, + &TLS13_AES_128_GCM_SHA256, + + // TLS1.2 suites + &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "aesgcm", not(feature = "chachapoly"), not(feature = "tls13"), feature = "ecdsa"))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 4] = + [// TLS1.2 suites + &TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "aesgcm", not(feature = "chachapoly"), not(feature = "tls13"), not(feature = "ecdsa")))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 2] = + [// TLS1.2 suites + &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "chachapoly", not(feature = "aesgcm"), feature = "tls13", feature = "ecdsa"))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 3] = + [// TLS1.3 suites + &TLS13_CHACHA20_POLY1305_SHA256, + + // TLS1.2 suites + &TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + &TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "chachapoly", not(feature = "aesgcm"), feature = "tls13", not(feature = "ecdsa")))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 2] = + [// TLS1.3 suites + &TLS13_CHACHA20_POLY1305_SHA256, + + // TLS1.2 suites + &TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "chachapoly", not(feature = "aesgcm"), not(feature = "tls13"), feature = "ecdsa"))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 2] = + [// TLS1.2 suites + &TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + &TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256]; + +/// A list of all the cipher suites supported by rustls. +#[cfg(all(feature = "chachapoly", not(feature = "aesgcm"), not(feature = "tls13"), not(feature = "ecdsa")))] +pub static ALL_CIPHERSUITES: [&'static SupportedCipherSuite; 1] = + [// TLS1.2 suites + &TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256]; + // These both O(N^2)! pub fn choose_ciphersuite_preferring_client(client_suites: &[CipherSuite], server_suites: &[&'static SupportedCipherSuite]) diff --git a/src/verify.rs b/src/verify.rs index 945763254db..f1311fecc40 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -15,6 +15,7 @@ type SignatureAlgorithms = &'static [&'static webpki::SignatureAlgorithm]; /// Which signature verification mechanisms we support. No particular /// order. +#[cfg(feature = "ecdsa")] static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[&webpki::ECDSA_P256_SHA256, &webpki::ECDSA_P256_SHA384, &webpki::ECDSA_P384_SHA256, @@ -28,6 +29,16 @@ static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[&webpki::ECDSA_P256_SHA256, &webpki::RSA_PKCS1_2048_8192_SHA512, &webpki::RSA_PKCS1_3072_8192_SHA384]; +#[cfg(not(feature = "ecdsa"))] +static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[&webpki::RSA_PSS_2048_8192_SHA256_LEGACY_KEY, + &webpki::RSA_PSS_2048_8192_SHA384_LEGACY_KEY, + &webpki::RSA_PSS_2048_8192_SHA512_LEGACY_KEY, + &webpki::RSA_PKCS1_2048_8192_SHA1, + &webpki::RSA_PKCS1_2048_8192_SHA256, + &webpki::RSA_PKCS1_2048_8192_SHA384, + &webpki::RSA_PKCS1_2048_8192_SHA512, + &webpki::RSA_PKCS1_3072_8192_SHA384]; + /// Marker types. These are used to bind the fact some verification /// (certificate chain or handshake signature) has taken place into /// protocol states. We use this to have the compiler check that there @@ -89,7 +100,9 @@ pub trait ClientCertVerifier : Send + Sync { presented_certs: &[Certificate]) -> Result; } +/// WebPKIVerifier pub struct WebPKIVerifier { + /// time pub time: fn() -> Result, } @@ -117,6 +130,7 @@ impl ServerCertVerifier for WebPKIVerifier { } impl WebPKIVerifier { + /// new() pub fn new() -> WebPKIVerifier { WebPKIVerifier { time: try_now, @@ -248,8 +262,10 @@ impl ClientCertVerifier for NoClientAuth { } } +#[cfg(feature = "ecdsa")] static ECDSA_SHA256: SignatureAlgorithms = &[&webpki::ECDSA_P256_SHA256, &webpki::ECDSA_P384_SHA256]; +#[cfg(feature = "ecdsa")] static ECDSA_SHA384: SignatureAlgorithms = &[&webpki::ECDSA_P256_SHA384, &webpki::ECDSA_P384_SHA384]; @@ -264,7 +280,9 @@ static RSA_PSS_SHA512: SignatureAlgorithms = &[&webpki::RSA_PSS_2048_8192_SHA512 fn convert_scheme(scheme: SignatureScheme) -> Result { match scheme { // nb. for TLS1.2 the curve is not fixed by SignatureScheme. + #[cfg(feature = "ecdsa")] SignatureScheme::ECDSA_NISTP256_SHA256 => Ok(ECDSA_SHA256), + #[cfg(feature = "ecdsa")] SignatureScheme::ECDSA_NISTP384_SHA384 => Ok(ECDSA_SHA384), SignatureScheme::RSA_PKCS1_SHA1 => Ok(RSA_SHA1), @@ -277,7 +295,10 @@ fn convert_scheme(scheme: SignatureScheme) -> Result Ok(RSA_PSS_SHA512), _ => { + #[cfg(feature = "logging")] let error_msg = format!("received unadvertised sig scheme {:?}", scheme); + #[cfg(not(feature = "logging"))] + let error_msg = format!("received unadvertised sig scheme"); Err(TLSError::PeerMisbehavedError(error_msg)) } } @@ -322,23 +343,30 @@ pub fn verify_signed_struct(message: &[u8], .map(|_| HandshakeSignatureValid::assertion()) } +#[cfg(feature = "tls13")] fn convert_alg_tls13(scheme: SignatureScheme) -> Result<&'static webpki::SignatureAlgorithm, TLSError> { use msgs::enums::SignatureScheme::*; match scheme { + #[cfg(feature = "ecdsa")] ECDSA_NISTP256_SHA256 => Ok(&webpki::ECDSA_P256_SHA256), + #[cfg(feature = "ecdsa")] ECDSA_NISTP384_SHA384 => Ok(&webpki::ECDSA_P384_SHA384), RSA_PSS_SHA256 => Ok(&webpki::RSA_PSS_2048_8192_SHA256_LEGACY_KEY), RSA_PSS_SHA384 => Ok(&webpki::RSA_PSS_2048_8192_SHA384_LEGACY_KEY), RSA_PSS_SHA512 => Ok(&webpki::RSA_PSS_2048_8192_SHA512_LEGACY_KEY), _ => { + #[cfg(feature = "logging")] let error_msg = format!("received unsupported sig scheme {:?}", scheme); + #[cfg(not(feature = "logging"))] + let error_msg = format!("received unsupported sig scheme"); Err(TLSError::PeerMisbehavedError(error_msg)) } } } +#[cfg(feature = "tls13")] pub fn verify_tls13(cert: &Certificate, dss: &DigitallySignedStruct, handshake_hash: &[u8],