AbstractTlsClient.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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.Utilities;
  6. namespace Org.BouncyCastle.Crypto.Tls
  7. {
  8. public abstract class AbstractTlsClient
  9. : AbstractTlsPeer, TlsClient
  10. {
  11. protected TlsCipherFactory mCipherFactory;
  12. protected TlsClientContext mContext;
  13. protected IList mSupportedSignatureAlgorithms;
  14. protected int[] mNamedCurves;
  15. protected byte[] mClientECPointFormats, mServerECPointFormats;
  16. protected int mSelectedCipherSuite;
  17. protected short mSelectedCompressionMethod;
  18. public System.Collections.Generic.List<string> HostNames { get; set; }
  19. public AbstractTlsClient()
  20. : this(new DefaultTlsCipherFactory())
  21. {
  22. }
  23. public AbstractTlsClient(TlsCipherFactory cipherFactory)
  24. {
  25. this.mCipherFactory = cipherFactory;
  26. }
  27. protected virtual bool AllowUnexpectedServerExtension(int extensionType, byte[] extensionData)
  28. {
  29. switch (extensionType)
  30. {
  31. case ExtensionType.elliptic_curves:
  32. /*
  33. * Exception added based on field reports that some servers do send this, although the
  34. * Supported Elliptic Curves Extension is clearly intended to be client-only. If
  35. * present, we still require that it is a valid EllipticCurveList.
  36. */
  37. TlsEccUtilities.ReadSupportedEllipticCurvesExtension(extensionData);
  38. return true;
  39. default:
  40. return false;
  41. }
  42. }
  43. protected virtual void CheckForUnexpectedServerExtension(IDictionary serverExtensions, int extensionType)
  44. {
  45. byte[] extensionData = TlsUtilities.GetExtensionData(serverExtensions, extensionType);
  46. if (extensionData != null && !AllowUnexpectedServerExtension(extensionType, extensionData))
  47. {
  48. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  49. }
  50. }
  51. public virtual void Init(TlsClientContext context)
  52. {
  53. this.mContext = context;
  54. }
  55. public virtual TlsSession GetSessionToResume()
  56. {
  57. return null;
  58. }
  59. public virtual ProtocolVersion ClientHelloRecordLayerVersion
  60. {
  61. get
  62. {
  63. // "{03,00}"
  64. //return ProtocolVersion.SSLv3;
  65. // "the lowest version number supported by the client"
  66. //return MinimumVersion;
  67. // "the value of ClientHello.client_version"
  68. return ClientVersion;
  69. }
  70. }
  71. public virtual ProtocolVersion ClientVersion
  72. {
  73. get { return ProtocolVersion.TLSv12; }
  74. }
  75. public virtual bool IsFallback
  76. {
  77. /*
  78. * RFC 7507 4. The TLS_FALLBACK_SCSV cipher suite value is meant for use by clients that
  79. * repeat a connection attempt with a downgraded protocol (perform a "fallback retry") in
  80. * order to work around interoperability problems with legacy servers.
  81. */
  82. get { return false; }
  83. }
  84. public virtual IDictionary GetClientExtensions()
  85. {
  86. IDictionary clientExtensions = null;
  87. ProtocolVersion clientVersion = mContext.ClientVersion;
  88. /*
  89. * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2.
  90. * Clients MUST NOT offer it if they are offering prior versions.
  91. */
  92. if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(clientVersion))
  93. {
  94. // TODO Provide a way for the user to specify the acceptable hash/signature algorithms.
  95. this.mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultSupportedSignatureAlgorithms();
  96. clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(clientExtensions);
  97. TlsUtilities.AddSignatureAlgorithmsExtension(clientExtensions, mSupportedSignatureAlgorithms);
  98. }
  99. if (TlsEccUtilities.ContainsEccCipherSuites(GetCipherSuites()))
  100. {
  101. /*
  102. * RFC 4492 5.1. A client that proposes ECC cipher suites in its ClientHello message
  103. * appends these extensions (along with any others), enumerating the curves it supports
  104. * and the point formats it can parse. Clients SHOULD send both the Supported Elliptic
  105. * Curves Extension and the Supported Point Formats Extension.
  106. */
  107. /*
  108. * TODO Could just add all the curves since we support them all, but users may not want
  109. * to use unnecessarily large fields. Need configuration options.
  110. */
  111. this.mNamedCurves = new int[]{ NamedCurve.secp256r1, NamedCurve.secp384r1 };
  112. this.mClientECPointFormats = new byte[]{ ECPointFormat.uncompressed,
  113. ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, };
  114. clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(clientExtensions);
  115. TlsEccUtilities.AddSupportedEllipticCurvesExtension(clientExtensions, mNamedCurves);
  116. TlsEccUtilities.AddSupportedPointFormatsExtension(clientExtensions, mClientECPointFormats);
  117. }
  118. if (this.HostNames != null && this.HostNames.Count > 0)
  119. {
  120. var list = new System.Collections.Generic.List<ServerName>(this.HostNames.Count);
  121. for (int i = 0; i < this.HostNames.Count; ++i)
  122. list.Add(new ServerName(Tls.NameType.host_name, this.HostNames[i]));
  123. TlsExtensionsUtilities.AddServerNameExtension(clientExtensions, new ServerNameList(list));
  124. }
  125. return clientExtensions;
  126. }
  127. public virtual ProtocolVersion MinimumVersion
  128. {
  129. get { return ProtocolVersion.TLSv10; }
  130. }
  131. public virtual void NotifyServerVersion(ProtocolVersion serverVersion)
  132. {
  133. if (!MinimumVersion.IsEqualOrEarlierVersionOf(serverVersion))
  134. throw new TlsFatalAlert(AlertDescription.protocol_version);
  135. }
  136. public abstract int[] GetCipherSuites();
  137. public virtual byte[] GetCompressionMethods()
  138. {
  139. return new byte[]{ CompressionMethod.cls_null };
  140. }
  141. public virtual void NotifySessionID(byte[] sessionID)
  142. {
  143. // Currently ignored
  144. }
  145. public virtual void NotifySelectedCipherSuite(int selectedCipherSuite)
  146. {
  147. this.mSelectedCipherSuite = selectedCipherSuite;
  148. }
  149. public virtual void NotifySelectedCompressionMethod(byte selectedCompressionMethod)
  150. {
  151. this.mSelectedCompressionMethod = selectedCompressionMethod;
  152. }
  153. public virtual void ProcessServerExtensions(IDictionary serverExtensions)
  154. {
  155. /*
  156. * TlsProtocol implementation validates that any server extensions received correspond to
  157. * client extensions sent. By default, we don't send any, and this method is not called.
  158. */
  159. if (serverExtensions != null)
  160. {
  161. /*
  162. * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension.
  163. */
  164. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.signature_algorithms);
  165. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.elliptic_curves);
  166. if (TlsEccUtilities.IsEccCipherSuite(this.mSelectedCipherSuite))
  167. {
  168. this.mServerECPointFormats = TlsEccUtilities.GetSupportedPointFormatsExtension(serverExtensions);
  169. }
  170. else
  171. {
  172. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.ec_point_formats);
  173. }
  174. /*
  175. * RFC 7685 3. The server MUST NOT echo the extension.
  176. */
  177. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.padding);
  178. }
  179. }
  180. public virtual void ProcessServerSupplementalData(IList serverSupplementalData)
  181. {
  182. if (serverSupplementalData != null)
  183. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  184. }
  185. public abstract TlsKeyExchange GetKeyExchange();
  186. public abstract TlsAuthentication GetAuthentication();
  187. public virtual IList GetClientSupplementalData()
  188. {
  189. return null;
  190. }
  191. public override TlsCompression GetCompression()
  192. {
  193. switch (mSelectedCompressionMethod)
  194. {
  195. case CompressionMethod.cls_null:
  196. return new TlsNullCompression();
  197. case CompressionMethod.DEFLATE:
  198. return new TlsDeflateCompression();
  199. default:
  200. /*
  201. * Note: internal error here; the TlsProtocol implementation verifies that the
  202. * server-selected compression method was in the list of client-offered compression
  203. * methods, so if we now can't produce an implementation, we shouldn't have offered it!
  204. */
  205. throw new TlsFatalAlert(AlertDescription.internal_error);
  206. }
  207. }
  208. public override TlsCipher GetCipher()
  209. {
  210. int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite);
  211. int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite);
  212. return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm);
  213. }
  214. public virtual void NotifyNewSessionTicket(NewSessionTicket newSessionTicket)
  215. {
  216. }
  217. }
  218. }
  219. #endif