@@ -1172,6 +1172,49 @@ mod _ssl {
11721172 }
11731173 }
11741174
1175+ #[ pymethod]
1176+ fn get_channel_binding (
1177+ & self ,
1178+ cb_type : OptionalArg < PyStrRef > ,
1179+ vm : & VirtualMachine ,
1180+ ) -> PyResult < Option < PyObjectRef > > {
1181+ const CB_MAXLEN : usize = 512 ;
1182+
1183+ let cb_type_str = cb_type. as_ref ( ) . map_or ( "tls-unique" , |s| s. as_str ( ) ) ;
1184+
1185+ if cb_type_str != "tls-unique" {
1186+ return Err ( vm. new_value_error ( format ! (
1187+ "Unsupported channel binding type '{}'" ,
1188+ cb_type_str
1189+ ) ) ) ;
1190+ }
1191+
1192+ let stream = self . stream . read ( ) ;
1193+ let ssl_ptr = stream. ssl ( ) . as_ptr ( ) ;
1194+
1195+ unsafe {
1196+ let session_reused = sys:: SSL_session_reused ( ssl_ptr) != 0 ;
1197+ let is_client = matches ! ( self . socket_type, SslServerOrClient :: Client ) ;
1198+
1199+ // Use XOR logic from CPython
1200+ let use_finished = session_reused ^ is_client;
1201+
1202+ let mut buf = vec ! [ 0u8 ; CB_MAXLEN ] ;
1203+ let len = if use_finished {
1204+ sys:: SSL_get_finished ( ssl_ptr, buf. as_mut_ptr ( ) as * mut _ , CB_MAXLEN )
1205+ } else {
1206+ sys:: SSL_get_peer_finished ( ssl_ptr, buf. as_mut_ptr ( ) as * mut _ , CB_MAXLEN )
1207+ } ;
1208+
1209+ if len == 0 {
1210+ Ok ( None )
1211+ } else {
1212+ buf. truncate ( len) ;
1213+ Ok ( Some ( vm. ctx . new_bytes ( buf) . into ( ) ) )
1214+ }
1215+ }
1216+ }
1217+
11751218 #[ cfg( osslconf = "OPENSSL_NO_COMP" ) ]
11761219 #[ pymethod]
11771220 fn compression ( & self ) -> Option < & ' static str > {
0 commit comments