@@ -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 , ' cert , ' pass , ' chain > {
128
+ pub struct TLSConfig < ' data , ' key , ' chain > {
129
129
/// Use for client certificate authentication
130
- pub identity : Option < Identity < ' der , ' cert , ' pass > > ,
130
+ pub identity : Option < Identity < ' data , ' key > > ,
131
131
/// The custom certificates chain in PEM format
132
132
pub cert_chain : Option < & ' chain str > ,
133
133
}
@@ -144,7 +144,7 @@ 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 ( ) ,
@@ -154,28 +154,28 @@ impl OwnedTLSConfig {
154
154
155
155
/// Holds one of:
156
156
/// - PKCS#12 DER-encoded identity and decryption password
157
- /// - PEM-encoded DER identity (without decryption password)
157
+ /// - PKCS#8 PEM-encoded certificate and key (without decryption password)
158
158
#[ derive( Debug , PartialEq ) ]
159
- pub enum Identity < ' der , ' cert , ' pass > {
159
+ pub enum Identity < ' data , ' key > {
160
160
/// PKCS#12 DER-encoded identity with decryption password
161
161
PKCS12 {
162
162
/// PKCS#12 DER-encoded identity
163
- der : & ' der [ u8 ] ,
163
+ der : & ' data [ u8 ] ,
164
164
/// Decryption password
165
- password : & ' pass str ,
165
+ password : & ' key str ,
166
166
} ,
167
167
/// PEM encoded DER private key with PEM encoded certificate
168
- PEM {
169
- /// PEM-encoded identity
170
- der : & ' der [ u8 ] ,
168
+ PKCS8 {
171
169
/// PEM-encoded certificate
172
- cert : & ' cert [ u8 ]
173
- }
170
+ pem : & ' data [ u8 ] ,
171
+ /// PEM-encoded key
172
+ key : & ' key [ u8 ] ,
173
+ } ,
174
174
}
175
175
176
176
/// Holds one of:
177
177
/// - PKCS#12 DER-encoded identity and decryption password
178
- /// - PEM-encoded DER identity (without decryption password)
178
+ /// - PKCS#8 PEM-encoded certificate and key (without decryption password)
179
179
#[ derive( Debug , PartialEq ) ]
180
180
pub enum OwnedIdentity {
181
181
/// PKCS#12 DER-encoded identity with decryption password
@@ -185,22 +185,22 @@ pub enum OwnedIdentity {
185
185
/// Decryption password
186
186
password : String ,
187
187
} ,
188
- /// PEM encoded DER private key with PEM encoded certificate
189
- PEM {
190
- /// PEM-encoded identity
191
- der : Vec < u8 > ,
188
+ /// PKCS#8 encoded DER private key with PEM encoded certificate
189
+ PKCS8 {
192
190
/// PEM-encoded certificate
193
- cert : Vec < u8 >
194
- }
191
+ pem : Vec < u8 > ,
192
+ /// PEM-encoded key
193
+ key : Vec < u8 > ,
194
+ } ,
195
195
}
196
196
197
197
impl OwnedIdentity {
198
198
/// Get the ephemeral `Identity` corresponding to the `OwnedIdentity`
199
199
#[ must_use]
200
- pub fn as_ref ( & self ) -> Identity < ' _ , ' _ , ' _ > {
200
+ pub fn as_ref ( & self ) -> Identity < ' _ , ' _ > {
201
201
match self {
202
- Self :: PEM { der , cert } => Identity :: PEM { der , cert } ,
203
- Self :: PKCS12 { der, password } => Identity :: PKCS12 { der, password }
202
+ Self :: PKCS8 { pem , key } => Identity :: PKCS8 { pem , key } ,
203
+ Self :: PKCS12 { der, password } => Identity :: PKCS12 { der, password } ,
204
204
}
205
205
}
206
206
}
@@ -265,7 +265,7 @@ impl TcpStream {
265
265
pub fn into_tls (
266
266
self ,
267
267
domain : & str ,
268
- config : TLSConfig < ' _ , ' _ , ' _ , ' _ > ,
268
+ config : TLSConfig < ' _ , ' _ , ' _ > ,
269
269
) -> Result < Self , HandshakeError > {
270
270
into_tls_impl ( self , domain, config)
271
271
}
@@ -349,9 +349,11 @@ fn into_rustls_common(
349
349
s : TcpStream ,
350
350
mut c : RustlsConnectorConfig ,
351
351
domain : & str ,
352
- config : TLSConfig < ' _ , ' _ , ' _ , ' _ > ,
352
+ config : TLSConfig < ' _ , ' _ , ' _ > ,
353
353
) -> HandshakeResult {
354
- use rustls_connector:: rustls_pki_types:: { pem:: PemObject , CertificateDer , PrivateKeyDer , PrivatePkcs8KeyDer } ;
354
+ use rustls_connector:: rustls_pki_types:: {
355
+ pem:: PemObject , CertificateDer , PrivateKeyDer , PrivatePkcs8KeyDer ,
356
+ } ;
355
357
356
358
if let Some ( cert_chain) = config. cert_chain {
357
359
let mut cert_chain = std:: io:: BufReader :: new ( cert_chain. as_bytes ( ) ) ;
@@ -366,23 +368,32 @@ fn into_rustls_common(
366
368
let pfx = p12_keystore:: KeyStore :: from_pkcs12 ( der, password)
367
369
. map_err ( |err| io:: Error :: new ( io:: ErrorKind :: Other , err) ) ?;
368
370
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
- ) ;
371
+ return Err ( io:: Error :: new (
372
+ io:: ErrorKind :: Other ,
373
+ "No private key in pkcs12 DER" ,
374
+ )
375
+ . into ( ) ) ;
372
376
} ;
373
377
let certs = keychain
374
378
. chain ( )
375
379
. iter ( )
376
380
. map ( |cert| CertificateDer :: from ( cert. as_der ( ) . to_vec ( ) ) )
377
381
. 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
+ (
383
+ certs,
384
+ PrivateKeyDer :: from ( PrivatePkcs8KeyDer :: from ( keychain. key ( ) . to_vec ( ) ) ) ,
385
+ )
386
+ }
387
+ Identity :: PKCS8 { pem, key } => {
388
+ let mut cert_reader = std:: io:: BufReader :: new ( pem) ;
382
389
let certs = rustls_pemfile:: certs ( & mut cert_reader)
383
390
. collect :: < Result < Vec < _ > , _ > > ( )
384
391
. 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) ) ?)
392
+ (
393
+ certs,
394
+ PrivateKeyDer :: from_pem_slice ( key)
395
+ . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?,
396
+ )
386
397
}
387
398
} ;
388
399
c. connector_with_single_cert ( certs, key)
@@ -395,31 +406,42 @@ fn into_rustls_common(
395
406
396
407
cfg_if ! {
397
408
if #[ cfg( feature = "rustls-native-certs" ) ] {
398
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
409
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
399
410
into_rustls_common( s, RustlsConnectorConfig :: new_with_native_certs( ) ?, domain, config)
400
411
}
401
412
} else if #[ cfg( feature = "rustls-webpki-roots-certs" ) ] {
402
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
413
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
403
414
into_rustls_common( s, RustlsConnectorConfig :: new_with_webpki_roots_certs( ) , domain, config)
404
415
}
405
416
} else if #[ cfg( feature = "rustls-common" ) ] {
406
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
417
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
407
418
into_rustls_common( s, RustlsConnectorConfig :: default ( ) , domain, config)
408
419
}
409
420
} else if #[ cfg( feature = "openssl" ) ] {
410
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
421
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
411
422
use openssl:: x509:: X509 ;
412
423
413
424
let mut builder = OpenSslConnector :: builder( OpenSslMethod :: tls( ) ) ?;
414
425
if let Some ( identity) = config. identity {
415
- let identity = openssl:: pkcs12:: Pkcs12 :: from_der( identity. der) ?. parse2( identity. password) ?;
416
- if let Some ( cert) = identity. cert. as_ref( ) {
426
+ let ( cert, pkey, chain) = match identity {
427
+ Identity :: PKCS8 { pem, key } => {
428
+ let pkey = openssl:: pkey:: PKey :: private_key_from_pem( key) ?;
429
+ let mut chain = openssl:: x509:: X509 :: stack_from_pem( pem) ?. into_iter( ) ;
430
+ let cert = chain. next( ) ;
431
+ ( cert, Some ( pkey) , Some ( chain. collect( ) ) )
432
+ }
433
+ Identity :: PKCS12 { der, password } => {
434
+ let mut openssl_identity = openssl:: pkcs12:: Pkcs12 :: from_der( der) ?. parse2( password) ?;
435
+ ( openssl_identity. cert, openssl_identity. pkey, openssl_identity. ca. take( ) . map( |stack| stack. into_iter( ) . collect:: <Vec <_>>( ) ) )
436
+ } ,
437
+ } ;
438
+ if let Some ( cert) = cert. as_ref( ) {
417
439
builder. set_certificate( cert) ?;
418
440
}
419
- if let Some ( pkey) = identity . pkey. as_ref( ) {
441
+ if let Some ( pkey) = pkey. as_ref( ) {
420
442
builder. set_private_key( pkey) ?;
421
443
}
422
- if let Some ( chain) = identity . ca . as_ref( ) {
444
+ if let Some ( chain) = chain . as_ref( ) {
423
445
for cert in chain. iter( ) . rev( ) {
424
446
builder. add_extra_chain_cert( cert. to_owned( ) ) ?;
425
447
}
@@ -433,12 +455,16 @@ cfg_if! {
433
455
s. into_openssl( & builder. build( ) , domain)
434
456
}
435
457
} else if #[ cfg( feature = "native-tls" ) ] {
436
- fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
458
+ fn into_tls_impl( s: TcpStream , domain: & str , config: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
437
459
use native_tls:: Certificate ;
438
460
439
461
let mut builder = NativeTlsConnector :: builder( ) ;
440
462
if let Some ( identity) = config. identity {
441
- builder. identity( native_tls:: Identity :: from_pkcs12( identity. der, identity. password) . map_err( |e| io:: Error :: new( io:: ErrorKind :: Other , e) ) ?) ;
463
+ let native_identity = match identity {
464
+ Identity :: PKCS8 { pem, key } => native_tls:: Identity :: from_pkcs8( pem, key) ,
465
+ Identity :: PKCS12 { der, password } => native_tls:: Identity :: from_pkcs12( der, password) ,
466
+ } ;
467
+ builder. identity( native_identity. map_err( |e| io:: Error :: new( io:: ErrorKind :: Other , e) ) ?) ;
442
468
}
443
469
if let Some ( cert_chain) = config. cert_chain {
444
470
let mut cert_chain = std:: io:: BufReader :: new( cert_chain. as_bytes( ) ) ;
@@ -449,7 +475,7 @@ cfg_if! {
449
475
s. into_native_tls( & builder. build( ) . map_err( |e| io:: Error :: new( io:: ErrorKind :: Other , e) ) ?, domain)
450
476
}
451
477
} else {
452
- fn into_tls_impl( s: TcpStream , _domain: & str , _: TLSConfig <' _, ' _, ' _, ' _ >) -> HandshakeResult {
478
+ fn into_tls_impl( s: TcpStream , _domain: & str , _: TLSConfig <' _, ' _, ' _>) -> HandshakeResult {
453
479
Ok ( s. into_plain( ) ?)
454
480
}
455
481
}
0 commit comments