diff --git a/src/connection/connection.rs b/src/connection/connection.rs index 1b4190bc5..2347ed5d0 100644 --- a/src/connection/connection.rs +++ b/src/connection/connection.rs @@ -1113,6 +1113,15 @@ impl Connection { /// Check and record handshake status. fn process_tls_session(&mut self, tls_result: Result<()>) -> Result<()> { + if let Some(tls_error) = self.tls_session.error() { + self.local_error = Some(ConnectionError { + is_app: false, + error_code: tls_error.error_code, + frame: None, + reason: tls_error.reason.clone(), + }); + } + if self.flags.contains(HandshakeCompleted) { return tls_result; } @@ -5623,7 +5632,20 @@ pub(crate) mod tests { server_config.set_tls_config(tls_config); let mut test_pair = TestPair::new(&mut client_config, &mut server_config)?; - assert!(test_pair.handshake().is_err()); + assert!(matches!(test_pair.handshake(), Err(Error::TlsFail(_)))); + + const TLS_ALERT_NO_APPLICATION_PROTOCOL: u8 = 0x78; + let expected_error = ConnectionError { + is_app: false, + error_code: Error::CryptoError(TLS_ALERT_NO_APPLICATION_PROTOCOL).to_wire(), + frame: None, + reason: Vec::new(), + }; + assert_eq!(test_pair.server.local_error(), Some(&expected_error)); + + let packets = TestPair::conn_packets_out(&mut test_pair.server)?; + TestPair::conn_packets_in(&mut test_pair.client, packets)?; + assert_eq!(test_pair.client.peer_error(), Some(&expected_error)); Ok(()) } diff --git a/src/error.rs b/src/error.rs index 5e925333c..6c32f3649 100644 --- a/src/error.rs +++ b/src/error.rs @@ -97,8 +97,8 @@ pub enum Error { /// enough MTU. NoViablePath, - /// The cryptographic handshake failed. A range of 256 values is reserved - /// for carrying error codes specific to the cryptographic handshake. + /// The cryptographic handshake failed. The value is a TLS alert + /// description, which is encoded in the reserved 0x100-0x1ff range. CryptoError(u8), /// An endpoint detected a multipath error with protocol compliance that @@ -175,7 +175,7 @@ impl Error { Error::KeyUpdateError => 0x0e, Error::AeadLimitReached => 0x0f, Error::NoViablePath => 0x10, - Error::CryptoError(v) => v as u64, + Error::CryptoError(v) => 0x100 + u64::from(v), Error::MultipathProtocolViolation => 0x1001d76d3ded42f3, _ => 0x0, } @@ -274,6 +274,9 @@ mod tests { #[test] fn error_to_wire() { + assert_eq!(Error::CryptoError(0).to_wire(), 0x100); + assert_eq!(Error::CryptoError(u8::MAX).to_wire(), 0x1ff); + let mut found_internal_err = false; for err in Error::iter() { if err == Error::NoError { @@ -287,11 +290,7 @@ mod tests { assert_eq!(err.to_wire(), 0); continue; } - if let Error::CryptoError(_) = err { - assert_eq!(err.to_wire(), 0); - } else { - assert!(err.to_wire() > 0); - } + assert!(err.to_wire() > 0); } } diff --git a/src/tls/boringssl/tls.rs b/src/tls/boringssl/tls.rs index 992ee79ca..4db1d02b5 100644 --- a/src/tls/boringssl/tls.rs +++ b/src/tls/boringssl/tls.rs @@ -1139,10 +1139,8 @@ extern "C" fn send_alert(ssl: *mut Ssl, level: tls::Level, alert: u8) -> c_int { alert ); - const TLS_ALERT_ERROR: u64 = 0x100; - let error: u64 = TLS_ALERT_ERROR + u64::from(alert); session_data.error = Some(tls::TlsError { - error_code: error, + error_code: Error::CryptoError(alert).to_wire(), reason: Vec::new(), });