/** * 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. * @param ocspResp the OCSP response * @param issuerCert the issuer certificate * @throws GeneralSecurityException * @throws IOException */ virtual public 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 X509Certificate[] certs = ocspResp.GetCerts(); foreach (X509Certificate cert in certs) { X509Certificate tempCert; try { tempCert = cert; } catch (Exception ex) { continue; } IList keyPurposes = null; try { keyPurposes = tempCert.GetExtendedKeyUsage(); if ((keyPurposes != null) && keyPurposes.Contains(id_kp_OCSPSigning) && IsSignatureValid(ocspResp, tempCert)) { responderCert = tempCert; break; } } catch (CertificateParsingException ignored) { } } // 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 (certificates != null) { foreach (X509Certificate anchor in certificates) { try { if (IsSignatureValid(ocspResp, anchor)) { responderCert = anchor; break; } } catch (GeneralSecurityException ignored) { } } } // 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 { X509CrlParser crlParser = new X509CrlParser(); // Creates the CRL Stream url = WebRequest.Create(CertificateUtil.GetCRLURL(responderCert)).GetResponse().GetResponseStream(); crl = crlParser.ReadCrl(url); } catch (Exception ignored) { crl = null; } if (crl != null) { CrlVerifier crlVerifier = new CrlVerifier(null, null); crlVerifier.Certificates = certificates; crlVerifier.OnlineCheckingAllowed = onlineCheckingAllowed; crlVerifier.Verify(crl, responderCert, issuerCert, DateTime.UtcNow); return; } } //check if lifetime of certificate is ok responderCert.CheckValidity(); }
/** * Gets an encoded byte array with OCSP validation. The method should not throw an exception. * @param checkCert to certificate to check * @param rootCert the parent certificate * @param the url to get the verification. It it's null it will be taken * from the check cert or from other implementation specific source * @return a byte array with the validation or null if the validation could not be obtained */ public virtual byte[] GetEncoded(X509Certificate checkCert, X509Certificate rootCert, String url) { try { if (checkCert == null || rootCert == null) { return(null); } if (url == null) { url = CertificateUtil.GetOCSPURL(checkCert); } if (url == null) { return(null); } OcspReq request = GenerateOCSPRequest(rootCert, checkCert.SerialNumber); byte[] array = request.GetEncoded(); HttpWebRequest con = (HttpWebRequest)WebRequest.Create(url); con.ContentLength = array.Length; con.ContentType = "application/ocsp-request"; con.Accept = "application/ocsp-response"; con.Method = "POST"; Stream outp = con.GetRequestStream(); outp.Write(array, 0, array.Length); outp.Close(); HttpWebResponse response = (HttpWebResponse)con.GetResponse(); if (response.StatusCode != HttpStatusCode.OK) { throw new IOException(MessageLocalization.GetComposedMessage("invalid.http.response.1", (int)response.StatusCode)); } Stream inp = response.GetResponseStream(); OcspResp ocspResponse = new OcspResp(inp); inp.Close(); response.Close(); if (ocspResponse.Status != 0) { throw new IOException(MessageLocalization.GetComposedMessage("invalid.status.1", ocspResponse.Status)); } BasicOcspResp basicResponse = (BasicOcspResp)ocspResponse.GetResponseObject(); if (basicResponse != null) { SingleResp[] responses = basicResponse.Responses; if (responses.Length == 1) { SingleResp resp = responses[0]; Object status = resp.GetCertStatus(); if (status == CertificateStatus.Good) { return(basicResponse.GetEncoded()); } else if (status is Org.BouncyCastle.Ocsp.RevokedStatus) { throw new IOException(MessageLocalization.GetComposedMessage("ocsp.status.is.revoked")); } else { throw new IOException(MessageLocalization.GetComposedMessage("ocsp.status.is.unknown")); } } } } catch (Exception ex) { if (LOGGER.IsLogging(Level.ERROR)) { LOGGER.Error("OcspClientBouncyCastle", ex); } } return(null); }
/** * Fetches the CRL bytes from an URL. * If no url is passed as parameter, the url will be obtained from the certificate. * If you want to load a CRL from a local file, subclass this method and pass an * URL with the path to the local file to this method. An other option is to use * the CrlClientOffline class. * @see com.itextpdf.text.pdf.security.CrlClient#getEncoded(java.security.cert.X509Certificate, java.lang.String) */ virtual public ICollection <byte[]> GetEncoded(X509Certificate checkCert, String url) { if (checkCert == null) { return(null); } List <String> urllist = new List <string>(urls); if (urllist.Count == 0) { LOGGER.Info("Looking for CRL for certificate " + checkCert.SubjectDN.ToString()); try { if (url == null) { url = CertificateUtil.GetCRLURL(checkCert); } if (url == null) { throw new ArgumentNullException(); } urllist.Add(url); LOGGER.Info("Found CRL url: " + url); } catch (Exception e) { LOGGER.Info("Skipped CRL url: " + e.Message); } } List <byte[]> ar = new List <byte[]>(); foreach (string urlt in urllist) { try { LOGGER.Info("Checking CRL: " + urlt); HttpWebRequest con = (HttpWebRequest)WebRequest.Create(urlt); HttpWebResponse response = (HttpWebResponse)con.GetResponse(); if (response.StatusCode != HttpStatusCode.OK) { throw new IOException(MessageLocalization.GetComposedMessage("invalid.http.response.1", (int)response.StatusCode)); } //Get Response Stream inp = response.GetResponseStream(); byte[] buf = new byte[1024]; MemoryStream bout = new MemoryStream(); while (true) { int n = inp.Read(buf, 0, buf.Length); if (n <= 0) { break; } bout.Write(buf, 0, n); } inp.Close(); ar.Add(bout.ToArray()); LOGGER.Info("Added CRL found at: " + urlt); } catch (Exception e) { LOGGER.Info("Skipped CRL: " + e.Message + " for " + urlt); } } return(ar); }