Certificate validation is not a one-step process. It's a complex procedure that involves validation of certificate chain from the end-entity certificate (the one being validated) to CA certificate and up to the trusted root certificate. For each certificate in the chain the following steps are taken:
- Analyzing the certificate itself (values of different certificate fields and extensions)
- Checking certificate integrity with CA certificate
- Checking certificate revocation status in Certificate Revocation Lists and using OCSP protocol
As CRLs and OCSP responses are signed using certificates, those certificates are validated as well, giving us extra certificate chains.
So we end up validating not a single certificate, and not a chain of certificates, but a tree of certificates.
SecureBlackbox includes functions and mechanisms for taking all of the above steps separately, and also TElX509CertificateValidator component is offered.
TElX509CertificateValidatorThis component (further referred to as Validator) encapsulates all above steps and provides a simple way to validate the certificate tree. At the same time it gives you complete control over the process, letting you tune-up validation procedure, define custom transports for CRL and OCSP requests, override validation results for each certificate, specify what certificates are known or trusted or known as invalid.
Additional certificate storagesWhen the certificate chain is built, it always ends with some self-signed certificate, called Root. And such root should be trusted (assumed to be valid), in other case validation will fail.
During certificate validation you often don't have all certificates in chain, so you need to rely on a set of known certificates which are stored in the OS or in your application. This set includes Roots as well as intermediate CA certificates.
On Windows Validator can use Windows Certificate Storage to find missing certificates (this is controlled by UseSystemStorages property). On other platforms (Linux, Mono, Silverlight etc), however, such storage is not present. Various applications, such as OpenSSL and various browsers, carry their own sets of known and trusted certificates. This is what your application needs to do as well. Put the certificates to application resources and load them on start-up or when certificate validation is performed for the first time.
Where do you get the list of known certificates? You can export ROOT and CA stores of Windows Certificate Storage in PKCS#7 format (.p7b files) and import that files using TElCustomCertStorage.LoadFromStreamPKCS7() method.
Then tell the Validator about additional storages using AddKnownCertificates() and AddTrustedCertificates() methods.
Note that known and trusted certificates are different entities. Known certificates are literally known but not trusted. Trusted are, well, trusted. Normally you put only trusted Roots to trusted certificates.
Self-signed certificatesBy default there's no trust to self-signed certificate and if the root certificate in chain is not trusted but is self-signed, such validation doesn't succeed. If you want to trust some or all self-signed certificates (or when you perform dynamic checks for trusted certificates), you need to override validation result for those certificates. See below how this is done.
Overriding validation resultValidator has OnAfterCertificateValidation event. By handling this event you can inspect validation result for each certificate that was validated and if necessary change this result. To change the result modify Validity and ValidityReason parameters of the event handler.
CRL and OCSP checksThe private key for the certificate can be compromised, or the certificate can be canceled (revoked) by the certificate authority that issued this certificate. In this case other users must be informed that the certificate can not be trusted anymore. This is done in two ways: by publishing Certificate Revocation Lists or by responding to real-time requests for certificate status (OCSP requests). Information about where to take the CRL and where to send OCSP request to is contained in the certificate itself.
Validator supports both CRLs and OCSP requests and uses them. You can disable use of CRLs or OCSPs or both or make such checks optional using properties of Validator. If the check is optional, failure in checking doesn't make validation result invalid, but just sets a flag in ValidityReason parameter, so you can know that something has failed.
To request CRLs and send OCSP requests Validator uses special classes – CRL retrievers and OCSP clients. By default Validator uses classes built into SecureBlackbox, that utilize TElHTTPSClient, HTTP client component of SecureBlackbox. Consequently to use built-in classes, you need to have a license for a package that covers TElHTTPSClient.
CRL and OCSP checks are most common reasons for validation problems as they involve lots of third-party certificates to be validated in addition to your main certificate chain.
In some cases it's possible that you already have a CRL or an OCSP response before validating the certificate (this happens when they are included in the signature of the *AdES document). In this case you can pass them to TElX509CertificateValidator class using AddKnownCRLs() or AddKnownOCSPResponses() method.
If validation failsIf you get “cvInvalid” as a result of validation, this is not something what you need to report to our technical support. All in all, the Validator is intended to return this result for any certificate which failed validation for whatever reason. Most common reasons of failure for supposedly valid certificates are:
- lack of certificates to build the chain (CA or Root certificates are not available)
- not trusted root certificate
- impossibility to retrieve the CRL or send OCSP request (this includes network failures and lack of license for HTTPS client)
- failure to use CRL or OCSP response (this includes malformed responses and failure in validation of signature of the CRL or OCSP response)
To check that you have all certificates, re-read the section about additional certificate storages above. You can handle OnAfterCertificateValidation event, find out what certificate was the last to be validated and if CA was not found for that certificate, inspect your setup. If the last CA was not a self-signed root, then you need to find a root certificate somewhere (maybe export it from browser, if validation succeeds in browser). If the root is present, but is reported as self-signed, you need to add it to trusted certificate storages.
If you suspect that CRL or OCSP check was the reason, first of all disable CRL and OCSP checks and see if the problem goes away. Check that you have the license for HTTPS client. Then handle OnAfterCertificateValidation event and see what certificate failed to validate and why. Next, take this certificate and run validation on it directly. This will give you more detailed information about what went wrong in validation. It can happen that several CRL or OCSP checks are involved (remember we mentioned a tree in the beginning?) and in this case you would need to take this step several times narrowing down the problem.
Finally, starting from version 9.1.214 Validator includes OnCRLError and OnOCSPError events which provide more information about the reason of failure of CRL and OCSP checks. Handle those events to find out what error happened if ValidityReason includes CRLNotVerified or OCSPNotVerified flags.