SecureBlackbox 16: Validation of Certificates in SecureBlackbox (Mini-FAQ)
Note: This article applies only to SecureBlackbox Legacy. For future development please consider using the latest version.
Certificate validation is not a one-step process. Rather, it is a complex procedure that involves the validation of the certificate chain from the end-entity certificate (the one being validated) to the CA certificate and up to the trusted root certificate. For each certificate in the chain the following steps are taken:
- Analyzing the certificate itself (the values of different certificate fields and extensions)
- Checking the certificate's integrity with the CA certificate
- Checking the certificate's revocation status in Certificate Revocation Lists and using the 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 separately performing all of the above steps and also offers the TElX509CertificateValidator component.
This component (further referred to as the Validator) encapsulates all of the 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 fine-tune the validation procedure, define custom transports for CRL and OCSP requests, override validation results for each certificate, and specify what certificates are known or trusted or known as invalid.
Additional Certificate Storages
When the certificate chain is built, it always ends with a self-signed certificate, root. The root should be trusted (assumed to be valid); in the other case, validation will fail. During certificate validation, you often do not have all the certificates in the chain, so you need to rely on a set of known certificates that are stored in the OS or in your application. This set includes root as well as intermediate CA certificates.
On Windows, the Validator can use Windows Certificate Storage to find missing certificates (this is controlled by the 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. Add the certificates to the application resources and load them on start-up or when certificate validation is performed for the first time.
To get the list of known certificates, you can export the ROOT and CA stores of Windows Certificate Storage in the PKCS#7 format (.p7b files) and import thsoe files using the TElCustomCertStorage.LoadFromStreamPKCS7 method.
You then need to specify any additional storages using the AddKnownCertificates and AddTrustedCertificates methods.
Note that known and trusted certificates are different entities. Known certificates are literally known but not trusted. Trusted certificates are, well, trusted. Normally you put only trusted roots into the trusted certificates.
By default, there is no trust in a self-signed certificate and if the root certificate in the chain is not trusted but is self-signed, validation will not 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 the validation result for those certificates. See below how this is done.
Overriding the Result of Validation
By handling the Validator's OnAfterCertificateValidation event, you can inspect the result of validation for each certificate that was validated and, if necessary, change this result. To change the result, modify the Validity and ValidityReason parameters of the event handler.
CRL and OCSP Checks
The private key for the certificate can be compromised, or the certificate can be canceled (revoked) by the certificate authority that issued this certificate. In these cases, other users must be informed that the certificate cannot 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 the OCSP request is contained in the certificate itself.
The 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 the properties of the Validator. If the check is optional, a failure in checking doesn't make the validation result invalid, but only sets a flag in the ValidityReason parameter, so you can know that something has failed.
To request CRLs and send OCSP requests, the Validator uses special classes – CRL retrievers and OCSP clients. By default the Validator uses classes built into SecureBlackbox that utilize TElHTTPSClient, the HTTP client component of SecureBlackbox. Consequently, to use the built-in classes, you need to have a license for a package that covers TElHTTPSClient.
CRL and OCSP checks are the most common reasons for validation problems as they involve many third-party certificates to be validated in addition to your main certificate chain.
In some cases it is 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 a *AdES document). In this case you can pass them to the TElX509CertificateValidator class using the AddKnownCRLs or AddKnownOCSPResponses methods.
If Validation Fails
The Validator is intended to return "cvInvalid" for any certificate that failed validation for whatever reason. The most common reasons for failure for supposedly valid certificates are below:
- Lack of certificates to build the chain (the CA or root certificates are not available)
- No trusted root certificate
- Impossibility to retrieve the CRL or send the OCSP request (this includes network failures and the lack of a license for the HTTPS client)
- Failure to use the CRL or OCSP response (this includes malformed responses and failure in the validation of the signature of the CRL or OCSP response)
Checking the Certificate Chain
To check that you have all certificates, read the section about additional certificate storages above. You can handle the OnAfterCertificateValidation event, find out what certificate was the last to be validated, and, if the 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. If validation succeeds in the browser, one way is to export the certificate from the browser. If the root is present, but is reported as self-signed, you need to add it to the trusted certificate storages.
Checking Component Events
If you suspect that the CRL or OCSP check was the reason, first of all disable the CRL and OCSP checks and see if the problem goes away. Check that you have the license for the HTTPS client. Then handle the 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 elsewhere along the aforementioned tree and in this case you would need to take this step several times to narrow down the problem.
Starting from version 9.1.214, the Validator also includes the OnCRLError and OnOCSPError events, which provide more information about the reason for a failure of the CRL and OCSP checks. Handle those events to find out what error happened if ValidityReason includes the CRLNotVerified or OCSPNotVerified flags.
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at firstname.lastname@example.org.