@@ -125,9 +125,9 @@ pub enum TcpStream {
125
125
126
126
/// Holds extra TLS configuration
127
127
#[ derive( Default , Debug , PartialEq ) ]
128
- pub struct TLSConfig < ' der , ' pass , ' chain > {
128
+ pub struct TLSConfig < ' der , ' cert , ' pass , ' chain > {
129
129
/// Use for client certificate authentication
130
- pub identity : Option < Identity < ' der , ' pass > > ,
130
+ pub identity : Option < Identity < ' der , ' cert , ' pass > > ,
131
131
/// The custom certificates chain in PEM format
132
132
pub cert_chain : Option < & ' chain str > ,
133
133
}
@@ -144,39 +144,63 @@ pub struct OwnedTLSConfig {
144
144
impl OwnedTLSConfig {
145
145
/// Get the ephemeral `TLSConfig` corresponding to the `OwnedTLSConfig`
146
146
#[ must_use]
147
- pub fn as_ref ( & self ) -> TLSConfig < ' _ , ' _ , ' _ > {
147
+ pub fn as_ref ( & self ) -> TLSConfig < ' _ , ' _ , ' _ , ' _ > {
148
148
TLSConfig {
149
149
identity : self . identity . as_ref ( ) . map ( OwnedIdentity :: as_ref) ,
150
150
cert_chain : self . cert_chain . as_deref ( ) ,
151
151
}
152
152
}
153
153
}
154
154
155
- /// Holds PKCS#12 DER-encoded identity and decryption password
155
+ /// Holds one of:
156
+ /// - PKCS#12 DER-encoded identity and decryption password
157
+ /// - PEM-encoded DER identity (without decryption password)
156
158
#[ derive( Debug , PartialEq ) ]
157
- pub struct Identity < ' der , ' pass > {
158
- /// PKCS#12 DER-encoded identity
159
- pub der : & ' der [ u8 ] ,
160
- /// Decryption password
161
- pub password : & ' pass str ,
162
- }
163
-
164
- /// Holds PKCS#12 DER-encoded identity and decryption password
159
+ pub enum Identity < ' der , ' cert , ' pass > {
160
+ /// PKCS#12 DER-encoded identity with decryption password
161
+ PKCS12 {
162
+ /// PKCS#12 DER-encoded identity
163
+ der : & ' der [ u8 ] ,
164
+ /// Decryption password
165
+ password : & ' pass str ,
166
+ } ,
167
+ /// PEM encoded DER private key with PEM encoded certificate
168
+ PEM {
169
+ /// PEM-encoded identity
170
+ der : & ' der [ u8 ] ,
171
+ /// PEM-encoded certificate
172
+ cert : & ' cert [ u8 ]
173
+ }
174
+ }
175
+
176
+ /// Holds one of:
177
+ /// - PKCS#12 DER-encoded identity and decryption password
178
+ /// - PEM-encoded DER identity (without decryption password)
165
179
#[ derive( Debug , PartialEq ) ]
166
- pub struct OwnedIdentity {
167
- /// PKCS#12 DER-encoded identity
168
- pub der : Vec < u8 > ,
169
- /// Decryption password
170
- pub password : String ,
180
+ pub enum OwnedIdentity {
181
+ /// PKCS#12 DER-encoded identity with decryption password
182
+ PKCS12 {
183
+ /// PKCS#12 DER-encoded identity
184
+ der : Vec < u8 > ,
185
+ /// Decryption password
186
+ password : String ,
187
+ } ,
188
+ /// PEM encoded DER private key with PEM encoded certificate
189
+ PEM {
190
+ /// PEM-encoded identity
191
+ der : Vec < u8 > ,
192
+ /// PEM-encoded certificate
193
+ cert : Vec < u8 >
194
+ }
171
195
}
172
196
173
197
impl OwnedIdentity {
174
198
/// Get the ephemeral `Identity` corresponding to the `OwnedIdentity`
175
199
#[ must_use]
176
- pub fn as_ref ( & self ) -> Identity < ' _ , ' _ > {
177
- Identity {
178
- der : & self . der ,
179
- password : & self . password ,
200
+ pub fn as_ref ( & self ) -> Identity < ' _ , ' _ , ' _ > {
201
+ match self {
202
+ Self :: PEM { der, cert } => Identity :: PEM { der, cert } ,
203
+ Self :: PKCS12 { der , password } => Identity :: PKCS12 { der , password }
180
204
}
181
205
}
182
206
}
@@ -241,7 +265,7 @@ impl TcpStream {
241
265
pub fn into_tls (
242
266
self ,
243
267
domain : & str ,
244
- config : TLSConfig < ' _ , ' _ , ' _ > ,
268
+ config : TLSConfig < ' _ , ' _ , ' _ , ' _ > ,
245
269
) -> Result < Self , HandshakeError > {
246
270
into_tls_impl ( self , domain, config)
247
271
}
@@ -325,9 +349,9 @@ fn into_rustls_common(
325
349
s : TcpStream ,
326
350
mut c : RustlsConnectorConfig ,
327
351
domain : & str ,
328
- config : TLSConfig < ' _ , ' _ , ' _ > ,
352
+ config : TLSConfig < ' _ , ' _ , ' _ , ' _ > ,
329
353
) -> HandshakeResult {
330
- use rustls_connector:: rustls_pki_types:: { CertificateDer , PrivateKeyDer , PrivatePkcs8KeyDer } ;
354
+ use rustls_connector:: rustls_pki_types:: { pem :: PemObject , CertificateDer , PrivateKeyDer , PrivatePkcs8KeyDer } ;
331
355
332
356
if let Some ( cert_chain) = config. cert_chain {
333
357
let mut cert_chain = std:: io:: BufReader :: new ( cert_chain. as_bytes ( ) ) ;
@@ -337,19 +361,30 @@ fn into_rustls_common(
337
361
c. add_parsable_certificates ( certs) ;
338
362
}
339
363
let connector = if let Some ( identity) = config. identity {
340
- let pfx = p12_keystore:: KeyStore :: from_pkcs12 ( identity. der , identity. password )
341
- . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: Other , err) ) ?;
342
- let Some ( ( _, keychain) ) = pfx. private_key_chain ( ) else {
343
- return Err (
344
- io:: Error :: new ( io:: ErrorKind :: Other , "No private key in pkcs12 DER" ) . into ( ) ,
345
- ) ;
364
+ let ( certs, key) = match identity {
365
+ Identity :: PKCS12 { der, password } => {
366
+ let pfx = p12_keystore:: KeyStore :: from_pkcs12 ( der, password)
367
+ . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: Other , err) ) ?;
368
+ let Some ( ( _, keychain) ) = pfx. private_key_chain ( ) else {
369
+ return Err (
370
+ io:: Error :: new ( io:: ErrorKind :: Other , "No private key in pkcs12 DER" ) . into ( ) ,
371
+ ) ;
372
+ } ;
373
+ let certs = keychain
374
+ . chain ( )
375
+ . iter ( )
376
+ . map ( |cert| CertificateDer :: from ( cert. as_der ( ) . to_vec ( ) ) )
377
+ . collect ( ) ;
378
+ ( certs, PrivateKeyDer :: from ( PrivatePkcs8KeyDer :: from ( keychain. key ( ) . to_vec ( ) ) ) )
379
+ } ,
380
+ Identity :: PEM { der, cert } => {
381
+ let mut cert_reader = std:: io:: BufReader :: new ( cert) ;
382
+ let certs = rustls_pemfile:: certs ( & mut cert_reader)
383
+ . collect :: < Result < Vec < _ > , _ > > ( )
384
+ . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
385
+ ( certs, PrivateKeyDer :: from_pem_slice ( der) . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?)
386
+ }
346
387
} ;
347
- let key = PrivateKeyDer :: from ( PrivatePkcs8KeyDer :: from ( keychain. key ( ) . to_vec ( ) ) ) ;
348
- let certs = keychain
349
- . chain ( )
350
- . iter ( )
351
- . map ( |cert| CertificateDer :: from ( cert. as_der ( ) . to_vec ( ) ) )
352
- . collect ( ) ;
353
388
c. connector_with_single_cert ( certs, key)
354
389
. map_err ( |err| io:: Error :: new ( io:: ErrorKind :: Other , err) ) ?
355
390
} else {
@@ -360,19 +395,19 @@ fn into_rustls_common(
360
395
361
396
cfg_if ! {
362
397
if #[ cfg( feature = "rustls-native-certs" ) ] {
363
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
398
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
364
399
into_rustls_common( s, RustlsConnectorConfig :: new_with_native_certs( ) ?, domain, config)
365
400
}
366
401
} else if #[ cfg( feature = "rustls-webpki-roots-certs" ) ] {
367
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
402
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
368
403
into_rustls_common( s, RustlsConnectorConfig :: new_with_webpki_roots_certs( ) , domain, config)
369
404
}
370
405
} else if #[ cfg( feature = "rustls-common" ) ] {
371
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
406
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
372
407
into_rustls_common( s, RustlsConnectorConfig :: default ( ) , domain, config)
373
408
}
374
409
} else if #[ cfg( feature = "openssl" ) ] {
375
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
410
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
376
411
use openssl:: x509:: X509 ;
377
412
378
413
let mut builder = OpenSslConnector :: builder( OpenSslMethod :: tls( ) ) ?;
@@ -398,7 +433,7 @@ cfg_if! {
398
433
s. into_openssl( & builder. build( ) , domain)
399
434
}
400
435
} else if #[ cfg( feature = "native-tls" ) ] {
401
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
436
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
402
437
use native_tls:: Certificate ;
403
438
404
439
let mut builder = NativeTlsConnector :: builder( ) ;
@@ -414,7 +449,7 @@ cfg_if! {
414
449
s. into_native_tls( & builder. build( ) . map_err( |e| io:: Error :: new( io:: ErrorKind :: Other , e) ) ?, domain)
415
450
}
416
451
} else {
417
- fn into_tls_impl( s: TcpStream , _domain: & str , _: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
452
+ fn into_tls_impl( s: TcpStream , _domain: & str , _: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
418
453
Ok ( s. into_plain( ) ?)
419
454
}
420
455
}
0 commit comments