PkixCertPathBuilder.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.Text;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.IsisMtt;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X500;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  11. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  12. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  13. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
  14. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  15. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
  16. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
  17. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Store;
  18. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Pkix
  19. {
  20. /**
  21. * Implements the PKIX CertPathBuilding algorithm for BouncyCastle.
  22. *
  23. * @see CertPathBuilderSpi
  24. */
  25. public class PkixCertPathBuilder
  26. // : CertPathBuilderSpi
  27. {
  28. /**
  29. * Build and validate a CertPath using the given parameter.
  30. *
  31. * @param params PKIXBuilderParameters object containing all information to
  32. * build the CertPath
  33. */
  34. public virtual PkixCertPathBuilderResult Build(
  35. PkixBuilderParameters pkixParams)
  36. {
  37. // search target certificates
  38. IX509Selector certSelect = pkixParams.GetTargetCertConstraints();
  39. if (!(certSelect is X509CertStoreSelector))
  40. {
  41. throw new PkixCertPathBuilderException(
  42. "TargetConstraints must be an instance of "
  43. + typeof(X509CertStoreSelector).FullName + " for "
  44. + BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.GetTypeName(this) + " class.");
  45. }
  46. ISet targets = new HashSet();
  47. try
  48. {
  49. targets.AddAll(PkixCertPathValidatorUtilities.FindCertificates((X509CertStoreSelector)certSelect, pkixParams.GetStores()));
  50. // TODO Should this include an entry for pkixParams.GetAdditionalStores() too?
  51. }
  52. catch (Exception e)
  53. {
  54. throw new PkixCertPathBuilderException(
  55. "Error finding target certificate.", e);
  56. }
  57. if (targets.IsEmpty)
  58. throw new PkixCertPathBuilderException("No certificate found matching targetConstraints.");
  59. PkixCertPathBuilderResult result = null;
  60. IList certPathList = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
  61. // check all potential target certificates
  62. foreach (X509Certificate cert in targets)
  63. {
  64. result = Build(cert, pkixParams, certPathList);
  65. if (result != null)
  66. break;
  67. }
  68. if (result == null && certPathException != null)
  69. {
  70. throw new PkixCertPathBuilderException(certPathException.Message, certPathException.InnerException);
  71. }
  72. if (result == null && certPathException == null)
  73. {
  74. throw new PkixCertPathBuilderException("Unable to find certificate chain.");
  75. }
  76. return result;
  77. }
  78. private Exception certPathException;
  79. protected virtual PkixCertPathBuilderResult Build(
  80. X509Certificate tbvCert,
  81. PkixBuilderParameters pkixParams,
  82. IList tbvPath)
  83. {
  84. // If tbvCert is readily present in tbvPath, it indicates having run
  85. // into a cycle in the PKI graph.
  86. if (tbvPath.Contains(tbvCert))
  87. return null;
  88. // step out, the certificate is not allowed to appear in a certification
  89. // chain.
  90. if (pkixParams.GetExcludedCerts().Contains(tbvCert))
  91. return null;
  92. // test if certificate path exceeds maximum length
  93. if (pkixParams.MaxPathLength != -1)
  94. {
  95. if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
  96. return null;
  97. }
  98. tbvPath.Add(tbvCert);
  99. // X509CertificateParser certParser = new X509CertificateParser();
  100. PkixCertPathBuilderResult builderResult = null;
  101. PkixCertPathValidator validator = new PkixCertPathValidator();
  102. try
  103. {
  104. // check whether the issuer of <tbvCert> is a TrustAnchor
  105. if (PkixCertPathValidatorUtilities.IsIssuerTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()))
  106. {
  107. // exception message from possibly later tried certification
  108. // chains
  109. PkixCertPath certPath = null;
  110. try
  111. {
  112. certPath = new PkixCertPath(tbvPath);
  113. }
  114. catch (Exception e)
  115. {
  116. throw new Exception(
  117. "Certification path could not be constructed from certificate list.",
  118. e);
  119. }
  120. PkixCertPathValidatorResult result = null;
  121. try
  122. {
  123. result = (PkixCertPathValidatorResult)validator.Validate(
  124. certPath, pkixParams);
  125. }
  126. catch (Exception e)
  127. {
  128. throw new Exception(
  129. "Certification path could not be validated.", e);
  130. }
  131. return new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
  132. result.PolicyTree, result.SubjectPublicKey);
  133. }
  134. else
  135. {
  136. // add additional X.509 stores from locations in certificate
  137. try
  138. {
  139. PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(
  140. tbvCert, pkixParams);
  141. }
  142. catch (CertificateParsingException e)
  143. {
  144. throw new Exception(
  145. "No additiontal X.509 stores can be added from certificate locations.",
  146. e);
  147. }
  148. // try to get the issuer certificate from one of the stores
  149. HashSet issuers = new HashSet();
  150. try
  151. {
  152. issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
  153. }
  154. catch (Exception e)
  155. {
  156. throw new Exception(
  157. "Cannot find issuer certificate for certificate in certification path.",
  158. e);
  159. }
  160. if (issuers.IsEmpty)
  161. throw new Exception("No issuer certificate for certificate in certification path found.");
  162. foreach (X509Certificate issuer in issuers)
  163. {
  164. builderResult = Build(issuer, pkixParams, tbvPath);
  165. if (builderResult != null)
  166. break;
  167. }
  168. }
  169. }
  170. catch (Exception e)
  171. {
  172. certPathException = e;
  173. }
  174. if (builderResult == null)
  175. {
  176. tbvPath.Remove(tbvCert);
  177. }
  178. return builderResult;
  179. }
  180. }
  181. }
  182. #pragma warning restore
  183. #endif