55//
66// The MIT License
77//
8- // Copyright (c) 2018 pastdue https://github.com/past-due/
8+ // Copyright (c) 2018-2019 pastdue https://github.com/past-due/
99//
1010// Permission is hereby granted, free of charge, to any person obtaining a copy
1111// of this software and associated documentation files (the "Software"), to deal
@@ -88,6 +88,10 @@ typedef DWORD (WINAPI *PCertGetNameString)(
8888 DWORD cchNameString
8989);
9090
91+ #if !defined(MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG)
92+ #define MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG 0x00020000
93+ #endif
94+
9195// Verifies that a certificate chain ends in a Microsoft Root
9296static bool CertChainMicrosoftRootVerify (HMODULE hCrypt32Module,
9397 PCCERT_CHAIN_CONTEXT pChainContext)
@@ -101,18 +105,39 @@ static bool CertChainMicrosoftRootVerify(HMODULE hCrypt32Module,
101105 ChainPolicyPara.dwFlags = 0 ;
102106 CERT_CHAIN_POLICY_STATUS ChainPolicyStatus;
103107 crtless_memset (&ChainPolicyStatus, 0 , sizeof (CERT_CHAIN_POLICY_STATUS));
108+ ChainPolicyStatus.cbSize = sizeof (CERT_CHAIN_POLICY_STATUS);
109+
110+ bool bMicrosoftRoot = false ;
104111
105112 if (Func_CertVerifyCertificateChainPolicy (CERT_CHAIN_POLICY_MICROSOFT_ROOT, pChainContext, &ChainPolicyPara, &ChainPolicyStatus) == TRUE )
106113 {
107114 // CertVerifyCertificateChainPolicy was able to check the policy
108115 // *Must* check ChainPolicyStatus.dwError to determine if the policy check was actually satisfied
109- return ChainPolicyStatus.dwError == 0 ;
116+ bMicrosoftRoot = ( ChainPolicyStatus.dwError == 0 ) ;
110117 }
111- else
118+
119+ if (!bMicrosoftRoot)
112120 {
113- // CertVerifyCertificateChainPolicy failed to check the policy
114- return false ;
121+ // If Microsoft Product Root verification was unsuccessful, check for the Microsoft Application Root
122+ // via: MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG
123+
124+ CERT_CHAIN_POLICY_PARA AppRootChainPolicyPara;
125+ crtless_memset (&AppRootChainPolicyPara, 0 , sizeof (CERT_CHAIN_POLICY_PARA));
126+ AppRootChainPolicyPara.cbSize = sizeof (CERT_CHAIN_POLICY_PARA);
127+ AppRootChainPolicyPara.dwFlags = MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG;
128+ CERT_CHAIN_POLICY_STATUS AppRootChainPolicyStatus;
129+ crtless_memset (&AppRootChainPolicyStatus, 0 , sizeof (CERT_CHAIN_POLICY_STATUS));
130+ AppRootChainPolicyStatus.cbSize = sizeof (CERT_CHAIN_POLICY_STATUS);
131+
132+ if (Func_CertVerifyCertificateChainPolicy (CERT_CHAIN_POLICY_MICROSOFT_ROOT, pChainContext, &AppRootChainPolicyPara, &AppRootChainPolicyStatus) == TRUE )
133+ {
134+ // CertVerifyCertificateChainPolicy was able to check the policy
135+ // *Must* check AppRootChainPolicyStatus.dwError to determine if the policy check was actually satisfied
136+ bMicrosoftRoot = (AppRootChainPolicyStatus.dwError == 0 );
137+ }
115138 }
139+
140+ return bMicrosoftRoot;
116141}
117142
118143// Calls CertGetNameString with the specified parameters, allocating an appropriately-sized buffer
0 commit comments