Exemple #1
0
        /// <summary>
        /// Verifies if an OCSP response is genuine
        /// If it doesn't verify against the issuer certificate and response's certificates, it may verify
        /// using a trusted anchor or cert.
        /// </summary>
        /// <param name="ocspResp">the OCSP response</param>
        /// <param name="issuerCert">the issuer certificate. This certificate is considered trusted and valid by this method.
        ///     </param>
        /// <param name="signDate">sign date</param>
        public virtual void IsValidResponse(BasicOcspResp ocspResp, X509Certificate issuerCert, DateTime signDate)
        {
            // OCSP response might be signed by the issuer certificate or
            // the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension
            X509Certificate responderCert = null;

            // first check if the issuer certificate signed the response
            // since it is expected to be the most common case
            if (IsSignatureValid(ocspResp, issuerCert))
            {
                responderCert = issuerCert;
            }
            // if the issuer certificate didn't sign the ocsp response, look for authorized ocsp responses
            // from properties or from certificate chain received with response
            if (responderCert == null)
            {
                if (ocspResp.GetCerts() != null)
                {
                    //look for existence of Authorized OCSP responder inside the cert chain in ocsp response
                    IEnumerable <X509Certificate> certs = SignUtils.GetCertsFromOcspResponse(ocspResp);
                    foreach (X509Certificate cert in certs)
                    {
                        IList keyPurposes = null;
                        try {
                            keyPurposes = cert.GetExtendedKeyUsage();
                            if ((keyPurposes != null) && keyPurposes.Contains(id_kp_OCSPSigning) && IsSignatureValid(ocspResp, cert))
                            {
                                responderCert = cert;
                                break;
                            }
                        }
                        catch (CertificateParsingException) {
                        }
                    }
                    // Certificate signing the ocsp response is not found in ocsp response's certificate chain received
                    // and is not signed by the issuer certificate.
                    if (responderCert == null)
                    {
                        throw new VerificationException(issuerCert, "OCSP response could not be verified");
                    }
                    // RFC 6960 4.2.2.2. Authorized Responders:
                    // "Systems relying on OCSP responses MUST recognize a delegation certificate as being issued
                    // by the CA that issued the certificate in question only if the delegation certificate and the
                    // certificate being checked for revocation were signed by the same key."
                    // and
                    // "This certificate MUST be issued directly by the CA that is identified in the request"
                    responderCert.Verify(issuerCert.GetPublicKey());
                    // check if lifetime of certificate is ok
                    responderCert.CheckValidity(signDate);
                    // validating ocsp signers certificate
                    // Check if responders certificate has id-pkix-ocsp-nocheck extension,
                    // in which case we do not validate (perform revocation check on) ocsp certs for lifetime of certificate
                    if (responderCert.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNocheck.Id) == null)
                    {
                        X509Crl crl;
                        try {
                            // TODO should also check for Authority Information Access according to RFC6960 4.2.2.2.1. "Revocation Checking of an Authorized Responder"
                            // TODO should also respect onlineCheckingAllowed property?
                            crl = CertificateUtil.GetCRL(responderCert);
                        }
                        catch (Exception) {
                            crl = (X509Crl)null;
                        }
                        if (crl != null && crl is X509Crl)
                        {
                            CRLVerifier crlVerifier = new CRLVerifier(null, null);
                            crlVerifier.SetRootStore(rootStore);
                            crlVerifier.SetOnlineCheckingAllowed(onlineCheckingAllowed);
                            if (!crlVerifier.Verify((X509Crl)crl, responderCert, issuerCert, signDate))
                            {
                                throw new VerificationException(issuerCert, "Authorized OCSP responder certificate was revoked.");
                            }
                        }
                        else
                        {
                            ILog logger = LogManager.GetLogger(typeof(iText.Signatures.OCSPVerifier));
                            logger.Error("Authorized OCSP responder certificate revocation status cannot be checked");
                        }
                    }
                }
                else
                {
                    // TODO throw exception starting from iText version 7.2, but only after OCSPVerifier would allow explicit setting revocation check end points/provide revocation data
                    // throw new VerificationException(issuerCert, "Authorized OCSP responder certificate revocation status cannot be checked.");
                    // certificate chain is not present in response received
                    // try to verify using rootStore according to RFC 6960 2.2. Response:
                    // "The key used to sign the response MUST belong to one of the following:
                    // - ...
                    // - a Trusted Responder whose public key is trusted by the requestor;
                    // - ..."
                    if (rootStore != null)
                    {
                        try {
                            foreach (X509Certificate anchor in SignUtils.GetCertificates(rootStore))
                            {
                                if (IsSignatureValid(ocspResp, anchor))
                                {
                                    // certificate from the root store is considered trusted and valid by this method
                                    responderCert = anchor;
                                    break;
                                }
                            }
                        }
                        catch (Exception) {
                            responderCert = (X509Certificate)null;
                        }
                    }
                    if (responderCert == null)
                    {
                        throw new VerificationException(issuerCert, "OCSP response could not be verified: it does not contain certificate chain and response is not signed by issuer certificate or any from the root store."
                                                        );
                    }
                }
            }
        }
Exemple #2
0
 // Certificate Revocation Lists
 /// <summary>Gets a CRL from an X509 certificate.</summary>
 /// <param name="certificate">the X509Certificate to extract the CRL from</param>
 /// <returns>CRL or null if there's no CRL available</returns>
 public static X509Crl GetCRL(X509Certificate certificate)
 {
     return(CertificateUtil.GetCRL(CertificateUtil.GetCRLURL(certificate)));
 }
        /// <summary>
        /// Verifies if an OCSP response is genuine
        /// If it doesn't verify against the issuer certificate and response's certificates, it may verify
        /// using a trusted anchor or cert.
        /// </summary>
        /// <param name="ocspResp">the OCSP response</param>
        /// <param name="issuerCert">the issuer certificate</param>
        /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/>
        /// <exception cref="System.IO.IOException"/>
        public virtual void IsValidResponse(BasicOcspResp ocspResp, X509Certificate issuerCert)
        {
            //OCSP response might be signed by the issuer certificate or
            //the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension
            X509Certificate responderCert = null;

            //first check if the issuer certificate signed the response
            //since it is expected to be the most common case
            if (IsSignatureValid(ocspResp, issuerCert))
            {
                responderCert = issuerCert;
            }
            //if the issuer certificate didn't sign the ocsp response, look for authorized ocsp responses
            // from properties or from certificate chain received with response
            if (responderCert == null)
            {
                if (ocspResp.GetCerts() != null)
                {
                    //look for existence of Authorized OCSP responder inside the cert chain in ocsp response
                    IEnumerable <X509Certificate> certs = SignUtils.GetCertsFromOcspResponse(ocspResp);
                    foreach (X509Certificate cert in certs)
                    {
                        IList keyPurposes = null;
                        try {
                            keyPurposes = cert.GetExtendedKeyUsage();
                            if ((keyPurposes != null) && keyPurposes.Contains(id_kp_OCSPSigning) && IsSignatureValid(ocspResp, cert))
                            {
                                responderCert = cert;
                                break;
                            }
                        }
                        catch (CertificateParsingException) {
                        }
                    }
                    // Certificate signing the ocsp response is not found in ocsp response's certificate chain received
                    // and is not signed by the issuer certificate.
                    if (responderCert == null)
                    {
                        throw new VerificationException(issuerCert, "OCSP response could not be verified");
                    }
                }
                else
                {
                    //certificate chain is not present in response received
                    //try to verify using rootStore
                    if (rootStore != null)
                    {
                        try {
                            foreach (X509Certificate anchor in SignUtils.GetCertificates(rootStore))
                            {
                                if (IsSignatureValid(ocspResp, anchor))
                                {
                                    responderCert = anchor;
                                    break;
                                }
                            }
                        }
                        catch (Exception) {
                            responderCert = (X509Certificate)null;
                        }
                    }
                    // OCSP Response does not contain certificate chain, and response is not signed by any
                    // of the rootStore or the issuer certificate.
                    if (responderCert == null)
                    {
                        throw new VerificationException(issuerCert, "OCSP response could not be verified");
                    }
                }
            }
            //check "This certificate MUST be issued directly by the CA that issued the certificate in question".
            responderCert.Verify(issuerCert.GetPublicKey());
            // validating ocsp signers certificate
            // Check if responders certificate has id-pkix-ocsp-nocheck extension,
            // in which case we do not validate (perform revocation check on) ocsp certs for lifetime of certificate
            if (responderCert.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNocheck.Id) == null)
            {
                X509Crl crl;
                try {
                    crl = CertificateUtil.GetCRL(responderCert);
                }
                catch (Exception) {
                    crl = (X509Crl)null;
                }
                if (crl != null && crl is X509Crl)
                {
                    CRLVerifier crlVerifier = new CRLVerifier(null, null);
                    crlVerifier.SetRootStore(rootStore);
                    crlVerifier.SetOnlineCheckingAllowed(onlineCheckingAllowed);
                    crlVerifier.Verify((X509Crl)crl, responderCert, issuerCert, DateTimeUtil.GetCurrentUtcTime());
                    return;
                }
            }
            //check if lifetime of certificate is ok
            responderCert.CheckValidity();
        }