/// <summary> /// Build a chain for the certificates and verifies the revocation (own implementation) /// </summary> /// <param name="cert">The certificate to validate</param> /// <param name="validationTime">The time upon wich the validate</param> /// <param name="extraStore">Extra certs to use when creating the chain</param> /// <param name="crls">Already known crl's, newly retrieved CRL's will be added here</param> /// <param name="ocsps">Already konwn ocsp's, newly retreived OCSP's will be added here</param> /// <returns>The chain with all the information about validity</returns> public static Chain BuildChain(this X509Certificate2 cert, DateTime validationTime, X509Certificate2Collection extraStore, IList <BCAX.CertificateList> crls, IList <BCAO.BasicOcspResponse> ocsps) { Chain chain = cert.BuildChain(validationTime, extraStore); if (cert.IsOcspNoCheck()) { return(chain); //nothing to do } for (int i = 0; i < (chain.ChainElements.Count - 1); i++) { X509Certificate2 nextCert = chain.ChainElements[i].Certificate; X509Certificate2 nextIssuer = chain.ChainElements[i + 1].Certificate; try { //try OCSP BCAO.BasicOcspResponse ocspResponse = nextCert.Verify(nextIssuer, validationTime, ocsps); if (ocspResponse == null) { //try to fetch a new one BCAO.OcspResponse ocspMsg = nextCert.GetOcspResponse(nextIssuer); if (ocspMsg != null) { //new one fetched, try again ocspResponse = BCAO.BasicOcspResponse.GetInstance(BCA.Asn1Object.FromByteArray(ocspMsg.ResponseBytes.Response.GetOctets())); ocsps.Add(ocspResponse); ocspResponse = nextCert.Verify(nextIssuer, validationTime, ocsps); } } //TODO::ignore OCSP retreival errors and try CRL ;-) if (ocspResponse == null) { //try CRL BCAX.CertificateList crl = nextCert.Verify(nextIssuer, validationTime, crls); if (crl == null) { //try to fetch a new one crl = nextCert.GetCertificateList(); if (crl != null) { //new one fetched, try again crls.Add(crl); crl = nextCert.Verify(nextIssuer, validationTime, crls); } } } } catch (RevocationException <BCAO.BasicOcspResponse> ) { AddErrorStatus(chain.ChainStatus, chain.ChainElements[i].ChainElementStatus, X509ChainStatusFlags.Revoked, "The certificate has been revoked"); } catch { AddErrorStatus(chain.ChainStatus, chain.ChainElements[i].ChainElementStatus, X509ChainStatusFlags.RevocationStatusUnknown, "Invalid OCSP/CRL found"); } } return(chain); }
public RevocationValues( CertificateList[] crlVals, BasicOcspResponse[] ocspVals, OtherRevVals otherRevVals) { if (crlVals != null) { this.crlVals = new DerSequence(crlVals); } if (ocspVals != null) { this.ocspVals = new DerSequence(ocspVals); } this.otherRevVals = otherRevVals; }
public RevocationValues( CertificateList[] crlVals, BasicOcspResponse[] ocspVals, OtherRevVals otherRevVals) { //if (otherRevVals == null) // throw new ArgumentNullException("otherRevVals"); if (crlVals != null) { this.crlVals = new DerSequence(crlVals); } if (ocspVals != null) { this.ocspVals = new DerSequence(ocspVals); } this.otherRevVals = otherRevVals; }
public BasicOcspResponse[] GetOcspVals() { BasicOcspResponse[] result = new BasicOcspResponse[ocspVals.Count]; for (int i = 0; i < ocspVals.Count; ++i) { result[i] = BasicOcspResponse.GetInstance(ocspVals[i].ToAsn1Object()); } return result; }
/// <summary> /// Validates the cert with the provided ocsp responses. /// </summary> /// <param name="certificate">The cert to validate</param> /// <param name="issuer">The issuer of the cert to validate</param> /// <param name="validationTime">The time on which the cert was needed to validated</param> /// <param name="ocspResponses">The list of ocsp responses to use</param> /// <returns>The OCSP response that was used, <c>null</c> if none was found</returns> /// <exception cref="RevocationException{T}">When the certificate was revoked on the provided time</exception> /// <exception cref="RevocationUnknownException">When the certificate (or the OCSP) can't be validated</exception> public static BCAO.BasicOcspResponse Verify(this X509Certificate2 certificate, X509Certificate2 issuer, DateTime validationTime, IList <BCAO.BasicOcspResponse> ocspResponses) { DateTime minTime = validationTime - ClockSkewness; DateTime maxTime = validationTime + ClockSkewness; BCX.X509Certificate certificateBC = DotNetUtilities.FromX509Certificate(certificate); BCX.X509Certificate issuerBC = DotNetUtilities.FromX509Certificate(issuer); ValueWithRef <BCO.SingleResp, ValueWithRef <BCO.BasicOcspResp, BCAO.BasicOcspResponse> > singleOcspRespLeaf = ocspResponses .Select((rsp) => new ValueWithRef <BCO.BasicOcspResp, BCAO.BasicOcspResponse>(new BCO.BasicOcspResp(rsp), rsp)) //convert, but keep the original .SelectMany((r) => r.Value.Responses.Select(sr => new ValueWithRef <BCO.SingleResp, ValueWithRef <BCO.BasicOcspResp, BCAO.BasicOcspResponse> >(sr, r))) //get the single respononses, but keep the parent .Where((sr) => sr.Value.GetCertID().SerialNumber.Equals(certificateBC.SerialNumber) && sr.Value.GetCertID().MatchesIssuer(issuerBC)) //is it for this cert? .Where((sr) => sr.Value.ThisUpdate >= minTime || (sr.Value.NextUpdate != null && sr.Value.NextUpdate.Value >= minTime)) //was it issued on time? .OrderByDescending((sr) => sr.Value.ThisUpdate) //newest first .FirstOrDefault(); if (singleOcspRespLeaf == null) { return(null); } BCO.SingleResp singleOcspResp = singleOcspRespLeaf.Value; BCO.BasicOcspResp basicOcspResp = singleOcspRespLeaf.Reference.Value; BCAO.BasicOcspResponse basicOcspResponse = singleOcspRespLeaf.Reference.Reference; //get the signer name BCAX.X509Name responderName = basicOcspResp.ResponderId.ToAsn1Object().Name; if (responderName == null) { trace.TraceEvent(TraceEventType.Error, 0, "OCSP response for {0} does not have a ResponderID", certificate.Subject); throw new RevocationUnknownException("OCSP response for {0} does not have a ResponderID"); } //Get the signer certificate var selector = new BCS.X509CertStoreSelector(); selector.Subject = responderName; BCX.X509Certificate ocspSignerBc = (BCX.X509Certificate)basicOcspResp .GetCertificates("Collection").GetMatches(selector) .Cast <BCX.X509Certificate>().FirstOrDefault(); if (ocspSignerBc == null) { throw new RevocationUnknownException("The OCSP is signed by a unknown certificate"); } //verify the response signature if (!basicOcspResp.Verify(ocspSignerBc.GetPublicKey())) { throw new RevocationUnknownException("The OCSP has an invalid signature"); } //OCSP must be issued by same issuer an the certificate that it validates. try { if (!ocspSignerBc.IssuerDN.Equals(issuerBC.SubjectDN)) { throw new ApplicationException(); } ocspSignerBc.Verify(issuerBC.GetPublicKey()); } catch (Exception e) { throw new RevocationUnknownException("The OCSP signer was not issued by the proper CA", e); } //verify if the OCSP signer certificate is stil valid if (!ocspSignerBc.IsValid(basicOcspResp.ProducedAt)) { throw new RevocationUnknownException("The OCSP signer was not valid at the time the ocsp was issued"); } //check if the signer may issue OCSP IList ocspSignerExtKeyUsage = ocspSignerBc.GetExtendedKeyUsage(); if (!ocspSignerExtKeyUsage.Contains("1.3.6.1.5.5.7.3.9")) { throw new RevocationUnknownException("The OCSP is signed by a certificate that isn't allowed to sign OCSP"); } //finally, check if the certificate is revoked or not var revokedStatus = (BCO.RevokedStatus)singleOcspResp.GetCertStatus(); if (revokedStatus != null) { trace.TraceEvent(TraceEventType.Verbose, 0, "OCSP response for {0} indicates that the certificate is revoked on {1}", certificate.Subject, revokedStatus.RevocationTime); if (maxTime >= revokedStatus.RevocationTime) { throw new RevocationException <BCAO.BasicOcspResponse>(basicOcspResponse, "The certificate was revoked on " + revokedStatus.RevocationTime.ToString("o")); } } return(basicOcspResponse); }
// private readonly X509Certificate[] chain; public BasicOcspResp( BasicOcspResponse resp) { this.resp = resp; this.data = resp.TbsResponseData; }
/// <exception cref="System.IO.IOException"></exception> //private IDictionary<DerObjectIdentifier, Asn1Encodable> ExtendUnsignedAttributes(IDictionary // <DerObjectIdentifier, Asn1Encodable> unsignedAttrs, X509Certificate signingCertificate // , DateTime signingDate, CertificateSource optionalCertificateSource) private IDictionary ExtendUnsignedAttributes(IDictionary unsignedAttrs , X509Certificate signingCertificate, DateTime signingDate , CertificateSource optionalCertificateSource) { ValidationContext validationContext = certificateVerifier.ValidateCertificate(signingCertificate , signingDate, optionalCertificateSource, null, null); try { IList<X509CertificateStructure> certificateValues = new AList<X509CertificateStructure >(); AList<CertificateList> crlValues = new AList<CertificateList>(); AList<BasicOcspResponse> ocspValues = new AList<BasicOcspResponse>(); foreach (CertificateAndContext c in validationContext.GetNeededCertificates()) { if (!c.Equals(signingCertificate)) { certificateValues.AddItem(X509CertificateStructure.GetInstance(((Asn1Sequence)Asn1Object.FromByteArray (c.GetCertificate().GetEncoded())))); } } foreach (X509Crl relatedcrl in validationContext.GetNeededCRL()) { crlValues.AddItem(CertificateList.GetInstance((Asn1Sequence)Asn1Object.FromByteArray(((X509Crl )relatedcrl).GetEncoded()))); } foreach (BasicOcspResp relatedocspresp in validationContext.GetNeededOCSPResp()) { ocspValues.AddItem((BasicOcspResponse.GetInstance((Asn1Sequence)Asn1Object.FromByteArray( relatedocspresp.GetEncoded())))); } CertificateList[] crlValuesArray = new CertificateList[crlValues.Count]; BasicOcspResponse[] ocspValuesArray = new BasicOcspResponse[ocspValues.Count]; RevocationValues revocationValues = new RevocationValues(Sharpen.Collections.ToArray (crlValues, crlValuesArray), Sharpen.Collections.ToArray(ocspValues, ocspValuesArray ), null); //unsignedAttrs.Put(PkcsObjectIdentifiers.IdAAEtsRevocationValues, new Attribute unsignedAttrs.Add(PkcsObjectIdentifiers.IdAAEtsRevocationValues, new BcCms.Attribute (PkcsObjectIdentifiers.IdAAEtsRevocationValues, new DerSet(revocationValues)) ); X509CertificateStructure[] certValuesArray = new X509CertificateStructure[certificateValues .Count]; //unsignedAttrs.Put(PkcsObjectIdentifiers.IdAAEtsCertValues, new Attribute(PkcsObjectIdentifiers.IdAAEtsCertValues, new DerSet(new DerSequence(Sharpen.Collections.ToArray(certificateValues unsignedAttrs.Add(PkcsObjectIdentifiers.IdAAEtsCertValues, new BcCms.Attribute(PkcsObjectIdentifiers.IdAAEtsCertValues, new DerSet(new DerSequence(Sharpen.Collections.ToArray(certificateValues , certValuesArray))))); } catch (CertificateEncodingException e) { throw new RuntimeException(e); } catch (CrlException e) { throw new RuntimeException(e); } return unsignedAttrs; }
private static List<X509Certificate2> CompleteOcspChain(BasicOcspResponse ocspResponse, IEnumerable<X509Certificate2> ocspChain) { var ocspCertificate = new X509Certificate2(ocspResponse.Certs[0].GetEncoded()); return new List<X509Certificate2>(ocspChain) {ocspCertificate}; }
public static BasicOcspResponse GetInstance(Asn1TaggedObject obj, bool explicitly) { return(BasicOcspResponse.GetInstance(Asn1Sequence.GetInstance(obj, explicitly))); }
public void Setup() { leafCert = new X509Certificate2("files/eid79021802145.crt"); intCaCert = new X509Certificate2("files/Citizen201204.crt"); intCaCrl = CertificateList.GetInstance(File.ReadAllBytes("files/Citizen201204.crl")); rootCaCrl = CertificateList.GetInstance(File.ReadAllBytes("files/rootca2.crl")); leafOcsp = BasicOcspResponse.GetInstance(Asn1Sequence.GetInstance(File.ReadAllBytes("files/eid79021802145.ocsp"))); leafOcsp2 = BasicOcspResponse.GetInstance(Asn1Sequence.GetInstance(File.ReadAllBytes("files/eid79021802145-2.ocsp"))); }