<PackageReference Include="BouncyCastle.Cryptography" Version="2.7.0-beta.98" />

PkixCertPathValidatorUtilities

Summary description for PkixCertPathValidatorUtilities.
using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.IsisMtt; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Collections; using Org.BouncyCastle.X509; using Org.BouncyCastle.X509.Extension; using Org.BouncyCastle.X509.Store; using System; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Pkix { internal static class PkixCertPathValidatorUtilities { internal static readonly string ANY_POLICY = "2.5.29.32.0"; internal static readonly DerObjectIdentifier ANY_POLICY_OID = new DerObjectIdentifier(ANY_POLICY); internal static readonly string CRL_NUMBER = X509Extensions.CrlNumber.Id; internal static readonly int KEY_CERT_SIGN = 5; internal static readonly int CRL_SIGN = 6; internal static TrustAnchor FindTrustAnchor(X509Certificate cert, ISet<TrustAnchor> trustAnchors) { IEnumerator<TrustAnchor> enumerator = trustAnchors.GetEnumerator(); TrustAnchor trustAnchor = null; AsymmetricKeyParameter asymmetricKeyParameter = null; Exception ex = null; X509CertStoreSelector x509CertStoreSelector = new X509CertStoreSelector(); try { x509CertStoreSelector.Subject = GetIssuerPrincipal(cert); } catch (IOException innerException) { throw new Exception("Cannot set subject search criteria for trust anchor.", innerException); } while (enumerator.MoveNext() && trustAnchor == null) { trustAnchor = enumerator.Current; if (trustAnchor.TrustedCert != null) { if (x509CertStoreSelector.Match(trustAnchor.TrustedCert)) asymmetricKeyParameter = trustAnchor.TrustedCert.GetPublicKey(); else trustAnchor = null; } else if (trustAnchor.CAName != null && trustAnchor.CAPublicKey != null) { try { X509Name issuerPrincipal = GetIssuerPrincipal(cert); X509Name other = new X509Name(trustAnchor.CAName); if (issuerPrincipal.Equivalent(other, true)) asymmetricKeyParameter = trustAnchor.CAPublicKey; else trustAnchor = null; } catch (InvalidParameterException) { trustAnchor = null; } } else { trustAnchor = null; } if (asymmetricKeyParameter != null) try { cert.Verify(asymmetricKeyParameter); } catch (Exception ex3) { ex = ex3; trustAnchor = null; } } if (trustAnchor == null && ex != null) throw new Exception("TrustAnchor found but certificate validation failed.", ex); return trustAnchor; } internal static bool IsIssuerTrustAnchor(X509Certificate cert, ISet<TrustAnchor> trustAnchors) { try { return FindTrustAnchor(cert, trustAnchors) != null; } catch (Exception) { return false; } } internal static void AddAdditionalStoresFromAltNames(X509Certificate cert, PkixParameters pkixParams) { IList<IList<object>> issuerAlternativeNames = cert.GetIssuerAlternativeNames(); if (issuerAlternativeNames != null) { foreach (IList<object> item in issuerAlternativeNames) { if (item.Count >= 2 && item[0].Equals(6)) AddAdditionalStoreFromLocation((string)item[1], pkixParams); } } } internal static DateTime GetValidDate(PkixParameters paramsPKIX) { DateTime? date = paramsPKIX.Date; if (!date.HasValue) return DateTime.UtcNow; return date.Value; } internal static X509Name GetIssuerPrincipal(object obj) { X509Certificate x509Certificate = obj as X509Certificate; if (x509Certificate != null) return x509Certificate.IssuerDN; X509V2AttributeCertificate x509V2AttributeCertificate = obj as X509V2AttributeCertificate; if (x509V2AttributeCertificate != null) return x509V2AttributeCertificate.Issuer.GetPrincipals()[0]; throw new InvalidOperationException(); } internal static X509Name GetIssuerPrincipal(X509V2AttributeCertificate attrCert) { return attrCert.Issuer.GetPrincipals()[0]; } internal static X509Name GetIssuerPrincipal(X509Certificate cert) { return cert.IssuerDN; } internal static bool IsSelfIssued(X509Certificate cert) { return cert.SubjectDN.Equivalent(cert.IssuerDN, true); } internal static AlgorithmIdentifier GetAlgorithmIdentifier(AsymmetricKeyParameter key) { try { return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key).Algorithm; } catch (Exception innerException) { throw new PkixCertPathValidatorException("Subject public key cannot be decoded.", innerException); } } internal static bool IsAnyPolicy(ISet<string> policySet) { if (policySet != null && policySet.Count >= 1) return policySet.Contains(ANY_POLICY); return true; } internal static void AddAdditionalStoreFromLocation(string location, PkixParameters pkixParams) { if (pkixParams.IsAdditionalLocationsEnabled) try { if (Platform.StartsWith(location, "ldap://")) { location = location.Substring(7); int num = location.IndexOf('/'); if (num != -1) { string text = "ldap://" + location.Substring(0, num); } else { string text2 = "ldap://" + location; } throw new NotImplementedException("LDAP cert/CRL stores"); } } catch (Exception) { throw new Exception("Exception adding X.509 stores."); } } private static BigInteger GetSerialNumber(object cert) { if (cert is X509Certificate) return ((X509Certificate)cert).SerialNumber; return ((X509V2AttributeCertificate)cert).SerialNumber; } internal static HashSet<PolicyQualifierInfo> GetQualifierSet(Asn1Sequence qualifiers) { HashSet<PolicyQualifierInfo> hashSet = new HashSet<PolicyQualifierInfo>(); if (qualifiers != null) { foreach (Asn1Encodable qualifier in qualifiers) { try { hashSet.Add(PolicyQualifierInfo.GetInstance(qualifier.ToAsn1Object())); } catch (IOException innerException) { throw new PkixCertPathValidatorException("Policy qualifier info cannot be decoded.", innerException); } } return hashSet; } return hashSet; } internal static PkixPolicyNode RemoveChildlessPolicyNodes(PkixPolicyNode validPolicyTree, List<PkixPolicyNode>[] policyNodes, int depthLimit) { if (validPolicyTree == null) return null; int num = depthLimit; while (--num >= 0) { List<PkixPolicyNode> list = policyNodes[num]; int num2 = list.Count; while (--num2 >= 0) { PkixPolicyNode pkixPolicyNode = list[num2]; if (!pkixPolicyNode.HasChildren) { list.RemoveAt(num2); PkixPolicyNode parent = pkixPolicyNode.Parent; if (parent == null) return null; parent.RemoveChild(pkixPolicyNode); } } } return validPolicyTree; } internal static PkixPolicyNode RemovePolicyNode(PkixPolicyNode validPolicyTree, List<PkixPolicyNode>[] policyNodes, PkixPolicyNode _node) { if (validPolicyTree == null) return null; PkixPolicyNode parent = _node.Parent; if (parent == null) { for (int i = 0; i < policyNodes.Length; i++) { policyNodes[i].Clear(); } return null; } parent.RemoveChild(_node); RemovePolicyNodeRecurse(policyNodes, _node); return validPolicyTree; } private static void RemovePolicyNodeRecurse(List<PkixPolicyNode>[] policyNodes, PkixPolicyNode _node) { policyNodes[_node.Depth].Remove(_node); if (_node.HasChildren) { foreach (PkixPolicyNode child in _node.Children) { RemovePolicyNodeRecurse(policyNodes, child); } } } internal static void GetCertStatus(DateTime validDate, X509Crl crl, object cert, CertStatus certStatus) { X509CrlEntry revokedCertificate = crl.GetRevokedCertificate(GetSerialNumber(cert)); if (revokedCertificate != null) { X509Name issuerPrincipal = GetIssuerPrincipal(cert); if (issuerPrincipal.Equivalent(revokedCertificate.GetCertificateIssuer(), true) || issuerPrincipal.Equivalent(crl.IssuerDN, true)) { int num = 0; if (revokedCertificate.HasExtensions) { CheckCrlEntryCriticalExtensions(revokedCertificate, "CRL entry has unsupported critical extensions."); try { DerEnumerated extension = revokedCertificate.GetExtension(X509Extensions.ReasonCode, DerEnumerated.GetInstance); if (extension != null) num = extension.IntValueExact; } catch (Exception innerException) { throw new Exception("Reason code CRL entry extension could not be decoded.", innerException); } } DateTime revocationDate = revokedCertificate.RevocationDate; if (validDate.Ticks >= revocationDate.Ticks || (uint)num <= 2 || num == 10) { certStatus.Status = num; certStatus.RevocationDate = revocationDate; } } } } internal static AsymmetricKeyParameter GetNextWorkingKey(IList<X509Certificate> certs, int index) { AsymmetricKeyParameter publicKey = certs[index].GetPublicKey(); DsaPublicKeyParameters dsaPublicKeyParameters = publicKey as DsaPublicKeyParameters; if (dsaPublicKeyParameters == null) return publicKey; if (dsaPublicKeyParameters.Parameters != null) return dsaPublicKeyParameters; for (int i = index + 1; i < certs.Count; i++) { publicKey = certs[i].GetPublicKey(); DsaPublicKeyParameters dsaPublicKeyParameters2 = publicKey as DsaPublicKeyParameters; if (dsaPublicKeyParameters2 == null) throw new PkixCertPathValidatorException("DSA parameters cannot be inherited from previous certificate."); if (dsaPublicKeyParameters2.Parameters != null) { DsaParameters parameters = dsaPublicKeyParameters2.Parameters; try { return new DsaPublicKeyParameters(dsaPublicKeyParameters.Y, parameters); } catch (Exception ex) { throw new Exception(ex.Message); } } } throw new PkixCertPathValidatorException("DSA parameters cannot be inherited from previous certificate."); } internal static DateTime GetValidCertDateFromValidityModel(PkixParameters paramsPkix, PkixCertPath certPath, int index) { if (1 != paramsPkix.ValidityModel || index <= 0) return GetValidDate(paramsPkix); X509Certificate x509Certificate = certPath.Certificates[index - 1]; if (index - 1 == 0) { Asn1GeneralizedTime extension; try { extension = x509Certificate.GetExtension(IsisMttObjectIdentifiers.IdIsisMttATDateOfCertGen, Asn1GeneralizedTime.GetInstance); } catch (ArgumentException innerException) { throw new Exception("Date of cert gen extension could not be read.", innerException); } if (extension != null) try { return extension.ToDateTime(); } catch (ArgumentException innerException2) { throw new Exception("Date from date of cert gen extension could not be parsed.", innerException2); } } return x509Certificate.NotBefore; } internal static void GetCrlIssuersFromDistributionPoint(DistributionPoint dp, ICollection<X509Name> issuerPrincipals, X509CrlStoreSelector selector, PkixParameters pkixParameters) { List<X509Name> list = new List<X509Name>(); if (dp.CrlIssuer != null) { GeneralName[] names = dp.CrlIssuer.GetNames(); for (int i = 0; i < names.Length; i++) { if (names[i].TagNo == 4) try { list.Add(X509Name.GetInstance(names[i].Name.ToAsn1Object())); } catch (IOException innerException) { throw new Exception("CRL issuer information from distribution point cannot be decoded.", innerException); } } } else { if (dp.DistributionPointName == null) throw new Exception("CRL issuer is omitted from distribution point but no distributionPoint field present."); list.AddRange(issuerPrincipals); } selector.Issuers = list; } internal static HashSet<X509Crl> GetCompleteCrls(DistributionPoint dp, object certObj, DateTime currentDate, PkixParameters pkixParameters) { X509Name issuerPrincipal = GetIssuerPrincipal(certObj); X509CrlStoreSelector x509CrlStoreSelector = new X509CrlStoreSelector(); try { HashSet<X509Name> hashSet = new HashSet<X509Name>(); hashSet.Add(issuerPrincipal); GetCrlIssuersFromDistributionPoint(dp, hashSet, x509CrlStoreSelector, pkixParameters); } catch (Exception innerException) { throw new Exception("Could not get issuer information from distribution point.", innerException); } X509Certificate x509Certificate = certObj as X509Certificate; if (x509Certificate != null) x509CrlStoreSelector.CertificateChecking = x509Certificate; else { X509V2AttributeCertificate x509V2AttributeCertificate = certObj as X509V2AttributeCertificate; if (x509V2AttributeCertificate != null) x509CrlStoreSelector.AttrCertChecking = x509V2AttributeCertificate; } x509CrlStoreSelector.CompleteCrlEnabled = true; HashSet<X509Crl> hashSet2 = PkixCrlUtilities.ImplFindCrls(x509CrlStoreSelector, pkixParameters, currentDate); if (hashSet2.Count < 1) throw new Exception("No CRLs found for issuer \"" + issuerPrincipal?.ToString() + "\""); return hashSet2; } internal static HashSet<X509Crl> GetDeltaCrls(DateTime currentDate, PkixParameters pkixParameters, X509Crl completeCrl) { X509CrlStoreSelector x509CrlStoreSelector = new X509CrlStoreSelector(); try { List<X509Name> list = new List<X509Name>(); list.Add(completeCrl.IssuerDN); x509CrlStoreSelector.Issuers = list; } catch (IOException innerException) { throw new Exception("Cannot extract issuer from CRL.", innerException); } BigInteger bigInteger; try { bigInteger = completeCrl.GetExtension(X509Extensions.CrlNumber, DerInteger.GetInstance)?.PositiveValue; } catch (Exception innerException2) { throw new Exception("CRL number extension could not be extracted from CRL.", innerException2); } byte[] issuingDistributionPoint; try { issuingDistributionPoint = completeCrl.GetExtension(X509Extensions.IssuingDistributionPoint, IssuingDistributionPoint.GetInstance)?.GetEncoded("DER"); } catch (Exception innerException3) { throw new Exception("Issuing distribution point extension value could not be read.", innerException3); } x509CrlStoreSelector.MinCrlNumber = bigInteger?.Add(BigInteger.One); x509CrlStoreSelector.IssuingDistributionPoint = issuingDistributionPoint; x509CrlStoreSelector.IssuingDistributionPointEnabled = true; x509CrlStoreSelector.MaxBaseCrlNumber = bigInteger; x509CrlStoreSelector.DeltaCrlIndicatorEnabled = true; HashSet<X509Crl> hashSet = PkixCrlUtilities.ImplFindCrls(x509CrlStoreSelector, pkixParameters, currentDate); RetainDeltaCrls(hashSet); return hashSet; } private static bool IsDeltaCrl(X509Crl crl) { return HasCriticalExtension(crl, X509Extensions.DeltaCrlIndicator); } private static void RetainDeltaCrls(HashSet<X509Crl> crls) { crls.RemoveWhere((X509Crl crl) => !IsDeltaCrl(crl)); } internal static void AddAdditionalStoresFromCrlDistributionPoint(CrlDistPoint crldp, PkixParameters pkixParams) { if (crldp != null) { DistributionPoint[] distributionPoints; try { distributionPoints = crldp.GetDistributionPoints(); } catch (Exception innerException) { throw new Exception("Distribution points could not be read.", innerException); } for (int i = 0; i < distributionPoints.Length; i++) { DistributionPointName distributionPointName = distributionPoints[i].DistributionPointName; if (distributionPointName != null && distributionPointName.Type == 0) { GeneralName[] names = GeneralNames.GetInstance(distributionPointName.Name).GetNames(); for (int j = 0; j < names.Length; j++) { if (names[j].TagNo == 6) AddAdditionalStoreFromLocation(DerIA5String.GetInstance(names[j].Name).GetString(), pkixParams); } } } } } internal static bool ProcessCertD1i(int index, IList<PkixPolicyNode>[] policyNodes, DerObjectIdentifier pOid, HashSet<PolicyQualifierInfo> pq) { string iD = pOid.GetID(); foreach (PkixPolicyNode item in policyNodes[index - 1]) { if (item.HasExpectedPolicy(iD)) { HashSet<string> hashSet = new HashSet<string>(); hashSet.Add(iD); PkixPolicyNode pkixPolicyNode = new PkixPolicyNode(null, index, hashSet, item, pq, iD, false); item.AddChild(pkixPolicyNode); policyNodes[index].Add(pkixPolicyNode); return true; } } return false; } internal static void ProcessCertD1ii(int index, IList<PkixPolicyNode>[] policyNodes, DerObjectIdentifier _poid, HashSet<PolicyQualifierInfo> _pq) { PkixPolicyNode pkixPolicyNode = FindValidPolicy(policyNodes[index - 1], ANY_POLICY); if (pkixPolicyNode != null) { string iD = _poid.GetID(); HashSet<string> hashSet = new HashSet<string>(); hashSet.Add(iD); PkixPolicyNode pkixPolicyNode2 = new PkixPolicyNode(null, index, hashSet, pkixPolicyNode, _pq, iD, false); pkixPolicyNode.AddChild(pkixPolicyNode2); policyNodes[index].Add(pkixPolicyNode2); } } internal static HashSet<X509Certificate> FindIssuerCerts(X509Certificate cert, PkixBuilderParameters pkixBuilderParameters) { X509CertStoreSelector x509CertStoreSelector = new X509CertStoreSelector(); try { x509CertStoreSelector.Subject = cert.IssuerDN; } catch (IOException innerException) { throw new Exception("Subject criteria for certificate selector to find issuer certificate could not be set.", innerException); } HashSet<X509Certificate> hashSet = new HashSet<X509Certificate>(); try { CollectionUtilities.CollectMatches(hashSet, x509CertStoreSelector, pkixBuilderParameters.GetStoresCert()); return hashSet; } catch (Exception innerException2) { throw new Exception("Issuer certificate cannot be searched.", innerException2); } } internal static void CheckCrlCriticalExtensions(X509Crl crl, string exceptionMessage) { TbsCertificateList tbsCertList = crl.CertificateList.TbsCertList; if (tbsCertList.Version >= 2) { X509Extensions extensions = tbsCertList.Extensions; if (extensions != null) { foreach (DerObjectIdentifier extensionOid in extensions.ExtensionOids) { if (!X509Extensions.IssuingDistributionPoint.Equals(extensionOid) && !X509Extensions.DeltaCrlIndicator.Equals(extensionOid) && extensions.GetExtension(extensionOid).IsCritical) throw new Exception(exceptionMessage); } } } } internal static void CheckCrlEntryCriticalExtensions(X509CrlEntry crlEntry, string exceptionMessage) { X509Extensions extensions = crlEntry.CrlEntry.Extensions; if (extensions != null && extensions.HasAnyCriticalExtensions()) throw new Exception(exceptionMessage); } internal static PkixPolicyNode FindValidPolicy(IEnumerable<PkixPolicyNode> policyNodes, string policy) { foreach (PkixPolicyNode policyNode in policyNodes) { if (policy.Equals(policyNode.ValidPolicy)) return policyNode; } return null; } internal static bool HasCriticalExtension(X509Certificate certificate, DerObjectIdentifier extensionOid) { TbsCertificateStructure tbsCertificate = certificate.CertificateStructure.TbsCertificate; if (tbsCertificate.Version >= 3) return HasCriticalExtension(tbsCertificate.Extensions, extensionOid); return false; } internal static bool HasCriticalExtension(X509Crl crl, DerObjectIdentifier extensionOid) { TbsCertificateList tbsCertList = crl.CertificateList.TbsCertList; if (tbsCertList.Version >= 2) return HasCriticalExtension(tbsCertList.Extensions, extensionOid); return false; } private static bool HasCriticalExtension(X509Extensions extensions, DerObjectIdentifier extensionOid) { if (extensions != null) { X509Extension extension = extensions.GetExtension(extensionOid); if (extension != null) return extension.IsCritical; } return false; } } }