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;
}
}
}