steffengy/schannel-rs

TLS 1.3 does not work (fails after a second SEC_I_RENEGOTIATE)

Closed this issue · 0 comments

When running the testcase tls_13 on my Windows 11 (24H2) system, and also on a Windows Server 2022 VM, I get the following failure:

D:\source\schannel-rs>cargo test tls_13
<snip>
running 1 test
test test::tls_13 ... FAILED

failures:

---- test::tls_13 stdout ----
thread 'test::tls_13' panicked at src\test.rs:293:34:
called `Result::unwrap()` on an `Err` value: Os { code: -2146893033, kind: Uncategorized, message: "The context has expired and can no longer be used." }
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\std\src\panicking.rs:665
   1: core::panicking::panic_fmt
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\core\src\panicking.rs:74
   2: core::result::unwrap_failed
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\core\src\result.rs:1679
   3: enum2$<core::result::Result<usize,std::io::error::Error> >::unwrap
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\core\src\result.rs:1102
   4: schannel::test::tls_13
             at .\src\test.rs:293
   5: schannel::test::tls_13::closure$0
             at .\src\test.rs:275
   6: core::ops::function::FnOnce::call_once<schannel::test::tls_13::closure_env$0,tuple$<> >
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\core\src\ops\function.rs:250
   7: core::ops::function::FnOnce::call_once
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\core\src\ops\function.rs:250
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.


failures:
    test::tls_13

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 41 filtered out; finished in 0.10s

error: test failed, to rerun pass `--lib`

where -2146893033 is SEC_E_CONTEXT_EXPIRED.
After adding the following debug prints:

diff --git a/src/tls_stream.rs b/src/tls_stream.rs
index 6f59f21..3d00ad1 100644
--- a/src/tls_stream.rs
+++ b/src/tls_stream.rs
@@ -487,6 +487,7 @@ where
                     _ => ptr::null_mut(),
                 };

+                println!("Calling InitializeSecurityContextW");
                 Identity::InitializeSecurityContextW(
                     &self.cred.as_inner(),
                     self.context.get_mut(),
@@ -835,6 +836,7 @@ where
             ];
             let bufdesc = secbuf_desc(&mut bufs);

+            println!("Calling DecryptMessage");
             match Identity::DecryptMessage(self.context.get_mut(), &bufdesc, 0, ptr::null_mut()) {
                 Foundation::SEC_E_OK => {
                     let start = bufs[1].pvBuffer as usize - self.enc_in.get_ref().as_ptr() as usize;
@@ -865,6 +867,7 @@ where
                 }
                 Foundation::SEC_I_CONTEXT_EXPIRED => Ok(true),
                 Foundation::SEC_I_RENEGOTIATE => {
+                    println!("Got SEC_I_RENEGOTIATE");
                     self.state = State::Initializing {
                         needs_flush: false,
                         more_calls: true,

I see the following:

D:\source\schannel-rs>cargo test tls_13 -- --nocapture
<snip>
running 1 test
Calling InitializeSecurityContextW
Calling InitializeSecurityContextW
Calling InitializeSecurityContextW
Calling DecryptMessage
Got SEC_I_RENEGOTIATE
Calling InitializeSecurityContextW
Calling DecryptMessage
Got SEC_I_RENEGOTIATE
Calling DecryptMessage
thread 'test::tls_13' panicked at src\test.rs:293:34:
called `Result::unwrap()` on an `Err` value: Os { code: -2146893033, kind: Uncategorized, message: "The context has expired and can no longer be used." }
<snip>

Apparently indicating that InitializeSecurityContext was not called again after the second SEC_I_RENEGOTIATE, which I believe is necessary according to https://learn.microsoft.com/en-us/windows/win32/secauthn/recognizing-a-request-to-renegotiate-a-connection.