@@ -6,13 +6,19 @@ 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;
12
- use rustls:: { ClientConfig , ServerName } ;
13
+ use rustls:: ClientConfig ;
14
+ use rustls:: pki_types:: ServerName ;
13
15
use tokio:: io:: { AsyncRead , AsyncWrite , ReadBuf } ;
14
16
use tokio_postgres:: tls:: { ChannelBinding , MakeTlsConnect , TlsConnect } ;
15
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
+ } ;
16
22
17
23
#[ derive( Clone ) ]
18
24
pub struct MakeRustlsConnect {
39
45
ServerName :: try_from ( hostname)
40
46
. map ( |dns_name| {
41
47
RustlsConnect ( Some ( RustlsConnectData {
42
- hostname : dns_name,
48
+ hostname : dns_name. to_owned ( ) ,
43
49
connector : Arc :: clone ( & self . config ) . into ( ) ,
44
50
} ) )
45
51
} )
50
56
pub struct RustlsConnect ( Option < RustlsConnectData > ) ;
51
57
52
58
struct RustlsConnectData {
53
- hostname : ServerName ,
59
+ hostname : ServerName < ' static > ,
54
60
connector : TlsConnector ,
55
61
}
56
62
@@ -83,10 +89,26 @@ where
83
89
fn channel_binding ( & self ) -> ChannelBinding {
84
90
let ( _, session) = self . 0 . get_ref ( ) ;
85
91
match session. peer_certificates ( ) {
86
- Some ( certs) if !certs. is_empty ( ) => {
87
- let sha256 = digest:: digest ( & digest:: SHA256 , certs[ 0 ] . as_ref ( ) ) ;
88
- ChannelBinding :: tls_server_end_point ( sha256. as_ref ( ) . into ( ) )
89
- }
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 ( ) ) ,
90
112
_ => ChannelBinding :: none ( ) ,
91
113
}
92
114
}
@@ -130,30 +152,62 @@ where
130
152
mod tests {
131
153
use super :: * ;
132
154
use futures:: future:: TryFutureExt ;
133
- use rustls:: { client:: ServerCertVerified , client:: ServerCertVerifier , Certificate , Error } ;
134
- use std:: time:: SystemTime ;
135
-
155
+ use rustls:: {
156
+ client:: danger:: ServerCertVerifier ,
157
+ client:: danger:: { HandshakeSignatureValid , ServerCertVerified } ,
158
+ Error , SignatureScheme ,
159
+ } ;
160
+ use rustls:: pki_types:: { CertificateDer , UnixTime } ;
161
+
162
+ #[ derive( Debug ) ]
136
163
struct AcceptAllVerifier { }
137
164
impl ServerCertVerifier for AcceptAllVerifier {
138
165
fn verify_server_cert (
139
166
& self ,
140
- _end_entity : & Certificate ,
141
- _intermediates : & [ Certificate ] ,
142
- _server_name : & ServerName ,
143
- _scts : & mut dyn Iterator < Item = & [ u8 ] > ,
167
+ _end_entity : & CertificateDer < ' _ > ,
168
+ _intermediates : & [ CertificateDer < ' _ > ] ,
169
+ _server_name : & ServerName < ' _ > ,
144
170
_ocsp_response : & [ u8 ] ,
145
- _now : SystemTime ,
171
+ _now : UnixTime ,
146
172
) -> Result < ServerCertVerified , Error > {
147
173
Ok ( ServerCertVerified :: assertion ( ) )
148
174
}
175
+
176
+ fn verify_tls12_signature (
177
+ & self ,
178
+ _message : & [ u8 ] ,
179
+ _cert : & CertificateDer < ' _ > ,
180
+ _dss : & rustls:: DigitallySignedStruct ,
181
+ ) -> Result < rustls:: client:: danger:: HandshakeSignatureValid , Error > {
182
+ Ok ( HandshakeSignatureValid :: assertion ( ) )
183
+ }
184
+
185
+ fn verify_tls13_signature (
186
+ & self ,
187
+ _message : & [ u8 ] ,
188
+ _cert : & CertificateDer < ' _ > ,
189
+ _dss : & rustls:: DigitallySignedStruct ,
190
+ ) -> Result < rustls:: client:: danger:: HandshakeSignatureValid , Error > {
191
+ Ok ( HandshakeSignatureValid :: assertion ( ) )
192
+ }
193
+
194
+ fn supported_verify_schemes ( & self ) -> Vec < SignatureScheme > {
195
+ vec ! [
196
+ SignatureScheme :: ECDSA_NISTP384_SHA384 ,
197
+ SignatureScheme :: ECDSA_NISTP256_SHA256 ,
198
+ SignatureScheme :: RSA_PSS_SHA512 ,
199
+ SignatureScheme :: RSA_PSS_SHA384 ,
200
+ SignatureScheme :: RSA_PSS_SHA256 ,
201
+ SignatureScheme :: ED25519 ,
202
+ ]
203
+ }
149
204
}
150
205
151
206
#[ tokio:: test]
152
207
async fn it_works ( ) {
153
208
env_logger:: builder ( ) . is_test ( true ) . try_init ( ) . unwrap ( ) ;
154
209
155
210
let mut config = rustls:: ClientConfig :: builder ( )
156
- . with_safe_defaults ( )
157
211
. with_root_certificates ( rustls:: RootCertStore :: empty ( ) )
158
212
. with_no_client_auth ( ) ;
159
213
config
0 commit comments