@@ -6,6 +6,7 @@ use std::{
6
6
sync:: Arc ,
7
7
task:: { Context , Poll } ,
8
8
} ;
9
+ use DigestAlgorithm :: { Sha1 , Sha256 , Sha384 , Sha512 } ;
9
10
10
11
use futures:: future:: { FutureExt , TryFutureExt } ;
11
12
use ring:: digest;
@@ -14,6 +15,10 @@ use rustls::pki_types::ServerName;
14
15
use tokio:: io:: { AsyncRead , AsyncWrite , ReadBuf } ;
15
16
use tokio_postgres:: tls:: { ChannelBinding , MakeTlsConnect , TlsConnect } ;
16
17
use tokio_rustls:: { client:: TlsStream , TlsConnector } ;
18
+ use x509_certificate:: { algorithm, DigestAlgorithm , SignatureAlgorithm , X509Certificate } ;
19
+ use SignatureAlgorithm :: {
20
+ EcdsaSha256 , EcdsaSha384 , Ed25519 , NoSignature , RsaSha1 , RsaSha256 , RsaSha384 , RsaSha512 ,
21
+ } ;
17
22
18
23
#[ derive( Clone ) ]
19
24
pub struct MakeRustlsConnect {
@@ -84,10 +89,26 @@ where
84
89
fn channel_binding ( & self ) -> ChannelBinding {
85
90
let ( _, session) = self . 0 . get_ref ( ) ;
86
91
match session. peer_certificates ( ) {
87
- Some ( certs) if !certs. is_empty ( ) => {
88
- let sha256 = digest:: digest ( & digest:: SHA256 , certs[ 0 ] . as_ref ( ) ) ;
89
- ChannelBinding :: tls_server_end_point ( sha256. as_ref ( ) . into ( ) )
90
- }
92
+ Some ( certs) if !certs. is_empty ( ) => X509Certificate :: from_der ( & certs[ 0 ] )
93
+ . ok ( )
94
+ . and_then ( |cert| cert. signature_algorithm ( ) )
95
+ . map ( |algorithm| match algorithm {
96
+ // Note: SHA1 is upgraded to SHA256 as per https://datatracker.ietf.org/doc/html/rfc5929#section-4.1
97
+ RsaSha1 | RsaSha256 | EcdsaSha256 => & digest:: SHA256 ,
98
+ RsaSha384 | EcdsaSha384 => & digest:: SHA384 ,
99
+ RsaSha512 => & digest:: SHA512 ,
100
+ Ed25519 => & digest:: SHA512 ,
101
+ NoSignature ( algo) => match algo {
102
+ Sha1 | Sha256 => & digest:: SHA256 ,
103
+ Sha384 => & digest:: SHA384 ,
104
+ Sha512 => & digest:: SHA512 ,
105
+ } ,
106
+ } )
107
+ . map ( |algorithm| {
108
+ let hash = digest:: digest ( algorithm, certs[ 0 ] . as_ref ( ) ) ;
109
+ ChannelBinding :: tls_server_end_point ( hash. as_ref ( ) . into ( ) )
110
+ } )
111
+ . unwrap_or ( ChannelBinding :: none ( ) ) ,
91
112
_ => ChannelBinding :: none ( ) ,
92
113
}
93
114
}
0 commit comments