diff --git a/CHANGELOG.md b/CHANGELOG.md index 2de3c31e..ad9479ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ +### 1.7.0-RC4 ### +* :lock: Fix inverted `MinTlsVersion` mapping. `MinTlsVersion::V13` previously enabled both TLS 1.2 and 1.3, so it did not exclude TLS 1.2 as documented, and `MinTlsVersion::V12` enabled TLS 1.2 only, disabling TLS 1.3. Both arms now match their documented meaning: `V12` allows TLS 1.2 and 1.3, `V13` allows only TLS 1.3. Affects 1.6.0 through 1.7.0-RC3. See [#437](https://github.com/stepfunc/dnp3/issues/437). +* :bell: **Behavior change for existing TLS configurations.** Users who set `V13` were silently permitting TLS 1.2 and will now reject peers that do not support TLS 1.3. Users on the default `V12` (including all bindings users who never overrode it) will now negotiate TLS 1.3 where the peer supports it, rather than being pinned to TLS 1.2. + ### 1.7.0-RC3 ### * :star: Add unstable, non-spawning master and outstation task APIs behind the semver-exempt `unstable` feature, allowing applications to obtain runnable tasks/futures without the library calling `tokio::spawn` internally. See [#433](https://github.com/stepfunc/dnp3/pull/433). * :star: Add `EndpointList::into_connect_handler()` and `EndpointList::into_connect_handler_with_options()` to build a `ClientConnectionHandler` from an endpoint list, e.g. for use with `spawn_master_tcp_client_3`. See [#433](https://github.com/stepfunc/dnp3/pull/433). diff --git a/dnp3/src/tcp/tls/mod.rs b/dnp3/src/tcp/tls/mod.rs index 09ed80f4..f54bac32 100644 --- a/dnp3/src/tcp/tls/mod.rs +++ b/dnp3/src/tcp/tls/mod.rs @@ -88,19 +88,50 @@ impl std::error::Error for TlsError {} derive(serde::Serialize, serde::Deserialize) )] pub enum MinTlsVersion { - /// TLS 1.2 + /// Allow TLS 1.2 and TLS 1.3 V12, - /// TLS 1.3 + /// Allow only TLS 1.3 + /// + /// A peer that does not support TLS 1.3 will fail to complete the handshake. V13, } impl From for sfio_rustls_config::ProtocolVersions { fn from(value: MinTlsVersion) -> Self { match value { - MinTlsVersion::V12 => sfio_rustls_config::ProtocolVersions::v12_only(), - MinTlsVersion::V13 => sfio_rustls_config::ProtocolVersions::new() + MinTlsVersion::V12 => sfio_rustls_config::ProtocolVersions::new() .enable_v12() .enable_v13(), + MinTlsVersion::V13 => sfio_rustls_config::ProtocolVersions::v13_only(), } } } + +#[cfg(test)] +mod tests { + use super::*; + use sfio_rustls_config::ProtocolVersions; + + /// `MinTlsVersion` is a *minimum*, so v1.2 must also allow v1.3 to be negotiated. + #[test] + fn v12_allows_both_versions() { + assert_eq!( + ProtocolVersions::from(MinTlsVersion::V12), + ProtocolVersions::new().enable_v12().enable_v13() + ); + } + + /// Requesting v1.3 must *exclude* v1.2 so that the handshake fails closed against + /// a peer that only supports v1.2. + #[test] + fn v13_excludes_v12() { + assert_eq!( + ProtocolVersions::from(MinTlsVersion::V13), + ProtocolVersions::v13_only() + ); + assert_ne!( + ProtocolVersions::from(MinTlsVersion::V13), + ProtocolVersions::from(MinTlsVersion::V12) + ); + } +} diff --git a/ffi/dnp3-schema/src/shared.rs b/ffi/dnp3-schema/src/shared.rs index e82d322e..86eed676 100644 --- a/ffi/dnp3-schema/src/shared.rs +++ b/ffi/dnp3-schema/src/shared.rs @@ -736,7 +736,10 @@ fn define_min_tls_version(lib: &mut LibraryBuilder) -> BackTraced { let handle = lib .define_enum("min_tls_version")? .push("v12", "Allow TLS 1.2 and 1.3")? - .push("v13", "Only allow TLS 1.3")? + .push( + "v13", + "Only allow TLS 1.3. A peer that does not support TLS 1.3 will fail to complete the handshake.", + )? .doc("Minimum TLS version to allow")? .build()?; diff --git a/guide/docs/api/tls.mdx b/guide/docs/api/tls.mdx index 69ea56ff..51a33d74 100644 --- a/guide/docs/api/tls.mdx +++ b/guide/docs/api/tls.mdx @@ -74,7 +74,7 @@ Configure TLS using `TlsClientConfig` or `TlsServerConfig`. Both contain these f - `password`: * Password used to decrypt the private key file. If the key is not encrypted, this **must** be an empty string (`""`) and not `null` or omitted. This applies to all language bindings (Rust, C, C++, Java, C#). See the next section for more details. - `min_tls_version`: - * Minimum TLS version to support. Setting this to `Tls1_3` will force the usage of TLSv1.3. + * Minimum TLS version to support. `V12` allows TLS 1.2 and 1.3 to be negotiated, and is the default in the bindings. Setting this to `V13` forces the usage of TLSv1.3: a peer that does not support TLS 1.3 will fail to complete the handshake. - `certificate_mode`: * Mode used to verify the peer certificate.