in src/main/java/org/jetbrains/nativecerts/win32/Crypt32ExtUtil.java [145:206]
public static void validateCertificate(byte[] encodedCertificate) {
var certificateContext = Crypt32Ext.INSTANCE.CertCreateCertificateContext(
WinCrypt.X509_ASN_ENCODING | WinCrypt.PKCS_7_ASN_ENCODING, encodedCertificate, encodedCertificate.length);
if (certificateContext == null) {
throw new Win32Exception(Native.getLastError());
}
try {
WinCrypt.CERT_CHAIN_PARA pChainPara = new WinCrypt.CERT_CHAIN_PARA();
pChainPara.cbSize = pChainPara.size();
pChainPara.RequestedUsage.dwType = WinCrypt.USAGE_MATCH_TYPE_AND;
pChainPara.RequestedUsage.Usage.cUsageIdentifier = 0;
pChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = null;
PointerByReference ppChainContext = new PointerByReference();
if (!Crypt32.INSTANCE.CertGetCertificateChain(
null, certificateContext, null, null, pChainPara,
Crypt32Ext.CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY,
null, ppChainContext)) {
throw new Win32Exception(Native.getLastError());
}
if (ppChainContext.getValue() == null) {
throw new IllegalStateException("CertGetCertificateChain was successful, but returned chain context is null");
}
WinCrypt.CERT_CHAIN_CONTEXT pChainContext = Structure.newInstance(WinCrypt.CERT_CHAIN_CONTEXT.class, ppChainContext.getValue());
pChainContext.read();
if (pChainContext.cbSize != pChainContext.size()) {
throw new IllegalStateException("CertGetCertificateChain was successful, but returned chain context size is incorrect." +
"returned cbSize is " + pChainContext.cbSize + ", but the structure size is " + pChainContext.size());
}
try {
WinCrypt.CERT_CHAIN_POLICY_PARA chainPolicyPara = new WinCrypt.CERT_CHAIN_POLICY_PARA();
chainPolicyPara.cbSize = chainPolicyPara.size();
chainPolicyPara.dwFlags = 0;
WinCrypt.CERT_CHAIN_POLICY_STATUS policyStatus = new WinCrypt.CERT_CHAIN_POLICY_STATUS();
policyStatus.dwError = 1; // extra check that CertVerifyCertificateChainPolicy actually sets this field
policyStatus.cbSize = policyStatus.size();
if (!Crypt32.INSTANCE.CertVerifyCertificateChainPolicy(
new WTypes.LPSTR(Pointer.createConstant(Crypt32Ext.CERT_CHAIN_POLICY_SSL)),
pChainContext, chainPolicyPara, policyStatus)) {
throw new Win32Exception(Native.getLastError());
}
int dwError = policyStatus.dwError;
if (dwError != 0) {
throw new Win32Exception(dwError, null, "CertVerifyCertificateChainPolicy failed to validate certificate with code " +
Integer.toHexString(dwError) + ":\n" + Kernel32Util.formatMessage(dwError)) {
};
}
} finally {
Crypt32.INSTANCE.CertFreeCertificateChain(pChainContext);
}
} finally {
Crypt32.INSTANCE.CertFreeCertificateContext(certificateContext);
}
}