CertificateRequest.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using Org.BouncyCastle.Asn1;
  6. using Org.BouncyCastle.Asn1.X509;
  7. using Org.BouncyCastle.Utilities;
  8. namespace Org.BouncyCastle.Crypto.Tls
  9. {
  10. /**
  11. * Parsing and encoding of a <i>CertificateRequest</i> struct from RFC 4346.
  12. * <p/>
  13. * <pre>
  14. * struct {
  15. * ClientCertificateType certificate_types&lt;1..2^8-1&gt;;
  16. * DistinguishedName certificate_authorities&lt;3..2^16-1&gt;
  17. * } CertificateRequest;
  18. * </pre>
  19. *
  20. * @see ClientCertificateType
  21. * @see X509Name
  22. */
  23. public class CertificateRequest
  24. {
  25. protected readonly byte[] mCertificateTypes;
  26. protected readonly IList mSupportedSignatureAlgorithms;
  27. protected readonly IList mCertificateAuthorities;
  28. /**
  29. * @param certificateTypes see {@link ClientCertificateType} for valid constants.
  30. * @param certificateAuthorities an {@link IList} of {@link X509Name}.
  31. */
  32. public CertificateRequest(byte[] certificateTypes, IList supportedSignatureAlgorithms,
  33. IList certificateAuthorities)
  34. {
  35. this.mCertificateTypes = certificateTypes;
  36. this.mSupportedSignatureAlgorithms = supportedSignatureAlgorithms;
  37. this.mCertificateAuthorities = certificateAuthorities;
  38. }
  39. /**
  40. * @return an array of certificate types
  41. * @see {@link ClientCertificateType}
  42. */
  43. public virtual byte[] CertificateTypes
  44. {
  45. get { return mCertificateTypes; }
  46. }
  47. /**
  48. * @return an {@link IList} of {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
  49. */
  50. public virtual IList SupportedSignatureAlgorithms
  51. {
  52. get { return mSupportedSignatureAlgorithms; }
  53. }
  54. /**
  55. * @return an {@link IList} of {@link X509Name}
  56. */
  57. public virtual IList CertificateAuthorities
  58. {
  59. get { return mCertificateAuthorities; }
  60. }
  61. /**
  62. * Encode this {@link CertificateRequest} to a {@link Stream}.
  63. *
  64. * @param output the {@link Stream} to encode to.
  65. * @throws IOException
  66. */
  67. public virtual void Encode(Stream output)
  68. {
  69. if (mCertificateTypes == null || mCertificateTypes.Length == 0)
  70. {
  71. TlsUtilities.WriteUint8(0, output);
  72. }
  73. else
  74. {
  75. TlsUtilities.WriteUint8ArrayWithUint8Length(mCertificateTypes, output);
  76. }
  77. if (mSupportedSignatureAlgorithms != null)
  78. {
  79. // TODO Check whether SignatureAlgorithm.anonymous is allowed here
  80. TlsUtilities.EncodeSupportedSignatureAlgorithms(mSupportedSignatureAlgorithms, false, output);
  81. }
  82. if (mCertificateAuthorities == null || mCertificateAuthorities.Count < 1)
  83. {
  84. TlsUtilities.WriteUint16(0, output);
  85. }
  86. else
  87. {
  88. IList derEncodings = Org.BouncyCastle.Utilities.Platform.CreateArrayList(mCertificateAuthorities.Count);
  89. int totalLength = 0;
  90. foreach (Asn1Encodable certificateAuthority in mCertificateAuthorities)
  91. {
  92. byte[] derEncoding = certificateAuthority.GetEncoded(Asn1Encodable.Der);
  93. derEncodings.Add(derEncoding);
  94. totalLength += derEncoding.Length + 2;
  95. }
  96. TlsUtilities.CheckUint16(totalLength);
  97. TlsUtilities.WriteUint16(totalLength, output);
  98. foreach (byte[] derEncoding in derEncodings)
  99. {
  100. TlsUtilities.WriteOpaque16(derEncoding, output);
  101. }
  102. }
  103. }
  104. /**
  105. * Parse a {@link CertificateRequest} from a {@link Stream}.
  106. *
  107. * @param context
  108. * the {@link TlsContext} of the current connection.
  109. * @param input
  110. * the {@link Stream} to parse from.
  111. * @return a {@link CertificateRequest} object.
  112. * @throws IOException
  113. */
  114. public static CertificateRequest Parse(TlsContext context, Stream input)
  115. {
  116. int numTypes = TlsUtilities.ReadUint8(input);
  117. byte[] certificateTypes = new byte[numTypes];
  118. for (int i = 0; i < numTypes; ++i)
  119. {
  120. certificateTypes[i] = TlsUtilities.ReadUint8(input);
  121. }
  122. IList supportedSignatureAlgorithms = null;
  123. if (TlsUtilities.IsTlsV12(context))
  124. {
  125. // TODO Check whether SignatureAlgorithm.anonymous is allowed here
  126. supportedSignatureAlgorithms = TlsUtilities.ParseSupportedSignatureAlgorithms(false, input);
  127. }
  128. IList certificateAuthorities = Org.BouncyCastle.Utilities.Platform.CreateArrayList();
  129. byte[] certAuthData = TlsUtilities.ReadOpaque16(input);
  130. MemoryStream bis = new MemoryStream(certAuthData, false);
  131. while (bis.Position < bis.Length)
  132. {
  133. byte[] derEncoding = TlsUtilities.ReadOpaque16(bis);
  134. Asn1Object asn1 = TlsUtilities.ReadDerObject(derEncoding);
  135. // TODO Switch to X500Name when available
  136. certificateAuthorities.Add(X509Name.GetInstance(asn1));
  137. }
  138. return new CertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities);
  139. }
  140. }
  141. }
  142. #endif