@@ -12,23 +12,23 @@ use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
12
12
use futures_util:: ready;
13
13
use hyper:: server:: accept:: Accept ;
14
14
use hyper:: server:: conn:: { AddrIncoming , AddrStream } ;
15
+ use tokio_rustls:: rustls:: server:: WebPkiClientVerifier ;
16
+ use tokio_rustls:: rustls:: { Error as TlsError , RootCertStore , ServerConfig } ;
15
17
16
18
use crate :: transport:: Transport ;
17
- use tokio_rustls:: rustls:: {
18
- server:: { AllowAnyAnonymousOrAuthenticatedClient , AllowAnyAuthenticatedClient , NoClientAuth } ,
19
- Certificate , Error as TlsError , PrivateKey , RootCertStore , ServerConfig ,
20
- } ;
21
19
22
20
/// Represents errors that can occur building the TlsConfig
23
21
#[ derive( Debug ) ]
24
22
pub ( crate ) enum TlsConfigError {
25
23
Io ( io:: Error ) ,
26
24
/// An Error parsing the Certificate
27
25
CertParseError ,
28
- /// An Error parsing a Pkcs8 key
29
- Pkcs8ParseError ,
30
- /// An Error parsing a Rsa key
31
- RsaParseError ,
26
+ /// Identity PEM is invalid
27
+ InvalidIdentityPem ,
28
+ /// Identity PEM is missing a private key such as RSA, ECC or PKCS8
29
+ MissingPrivateKey ,
30
+ /// Unknown private key format
31
+ UnknownPrivateKeyFormat ,
32
32
/// An error from an empty key
33
33
EmptyKey ,
34
34
/// An error from an invalid key
@@ -40,8 +40,12 @@ impl fmt::Display for TlsConfigError {
40
40
match self {
41
41
TlsConfigError :: Io ( err) => err. fmt ( f) ,
42
42
TlsConfigError :: CertParseError => write ! ( f, "certificate parse error" ) ,
43
- TlsConfigError :: Pkcs8ParseError => write ! ( f, "pkcs8 parse error" ) ,
44
- TlsConfigError :: RsaParseError => write ! ( f, "rsa parse error" ) ,
43
+ TlsConfigError :: UnknownPrivateKeyFormat => write ! ( f, "unknown private key format" ) ,
44
+ TlsConfigError :: MissingPrivateKey => write ! (
45
+ f,
46
+ "Identity PEM is missing a private key such as RSA, ECC or PKCS8"
47
+ ) ,
48
+ TlsConfigError :: InvalidIdentityPem => write ! ( f, "identity PEM is invalid" ) ,
45
49
TlsConfigError :: EmptyKey => write ! ( f, "key contains no private key" ) ,
46
50
TlsConfigError :: InvalidKey ( err) => write ! ( f, "key contains an invalid key, {}" , err) ,
47
51
}
@@ -170,73 +174,81 @@ impl TlsConfigBuilder {
170
174
pub ( crate ) fn build ( mut self ) -> Result < ServerConfig , TlsConfigError > {
171
175
let mut cert_rdr = BufReader :: new ( self . cert ) ;
172
176
let cert = rustls_pemfile:: certs ( & mut cert_rdr)
173
- . map_err ( |_e| TlsConfigError :: CertParseError ) ?
174
- . into_iter ( )
175
- . map ( Certificate )
176
- . collect ( ) ;
177
-
178
- let key = {
179
- // convert it to Vec<u8> to allow reading it again if key is RSA
180
- let mut key_vec = Vec :: new ( ) ;
181
- self . key
182
- . read_to_end ( & mut key_vec)
183
- . map_err ( TlsConfigError :: Io ) ?;
184
-
185
- if key_vec. is_empty ( ) {
186
- return Err ( TlsConfigError :: EmptyKey ) ;
187
- }
177
+ . collect :: < Result < Vec < _ > , _ > > ( )
178
+ . map_err ( |_e| TlsConfigError :: CertParseError ) ?;
188
179
189
- let mut pkcs8 = rustls_pemfile:: pkcs8_private_keys ( & mut key_vec. as_slice ( ) )
190
- . map_err ( |_e| TlsConfigError :: Pkcs8ParseError ) ?;
180
+ let mut key_vec = Vec :: new ( ) ;
181
+ self . key
182
+ . read_to_end ( & mut key_vec)
183
+ . map_err ( TlsConfigError :: Io ) ?;
191
184
192
- if !pkcs8. is_empty ( ) {
193
- PrivateKey ( pkcs8. remove ( 0 ) )
194
- } else {
195
- let mut rsa = rustls_pemfile:: rsa_private_keys ( & mut key_vec. as_slice ( ) )
196
- . map_err ( |_e| TlsConfigError :: RsaParseError ) ?;
185
+ if key_vec. is_empty ( ) {
186
+ return Err ( TlsConfigError :: EmptyKey ) ;
187
+ }
197
188
198
- if !rsa. is_empty ( ) {
199
- PrivateKey ( rsa. remove ( 0 ) )
200
- } else {
201
- return Err ( TlsConfigError :: EmptyKey ) ;
202
- }
189
+ let mut key_opt = None ;
190
+ let mut key_cur = std:: io:: Cursor :: new ( key_vec) ;
191
+ for item in rustls_pemfile:: read_all ( & mut key_cur)
192
+ . collect :: < Result < Vec < _ > , _ > > ( )
193
+ . map_err ( |_e| TlsConfigError :: InvalidIdentityPem ) ?
194
+ {
195
+ match item {
196
+ rustls_pemfile:: Item :: Pkcs1Key ( k) => key_opt = Some ( k. into ( ) ) ,
197
+ rustls_pemfile:: Item :: Pkcs8Key ( k) => key_opt = Some ( k. into ( ) ) ,
198
+ rustls_pemfile:: Item :: Sec1Key ( k) => key_opt = Some ( k. into ( ) ) ,
199
+ _ => return Err ( TlsConfigError :: UnknownPrivateKeyFormat ) ,
203
200
}
201
+ }
202
+ let key = match key_opt {
203
+ Some ( v) => v,
204
+ _ => return Err ( TlsConfigError :: MissingPrivateKey ) ,
204
205
} ;
205
206
206
207
fn read_trust_anchor (
207
208
trust_anchor : Box < dyn Read + Send + Sync > ,
208
209
) -> Result < RootCertStore , TlsConfigError > {
209
210
let trust_anchors = {
210
211
let mut reader = BufReader :: new ( trust_anchor) ;
211
- rustls_pemfile:: certs ( & mut reader) . map_err ( TlsConfigError :: Io ) ?
212
+ rustls_pemfile:: certs ( & mut reader)
213
+ . collect :: < Result < Vec < _ > , _ > > ( )
214
+ . map_err ( TlsConfigError :: Io ) ?
212
215
} ;
213
216
214
217
let mut store = RootCertStore :: empty ( ) ;
215
- let ( added, _skipped) = store. add_parsable_certificates ( & trust_anchors) ;
218
+ let ( added, _skipped) = store. add_parsable_certificates ( trust_anchors) ;
216
219
if added == 0 {
217
220
return Err ( TlsConfigError :: CertParseError ) ;
218
221
}
219
222
220
223
Ok ( store)
221
224
}
222
225
223
- let client_auth = match self . client_auth {
224
- TlsClientAuth :: Off => NoClientAuth :: boxed ( ) ,
225
- TlsClientAuth :: Optional ( trust_anchor) => {
226
- AllowAnyAnonymousOrAuthenticatedClient :: new ( read_trust_anchor ( trust_anchor) ?)
227
- . boxed ( )
228
- }
229
- TlsClientAuth :: Required ( trust_anchor) => {
230
- AllowAnyAuthenticatedClient :: new ( read_trust_anchor ( trust_anchor) ?) . boxed ( )
226
+ let config = {
227
+ let builder = ServerConfig :: builder ( ) ;
228
+ let mut config = match self . client_auth {
229
+ TlsClientAuth :: Off => builder. with_no_client_auth ( ) ,
230
+ TlsClientAuth :: Optional ( trust_anchor) => {
231
+ let verifier =
232
+ WebPkiClientVerifier :: builder ( read_trust_anchor ( trust_anchor) ?. into ( ) )
233
+ . allow_unauthenticated ( )
234
+ . build ( )
235
+ . map_err ( |_| TlsConfigError :: CertParseError ) ?;
236
+ builder. with_client_cert_verifier ( verifier)
237
+ }
238
+ TlsClientAuth :: Required ( trust_anchor) => {
239
+ let verifier =
240
+ WebPkiClientVerifier :: builder ( read_trust_anchor ( trust_anchor) ?. into ( ) )
241
+ . build ( )
242
+ . map_err ( |_| TlsConfigError :: CertParseError ) ?;
243
+ builder. with_client_cert_verifier ( verifier)
244
+ }
231
245
}
246
+ . with_single_cert_with_ocsp ( cert, key, self . ocsp_resp )
247
+ . map_err ( TlsConfigError :: InvalidKey ) ?;
248
+ config. alpn_protocols = vec ! [ "h2" . into( ) , "http/1.1" . into( ) ] ;
249
+ config
232
250
} ;
233
251
234
- let mut config = ServerConfig :: builder ( )
235
- . with_safe_defaults ( )
236
- . with_client_cert_verifier ( client_auth)
237
- . with_single_cert_with_ocsp_and_sct ( cert, key, self . ocsp_resp , Vec :: new ( ) )
238
- . map_err ( TlsConfigError :: InvalidKey ) ?;
239
- config. alpn_protocols = vec ! [ "h2" . into( ) , "http/1.1" . into( ) ] ;
240
252
Ok ( config)
241
253
}
242
254
}
@@ -416,4 +428,25 @@ mod tests {
416
428
. build ( )
417
429
. unwrap ( ) ;
418
430
}
431
+
432
+ #[ test]
433
+ fn file_ecc_cert_key ( ) {
434
+ TlsConfigBuilder :: new ( )
435
+ . key_path ( "examples/tls/key.ecc" )
436
+ . cert_path ( "examples/tls/cert.ecc.pem" )
437
+ . build ( )
438
+ . unwrap ( ) ;
439
+ }
440
+
441
+ #[ test]
442
+ fn bytes_ecc_cert_key ( ) {
443
+ let key = include_str ! ( "../examples/tls/key.ecc" ) ;
444
+ let cert = include_str ! ( "../examples/tls/cert.ecc.pem" ) ;
445
+
446
+ TlsConfigBuilder :: new ( )
447
+ . key ( key. as_bytes ( ) )
448
+ . cert ( cert. as_bytes ( ) )
449
+ . build ( )
450
+ . unwrap ( ) ;
451
+ }
419
452
}
0 commit comments