PkixCertPathValidatorUtilities.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.IsisMtt;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  11. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  12. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  13. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  14. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
  15. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
  16. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension;
  17. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Store;
  18. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Pkix
  19. {
  20. /// <summary>
  21. /// Summary description for PkixCertPathValidatorUtilities.
  22. /// </summary>
  23. internal static class PkixCertPathValidatorUtilities
  24. {
  25. private static readonly PkixCrlUtilities CrlUtilities = new PkixCrlUtilities();
  26. internal static readonly string ANY_POLICY = "2.5.29.32.0";
  27. internal static readonly string CRL_NUMBER = X509Extensions.CrlNumber.Id;
  28. /// <summary>
  29. /// key usage bits
  30. /// </summary>
  31. internal static readonly int KEY_CERT_SIGN = 5;
  32. internal static readonly int CRL_SIGN = 6;
  33. //internal static readonly string[] crlReasons = new string[]
  34. //{
  35. // "unspecified",
  36. // "keyCompromise",
  37. // "cACompromise",
  38. // "affiliationChanged",
  39. // "superseded",
  40. // "cessationOfOperation",
  41. // "certificateHold",
  42. // "unknown",
  43. // "removeFromCRL",
  44. // "privilegeWithdrawn",
  45. // "aACompromise"
  46. //};
  47. /// <summary>
  48. /// Search the given Set of TrustAnchor's for one that is the
  49. /// issuer of the given X509 certificate.
  50. /// </summary>
  51. /// <param name="cert">the X509 certificate</param>
  52. /// <param name="trustAnchors">a Set of TrustAnchor's</param>
  53. /// <returns>the <code>TrustAnchor</code> object if found or
  54. /// <code>null</code> if not.
  55. /// </returns>
  56. /// @exception
  57. internal static TrustAnchor FindTrustAnchor(X509Certificate cert, ISet<TrustAnchor> trustAnchors)
  58. {
  59. var iter = trustAnchors.GetEnumerator();
  60. TrustAnchor trust = null;
  61. AsymmetricKeyParameter trustPublicKey = null;
  62. Exception invalidKeyEx = null;
  63. X509CertStoreSelector certSelectX509 = new X509CertStoreSelector();
  64. try
  65. {
  66. certSelectX509.Subject = GetIssuerPrincipal(cert);
  67. }
  68. catch (IOException ex)
  69. {
  70. throw new Exception("Cannot set subject search criteria for trust anchor.", ex);
  71. }
  72. while (iter.MoveNext() && trust == null)
  73. {
  74. trust = iter.Current;
  75. if (trust.TrustedCert != null)
  76. {
  77. if (certSelectX509.Match(trust.TrustedCert))
  78. {
  79. trustPublicKey = trust.TrustedCert.GetPublicKey();
  80. }
  81. else
  82. {
  83. trust = null;
  84. }
  85. }
  86. else if (trust.CAName != null && trust.CAPublicKey != null)
  87. {
  88. try
  89. {
  90. X509Name certIssuer = GetIssuerPrincipal(cert);
  91. X509Name caName = new X509Name(trust.CAName);
  92. if (certIssuer.Equivalent(caName, true))
  93. {
  94. trustPublicKey = trust.CAPublicKey;
  95. }
  96. else
  97. {
  98. trust = null;
  99. }
  100. }
  101. catch (InvalidParameterException)
  102. {
  103. trust = null;
  104. }
  105. }
  106. else
  107. {
  108. trust = null;
  109. }
  110. if (trustPublicKey != null)
  111. {
  112. try
  113. {
  114. cert.Verify(trustPublicKey);
  115. }
  116. catch (Exception ex)
  117. {
  118. invalidKeyEx = ex;
  119. trust = null;
  120. }
  121. }
  122. }
  123. if (trust == null && invalidKeyEx != null)
  124. {
  125. throw new Exception("TrustAnchor found but certificate validation failed.", invalidKeyEx);
  126. }
  127. return trust;
  128. }
  129. internal static bool IsIssuerTrustAnchor(X509Certificate cert, ISet<TrustAnchor> trustAnchors)
  130. {
  131. try
  132. {
  133. return FindTrustAnchor(cert, trustAnchors) != null;
  134. }
  135. catch (Exception)
  136. {
  137. return false;
  138. }
  139. }
  140. internal static void AddAdditionalStoresFromAltNames(X509Certificate cert, PkixParameters pkixParams)
  141. {
  142. // if in the IssuerAltName extension an URI
  143. // is given, add an additinal X.509 store
  144. var issuerAltNames = cert.GetIssuerAlternativeNames();
  145. if (issuerAltNames != null)
  146. {
  147. foreach (var list in issuerAltNames)
  148. {
  149. // look for URI
  150. if (list.Count >= 2 && list[0].Equals(GeneralName.UniformResourceIdentifier))
  151. {
  152. string location = (string)list[1];
  153. AddAdditionalStoreFromLocation(location, pkixParams);
  154. }
  155. }
  156. }
  157. }
  158. internal static DateTime GetValidDate(PkixParameters paramsPKIX)
  159. {
  160. DateTime? validDate = paramsPKIX.Date;
  161. if (validDate == null)
  162. return DateTime.UtcNow;
  163. return validDate.Value;
  164. }
  165. /// <summary>
  166. /// Returns the issuer of an attribute certificate or certificate.
  167. /// </summary>
  168. /// <param name="obj">The attribute certificate or certificate.</param>
  169. /// <returns>The issuer as <code>X500Principal</code>.</returns>
  170. internal static X509Name GetIssuerPrincipal(object obj)
  171. {
  172. if (obj is X509Certificate cert)
  173. return cert.IssuerDN;
  174. if (obj is X509V2AttributeCertificate attrCert)
  175. return attrCert.Issuer.GetPrincipals()[0];
  176. throw new InvalidOperationException();
  177. }
  178. internal static X509Name GetIssuerPrincipal(X509V2AttributeCertificate attrCert)
  179. {
  180. return attrCert.Issuer.GetPrincipals()[0];
  181. }
  182. internal static X509Name GetIssuerPrincipal(X509Certificate cert)
  183. {
  184. return cert.IssuerDN;
  185. }
  186. internal static bool IsSelfIssued(
  187. X509Certificate cert)
  188. {
  189. return cert.SubjectDN.Equivalent(cert.IssuerDN, true);
  190. }
  191. internal static AlgorithmIdentifier GetAlgorithmIdentifier(
  192. AsymmetricKeyParameter key)
  193. {
  194. try
  195. {
  196. SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);
  197. return info.AlgorithmID;
  198. }
  199. catch (Exception e)
  200. {
  201. throw new PkixCertPathValidatorException("Subject public key cannot be decoded.", e);
  202. }
  203. }
  204. internal static bool IsAnyPolicy(ISet<string> policySet)
  205. {
  206. return policySet == null || policySet.Count < 1 || policySet.Contains(ANY_POLICY);
  207. }
  208. internal static void AddAdditionalStoreFromLocation(
  209. string location,
  210. PkixParameters pkixParams)
  211. {
  212. if (pkixParams.IsAdditionalLocationsEnabled)
  213. {
  214. try
  215. {
  216. if (Org.BouncyCastle.Utilities.Platform.StartsWith(location, "ldap://"))
  217. {
  218. // ldap://directory.d-trust.net/CN=D-TRUST
  219. // Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE
  220. // skip "ldap://"
  221. location = location.Substring(7);
  222. // after first / baseDN starts
  223. string url;//, baseDN;
  224. int slashPos = location.IndexOf('/');
  225. if (slashPos != -1)
  226. {
  227. url = "ldap://" + location.Substring(0, slashPos);
  228. // baseDN = location.Substring(slashPos);
  229. }
  230. else
  231. {
  232. url = "ldap://" + location;
  233. // baseDN = nsull;
  234. }
  235. throw new NotImplementedException("LDAP cert/CRL stores");
  236. // use all purpose parameters
  237. //X509LDAPCertStoreParameters ldapParams = new X509LDAPCertStoreParameters.Builder(
  238. // url, baseDN).build();
  239. //pkixParams.AddAdditionalStore(X509Store.getInstance(
  240. // "CERTIFICATE/LDAP", ldapParams));
  241. //pkixParams.AddAdditionalStore(X509Store.getInstance(
  242. // "CRL/LDAP", ldapParams));
  243. //pkixParams.AddAdditionalStore(X509Store.getInstance(
  244. // "ATTRIBUTECERTIFICATE/LDAP", ldapParams));
  245. //pkixParams.AddAdditionalStore(X509Store.getInstance(
  246. // "CERTIFICATEPAIR/LDAP", ldapParams));
  247. }
  248. }
  249. catch (Exception)
  250. {
  251. // cannot happen
  252. throw new Exception("Exception adding X.509 stores.");
  253. }
  254. }
  255. }
  256. private static BigInteger GetSerialNumber(
  257. object cert)
  258. {
  259. if (cert is X509Certificate)
  260. {
  261. return ((X509Certificate)cert).SerialNumber;
  262. }
  263. else
  264. {
  265. return ((X509V2AttributeCertificate)cert).SerialNumber;
  266. }
  267. }
  268. //
  269. // policy checking
  270. //
  271. internal static ISet<PolicyQualifierInfo> GetQualifierSet(Asn1Sequence qualifiers)
  272. {
  273. var pq = new HashSet<PolicyQualifierInfo>();
  274. if (qualifiers != null)
  275. {
  276. foreach (Asn1Encodable ae in qualifiers)
  277. {
  278. try
  279. {
  280. pq.Add(PolicyQualifierInfo.GetInstance(ae.ToAsn1Object()));
  281. }
  282. catch (IOException ex)
  283. {
  284. throw new PkixCertPathValidatorException("Policy qualifier info cannot be decoded.", ex);
  285. }
  286. }
  287. }
  288. return pq;
  289. }
  290. internal static PkixPolicyNode RemovePolicyNode(PkixPolicyNode validPolicyTree,
  291. IList<PkixPolicyNode>[] policyNodes, PkixPolicyNode _node)
  292. {
  293. PkixPolicyNode _parent = _node.Parent;
  294. if (validPolicyTree == null)
  295. {
  296. return null;
  297. }
  298. if (_parent == null)
  299. {
  300. for (int j = 0; j < policyNodes.Length; j++)
  301. {
  302. policyNodes[j] = new List<PkixPolicyNode>();
  303. }
  304. return null;
  305. }
  306. else
  307. {
  308. _parent.RemoveChild(_node);
  309. RemovePolicyNodeRecurse(policyNodes, _node);
  310. return validPolicyTree;
  311. }
  312. }
  313. private static void RemovePolicyNodeRecurse(IList<PkixPolicyNode>[] policyNodes, PkixPolicyNode _node)
  314. {
  315. policyNodes[_node.Depth].Remove(_node);
  316. if (_node.HasChildren)
  317. {
  318. foreach (PkixPolicyNode _child in _node.Children)
  319. {
  320. RemovePolicyNodeRecurse(policyNodes, _child);
  321. }
  322. }
  323. }
  324. internal static void PrepareNextCertB1(int i, IList<PkixPolicyNode>[] policyNodes, string id_p,
  325. IDictionary<string, ISet<string>> m_idp, X509Certificate cert)
  326. {
  327. foreach (var node in policyNodes[i])
  328. {
  329. if (node.ValidPolicy.Equals(id_p))
  330. {
  331. node.ExpectedPolicies = CollectionUtilities.GetValueOrNull(m_idp, id_p);
  332. return;
  333. }
  334. }
  335. foreach (var node in policyNodes[i])
  336. {
  337. if (ANY_POLICY.Equals(node.ValidPolicy))
  338. {
  339. Asn1Sequence policies;
  340. try
  341. {
  342. policies = Asn1Sequence.GetInstance(
  343. GetExtensionValue(cert, X509Extensions.CertificatePolicies));
  344. }
  345. catch (Exception e)
  346. {
  347. throw new Exception("Certificate policies cannot be decoded.", e);
  348. }
  349. ISet<PolicyQualifierInfo> pq = null;
  350. foreach (var policy in policies)
  351. {
  352. PolicyInformation pinfo;
  353. try
  354. {
  355. pinfo = PolicyInformation.GetInstance(policy);
  356. }
  357. catch (Exception ex)
  358. {
  359. throw new Exception("Policy information cannot be decoded.", ex);
  360. }
  361. if (ANY_POLICY.Equals(pinfo.PolicyIdentifier.Id))
  362. {
  363. try
  364. {
  365. pq = GetQualifierSet(pinfo.PolicyQualifiers);
  366. }
  367. catch (PkixCertPathValidatorException ex)
  368. {
  369. throw new PkixCertPathValidatorException(
  370. "Policy qualifier info set could not be built.", ex);
  371. }
  372. break;
  373. }
  374. }
  375. bool ci = false;
  376. var critExtOids = cert.GetCriticalExtensionOids();
  377. if (critExtOids != null)
  378. {
  379. ci = critExtOids.Contains(X509Extensions.CertificatePolicies.Id);
  380. }
  381. PkixPolicyNode p_node = node.Parent;
  382. if (ANY_POLICY.Equals(p_node.ValidPolicy))
  383. {
  384. PkixPolicyNode c_node = new PkixPolicyNode(new List<PkixPolicyNode>(), i,
  385. CollectionUtilities.GetValueOrNull(m_idp, id_p), p_node, pq, id_p, ci);
  386. p_node.AddChild(c_node);
  387. policyNodes[i].Add(c_node);
  388. }
  389. break;
  390. }
  391. }
  392. }
  393. internal static PkixPolicyNode PrepareNextCertB2(int i, IList<PkixPolicyNode>[] policyNodes, string id_p,
  394. PkixPolicyNode validPolicyTree)
  395. {
  396. int pos = 0;
  397. // Copy to avoid RemoveAt calls interfering with enumeration
  398. foreach (var node in new List<PkixPolicyNode>(policyNodes[i]))
  399. {
  400. if (!node.ValidPolicy.Equals(id_p))
  401. {
  402. ++pos;
  403. continue;
  404. }
  405. node.Parent.RemoveChild(node);
  406. policyNodes[i].RemoveAt(pos);
  407. for (int k = i - 1; k >= 0; k--)
  408. {
  409. var nodes = policyNodes[k];
  410. for (int l = 0; l < nodes.Count; l++)
  411. {
  412. var node2 = nodes[l];
  413. if (!node2.HasChildren)
  414. {
  415. validPolicyTree = RemovePolicyNode(validPolicyTree, policyNodes, node2);
  416. if (validPolicyTree == null)
  417. break;
  418. }
  419. }
  420. }
  421. }
  422. return validPolicyTree;
  423. }
  424. internal static void GetCertStatus(
  425. DateTime validDate,
  426. X509Crl crl,
  427. object cert,
  428. CertStatus certStatus)
  429. {
  430. X509Crl bcCRL;
  431. try
  432. {
  433. bcCRL = new X509Crl(CertificateList.GetInstance((Asn1Sequence)Asn1Sequence.FromByteArray(crl.GetEncoded())));
  434. }
  435. catch (Exception exception)
  436. {
  437. throw new Exception("X509Crl could not be created.", exception);
  438. }
  439. X509CrlEntry crl_entry = (X509CrlEntry)bcCRL.GetRevokedCertificate(GetSerialNumber(cert));
  440. if (crl_entry == null)
  441. return;
  442. X509Name issuer = GetIssuerPrincipal(cert);
  443. if (!issuer.Equivalent(crl_entry.GetCertificateIssuer(), true)
  444. && !issuer.Equivalent(crl.IssuerDN, true))
  445. {
  446. return;
  447. }
  448. int reasonCodeValue = CrlReason.Unspecified;
  449. if (crl_entry.HasExtensions)
  450. {
  451. try
  452. {
  453. Asn1Object extValue = GetExtensionValue(crl_entry, X509Extensions.ReasonCode);
  454. DerEnumerated reasonCode = DerEnumerated.GetInstance(extValue);
  455. if (null != reasonCode)
  456. {
  457. reasonCodeValue = reasonCode.IntValueExact;
  458. }
  459. }
  460. catch (Exception e)
  461. {
  462. throw new Exception("Reason code CRL entry extension could not be decoded.", e);
  463. }
  464. }
  465. DateTime revocationDate = crl_entry.RevocationDate;
  466. if (validDate.Ticks < revocationDate.Ticks)
  467. {
  468. switch (reasonCodeValue)
  469. {
  470. case CrlReason.Unspecified:
  471. case CrlReason.KeyCompromise:
  472. case CrlReason.CACompromise:
  473. case CrlReason.AACompromise:
  474. break;
  475. default:
  476. return;
  477. }
  478. }
  479. // (i) or (j)
  480. certStatus.Status = reasonCodeValue;
  481. certStatus.RevocationDate = revocationDate;
  482. }
  483. /**
  484. * Return the next working key inheriting DSA parameters if necessary.
  485. * <p>
  486. * This methods inherits DSA parameters from the indexed certificate or
  487. * previous certificates in the certificate chain to the returned
  488. * <code>PublicKey</code>. The list is searched upwards, meaning the end
  489. * certificate is at position 0 and previous certificates are following.
  490. * </p>
  491. * <p>
  492. * If the indexed certificate does not contain a DSA key this method simply
  493. * returns the public key. If the DSA key already contains DSA parameters
  494. * the key is also only returned.
  495. * </p>
  496. *
  497. * @param certs The certification path.
  498. * @param index The index of the certificate which contains the public key
  499. * which should be extended with DSA parameters.
  500. * @return The public key of the certificate in list position
  501. * <code>index</code> extended with DSA parameters if applicable.
  502. * @throws Exception if DSA parameters cannot be inherited.
  503. */
  504. internal static AsymmetricKeyParameter GetNextWorkingKey(IList<X509Certificate> certs, int index)
  505. {
  506. X509Certificate cert = certs[index];
  507. AsymmetricKeyParameter pubKey = cert.GetPublicKey();
  508. if (!(pubKey is DsaPublicKeyParameters))
  509. return pubKey;
  510. DsaPublicKeyParameters dsaPubKey = (DsaPublicKeyParameters)pubKey;
  511. if (dsaPubKey.Parameters != null)
  512. return dsaPubKey;
  513. for (int i = index + 1; i < certs.Count; i++)
  514. {
  515. X509Certificate parentCert = certs[i];
  516. pubKey = parentCert.GetPublicKey();
  517. if (!(pubKey is DsaPublicKeyParameters))
  518. {
  519. throw new PkixCertPathValidatorException(
  520. "DSA parameters cannot be inherited from previous certificate.");
  521. }
  522. DsaPublicKeyParameters prevDSAPubKey = (DsaPublicKeyParameters)pubKey;
  523. if (prevDSAPubKey.Parameters == null)
  524. continue;
  525. DsaParameters dsaParams = prevDSAPubKey.Parameters;
  526. try
  527. {
  528. return new DsaPublicKeyParameters(dsaPubKey.Y, dsaParams);
  529. }
  530. catch (Exception exception)
  531. {
  532. throw new Exception(exception.Message);
  533. }
  534. }
  535. throw new PkixCertPathValidatorException("DSA parameters cannot be inherited from previous certificate.");
  536. }
  537. internal static DateTime GetValidCertDateFromValidityModel(
  538. PkixParameters paramsPkix,
  539. PkixCertPath certPath,
  540. int index)
  541. {
  542. if (paramsPkix.ValidityModel != PkixParameters.ChainValidityModel)
  543. {
  544. return GetValidDate(paramsPkix);
  545. }
  546. // if end cert use given signing/encryption/... time
  547. if (index <= 0)
  548. {
  549. return GetValidDate(paramsPkix);
  550. // else use time when previous cert was created
  551. }
  552. var cert = certPath.Certificates[index - 1];
  553. if (index - 1 == 0)
  554. {
  555. Asn1GeneralizedTime dateOfCertgen;
  556. try
  557. {
  558. Asn1OctetString extVal = cert.GetExtensionValue(IsisMttObjectIdentifiers.IdIsisMttATDateOfCertGen);
  559. dateOfCertgen = Asn1GeneralizedTime.GetInstance(extVal);
  560. }
  561. catch (ArgumentException)
  562. {
  563. throw new Exception(
  564. "Date of cert gen extension could not be read.");
  565. }
  566. if (dateOfCertgen != null)
  567. {
  568. try
  569. {
  570. return dateOfCertgen.ToDateTime();
  571. }
  572. catch (ArgumentException e)
  573. {
  574. throw new Exception(
  575. "Date from date of cert gen extension could not be parsed.",
  576. e);
  577. }
  578. }
  579. }
  580. return cert.NotBefore;
  581. }
  582. /**
  583. * Add the CRL issuers from the cRLIssuer field of the distribution point or
  584. * from the certificate if not given to the issuer criterion of the
  585. * <code>selector</code>.
  586. * <p>
  587. * The <code>issuerPrincipals</code> are a collection with a single
  588. * <code>X500Principal</code> for <code>X509Certificate</code>s. For
  589. * {@link X509AttributeCertificate}s the issuer may contain more than one
  590. * <code>X500Principal</code>.
  591. * </p>
  592. *
  593. * @param dp The distribution point.
  594. * @param issuerPrincipals The issuers of the certificate or attribute
  595. * certificate which contains the distribution point.
  596. * @param selector The CRL selector.
  597. * @param pkixParams The PKIX parameters containing the cert stores.
  598. * @throws Exception if an exception occurs while processing.
  599. * @throws ClassCastException if <code>issuerPrincipals</code> does not
  600. * contain only <code>X500Principal</code>s.
  601. */
  602. internal static void GetCrlIssuersFromDistributionPoint(
  603. DistributionPoint dp,
  604. ICollection<X509Name> issuerPrincipals,
  605. X509CrlStoreSelector selector,
  606. PkixParameters pkixParams)
  607. {
  608. var issuers = new List<X509Name>();
  609. // indirect CRL
  610. if (dp.CrlIssuer != null)
  611. {
  612. GeneralName[] genNames = dp.CrlIssuer.GetNames();
  613. // look for a DN
  614. for (int j = 0; j < genNames.Length; j++)
  615. {
  616. if (genNames[j].TagNo == GeneralName.DirectoryName)
  617. {
  618. try
  619. {
  620. issuers.Add(X509Name.GetInstance(genNames[j].Name.ToAsn1Object()));
  621. }
  622. catch (IOException e)
  623. {
  624. throw new Exception("CRL issuer information from distribution point cannot be decoded.", e);
  625. }
  626. }
  627. }
  628. }
  629. else
  630. {
  631. /*
  632. * certificate issuer is CRL issuer, distributionPoint field MUST be
  633. * present.
  634. */
  635. if (dp.DistributionPointName == null)
  636. {
  637. throw new Exception(
  638. "CRL issuer is omitted from distribution point but no distributionPoint field present.");
  639. }
  640. // add and check issuer principals
  641. issuers.AddRange(issuerPrincipals);
  642. }
  643. // TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid
  644. // distributionPoint
  645. // if (dp.getDistributionPoint() != null)
  646. // {
  647. // // look for nameRelativeToCRLIssuer
  648. // if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER)
  649. // {
  650. // // append fragment to issuer, only one
  651. // // issuer can be there, if this is given
  652. // if (issuers.size() != 1)
  653. // {
  654. // throw new AnnotatedException(
  655. // "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given.");
  656. // }
  657. // DEREncodable relName = dp.getDistributionPoint().getName();
  658. // Iterator it = issuers.iterator();
  659. // List issuersTemp = new ArrayList(issuers.size());
  660. // while (it.hasNext())
  661. // {
  662. // Enumeration e = null;
  663. // try
  664. // {
  665. // e = ASN1Sequence.getInstance(
  666. // new ASN1InputStream(((X500Principal) it.next())
  667. // .getEncoded()).readObject()).getObjects();
  668. // }
  669. // catch (IOException ex)
  670. // {
  671. // throw new AnnotatedException(
  672. // "Cannot decode CRL issuer information.", ex);
  673. // }
  674. // ASN1EncodableVector v = new ASN1EncodableVector();
  675. // while (e.hasMoreElements())
  676. // {
  677. // v.add((DEREncodable) e.nextElement());
  678. // }
  679. // v.add(relName);
  680. // issuersTemp.add(new X500Principal(new DERSequence(v)
  681. // .getDEREncoded()));
  682. // }
  683. // issuers.clear();
  684. // issuers.addAll(issuersTemp);
  685. // }
  686. // }
  687. selector.Issuers = issuers;
  688. }
  689. /**
  690. * Fetches complete CRLs according to RFC 3280.
  691. *
  692. * @param dp The distribution point for which the complete CRL
  693. * @param cert The <code>X509Certificate</code> or
  694. * {@link org.bouncycastle.x509.X509AttributeCertificate} for
  695. * which the CRL should be searched.
  696. * @param currentDate The date for which the delta CRLs must be valid.
  697. * @param paramsPKIX The extended PKIX parameters.
  698. * @return A <code>Set</code> of <code>X509CRL</code>s with complete
  699. * CRLs.
  700. * @throws Exception if an exception occurs while picking the CRLs
  701. * or no CRLs are found.
  702. */
  703. internal static ISet<X509Crl> GetCompleteCrls(DistributionPoint dp, object certObj, DateTime currentDate,
  704. PkixParameters paramsPKIX)
  705. {
  706. var certObjIssuer = GetIssuerPrincipal(certObj);
  707. X509CrlStoreSelector crlselect = new X509CrlStoreSelector();
  708. try
  709. {
  710. var issuers = new HashSet<X509Name>();
  711. issuers.Add(certObjIssuer);
  712. GetCrlIssuersFromDistributionPoint(dp, issuers, crlselect, paramsPKIX);
  713. }
  714. catch (Exception e)
  715. {
  716. throw new Exception("Could not get issuer information from distribution point.", e);
  717. }
  718. {
  719. if (certObj is X509Certificate cert)
  720. {
  721. crlselect.CertificateChecking = cert;
  722. }
  723. else if (certObj is X509V2AttributeCertificate attrCert)
  724. {
  725. crlselect.AttrCertChecking = attrCert;
  726. }
  727. }
  728. crlselect.CompleteCrlEnabled = true;
  729. ISet<X509Crl> crls = CrlUtilities.FindCrls(crlselect, paramsPKIX, currentDate);
  730. if (crls.Count < 1)
  731. throw new Exception("No CRLs found for issuer \"" + certObjIssuer + "\"");
  732. return crls;
  733. }
  734. /**
  735. * Fetches delta CRLs according to RFC 3280 section 5.2.4.
  736. *
  737. * @param currentDate The date for which the delta CRLs must be valid.
  738. * @param paramsPKIX The extended PKIX parameters.
  739. * @param completeCRL The complete CRL the delta CRL is for.
  740. * @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs.
  741. * @throws Exception if an exception occurs while picking the delta
  742. * CRLs.
  743. */
  744. internal static ISet<X509Crl> GetDeltaCrls(
  745. DateTime currentDate,
  746. PkixParameters paramsPKIX,
  747. X509Crl completeCRL)
  748. {
  749. X509CrlStoreSelector deltaSelect = new X509CrlStoreSelector();
  750. // 5.2.4 (a)
  751. try
  752. {
  753. var deltaSelectIssuer = new List<X509Name>();
  754. deltaSelectIssuer.Add(completeCRL.IssuerDN);
  755. deltaSelect.Issuers = deltaSelectIssuer;
  756. }
  757. catch (IOException e)
  758. {
  759. throw new Exception("Cannot extract issuer from CRL.", e);
  760. }
  761. BigInteger completeCRLNumber = null;
  762. try
  763. {
  764. Asn1Object asn1Object = GetExtensionValue(completeCRL, X509Extensions.CrlNumber);
  765. if (asn1Object != null)
  766. {
  767. completeCRLNumber = CrlNumber.GetInstance(asn1Object).PositiveValue;
  768. }
  769. }
  770. catch (Exception e)
  771. {
  772. throw new Exception(
  773. "CRL number extension could not be extracted from CRL.", e);
  774. }
  775. // 5.2.4 (b)
  776. byte[] idp = null;
  777. try
  778. {
  779. Asn1Object obj = GetExtensionValue(completeCRL, X509Extensions.IssuingDistributionPoint);
  780. if (obj != null)
  781. {
  782. idp = obj.GetDerEncoded();
  783. }
  784. }
  785. catch (Exception e)
  786. {
  787. throw new Exception(
  788. "Issuing distribution point extension value could not be read.",
  789. e);
  790. }
  791. // 5.2.4 (d)
  792. deltaSelect.MinCrlNumber = (completeCRLNumber == null)
  793. ? null
  794. : completeCRLNumber.Add(BigInteger.One);
  795. deltaSelect.IssuingDistributionPoint = idp;
  796. deltaSelect.IssuingDistributionPointEnabled = true;
  797. // 5.2.4 (c)
  798. deltaSelect.MaxBaseCrlNumber = completeCRLNumber;
  799. // find delta CRLs
  800. ISet<X509Crl> temp = CrlUtilities.FindCrls(deltaSelect, paramsPKIX, currentDate);
  801. var result = new HashSet<X509Crl>();
  802. foreach (X509Crl crl in temp)
  803. {
  804. if (IsDeltaCrl(crl))
  805. {
  806. result.Add(crl);
  807. }
  808. }
  809. return result;
  810. }
  811. private static bool IsDeltaCrl(X509Crl crl)
  812. {
  813. var critical = crl.GetCriticalExtensionOids();
  814. return critical.Contains(X509Extensions.DeltaCrlIndicator.Id);
  815. }
  816. internal static void AddAdditionalStoresFromCrlDistributionPoint(
  817. CrlDistPoint crldp,
  818. PkixParameters pkixParams)
  819. {
  820. if (crldp != null)
  821. {
  822. DistributionPoint[] dps = null;
  823. try
  824. {
  825. dps = crldp.GetDistributionPoints();
  826. }
  827. catch (Exception e)
  828. {
  829. throw new Exception(
  830. "Distribution points could not be read.", e);
  831. }
  832. for (int i = 0; i < dps.Length; i++)
  833. {
  834. DistributionPointName dpn = dps[i].DistributionPointName;
  835. // look for URIs in fullName
  836. if (dpn != null)
  837. {
  838. if (dpn.PointType == DistributionPointName.FullName)
  839. {
  840. GeneralName[] genNames = GeneralNames.GetInstance(
  841. dpn.Name).GetNames();
  842. // look for an URI
  843. for (int j = 0; j < genNames.Length; j++)
  844. {
  845. if (genNames[j].TagNo == GeneralName.UniformResourceIdentifier)
  846. {
  847. string location = DerIA5String.GetInstance(genNames[j].Name).GetString();
  848. AddAdditionalStoreFromLocation(location, pkixParams);
  849. }
  850. }
  851. }
  852. }
  853. }
  854. }
  855. }
  856. internal static bool ProcessCertD1i(int index, IList<PkixPolicyNode>[] policyNodes, DerObjectIdentifier pOid,
  857. ISet<PolicyQualifierInfo> pq)
  858. {
  859. foreach (var node in policyNodes[index - 1])
  860. {
  861. if (node.ExpectedPolicies.Contains(pOid.Id))
  862. {
  863. var childExpectedPolicies = new HashSet<string>();
  864. childExpectedPolicies.Add(pOid.Id);
  865. var child = new PkixPolicyNode(new List<PkixPolicyNode>(), index, childExpectedPolicies, node, pq,
  866. pOid.Id, false);
  867. node.AddChild(child);
  868. policyNodes[index].Add(child);
  869. return true;
  870. }
  871. }
  872. return false;
  873. }
  874. internal static void ProcessCertD1ii(int index, IList<PkixPolicyNode>[] policyNodes,
  875. DerObjectIdentifier _poid, ISet<PolicyQualifierInfo> _pq)
  876. {
  877. foreach (var _node in policyNodes[index - 1])
  878. {
  879. if (ANY_POLICY.Equals(_node.ValidPolicy))
  880. {
  881. var _childExpectedPolicies = new HashSet<string>();
  882. _childExpectedPolicies.Add(_poid.Id);
  883. var _child = new PkixPolicyNode(new List<PkixPolicyNode>(), index, _childExpectedPolicies, _node,
  884. _pq, _poid.Id, false);
  885. _node.AddChild(_child);
  886. policyNodes[index].Add(_child);
  887. return;
  888. }
  889. }
  890. }
  891. /**
  892. * Find the issuer certificates of a given certificate.
  893. *
  894. * @param cert
  895. * The certificate for which an issuer should be found.
  896. * @param pkixParams
  897. * @return A <code>Collection</code> object containing the issuer
  898. * <code>X509Certificate</code>s. Never <code>null</code>.
  899. *
  900. * @exception Exception
  901. * if an error occurs.
  902. */
  903. internal static HashSet<X509Certificate> FindIssuerCerts(
  904. X509Certificate cert,
  905. PkixBuilderParameters pkixParams)
  906. {
  907. X509CertStoreSelector certSelector = new X509CertStoreSelector();
  908. try
  909. {
  910. certSelector.Subject = cert.IssuerDN;
  911. }
  912. catch (IOException ex)
  913. {
  914. throw new Exception(
  915. "Subject criteria for certificate selector to find issuer certificate could not be set.", ex);
  916. }
  917. var certs = new HashSet<X509Certificate>();
  918. try
  919. {
  920. CollectionUtilities.CollectMatches(certs, certSelector, pkixParams.GetStoresCert());
  921. }
  922. catch (Exception e)
  923. {
  924. throw new Exception("Issuer certificate cannot be searched.", e);
  925. }
  926. return certs;
  927. }
  928. internal static Asn1Object GetExtensionValue(IX509Extension extensions, DerObjectIdentifier oid)
  929. {
  930. return X509ExtensionUtilities.FromExtensionValue(extensions, oid);
  931. }
  932. }
  933. }
  934. #pragma warning restore
  935. #endif