@@ -5,23 +5,44 @@ 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
+ . context ( format ! ( "reading server cert `{cert_path:?}`" ) ) ?
27
+ . map ( |cert| cert. unwrap ( ) )
28
+ . collect ( )
29
+ } else {
30
+ certs ( & mut BufReader :: new ( File :: open ( cert_path) ?) ) . collect :: < Result < _ , _ > > ( ) ?
31
+ } ;
19
32
20
- let cert = certs ( & mut BufReader :: new ( File :: open ( cert_path) ?) )
21
- . next ( )
22
- . context ( "no certificate" ) ??;
33
+ let priv_key = if key_path. extension ( ) . map_or ( false , |ext| ext == "pem" ) {
34
+ PrivateKeyDer :: from_pem_file ( key_path) . context ( "reading server key `{key_path:?}`" ) ?
35
+ } else {
36
+ pkcs8_private_keys ( & mut BufReader :: new ( File :: open ( key_path) ?) )
37
+ . next ( )
38
+ . context ( "no private key" ) ?
39
+ . map ( PrivateKeyDer :: from) ?
40
+ } ;
23
41
24
42
let pub_key = {
43
+ use x509_cert:: der:: Decode as _;
44
+
45
+ let cert = certs. first ( ) . ok_or_else ( || std:: io:: Error :: other ( "invalid cert" ) ) ?;
25
46
let cert = x509_cert:: Certificate :: from_der ( & cert) . map_err ( std:: io:: Error :: other) ?;
26
47
cert. tbs_certificate
27
48
. subject_public_key_info
@@ -31,13 +52,8 @@ impl TlsIdentityCtx {
31
52
. to_owned ( )
32
53
} ;
33
54
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
55
Ok ( Self {
40
- cert ,
56
+ certs ,
41
57
priv_key,
42
58
pub_key,
43
59
} )
@@ -46,7 +62,7 @@ impl TlsIdentityCtx {
46
62
pub fn make_acceptor ( & self ) -> anyhow:: Result < TlsAcceptor > {
47
63
let mut server_config = rustls:: ServerConfig :: builder ( )
48
64
. with_no_client_auth ( )
49
- . with_single_cert ( vec ! [ self . cert . clone( ) ] , self . priv_key . clone_key ( ) )
65
+ . with_single_cert ( self . certs . clone ( ) , self . priv_key . clone_key ( ) )
50
66
. context ( "bad certificate/key" ) ?;
51
67
52
68
// This adds support for the SSLKEYLOGFILE env variable (https://wiki.wireshark.org/TLS#using-the-pre-master-secret)
0 commit comments