| 2746 | |
| 2747 | #[pymethod] |
| 2748 | fn get_channel_binding( |
| 2749 | &self, |
| 2750 | cb_type: OptionalArg<PyStrRef>, |
| 2751 | vm: &VirtualMachine, |
| 2752 | ) -> PyResult<Option<PyBytesRef>> { |
| 2753 | const CB_MAXLEN: usize = 512; |
| 2754 | |
| 2755 | let cb_type_str = cb_type.as_ref().map_or("tls-unique", |s| s.as_str()); |
| 2756 | |
| 2757 | if cb_type_str != "tls-unique" { |
| 2758 | return Err(vm.new_value_error(format!( |
| 2759 | "Unsupported channel binding type '{}'", |
| 2760 | cb_type_str |
| 2761 | ))); |
| 2762 | } |
| 2763 | |
| 2764 | let stream = self.connection.read(); |
| 2765 | let ssl_ptr = stream.ssl().as_ptr(); |
| 2766 | |
| 2767 | unsafe { |
| 2768 | let session_reused = sys::SSL_session_reused(ssl_ptr) != 0; |
| 2769 | let is_client = matches!(self.socket_type, SslServerOrClient::Client); |
| 2770 | |
| 2771 | // Use XOR logic from CPython |
| 2772 | let use_finished = session_reused ^ is_client; |
| 2773 | |
| 2774 | let mut buf = vec![0u8; CB_MAXLEN]; |
| 2775 | let len = if use_finished { |
| 2776 | sys::SSL_get_finished(ssl_ptr, buf.as_mut_ptr() as *mut _, CB_MAXLEN) |
| 2777 | } else { |
| 2778 | sys::SSL_get_peer_finished(ssl_ptr, buf.as_mut_ptr() as *mut _, CB_MAXLEN) |
| 2779 | }; |
| 2780 | |
| 2781 | if len == 0 { |
| 2782 | Ok(None) |
| 2783 | } else { |
| 2784 | buf.truncate(len); |
| 2785 | Ok(Some(vm.ctx.new_bytes(buf))) |
| 2786 | } |
| 2787 | } |
| 2788 | } |
| 2789 | |
| 2790 | #[pymethod] |
| 2791 | fn verify_client_post_handshake(&self, vm: &VirtualMachine) -> PyResult<()> { |