@@ -5,23 +5,43 @@ use std::sync::Arc;
5
5
6
6
use anyhow:: Context ;
7
7
use rustls_pemfile:: { certs, pkcs8_private_keys} ;
8
- use tokio_rustls:: { rustls, TlsAcceptor } ;
8
+ use tokio_rustls:: rustls:: pki_types:: pem:: PemObject ;
9
+ use tokio_rustls:: rustls:: pki_types:: { CertificateDer , PrivateKeyDer } ;
10
+ use tokio_rustls:: rustls:: { self } ;
11
+ use tokio_rustls:: TlsAcceptor ;
9
12
10
13
pub struct TlsIdentityCtx {
11
- pub cert : rustls :: pki_types :: CertificateDer < ' static > ,
12
- pub priv_key : rustls :: pki_types :: PrivateKeyDer < ' static > ,
14
+ pub certs : Vec < CertificateDer < ' static > > ,
15
+ pub priv_key : PrivateKeyDer < ' static > ,
13
16
pub pub_key : Vec < u8 > ,
14
17
}
15
18
16
19
impl TlsIdentityCtx {
20
+ /// A constructor to create a `TlsIdentityCtx` from the given certificate and key paths.
21
+ ///
22
+ /// The file format can be either PEM (if the file extension ends with .pem) or DER.
17
23
pub fn init_from_paths ( cert_path : & Path , key_path : & Path ) -> anyhow:: Result < Self > {
18
- use x509_cert:: der:: Decode as _;
24
+ let certs: Vec < _ > = if cert_path. extension ( ) . map_or ( false , |ext| ext == "pem" ) {
25
+ CertificateDer :: pem_file_iter ( cert_path)
26
+ } else {
27
+ certs ( & mut BufReader :: new ( File :: open ( cert_path) ?) )
28
+ }
29
+ . collect :: < Result < _ , _ > > ( )
30
+ . context ( format ! ( "reading server cert `{cert_path:?}`" ) ) ?;
19
31
20
- let cert = certs ( & mut BufReader :: new ( File :: open ( cert_path) ?) )
21
- . next ( )
22
- . context ( "no certificate" ) ??;
32
+ let priv_key = if key_path. extension ( ) . map_or ( false , |ext| ext == "pem" ) {
33
+ PrivateKeyDer :: from_pem_file ( key_path) . context ( "reading server key `{key_path:?}`" ) ?
34
+ } else {
35
+ pkcs8_private_keys ( & mut BufReader :: new ( File :: open ( key_path) ?) )
36
+ . next ( )
37
+ . context ( "no private key" ) ?
38
+ . map ( PrivateKeyDer :: from) ?
39
+ } ;
23
40
24
41
let pub_key = {
42
+ use x509_cert:: der:: Decode as _;
43
+
44
+ let cert = certs. first ( ) . ok_or_else ( || std:: io:: Error :: other ( "invalid cert" ) ) ?;
25
45
let cert = x509_cert:: Certificate :: from_der ( & cert) . map_err ( std:: io:: Error :: other) ?;
26
46
cert. tbs_certificate
27
47
. subject_public_key_info
@@ -31,13 +51,8 @@ impl TlsIdentityCtx {
31
51
. to_owned ( )
32
52
} ;
33
53
34
- let priv_key = pkcs8_private_keys ( & mut BufReader :: new ( File :: open ( key_path) ?) )
35
- . next ( )
36
- . context ( "no private key" ) ?
37
- . map ( rustls:: pki_types:: PrivateKeyDer :: from) ?;
38
-
39
54
Ok ( Self {
40
- cert ,
55
+ certs ,
41
56
priv_key,
42
57
pub_key,
43
58
} )
@@ -46,7 +61,7 @@ impl TlsIdentityCtx {
46
61
pub fn make_acceptor ( & self ) -> anyhow:: Result < TlsAcceptor > {
47
62
let mut server_config = rustls:: ServerConfig :: builder ( )
48
63
. with_no_client_auth ( )
49
- . with_single_cert ( vec ! [ self . cert . clone( ) ] , self . priv_key . clone_key ( ) )
64
+ . with_single_cert ( self . certs . clone ( ) , self . priv_key . clone_key ( ) )
50
65
. context ( "bad certificate/key" ) ?;
51
66
52
67
// This adds support for the SSLKEYLOGFILE env variable (https://wiki.wireshark.org/TLS#using-the-pre-master-secret)
0 commit comments