PkixCertPathBuilder.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections.Generic;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
  8. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Pkix
  9. {
  10. /**
  11. * Implements the PKIX CertPathBuilding algorithm for BouncyCastle.
  12. *
  13. * @see CertPathBuilderSpi
  14. */
  15. public class PkixCertPathBuilder
  16. {
  17. /**
  18. * Build and validate a CertPath using the given parameter.
  19. *
  20. * @param params PKIXBuilderParameters object containing all information to
  21. * build the CertPath
  22. */
  23. public virtual PkixCertPathBuilderResult Build(PkixBuilderParameters pkixParams)
  24. {
  25. // search target certificates
  26. var certSelector = pkixParams.GetTargetConstraintsCert();
  27. var targets = new HashSet<X509Certificate>();
  28. try
  29. {
  30. CollectionUtilities.CollectMatches(targets, certSelector, pkixParams.GetStoresCert());
  31. }
  32. catch (Exception e)
  33. {
  34. throw new PkixCertPathBuilderException(
  35. "Error finding target certificate.", e);
  36. }
  37. if (targets.Count < 1)
  38. throw new PkixCertPathBuilderException("No certificate found matching targetConstraints.");
  39. PkixCertPathBuilderResult result = null;
  40. var certPathList = new List<X509Certificate>();
  41. // check all potential target certificates
  42. foreach (X509Certificate cert in targets)
  43. {
  44. result = Build(cert, pkixParams, certPathList);
  45. if (result != null)
  46. break;
  47. }
  48. if (result == null && certPathException != null)
  49. throw new PkixCertPathBuilderException(certPathException.Message, certPathException.InnerException);
  50. if (result == null && certPathException == null)
  51. throw new PkixCertPathBuilderException("Unable to find certificate chain.");
  52. return result;
  53. }
  54. private Exception certPathException;
  55. protected virtual PkixCertPathBuilderResult Build(
  56. X509Certificate tbvCert,
  57. PkixBuilderParameters pkixParams,
  58. IList<X509Certificate> tbvPath)
  59. {
  60. // If tbvCert is already present in tbvPath, it indicates having run into a cycle in the PKI graph.
  61. if (tbvPath.Contains(tbvCert))
  62. return null;
  63. // step out, the certificate is not allowed to appear in a certification chain.
  64. if (pkixParams.GetExcludedCerts().Contains(tbvCert))
  65. return null;
  66. // test if certificate path exceeds maximum length
  67. if (pkixParams.MaxPathLength != -1)
  68. {
  69. if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
  70. return null;
  71. }
  72. tbvPath.Add(tbvCert);
  73. PkixCertPathBuilderResult builderResult = null;
  74. PkixCertPathValidator validator = new PkixCertPathValidator();
  75. try
  76. {
  77. // check whether the issuer of <tbvCert> is a TrustAnchor
  78. if (PkixCertPathValidatorUtilities.IsIssuerTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()))
  79. {
  80. // exception message from possibly later tried certification chains
  81. PkixCertPath certPath;
  82. try
  83. {
  84. certPath = new PkixCertPath(tbvPath);
  85. }
  86. catch (Exception e)
  87. {
  88. throw new Exception("Certification path could not be constructed from certificate list.", e);
  89. }
  90. PkixCertPathValidatorResult result;
  91. try
  92. {
  93. result = validator.Validate(certPath, pkixParams);
  94. }
  95. catch (Exception e)
  96. {
  97. throw new Exception(
  98. "Certification path could not be validated.", e);
  99. }
  100. return new PkixCertPathBuilderResult(certPath, result.TrustAnchor, result.PolicyTree,
  101. result.SubjectPublicKey);
  102. }
  103. else
  104. {
  105. // add additional X.509 stores from locations in certificate
  106. try
  107. {
  108. PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(tbvCert, pkixParams);
  109. }
  110. catch (CertificateParsingException e)
  111. {
  112. throw new Exception("No additiontal X.509 stores can be added from certificate locations.", e);
  113. }
  114. // try to get the issuer certificate from one of the stores
  115. ISet<X509Certificate> issuers;
  116. try
  117. {
  118. issuers = PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams);
  119. }
  120. catch (Exception e)
  121. {
  122. throw new Exception("Cannot find issuer certificate for certificate in certification path.", e);
  123. }
  124. if (issuers.Count < 1)
  125. throw new Exception("No issuer certificate for certificate in certification path found.");
  126. foreach (X509Certificate issuer in issuers)
  127. {
  128. builderResult = Build(issuer, pkixParams, tbvPath);
  129. if (builderResult != null)
  130. break;
  131. }
  132. }
  133. }
  134. catch (Exception e)
  135. {
  136. certPathException = e;
  137. }
  138. if (builderResult == null)
  139. {
  140. tbvPath.Remove(tbvCert);
  141. }
  142. return builderResult;
  143. }
  144. }
  145. }
  146. #pragma warning restore
  147. #endif