@@ -43,21 +43,21 @@ use windows_sys::Win32::{
4343 CertFreeCertificateChain , CertFreeCertificateChainEngine , CertFreeCertificateContext ,
4444 CertGetCertificateChain , CertOpenStore , CertSetCertificateContextProperty ,
4545 CertVerifyCertificateChainPolicy , HTTPSPolicyCallbackData , AUTHTYPE_SERVER ,
46- CERT_CHAIN_CACHE_END_CERT , CERT_CHAIN_CONTEXT , CERT_CHAIN_ENGINE_CONFIG ,
46+ CERT_CHAIN_CACHE_END_CERT , CERT_CHAIN_CONTEXT ,
4747 CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS , CERT_CHAIN_POLICY_PARA ,
4848 CERT_CHAIN_POLICY_SSL , CERT_CHAIN_POLICY_STATUS ,
4949 CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT , CERT_CHAIN_REVOCATION_CHECK_END_CERT ,
5050 CERT_CONTEXT , CERT_OCSP_RESPONSE_PROP_ID , CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG ,
5151 CERT_STORE_ADD_ALWAYS , CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG , CERT_STORE_PROV_MEMORY ,
5252 CERT_STRONG_SIGN_PARA , CERT_TRUST_IS_PARTIAL_CHAIN , CERT_USAGE_MATCH , CRYPT_INTEGER_BLOB ,
53- CTL_USAGE , USAGE_MATCH_TYPE_AND , X509_ASN_ENCODING ,
53+ CTL_USAGE , HCERTSTORE , USAGE_MATCH_TYPE_AND , X509_ASN_ENCODING ,
5454 } ,
5555} ;
5656
5757use super :: { log_server_cert, ALLOWED_EKUS } ;
5858
5959// The `windows-sys` definition for `CERT_CHAIN_PARA` does not take old OS versions
60- // into account so we define it ourselves for better (hypothetical) OS backwards compat.
60+ // into account so we define it ourselves for better OS backwards compat.
6161// In the future a compile-time size assertion can be added against the upstream type to help stay in sync.
6262#[ allow( non_camel_case_types, non_snake_case) ]
6363#[ repr( C ) ]
@@ -77,6 +77,29 @@ struct CERT_CHAIN_PARA {
7777 pub dwStrongSignFlags : u32 ,
7878}
7979
80+ // Same workaround with CERT_CHAIN_PARA
81+ #[ allow( non_camel_case_types, non_snake_case) ]
82+ #[ repr( C ) ]
83+ #[ derive( Clone , Copy ) ]
84+ pub struct CERT_CHAIN_ENGINE_CONFIG {
85+ pub cbSize : u32 ,
86+ pub hRestrictedRoot : HCERTSTORE ,
87+ pub hRestrictedTrust : HCERTSTORE ,
88+ pub hRestrictedOther : HCERTSTORE ,
89+ pub cAdditionalStore : u32 ,
90+ pub rghAdditionalStore : * mut HCERTSTORE ,
91+ pub dwFlags : u32 ,
92+ pub dwUrlRetrievalTimeout : u32 ,
93+ pub MaximumCachedCertificates : u32 ,
94+ pub CycleDetectionModulus : u32 ,
95+ pub hExclusiveRoot : HCERTSTORE ,
96+ pub hExclusiveTrustedPeople : HCERTSTORE ,
97+ // XXX: `dwExclusiveFlags` started being available in Windows 8 and Windows Server 2012
98+ // See https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_chain_engine_config
99+ #[ cfg( not( target_vendor = "win7" ) ) ]
100+ pub dwExclusiveFlags : u32 ,
101+ }
102+
80103use crate :: verification:: invalid_certificate;
81104
82105// SAFETY: see method implementation
@@ -231,8 +254,13 @@ impl CertEngine {
231254 config. hExclusiveRoot = exclusive_store. inner . as_ptr ( ) ;
232255
233256 let mut engine = EnginePtr :: NULL ;
257+
258+ // XXX: Due to the redefinition of `CERT_CHAIN_ENGINE_CONFIG`, we need to do pointer casts
259+ // in order to pass our expanded structure into `CertCreateCertificateChainEngine`.
260+ // See also `CERT_CHAIN_PARA` casting below.
261+ let config = NonNull :: from ( & config) . cast ( ) . as_ptr ( ) ;
234262 // SAFETY: `engine` is valid to be written to and the config is valid to be read.
235- let res = unsafe { CertCreateCertificateChainEngine ( & config, & mut engine) } ;
263+ let res = unsafe { CertCreateCertificateChainEngine ( config, & mut engine) } ;
236264
237265 #[ allow( clippy:: as_conversions) ]
238266 let engine = call_with_last_error ( || match NonNull :: new ( engine as * mut c_void ) {
@@ -265,8 +293,10 @@ impl CertEngine {
265293 config. hExclusiveRoot = root_store. inner . as_ptr ( ) ;
266294
267295 let mut engine = EnginePtr :: NULL ;
296+ // Same workaround with as above when creating the engine.
297+ let config = NonNull :: from ( & config) . cast ( ) . as_ptr ( ) ;
268298 // SAFETY: `engine` is valid to be written to and the config is valid to be read.
269- let res = unsafe { CertCreateCertificateChainEngine ( & config, & mut engine) } ;
299+ let res = unsafe { CertCreateCertificateChainEngine ( config, & mut engine) } ;
270300
271301 #[ allow( clippy:: as_conversions) ]
272302 let engine = call_with_last_error ( || match NonNull :: new ( engine as * mut c_void ) {
0 commit comments