@@ -19,18 +19,7 @@ use crate::x509::OwnedX509Stack;
1919/// and `SSL_CTX_use_PrivateKey_file`, and matching man pages.
2020#[ derive( Clone , Default , Debug ) ]
2121pub struct CertifiedKeySet {
22- /// Last `SSL_CTX_use_certificate_chain_file` result, pending a matching
23- /// `SSL_CTX_use_PrivateKey_file`.
24- pending_cert_chain : Option < Vec < CertificateDer < ' static > > > ,
25-
26- /// Last `SSL_CTX_use_certificate` result, prepended to chain during commit.
27- /// May be absent.
28- pending_cert_end_entity : Option < CertificateDer < ' static > > ,
29-
30- /// The key and certificate we're currently using.
31- ///
32- /// TODO: support multiple key types, and demultiplex them by type.
33- current_key : Option < OpenSslCertifiedKey > ,
22+ item : KeySetItem ,
3423}
3524
3625impl CertifiedKeySet {
@@ -58,63 +47,103 @@ impl CertifiedKeySet {
5847 & mut self ,
5948 chain : Vec < CertificateDer < ' static > > ,
6049 ) -> Result < ( ) , error:: Error > {
61- self . pending_cert_chain = Some ( chain) ;
50+ self . item . adopt_chain_tail ( Some ( chain) ) ;
6251 Ok ( ( ) )
6352 }
6453
6554 pub fn stage_certificate_end_entity (
6655 & mut self ,
6756 end : CertificateDer < ' static > ,
6857 ) -> Result < ( ) , error:: Error > {
69- self . pending_cert_end_entity = Some ( end) ;
70- Ok ( ( ) )
58+ self . item . cert_end_entity = Some ( end) ;
59+ self . item . promote ( )
7160 }
7261
7362 pub fn commit_private_key ( & mut self , key : EvpPkey ) -> Result < ( ) , error:: Error > {
74- let chain = match (
75- self . pending_cert_end_entity . take ( ) ,
76- self . pending_cert_chain . take ( ) ,
77- ) {
78- ( Some ( end_entity) , Some ( mut chain) ) => {
79- chain. insert ( 0 , end_entity) ;
80- chain
81- }
82- ( None , Some ( chain) ) => chain,
83- ( Some ( end_entity) , None ) => vec ! [ end_entity] ,
84- ( None , None ) => {
85- return Err ( error:: Error :: bad_data ( "no certificate found for key" ) ) ;
86- }
87- } ;
88-
89- self . current_key = Some ( OpenSslCertifiedKey :: new ( chain, key) ?) ;
90- Ok ( ( ) )
63+ self . item . key = Some ( key) ;
64+ self . item . promote ( )
9165 }
9266
9367 pub fn client_resolver ( & self ) -> Option < Arc < dyn ResolvesClientCert > > {
94- self . current_key . as_ref ( ) . map ( |ck| ck. client_resolver ( ) )
68+ self . item
69+ . constructed
70+ . as_ref ( )
71+ . map ( |ck| ck. client_resolver ( ) )
9572 }
9673
9774 pub fn server_resolver ( & self ) -> Option < Arc < dyn ResolvesServerCert > > {
98- self . current_key . as_ref ( ) . map ( |ck| ck. server_resolver ( ) )
75+ self . item
76+ . constructed
77+ . as_ref ( )
78+ . map ( |ck| ck. server_resolver ( ) )
9979 }
10080
10181 /// For `SSL_get_certificate`
10282 pub fn borrow_current_cert ( & self ) -> * mut X509 {
103- self . current_key
83+ self . item
84+ . constructed
10485 . as_ref ( )
10586 . map ( |ck| ck. borrow_cert ( ) )
10687 . unwrap_or ( ptr:: null_mut ( ) )
10788 }
10889
10990 /// For `SSL_get_privatekey`
11091 pub fn borrow_current_key ( & self ) -> * mut EVP_PKEY {
111- self . current_key
92+ self . item
93+ . constructed
11294 . as_ref ( )
11395 . map ( |ck| ck. borrow_key ( ) )
11496 . unwrap_or ( ptr:: null_mut ( ) )
11597 }
11698}
11799
100+ #[ derive( Clone , Debug , Default ) ]
101+ pub struct KeySetItem {
102+ /// Most recent certificate chain tail.
103+ cert_chain_tail : Option < Vec < CertificateDer < ' static > > > ,
104+
105+ /// Most recent end-entity certificate.
106+ cert_end_entity : Option < CertificateDer < ' static > > ,
107+
108+ /// Most recent value from `SSL_CTX_use_PrivateKey_file`
109+ key : Option < EvpPkey > ,
110+
111+ /// The key and certificate we're currently using.
112+ ///
113+ /// This is constructed eagerly to validate the cert/key are consistent.
114+ constructed : Option < OpenSslCertifiedKey > ,
115+ }
116+
117+ impl KeySetItem {
118+ fn adopt_chain_tail ( & mut self , cert_chain_tail : Option < Vec < CertificateDer < ' static > > > ) {
119+ if let Some ( tail) = cert_chain_tail {
120+ self . cert_chain_tail = Some ( tail) ;
121+ }
122+ }
123+
124+ /// If `self` has enough parts (a key and at least an end-entity cert) then fill in
125+ /// `constructed`.
126+ fn promote ( & mut self ) -> Result < ( ) , error:: Error > {
127+ let Some ( key) = & self . key else {
128+ return Ok ( ( ) ) ;
129+ } ;
130+
131+ // Reconstitute full chain from parts.
132+ let chain = match ( & self . cert_end_entity , & self . cert_chain_tail ) {
133+ ( Some ( end_entity) , Some ( tail) ) => {
134+ let mut chain = tail. clone ( ) ;
135+ chain. insert ( 0 , end_entity. clone ( ) ) ;
136+ chain
137+ }
138+ ( Some ( end_entity) , None ) => vec ! [ end_entity. clone( ) ] ,
139+ _ => return Ok ( ( ) ) ,
140+ } ;
141+
142+ self . constructed = Some ( OpenSslCertifiedKey :: new ( chain, key. clone ( ) ) ?) ;
143+ Ok ( ( ) )
144+ }
145+ }
146+
118147#[ derive( Clone , Debug ) ]
119148pub ( super ) struct OpenSslCertifiedKey {
120149 key : EvpPkey ,
0 commit comments