public void AddRange(BCX509CertificateCollection value) { if (value == null) { throw new ArgumentNullException("value"); } for (int i = 0; i < value.InnerList.Count; i++) { InnerList.Add(value[i]); } }
private BCX509Certificate2 FindParent(BCX509Certificate2 certificate) { BCX509CertificateCollection subset = CertificateCollection.Find(BCX509FindType.FindBySubjectDistinguishedName, certificate.IssuerDN, false); string aki = GetAuthorityKeyIdentifier(certificate); if ((aki != null) && (aki.Length > 0)) { subset.AddRange(CertificateCollection.Find(BCX509FindType.FindBySubjectKeyIdentifier, aki, false)); } BCX509Certificate2 parent = SelectBestFromCollection(certificate, subset); // if parent==certificate we're looping but it's not (probably) a bug and not a true cyclic (over n certs) return(certificate.Equals(parent) ? null : parent); }
private BCX509Certificate2 SelectBestFromCollection(BCX509Certificate2 child, BCX509CertificateCollection c) { switch (c.Count) { case 0: return(null); case 1: return(c[0]); default: // multiple candidate, keep only the ones that are still valid BCX509CertificateCollection time_valid = c.Find(BCX509FindType.FindByTimeValid, ChainPolicy.VerificationTime, false); switch (time_valid.Count) { case 0: // that's too restrictive, let's revert and try another thing... time_valid = c; break; case 1: return(time_valid[0]); default: break; } // again multiple candidates, let's find the AKI that match the SKI (if we have one) string aki = GetAuthorityKeyIdentifier(child); if (String.IsNullOrEmpty(aki)) { return(time_valid[0]); // FIXME: out of luck, you get the first one } foreach (BCX509Certificate2 parent in time_valid) { string ski = GetSubjectKeyIdentifier(parent); // if both id are available then they must match if (aki == ski) { return(parent); } } return(time_valid[0]); // FIXME: out of luck, you get the first one } }
public BCX509CertificateCollection(BCX509CertificateCollection value) { AddRange(value); }
// Constructors public BCX509CertificateEnumerator(BCX509CertificateCollection mappings) { enumerator = ((IEnumerable)mappings).GetEnumerator(); }
public BCX509CertificateCollection Find(BCX509FindType findType, object findValue, bool validOnly) { if (findValue == null) { throw new ArgumentNullException("findValue"); } string str = String.Empty; DerObjectIdentifier oid = null; string oidStr = String.Empty; KeyUsage ku = new KeyUsage(0); DateTime dt = DateTime.MinValue; switch (findType) { case BCX509FindType.FindByThumbprint: case BCX509FindType.FindBySubjectName: case BCX509FindType.FindBySubjectDistinguishedName: case BCX509FindType.FindByIssuerName: case BCX509FindType.FindByIssuerDistinguishedName: case BCX509FindType.FindBySerialNumber: case BCX509FindType.FindByTemplateName: case BCX509FindType.FindBySubjectKeyIdentifier: try { str = (string)findValue; } catch (Exception e) { string msg = String.Format("Invalid find value type '{0}', expected '{1}'.", findValue.GetType(), "string"); throw new CryptographicException(msg, e); } break; case BCX509FindType.FindByApplicationPolicy: case BCX509FindType.FindByCertificatePolicy: case BCX509FindType.FindByExtension: try { oidStr = (string)findValue; } catch (Exception e) { string msg = String.Format("Invalid find value type '{0}', expected '{1}'.", findValue.GetType(), "X509KeyUsageFlags"); throw new CryptographicException(msg, e); } // OID validation try { oid = new DerObjectIdentifier(oidStr); } catch (FormatException) { string msg = String.Format("Invalid OID value '{0}'.", oidStr); throw new ArgumentException("findValue", msg); } break; case BCX509FindType.FindByKeyUsage: try { ku = new KeyUsage((int)findValue); } catch (Exception e) { string msg = String.Format("Invalid find value type '{0}', expected '{1}'.", findValue.GetType(), "X509KeyUsageFlags"); throw new CryptographicException(msg, e); } break; case BCX509FindType.FindByTimeValid: case BCX509FindType.FindByTimeNotYetValid: case BCX509FindType.FindByTimeExpired: try { dt = (DateTime)findValue; } catch (Exception e) { string msg = String.Format("Invalid find value type '{0}', expected '{1}'.", findValue.GetType(), "X509DateTime"); throw new CryptographicException(msg, e); } break; default: { string msg = String.Format("Invalid find type '{0}'.", findType); throw new CryptographicException(msg); } } CultureInfo cinv = CultureInfo.InvariantCulture; BCX509CertificateCollection results = new BCX509CertificateCollection(); foreach (BCX509Certificate2 x in InnerList) { bool value_match = false; switch (findType) { case BCX509FindType.FindByThumbprint: // works with Thumbprint, GetCertHashString in both normal (upper) and lower case value_match = ((String.Compare(str, Hex.ToHexString(x.GetSignature()), true, cinv) == 0) || (String.Compare(str, DotNetUtilities.ToX509Certificate(x).GetCertHashString(), true, cinv) == 0)); break; case BCX509FindType.FindBySubjectName: { string[] names = x.SubjectDN.ToString().Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string name in names) { int pos = name.IndexOf('='); value_match = (name.IndexOf(str, pos, StringComparison.InvariantCultureIgnoreCase) >= 0); if (value_match) { break; } } break; } case BCX509FindType.FindBySubjectDistinguishedName: value_match = (String.Compare(str, x.SubjectDN.ToString(), true, cinv) == 0); break; case BCX509FindType.FindByIssuerName: { //string iname = x.GetNameInfo (X509NameType.SimpleName, true); //value_match = (iname.IndexOf (str, StringComparison.InvariantCultureIgnoreCase) >= 0); string[] names = x.IssuerDN.ToString().Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string name in names) { int pos = name.IndexOf('='); value_match = (name.IndexOf(str, pos, StringComparison.InvariantCultureIgnoreCase) >= 0); if (value_match) { break; } } } break; case BCX509FindType.FindByIssuerDistinguishedName: value_match = (String.Compare(str, x.IssuerDN.ToString(), true, cinv) == 0); break; case BCX509FindType.FindBySerialNumber: value_match = (String.Compare(str, x.SerialNumber.ToString(), true, cinv) == 0); break; case BCX509FindType.FindByTemplateName: // TODO - find a valid test case break; case BCX509FindType.FindBySubjectKeyIdentifier: SubjectKeyIdentifier ski = SubjectKeyIdentifier.GetInstance(x.CertificateStructure.TbsCertificate.Extensions.GetExtension(X509Extensions.SubjectKeyIdentifier)); if (ski != null) { value_match = (String.Compare(str, Hex.ToHexString(ski.GetKeyIdentifier()), true, cinv) == 0); } break; case BCX509FindType.FindByApplicationPolicy: // note: include when no extensions are present (even if v3) value_match = (x.GetCriticalExtensionOids().Count == 0 && x.GetNonCriticalExtensionOids().Count == 0); // TODO - find test case with extension break; case BCX509FindType.FindByCertificatePolicy: // TODO - find test case with extension break; case BCX509FindType.FindByExtension: value_match = (x.GetExtensionValue(oid) != null); break; case BCX509FindType.FindByKeyUsage: KeyUsage kue = KeyUsage.GetInstance(x.CertificateStructure.TbsCertificate.Extensions.GetExtension(X509Extensions.KeyUsage)); if (kue == null) { // key doesn't have any hard coded limitations // note: MS doesn't check for ExtendedKeyUsage value_match = true; } else { value_match = ((kue.IntValue & ku.IntValue) == ku.IntValue); } break; case BCX509FindType.FindByTimeValid: value_match = ((dt >= x.NotBefore) && (dt <= x.NotAfter)); break; case BCX509FindType.FindByTimeNotYetValid: value_match = (dt < x.NotBefore); break; case BCX509FindType.FindByTimeExpired: value_match = (dt > x.NotAfter); break; } if (!value_match) { continue; } if (validOnly) { try { x.Verify(x.GetPublicKey()); results.Add(x); } catch { } } else { results.Add(x); } } return(results); }