/// <summary> /// Checks the status of the certificate against an OCSP server. /// Updates the internal state with the result. /// </summary> /// <param name="revocationLookupClient">The OCSP client to use for the request</param> /// <returns>Returns the check status</returns> public RevocationResponse CheckRevocationStatus(IRevocationLookup revocationLookupClient) { RevocationResponse response = new RevocationResponse(); try { response = revocationLookupClient.CheckCertificate(x509Certificate); if (response.Exception == null) { if (response.IsValid) { response.RevocationCheckStatus = RevocationCheckStatus.AllChecksPassed; } else { response.RevocationCheckStatus = RevocationCheckStatus.CertificateRevoked; } } else { response.RevocationCheckStatus = RevocationCheckStatus.UnknownIssue; } } catch (Exception e) { response.Exception = e; response.RevocationCheckStatus = RevocationCheckStatus.UnknownIssue; } return(response); }
/// <summary> /// Returns the status of the certificate. In this offline test implementation of the /// IRevocationLookup interface, the response can be set in the configuration file /// </summary> /// <param name="certificate">The certificate to check</param> /// <returns>Returns a revocation status</returns> public RevocationResponse CheckCertificate(X509Certificate2 certificate) { RevocationResponse response = new RevocationResponse(); response.IsValid = _testConfig.ReturnPositiveResponse; response.NextUpdate = DateTime.MaxValue; return(response); }
public void LookupTestOkayFoces2() { try { X509Certificate2 certificate = new X509Certificate2(LookupTest.foces2OkayCertificate, "Test1234"); Assert.IsNotNull(certificate, "Test certificate was null."); CrlLookup crlLookup = new CrlLookup(); RevocationResponse response = crlLookup.CheckCertificate(certificate); Assert.IsTrue(response.IsValid); Assert.IsNull(response.Exception, "The lookup return an exception."); Assert.AreEqual(RevocationCheckStatus.AllChecksPassed, response.RevocationCheckStatus, "Not all check was performed."); } catch (Exception exception) { Assert.Fail(exception.ToString()); } }
public void LookupTestRevokedFoces2() { try { X509Certificate2 certificate = new X509Certificate2(LookupTest.foces2RevokedCertificate, "Test1234"); Assert.IsNotNull(certificate, "Test certificate was null."); CrlLookup crlLookup = new CrlLookup(); RevocationResponse response = crlLookup.CheckCertificate(certificate); Assert.IsNull(response.Exception, "The lookup return an exception."); Assert.AreEqual(RevocationCheckStatus.CertificateRevoked, response.RevocationCheckStatus, "The revokation validation did not parse all check"); Assert.IsFalse(response.IsValid, "The revoked certifikate was valid"); } catch (Exception exception) { Assert.Fail(exception.ToString()); } }
public void LookupTestRevokedFoces2() { try { X509Certificate2 certificate = new X509Certificate2(LookupTest.foces2RevokedCertificate, "Test1234"); Assert.IsNotNull(certificate, "Test certificate was null."); OcspLookup ocspLookup = this.CreateOcesLookup(); RevocationResponse response = ocspLookup.CheckCertificate(certificate); Assert.IsFalse(response.IsValid, "Certificate is not valid."); Assert.IsNull(response.Exception, "The lookup return an exception."); Assert.AreEqual(RevocationCheckStatus.CertificateRevoked, response.RevocationCheckStatus, "Not all check was performed."); } catch (Exception exception) { Assert.Fail(exception.ToString()); } }
private void Revocation(X509Certificate2 certificate) { // Create the OCSP client RevocationLookupFactory revocationLookupFactory = new RevocationLookupFactory(); IRevocationLookup revocationClient = revocationLookupFactory.CreateRevocationLookupClient(); // Check the validity status of the certificate using OCSP RevocationResponse revocationResponse = revocationClient.CheckCertificate(certificate); // Print out info Console.Write(" 3. Certificate status returned by RevocationLookup.\n Is valid: "); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(revocationResponse.IsValid.ToString()); Console.ForegroundColor = ConsoleColor.White; // Make sure the cert was valid if (!revocationResponse.IsValid) { throw new Exception("The certificate returned by RevocationLookup was not valid"); } }
protected void ValidateEndpointCertificate(OcesX509Certificate endpointOcesCertificate) { RevocationLookupFactory ocspLookupFactory = new RevocationLookupFactory(); IRevocationLookup ocspClient = ocspLookupFactory.CreateRevocationLookupClient(); RevocationResponse ocspStatus = endpointOcesCertificate.CheckRevocationStatus(ocspClient); switch (ocspStatus.RevocationCheckStatus) { case RevocationCheckStatus.AllChecksPassed: { // all okay break; } case RevocationCheckStatus.CertificateRevoked: { throw new Exception("Certificate validation error - CertificateRevoked"); //break; } case RevocationCheckStatus.NotChecked: { throw new Exception("Certificate validation error - NotChecked"); //break; } case RevocationCheckStatus.UnknownIssue: { throw new Exception("Certificate validation error - UnknownIssue"); // break; } default: { throw new Exception("Certificate validation error"); // break; } } }
/// <summary> /// Check if the certificate is revoked against ocsp server /// </summary> /// <param name="certificate">the certificate to check</param> /// <returns>RevocationResponse object to store the result</returns> /// <exception cref="CheckCertificateOcspUnexpectedException">This exception is thrown, if an unexpected exception is thrown during the method</exception> /// <exception cref="CertificateRevokedTimeoutException">This exception is thrown, if the call to Ocsp server takes longer time than the allowed timeout</exception> /// <exception cref="CheckCertificateRevokedUnexpectedException">Thrown if an unexpected error occured</exception> private RevocationResponse CheckCertificateRevocation(X509Certificate2 certificate) { RevocationResponse validityCheck = null; try { // Checks the certificate validityCheck = _lookup.CheckCertificate(certificate); } catch (ArgumentNullException) { throw; } catch (CryptographicUnexpectedOperationException) { throw; } catch (CryptographicException) { throw; } catch (ArithmeticException) { throw; } catch (CheckCertificateOcspUnexpectedException) { throw; } catch (CertificateRevokedTimeoutException) { throw; } catch (Exception e) { throw new CheckCertificateRevokedUnexpectedException(e); } return(validityCheck); }
public RevocationResponse RevocationResponseOnline(X509Certificate2 serverX509Certificate2, X509Certificate2 issuerX509Certificate2) { RevocationResponse revocationResponse = new RevocationResponse(); try { if (serverX509Certificate2 == null) { throw new Exception("Server certificate is null"); } // create BouncyCastle certificates //X509CertificateParser certParser = new X509CertificateParser(); //Org.BouncyCastle.X509.X509Certificate serverX509Certificate = certParser.ReadCertificate(serverX509Certificate2.RawData); // 1. Get server url List <string> urlList = this.GetAuthorityInformationAccessOcspUrl(serverX509Certificate2); if (urlList.Count == 0) { throw new Exception("No OCSP url found in ee certificate."); } // we always validate against the first defined url string url = urlList[0]; revocationResponse = this.RevocationResponseOnline(serverX509Certificate2, issuerX509Certificate2, url); } catch (Exception e) { revocationResponse.Exception = new CheckCertificateOcspUnexpectedException("OCSP valideringen fejlede.", e); } return(revocationResponse); }
private void TextCertificate() { string subject = string.Empty; /* Production configuration */ // specifie the subject to test // Production certificates valid // subject = "CN = NemHandel test service (funktionscertifikat) + SERIALNUMBER = CVR:26769388-FID:1200406941690, O = IT- og Telestyrelsen // CVR:26769388, C = DK"; //subject = "SERIALNUMBER=CVR:30808460-FID:1320135775022 + CN=TEST FOCES1 (funktionscertifikat), O=DANID A/S // CVR:30808460, C=DK"; // Production certificates not valid /* Test configuration */ // // Test certificates valid // subject = "CN = Testendpoint (funktionscertifikat) + SERIALNUMBER = CVR:26769388-FID:1208430425605, O = IT- og Telestyrelsen // CVR:26769388, C = DK"; //subject = "CN = Testendpoint (funktionscertifikat) + SERIALNUMBER = CVR:26769388-FID:1208430425605, O = IT- og Telestyrelsen // CVR:26769388, C = DK"; // Test certificates not valid //subject = "CN = TU GENEREL FOCES gyldig (funktionscertifikat) + SERIALNUMBER = CVR:30808460-FID:94731315, O = Danid A/S // CVR:30808460, C = DK"; // subject = "CN=Navision (funktionscertifikat) + OID.2.5.4.5=CVR:23267519-FID:1257424251148, O=TIETGENSKOLEN // CVR:23267519, C=DK"; //subject = "CN = TEST FOCES1 (funktionscertifikat) + SERIALNUMBER = CVR:30808460-FID:1320135775022, O = DANID A/S // CVR:30808460, C = DK"; // not valid any more //subject = "CN=TU GENEREL FOCES gyldig (funktionscertifikat) + SERIALNUMBER = CVR:30808460-FID:94731315, O = Danid A/S // CVR:30808460, C = DK"; // subject = "CN=TU GENEREL FOCES gyldig (funktionscertifikat) + SERIALNUMBER=CVR:30808460-FID:94731315, O=Danid A/S // CVR:30808460, C=DK"; // subject = "CN=FOCES1 (funktionscertifikat) + SERIALNUMBER=CVR:30808460-FID:1255692730737, O=DANID A/S // CVR:30808460, C=DK"; // subject = "CN=TU GENEREL MOCES gyldig + SERIALNUMBER=CVR:30808460-RID:45490598, O=Danid A/S // CVR:30808460, C=DK"; subject = "CN = mySupply NemHandel - Foces2 (funktionscertifikat) + SERIALNUMBER = CVR:32433030-FID:27705483, O = mySupply NemHandel // CVR:32433030, C = DK"; //subject = "SERIALNUMBER=CVR:34051178-FID:56940413 + CN=NemLog-in ADFS Test (funktionscertifikat), O=Digitaliseringsstyrelsen // CVR:34051178, C=DK"; // Now - retrive the certificate in LDAP, if the certificate is pressen... CertificateSubject certificateSubject = new CertificateSubject(subject); LdapLookupFactory ldapClientFactory = new LdapLookupFactory(); ICertificateLookup ldapClient = ldapClientFactory.CreateLdapLookupClient(); // Lookup the certificate using LDAP X509Certificate2 certificate = ldapClient.GetCertificate(certificateSubject); if (certificate != null) { Console.Write("Certificate whith subject "); Console.ForegroundColor = ConsoleColor.Yellow; Console.Write(subject); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(" found in LDAP."); // Validate that the certificate is valid in OCSP RevocationLookupFactory revocationLookupFactory = new RevocationLookupFactory(); IRevocationLookup revocationClient = revocationLookupFactory.CreateRevocationLookupClient(); // Check the validity status of the certificate using OCSP RevocationResponse revocationResponse = revocationClient.CheckCertificate(certificate); if (revocationResponse.IsValid) { Console.ForegroundColor = ConsoleColor.Green; Console.Write("Certificate valid in OCSP/CRL"); } else { Console.ForegroundColor = ConsoleColor.Red; Console.Write("Certificate not valid in OCSP/CRL"); } } else { Console.Write("Certificate whith subject "); Console.ForegroundColor = ConsoleColor.Red; Console.Write(subject); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(" NOT found in LDAP."); } Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(); Console.WriteLine("Press any key to exit."); Console.ReadLine(); }
//private X509Certificate2 certificateMoces = new X509Certificate2(CrlLookupTest. medarbejdercertifikatRevoked, "Test1234"); private void ThreadCertificateCheck() { CrlLookup crlLookup = new CrlLookup(); for (int i = 0; i < 16; i++) { Random random = new Random(); int select = random.Next(2); if (select < 1) { Console.WriteLine("{0} ThreadCertificateCheck number:{1} foces1 allOkay", DateTime.Now, i); RevocationResponse response = crlLookup.CheckCertificate(certificateFoces); if (response.Exception != null) { Console.WriteLine("{0} ThreadCertificateCheck number:{1} foces1 Exception: " + response.Exception.ToString(), DateTime.Now, i); } if (response.IsValid) { // yes - certificate is valid if (response.RevocationCheckStatus == RevocationCheckStatus.AllChecksPassed) { // yes - check all parsed } else { Console.WriteLine("{0} ThreadCertificateCheck number:{1} foces1 not all checked parsed ", DateTime.Now, i); Assert.Fail("Foces2 certifiate should have been valid."); } } else { // arg - certificate is not valid Assert.IsTrue(response.IsValid, "Foces certifiate should have been valid."); Console.WriteLine("{0} ThreadCertificateCheck number:{1} foces1 not all checked parsed ", DateTime.Now, i); } } else { //// moces1 //Console.WriteLine("{0} ThreadCertificateCheck number:{1} moces1 revoked", DateTime.Now, i); //RevocationResponse response = crlLookup.CheckCertificate(certificateMoces); //if (response.Exception != null) //{ // Console.WriteLine("{0} ThreadCertificateCheck number:{1} foces1 Exception: " + response.Exception.ToString(), DateTime.Now, i); //} //if (!response.IsValid) //{ // // yes - certificate is revoked // if (response.RevocationCheckStatus == RevocationCheckStatus.CertificateRevoked) // { // // yes - check all parsed // } // else // { // Console.WriteLine("{0} ThreadCertificateCheck number:{1} moces1 RevocationCheckStatus is not revoked as expected.", DateTime.Now, i); // Assert.Fail("Moces2 RevocationCheckStatus is not revoked as expected"); // } //} //else //{ // // arg - certificate is valid // Assert.IsFalse(response.IsValid, "Moces certificate should have been revoked."); // Console.WriteLine("{0} ThreadCertificateCheck number:{1} moces1 certificate is not revoked as expected.", DateTime.Now, i); //} } Console.WriteLine("{0} ThreadCertificateCheck number:{1} done", DateTime.Now, i); } }
/// <summary> /// Checks a certificate status in a CRL. /// </summary> /// <param name="certificate">The certificate to check</param> /// <returns>The RevocationResponse object that contains the result</returns> public RevocationResponse CheckCertificate(X509Certificate2 certificate) { /* * Assumptions: * - Certificate has an CRL Distribution Points extension value. * - An HTTP distribution point is present. */ // create RevocationResponse and set default values RevocationResponse response = new RevocationResponse(); response.IsValid = true; response.NextUpdate = DateTime.MinValue; if (certificate != null) { X509Chain x509Chain = new X509Chain(); x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; x509Chain.Build(certificate); // Iterate though the chain, to get the certificate list X509ChainElementCollection x509ChainElementCollection = x509Chain.ChainElements; X509ChainElementEnumerator enumerator = x509ChainElementCollection.GetEnumerator(); X509ChainElement x509ChainElement; X509Certificate2 x509Certificate2 = null; IDictionary <string, X509Certificate2> map = new Dictionary <string, X509Certificate2>(); IList <X509Certificate2> list = new List <X509Certificate2>(); while (enumerator.MoveNext()) { x509ChainElement = enumerator.Current; x509Certificate2 = x509ChainElement.Certificate; list.Add(x509Certificate2); } // now we have a list of the certificate chain // list[0] -> the function certificate // list[0 .. lsit.Count] -> middel certificates // oces1 : none middle certificate exist // oces2 : one middle certificate exist // list[list.Count] - > root certificate // we needed to validate all certificates, except the root certificates // The question wheather the root certificates is trusted, is validated in MultipleRootX509CertificateValidator // However - In the case where the root certificate is not installed, // the chain list will only be 1 length, so no validation is perfored at all. int index = 0; //bool chainValid = true; while (index < (list.Count - 1) && response.IsValid == true) { // this.logger.Info("CRL validation the certificate: " + list[index].Subject); // Retrieve URL distribution points List <Uri> URLs = this.GetURLs(list[index]); // The list should only contain one element // so we are only interesting in the first CRL list if (URLs.Count > 0) { Uri url = URLs[0]; CrlInstance crl = this.GetInstance(url); try { if (!crl.IsRevoked(certificate)) { // so the certificate is not revoked. // remember, that the issueing certificate could be revoked. // So the next update must be the earlist of the all response.IsValid = true; if (response.NextUpdate == DateTime.MinValue) { response.NextUpdate = crl.getNextUpdate(); } else if (response.NextUpdate < crl.getNextUpdate()) { // no new update // the already registrated 'NextUpdate' is before the crl.getNextUpdate } else { // new update time // The already registrated 'NextUpdate', is greater (futher in the future) then crl.getNextUpdate // so we use the crl.getNextUpdate as next update response.NextUpdate = crl.getNextUpdate(); } } else { response.IsValid = false; } } catch (CheckCertificateRevokedUnexpectedException exception) { // could not validate the certificate - so i don't trust it response.Exception = exception; response.IsValid = false; } } else { // url server not identified, so we don't trust this certificate response.IsValid = false; } // increase the index, to check the next certificate index++; } // all the certificate in the chain is now checked. if (response.IsValid == true) { response.RevocationCheckStatus = RevocationCheckStatus.AllChecksPassed; } else { response.RevocationCheckStatus = RevocationCheckStatus.CertificateRevoked; } x509Chain.Reset(); } else { response.IsValid = false; response.Exception = new CheckCertificateRevokedUnexpectedException(new Exception("Error during CRL lookup. The certificate is null"));//did not have any CRL DistPoints. Certificate: " + certificate)); response.RevocationCheckStatus = RevocationCheckStatus.UnknownIssue; } return(response); }
/// <summary> /// Checks a certificate, with default rootcertificate. /// All fields of the CertificateCheckResult structure are initialized as "false". /// Certificate checking may end before all checks have been performed, if individual /// checks fail. In that case, only the fields of the CertificateCheckResult structure that /// corresponds to checks already performed are valid. /// </summary> /// <param name="certificate">certificate to check</param> /// <param name="rootCertificate">a given rootcertificate</param> /// <returns>The object that contains the result. Note that all fields of the CertificateCheckResult /// structure are initialized as "false". Certificate checking may end before all checks have /// been performed, if individual checks fail. In that case, only the fields of the /// CertificateCheckResult structure that /// corresponds to checks already performed are valid.</returns> public CertificateCheckResult CheckCertificate(X509Certificate2 certificate, X509Certificate2 rootCertificate) { CertificateCheckResult result = new CertificateCheckResult(); try { //1. that the certificate has the default rootcertificate as root. // Also checks that the cert is not expired or not yet activated. CheckCertificateChain(certificate, result); if (!result.CertificateActivated || !result.CertificateValid || !result.RootCertificateAsRoot ) { result.AllTestsPassed = false; return(result); } //2. that the rootcertificate is not expired or not activated if (rootCertificate == null) { CheckRootCertificateValidation(_defaultOCESrootCertificate, result); CheckRootCertificateActivated(_defaultOCESrootCertificate, result); } else { CheckRootCertificateValidation(rootCertificate, result); CheckRootCertificateActivated(rootCertificate, result); } if (!result.RootCertificateValid || !result.RootCertificateActivated) { result.AllTestsPassed = false; return(result); } //4. check if the certificate is revoked async RevocationResponse response = CheckCertificateRevocation(certificate); if (!response.IsValid) { result.AllTestsPassed = false; result.CertificateRevoked = true; return(result); } //5. check certificatetype CheckCertificateType(certificate, result); if (result.CertificateActivated && !result.CertificateRevoked && result.CertificateValid && result.RootCertificateActivated && result.RootCertificateAsRoot && result.RootCertificateValid) { result.AllTestsPassed = true; } } catch (ArgumentNullException) { throw; } catch (OverflowException) { throw; } catch (FormatException) { throw; } catch (CryptographicUnexpectedOperationException) { throw; } catch (CryptographicException) { throw; } catch (CheckCertificateOcspUnexpectedException) { throw; } catch (CertificateRevokedTimeoutException) { throw; } catch (Exception) { throw; } return(result); }
/* /// <summary> * /// Overrides the method to validate the binding element order. * /// </summary> * /// <typeparam name="TChannel"></typeparam> * /// <param name="context"></param> * /// <returns></returns> * public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context) * { * BindingElementCollection bindingElements = context.Binding.Elements; * this.stackCheck.Check(bindingElements); * return base.BuildChannelListener<TChannel>(context); * }*/ /// <summary> /// Intercept requests and creates the proof of validation interception before /// attaching it to the message. /// </summary> /// <param name="interceptorMessage"></param> public override void InterceptRequest(InterceptorMessage interceptorMessage) { this.logger.Trace("Security validate the foces certificate."); try { Headers headers = new Headers(interceptorMessage); if (interceptorMessage.IsFault) { // do nothing } else if (headers.IsCreateSequence) { // do nothing } else if (headers.SequenceHeader == null) { // do nothing } else if (headers.SequenceHeader.IsLastMessage) { // do nothing } else { // Get the certificate from the message X509Certificate2 certificate; try { certificate = interceptorMessage.Certificate; } catch { throw new FailedToGetCertificateSubjectException(interceptorMessage); } // now we must revocate check the certificate OcesX509Certificate ocesCertificate = new OcesX509Certificate(certificate); RevocationResponse response = ocesCertificate.CheckRevocationStatus(revocationLookup); if (response.Exception != null) { string msg; try { msg = response.Exception.Message; } catch (Exception ex) { this.logger.Debug("Error finding the correct error message.", ex); msg = "unknown"; } this.logger.Warn(string.Format("The certificate '{0}' revocation check failed. Reason is: ", ocesCertificate.Certificate.SubjectName.Name, msg)); // some error checking the certificate // make sure the error is of the correct type, and throw it // note - if the original exception was not a communikation exception, it is wraped in a communikation exception if (response.Exception is CertificateRevokedTimeoutException) { throw new CertificateRevokedValidationFailedException(response.Exception); } else if (response.Exception is CertificateRevokedException) { throw response.Exception; } else if (response.Exception is CertificateRevokedValidationFailedException) { throw response.Exception; } else if (response.Exception is CheckCertificateOcspUnexpectedException) { throw new CertificateRevokedValidationFailedException(response.Exception); } else if (response.Exception is CheckCertificateRevokedUnexpectedException) { throw new CertificateRevokedValidationFailedException(response.Exception); } else { throw new CertificateRevokedValidationFailedException(response.Exception); } } else { // no exception - all good so far switch (response.RevocationCheckStatus) { case RevocationCheckStatus.AllChecksPassed: { // all good this.logger.Debug(string.Format("Certificate '{0}' has parsed the revocation validate.", certificate.SubjectName.Name)); SignatureValidationProof signatureValidationProof = new SignatureValidationProof(certificate.Subject); interceptorMessage.AddProperty(ServerSignatureValidationProofBindingExtensionElement.SignatureValidationProofKey, signatureValidationProof); break; } case RevocationCheckStatus.CertificateRevoked: { this.logger.Warn(string.Format("The certificate '{0}' is revoked.", ocesCertificate.Certificate.SubjectName.Name)); throw new CertificateRevokedException(); //break; } default: { this.logger.Warn(string.Format("The certificate '{0}' failed in revocation check - reason unknown", ocesCertificate.Certificate.SubjectName.Name)); throw new CertificateRevokedValidationFailedException("The certificate failed in revocation check - reason unknown."); //break; } } } } } catch (FailedToGetCertificateSubjectException) { // exception is of the correct type - rethrowing it throw; } /* catch (CertificateRevokedTimeoutException e) * { * // exception is of the correct type - rethrowing it * throw new CertificateRevokedValidationFailedException(e); * }*/ catch (CertificateRevokedException) { // exception is of the correct type - rethrowing it throw; } catch (CertificateRevokedValidationFailedException) { // exception is of the correct type - rethrowing it throw; } /* catch (CheckCertificateOcspUnexpectedException) * { * // exception is of the correct type - rethrowing it * throw; * }*/ /* catch (CheckCertificateRevokedUnexpectedException) * { * // exception is of the correct type - rethrowing it * throw; * }*/ catch (Exception ex) { this.logger.Debug("Security validate the foces certificate", ex); throw new CertificateRevokedValidationFailedException(ex); } this.logger.Trace("Security validate the foces certificate - Finish."); }
/// <summary> /// Checks a certificate status on a ocsp server /// </summary> /// <param name="x509Certificate2">The certificate to check</param> /// <returns>The RevocationResponse object that contains the result</returns> /// <exception cref="CheckCertificateOcspUnexpectedException">This exception is thrown, if an unexpected exception is thrown during the method</exception> private RevocationResponse RevocationResponseOnline(X509Certificate2 x509Certificate2) { RevocationResponse revocationResponse = new RevocationResponse(); if (x509Certificate2 == null) { throw new CheckCertificateOcspUnexpectedException(); } // http://bouncy-castle.1462172.n4.nabble.com/c-ocsp-verification-td3160243.html X509Certificate2 issuerX509Certificate2 = this.FindIssuerCertificate(x509Certificate2); if (issuerX509Certificate2 == null) { throw new CheckCertificateOcspUnexpectedException("Issuer certificate '" + x509Certificate2.Issuer + "' not found."); } if (issuerX509Certificate2.Thumbprint.Equals(x509Certificate2.Thumbprint, StringComparison.OrdinalIgnoreCase)) { // the certificate and the issuer certificace is the same // this mean that the root certificate is not trusted revocationResponse = null; } else { revocationResponse = this.RevocationResponseOnline(x509Certificate2, issuerX509Certificate2); if (revocationResponse != null) { if (revocationResponse.Exception == null) { // no exception recorded if (revocationResponse.IsValid) { // now we know the certificate is valid. // if the issuer is a trusted root certificate, all is good if (this.rootCertificateDirectory.ContainsKey(issuerX509Certificate2.Thumbprint.ToLowerInvariant())) { // the root certificate is trusted, so the RevocationResponse can be put on the cache this.ocspCache.Set(x509Certificate2.Thumbprint.ToLowerInvariant(), revocationResponse); } else { // we do not yet know if the certificate is valid. // the certificate migth be good, but if the issueing certificate is revoked, // then the certificate should also be revoked. // Validate the issuer certificate // this is required, because certificate can have a chain that is longer then 2 // The only problem is, that we can not ocsp validate the intermiddel certificate (the issuer certificate). // acording to DanID - that certificate can only be validated with CRL // Note : The crl list will be/should be very short. Only containing the issuer certificate that has been revoked. // A good guess is that there at all time will be most 10 issuer certificate, so the list of revoked issuer certificate is short. IList <string> issuerUrl = this.GetAuthorityInformationAccessOcspUrl(issuerX509Certificate2); RevocationResponse issuerRevocationResponse; if (issuerUrl.Count > 0) { // hey, wow some url exist - lets use that // don't thing this will ever happens anyway issuerRevocationResponse = this.RevocationResponse(issuerX509Certificate2); } else { // we need to validate with crl instead // It does not contain the Authority Info Access, containng the rl to where the certificate must be validated // We must therefore gues, that the certificate is valid. CrlLookup crlLookupClient = new CrlLookup(); issuerRevocationResponse = crlLookupClient.CheckCertificate(issuerX509Certificate2); } // now to handle the issuerRevocationResponse if (issuerRevocationResponse != null) { // the issuer certificate is validated, the validity of the issuer certificate // is copied to the revocationResponse revocationResponse.IsValid = issuerRevocationResponse.IsValid; revocationResponse.Exception = issuerRevocationResponse.Exception; } else { revocationResponse.IsValid = false; revocationResponse.Exception = new CheckCertificateOcspUnexpectedException("The issueing certificate could not be validated."); } // update the cache this.ocspCache.Set(x509Certificate2.Thumbprint.ToLowerInvariant(), revocationResponse); } } else { // the certificate is NOT valid // no need to check the issuer certificate this.ocspCache.Set(x509Certificate2.Thumbprint.ToLowerInvariant(), revocationResponse); } } else { // some exception returned. // do not add to cache } } } return(revocationResponse); }
private RevocationResponse ProcessOcspResponse(Org.BouncyCastle.X509.X509Certificate serverX509Certificate, Org.BouncyCastle.X509.X509Certificate rootX509Certificate, byte[] binaryResp) { OcspResp r = new OcspResp(binaryResp); //CertificateStatus cStatus = CertificateStatus.Unknown; RevocationResponse revocationResponse = new RevocationResponse(); //X509CertificateParser parser = null; //OcspRespStatus.Unauthorized switch (r.Status) { case OcspRespStatus.Successful: { BasicOcspResp or = (BasicOcspResp)r.GetResponseObject(); // ValidateResponse(or, issuerCert); string certificateSerial = Convert.ToUInt32(serverX509Certificate.SerialNumber.IntValue).ToString(); bool found = false; foreach (SingleResp singleResp in or.Responses) { if (singleResp.GetCertID().SerialNumber.ToString().Equals(certificateSerial)) { found = true; this.ValidateCertificateId(serverX509Certificate, rootX509Certificate, singleResp.GetCertID()); // ValidateThisUpdate(resp); // ValidateNextUpdate(resp); Object certificateStatus = singleResp.GetCertStatus(); if (certificateStatus == null) { // acording to org.openoces.ooapi.utils.ocsp.ResponseParser.cs (DanID test code) // in the TU11, method SerialNumberInResponseIsNotRevoked(..), // when the certificateStatus is empty, all is okay - not revoked // no revocation data exist - the certificate must be valid revocationResponse.IsValid = true; revocationResponse.NextUpdate = singleResp.NextUpdate.Value; revocationResponse.RevocationCheckStatus = RevocationCheckStatus.AllChecksPassed; } else if (certificateStatus == Org.BouncyCastle.Ocsp.CertificateStatus.Good) { // this is the expected certificateStatus for valid certificates // however if the status is good the certificateStatus is null revocationResponse.IsValid = true; revocationResponse.NextUpdate = singleResp.NextUpdate.Value; revocationResponse.RevocationCheckStatus = RevocationCheckStatus.AllChecksPassed; } else if (certificateStatus is Org.BouncyCastle.Ocsp.RevokedStatus) { revocationResponse.IsValid = false; revocationResponse.NextUpdate = singleResp.NextUpdate.Value; revocationResponse.RevocationCheckStatus = RevocationCheckStatus.CertificateRevoked; } else if (certificateStatus is Org.BouncyCastle.Ocsp.UnknownStatus) { throw new CheckCertificateOcspUnexpectedException("CertificateStatus is Unknown"); } else { throw new CheckCertificateOcspUnexpectedException("CertificateStatus is unknown '" + certificateStatus.ToString() + "'."); } // break foreach loop break; } } if (!found) { // the returned result did not contain the desired certificate throw new CheckCertificateOcspUnexpectedException("Revokation result did not contain the desired certificate serial number."); } break; } default: { throw new CheckCertificateOcspUnexpectedException("Unknow status '" + r.Status + "'."); } } return(revocationResponse); }
public RevocationResponse RevocationResponseOnline(X509Certificate2 serverX509Certificate2, X509Certificate2 issuerX509Certificate2, string url) { RevocationResponse revocationResponse = new RevocationResponse(); try { if (serverX509Certificate2 == null) { throw new Exception("Server certificate is null"); } if (issuerX509Certificate2 == null) { throw new Exception("Issuer certificate for server certificate not identified"); } // create BouncyCastle certificates X509CertificateParser certParser = new X509CertificateParser(); Org.BouncyCastle.X509.X509Certificate issuerX509Certificate = certParser.ReadCertificate(issuerX509Certificate2.RawData); Org.BouncyCastle.X509.X509Certificate serverX509Certificate = certParser.ReadCertificate(serverX509Certificate2.RawData); // 1. Generate request OcspReq req = this.GenerateOcspRequest(issuerX509Certificate, serverX509Certificate.SerialNumber); // 2. make binary request online byte[] encoded = req.GetEncoded(); byte[] binaryResp = this.PostData(url, encoded, "application/ocsp-request", "application/ocsp-response"); //3. check result revocationResponse = this.ProcessOcspResponse(serverX509Certificate, issuerX509Certificate, binaryResp); } catch (CheckCertificateOcspUnexpectedException) { throw; } catch (ArgumentNullException e) { revocationResponse.Exception = new CheckCertificateOcspUnexpectedException("ArgumentNullException", e); } catch (OverflowException e) { revocationResponse.Exception = new CheckCertificateOcspUnexpectedException("OverflowException", e); } catch (FormatException e) { revocationResponse.Exception = new CheckCertificateOcspUnexpectedException("FormatException", e); } catch (CryptographicUnexpectedOperationException e) { revocationResponse.Exception = new CheckCertificateOcspUnexpectedException("CryptographicUnexpectedOperationException", e); } catch (CryptographicException e) { revocationResponse.Exception = new CheckCertificateOcspUnexpectedException("CryptographicException", e); } catch (Exception e) { revocationResponse.Exception = new CheckCertificateOcspUnexpectedException("OCSP valideringen fejlede.", e); } return(revocationResponse); }