AbstractTlsClient.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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 Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  9. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Tls
  10. {
  11. /// <summary>Base class for a TLS client.</summary>
  12. public abstract class AbstractTlsClient
  13. : AbstractTlsPeer, TlsClient
  14. {
  15. protected TlsClientContext m_context;
  16. protected ProtocolVersion[] m_protocolVersions;
  17. protected int[] m_cipherSuites;
  18. protected IList<int> m_supportedGroups;
  19. protected IList<SignatureAndHashAlgorithm> m_supportedSignatureAlgorithms;
  20. protected IList<SignatureAndHashAlgorithm> m_supportedSignatureAlgorithmsCert;
  21. protected AbstractTlsClient(TlsCrypto crypto)
  22. : base(crypto)
  23. {
  24. }
  25. /// <exception cref="IOException"/>
  26. protected virtual bool AllowUnexpectedServerExtension(int extensionType, byte[] extensionData)
  27. {
  28. switch (extensionType)
  29. {
  30. case ExtensionType.supported_groups:
  31. /*
  32. * Exception added based on field reports that some servers do send this, although the
  33. * Supported Elliptic Curves Extension is clearly intended to be client-only. If
  34. * present, we still require that it is a valid EllipticCurveList.
  35. */
  36. TlsExtensionsUtilities.ReadSupportedGroupsExtension(extensionData);
  37. return true;
  38. case ExtensionType.ec_point_formats:
  39. /*
  40. * Exception added based on field reports that some servers send this even when they
  41. * didn't negotiate an ECC cipher suite. If present, we still require that it is a valid
  42. * ECPointFormatList.
  43. */
  44. TlsExtensionsUtilities.ReadSupportedPointFormatsExtension(extensionData);
  45. return true;
  46. default:
  47. return false;
  48. }
  49. }
  50. protected virtual IList<int> GetNamedGroupRoles()
  51. {
  52. var namedGroupRoles = TlsUtilities.GetNamedGroupRoles(GetCipherSuites());
  53. var sigAlgs = m_supportedSignatureAlgorithms;
  54. var sigAlgsCert = m_supportedSignatureAlgorithmsCert;
  55. if ((null == sigAlgs || TlsUtilities.ContainsAnySignatureAlgorithm(sigAlgs, SignatureAlgorithm.ecdsa)) ||
  56. (null != sigAlgsCert && TlsUtilities.ContainsAnySignatureAlgorithm(sigAlgsCert, SignatureAlgorithm.ecdsa)))
  57. {
  58. TlsUtilities.AddToSet(namedGroupRoles, NamedGroupRole.ecdsa);
  59. }
  60. return namedGroupRoles;
  61. }
  62. /// <exception cref="IOException"/>
  63. protected virtual void CheckForUnexpectedServerExtension(IDictionary<int, byte[]> serverExtensions,
  64. int extensionType)
  65. {
  66. byte[] extensionData = TlsUtilities.GetExtensionData(serverExtensions, extensionType);
  67. if (extensionData != null && !AllowUnexpectedServerExtension(extensionType, extensionData))
  68. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  69. }
  70. /// <exception cref="IOException"/>
  71. public virtual TlsPskIdentity GetPskIdentity()
  72. {
  73. return null;
  74. }
  75. /// <exception cref="IOException"/>
  76. public virtual TlsSrpIdentity GetSrpIdentity()
  77. {
  78. return null;
  79. }
  80. public virtual TlsDHGroupVerifier GetDHGroupVerifier()
  81. {
  82. return new DefaultTlsDHGroupVerifier();
  83. }
  84. public virtual TlsSrpConfigVerifier GetSrpConfigVerifier()
  85. {
  86. return new DefaultTlsSrpConfigVerifier();
  87. }
  88. protected virtual IList<X509Name> GetCertificateAuthorities()
  89. {
  90. return null;
  91. }
  92. protected virtual IList<ProtocolName> GetProtocolNames()
  93. {
  94. return null;
  95. }
  96. protected virtual CertificateStatusRequest GetCertificateStatusRequest()
  97. {
  98. return new CertificateStatusRequest(CertificateStatusType.ocsp, new OcspStatusRequest(null, null));
  99. }
  100. /// <returns>an <see cref="IList{T}"/> of <see cref="CertificateStatusRequestItemV2"/> (or null).</returns>
  101. protected virtual IList<CertificateStatusRequestItemV2> GetMultiCertStatusRequest()
  102. {
  103. return null;
  104. }
  105. protected virtual IList<ServerName> GetSniServerNames()
  106. {
  107. return null;
  108. }
  109. /// <summary>The default <see cref="GetClientExtensions"/> implementation calls this to determine which named
  110. /// groups to include in the supported_groups extension for the ClientHello.</summary>
  111. /// <param name="namedGroupRoles">The <see cref="NamedGroupRole">named group roles</see> for which there should
  112. /// be at least one supported group. By default this is inferred from the offered cipher suites and signature
  113. /// algorithms.</param>
  114. /// <returns>an <see cref="IList{T}"/> of <see cref="Int32"/>. See <see cref="NamedGroup"/> for group constants.
  115. /// </returns>
  116. protected virtual IList<int> GetSupportedGroups(IList<int> namedGroupRoles)
  117. {
  118. TlsCrypto crypto = Crypto;
  119. var supportedGroups = new List<int>();
  120. if (namedGroupRoles.Contains(NamedGroupRole.ecdh))
  121. {
  122. TlsUtilities.AddIfSupported(supportedGroups, crypto,
  123. new int[]{ NamedGroup.x25519, NamedGroup.x448 });
  124. }
  125. if (namedGroupRoles.Contains(NamedGroupRole.ecdh) ||
  126. namedGroupRoles.Contains(NamedGroupRole.ecdsa))
  127. {
  128. TlsUtilities.AddIfSupported(supportedGroups, crypto,
  129. new int[]{ NamedGroup.secp256r1, NamedGroup.secp384r1 });
  130. }
  131. if (namedGroupRoles.Contains(NamedGroupRole.dh))
  132. {
  133. TlsUtilities.AddIfSupported(supportedGroups, crypto,
  134. new int[]{ NamedGroup.ffdhe2048, NamedGroup.ffdhe3072, NamedGroup.ffdhe4096 });
  135. }
  136. return supportedGroups;
  137. }
  138. protected virtual IList<SignatureAndHashAlgorithm> GetSupportedSignatureAlgorithms()
  139. {
  140. return TlsUtilities.GetDefaultSupportedSignatureAlgorithms(m_context);
  141. }
  142. protected virtual IList<SignatureAndHashAlgorithm> GetSupportedSignatureAlgorithmsCert()
  143. {
  144. return null;
  145. }
  146. protected virtual IList<TrustedAuthority> GetTrustedCAIndication()
  147. {
  148. return null;
  149. }
  150. protected virtual short[] GetAllowedClientCertificateTypes()
  151. {
  152. return null;
  153. }
  154. protected virtual short[] GetAllowedServerCertificateTypes()
  155. {
  156. return null;
  157. }
  158. public virtual void Init(TlsClientContext context)
  159. {
  160. this.m_context = context;
  161. this.m_protocolVersions = GetSupportedVersions();
  162. this.m_cipherSuites = GetSupportedCipherSuites();
  163. }
  164. public override ProtocolVersion[] GetProtocolVersions()
  165. {
  166. return m_protocolVersions;
  167. }
  168. public override int[] GetCipherSuites()
  169. {
  170. return m_cipherSuites;
  171. }
  172. /// <exception cref="IOException"/>
  173. public override void NotifyHandshakeBeginning()
  174. {
  175. base.NotifyHandshakeBeginning();
  176. this.m_supportedGroups = null;
  177. this.m_supportedSignatureAlgorithms = null;
  178. this.m_supportedSignatureAlgorithmsCert = null;
  179. }
  180. public virtual TlsSession GetSessionToResume()
  181. {
  182. return null;
  183. }
  184. public virtual IList<TlsPskExternal> GetExternalPsks()
  185. {
  186. return null;
  187. }
  188. public virtual bool IsFallback()
  189. {
  190. /*
  191. * RFC 7507 4. The TLS_FALLBACK_SCSV cipher suite value is meant for use by clients that
  192. * repeat a connection attempt with a downgraded protocol (perform a "fallback retry") in
  193. * order to work around interoperability problems with legacy servers.
  194. */
  195. return false;
  196. }
  197. /// <exception cref="IOException"/>
  198. public virtual IDictionary<int, byte[]> GetClientExtensions()
  199. {
  200. var clientExtensions = new Dictionary<int, byte[]>();
  201. bool offeringTlsV13Plus = false;
  202. bool offeringPreTlsV13 = false;
  203. {
  204. ProtocolVersion[] supportedVersions = GetProtocolVersions();
  205. for (int i = 0; i < supportedVersions.Length; ++i)
  206. {
  207. if (TlsUtilities.IsTlsV13(supportedVersions[i]))
  208. {
  209. offeringTlsV13Plus = true;
  210. }
  211. else
  212. {
  213. offeringPreTlsV13 = true;
  214. }
  215. }
  216. }
  217. var protocolNames = GetProtocolNames();
  218. if (protocolNames != null)
  219. {
  220. TlsExtensionsUtilities.AddAlpnExtensionClient(clientExtensions, protocolNames);
  221. }
  222. var sniServerNames = GetSniServerNames();
  223. if (sniServerNames != null)
  224. {
  225. TlsExtensionsUtilities.AddServerNameExtensionClient(clientExtensions, sniServerNames);
  226. }
  227. CertificateStatusRequest statusRequest = GetCertificateStatusRequest();
  228. if (statusRequest != null)
  229. {
  230. TlsExtensionsUtilities.AddStatusRequestExtension(clientExtensions, statusRequest);
  231. }
  232. if (offeringTlsV13Plus)
  233. {
  234. var certificateAuthorities = GetCertificateAuthorities();
  235. if (certificateAuthorities != null)
  236. {
  237. TlsExtensionsUtilities.AddCertificateAuthoritiesExtension(clientExtensions, certificateAuthorities);
  238. }
  239. }
  240. if (offeringPreTlsV13)
  241. {
  242. // TODO Shouldn't add if no offered cipher suite uses a block cipher?
  243. TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
  244. var statusRequestV2 = GetMultiCertStatusRequest();
  245. if (statusRequestV2 != null)
  246. {
  247. TlsExtensionsUtilities.AddStatusRequestV2Extension(clientExtensions, statusRequestV2);
  248. }
  249. var trustedCAKeys = GetTrustedCAIndication();
  250. if (trustedCAKeys != null)
  251. {
  252. TlsExtensionsUtilities.AddTrustedCAKeysExtensionClient(clientExtensions, trustedCAKeys);
  253. }
  254. }
  255. ProtocolVersion clientVersion = m_context.ClientVersion;
  256. /*
  257. * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2.
  258. * Clients MUST NOT offer it if they are offering prior versions.
  259. */
  260. if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(clientVersion))
  261. {
  262. var supportedSigAlgs = GetSupportedSignatureAlgorithms();
  263. if (null != supportedSigAlgs && supportedSigAlgs.Count > 0)
  264. {
  265. this.m_supportedSignatureAlgorithms = supportedSigAlgs;
  266. TlsExtensionsUtilities.AddSignatureAlgorithmsExtension(clientExtensions, supportedSigAlgs);
  267. }
  268. var supportedSigAlgsCert = GetSupportedSignatureAlgorithmsCert();
  269. if (null != supportedSigAlgsCert && supportedSigAlgsCert.Count > 0)
  270. {
  271. this.m_supportedSignatureAlgorithmsCert = supportedSigAlgsCert;
  272. TlsExtensionsUtilities.AddSignatureAlgorithmsCertExtension(clientExtensions, supportedSigAlgsCert);
  273. }
  274. }
  275. var namedGroupRoles = GetNamedGroupRoles();
  276. var supportedGroups = GetSupportedGroups(namedGroupRoles);
  277. if (supportedGroups != null && supportedGroups.Count > 0)
  278. {
  279. this.m_supportedGroups = supportedGroups;
  280. TlsExtensionsUtilities.AddSupportedGroupsExtension(clientExtensions, supportedGroups);
  281. }
  282. if (offeringPreTlsV13)
  283. {
  284. if (namedGroupRoles.Contains(NamedGroupRole.ecdh) ||
  285. namedGroupRoles.Contains(NamedGroupRole.ecdsa))
  286. {
  287. TlsExtensionsUtilities.AddSupportedPointFormatsExtension(clientExtensions,
  288. new short[]{ ECPointFormat.uncompressed });
  289. }
  290. }
  291. /*
  292. * RFC 7250 4.1:
  293. *
  294. * If the client has no remaining certificate types to send in
  295. * the client hello, other than the default X.509 type, it MUST omit the
  296. * client_certificate_type extension in the client hello.
  297. */
  298. short[] clientCertTypes = GetAllowedClientCertificateTypes();
  299. if (clientCertTypes != null && (clientCertTypes.Length > 1 || clientCertTypes[0] != CertificateType.X509))
  300. {
  301. TlsExtensionsUtilities.AddClientCertificateTypeExtensionClient(clientExtensions, clientCertTypes);
  302. }
  303. /*
  304. * RFC 7250 4.1:
  305. *
  306. * If the client has no remaining certificate types to send in
  307. * the client hello, other than the default X.509 certificate type, it
  308. * MUST omit the entire server_certificate_type extension from the
  309. * client hello.
  310. */
  311. short[] serverCertTypes = GetAllowedServerCertificateTypes();
  312. if (serverCertTypes != null && (serverCertTypes.Length > 1 || serverCertTypes[0] != CertificateType.X509))
  313. {
  314. TlsExtensionsUtilities.AddServerCertificateTypeExtensionClient(clientExtensions, serverCertTypes);
  315. }
  316. return clientExtensions;
  317. }
  318. public virtual IList<int> GetEarlyKeyShareGroups()
  319. {
  320. /*
  321. * RFC 8446 4.2.8. Each KeyShareEntry value MUST correspond to a group offered in the
  322. * "supported_groups" extension and MUST appear in the same order. However, the values MAY
  323. * be a non-contiguous subset of the "supported_groups" extension and MAY omit the most
  324. * preferred groups.
  325. */
  326. if (null == m_supportedGroups || m_supportedGroups.Count < 1)
  327. return null;
  328. if (m_supportedGroups.Contains(NamedGroup.x25519))
  329. return TlsUtilities.VectorOfOne(NamedGroup.x25519);
  330. if (m_supportedGroups.Contains(NamedGroup.secp256r1))
  331. return TlsUtilities.VectorOfOne(NamedGroup.secp256r1);
  332. return TlsUtilities.VectorOfOne(m_supportedGroups[0]);
  333. }
  334. /// <exception cref="IOException"/>
  335. public virtual void NotifyServerVersion(ProtocolVersion serverVersion)
  336. {
  337. }
  338. public virtual void NotifySessionToResume(TlsSession session)
  339. {
  340. }
  341. public virtual void NotifySessionID(byte[] sessionID)
  342. {
  343. }
  344. public virtual void NotifySelectedCipherSuite(int selectedCipherSuite)
  345. {
  346. }
  347. /// <exception cref="IOException"/>
  348. public virtual void NotifySelectedPsk(TlsPsk selectedPsk)
  349. {
  350. }
  351. /// <exception cref="IOException"/>
  352. public virtual void ProcessServerExtensions(IDictionary<int, byte[]> serverExtensions)
  353. {
  354. if (null == serverExtensions)
  355. return;
  356. SecurityParameters securityParameters = m_context.SecurityParameters;
  357. bool isTlsV13 = TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion);
  358. if (isTlsV13)
  359. {
  360. /*
  361. * NOTE: From TLS 1.3 the protocol classes are strict about what extensions can appear.
  362. */
  363. }
  364. else
  365. {
  366. /*
  367. * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension.
  368. */
  369. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.signature_algorithms);
  370. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.signature_algorithms_cert);
  371. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.supported_groups);
  372. int selectedCipherSuite = securityParameters.CipherSuite;
  373. if (TlsEccUtilities.IsEccCipherSuite(selectedCipherSuite))
  374. {
  375. // We only support uncompressed format, this is just to validate the extension, if present.
  376. TlsExtensionsUtilities.GetSupportedPointFormatsExtension(serverExtensions);
  377. }
  378. else
  379. {
  380. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.ec_point_formats);
  381. }
  382. /*
  383. * RFC 7685 3. The server MUST NOT echo the extension.
  384. */
  385. CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.padding);
  386. }
  387. }
  388. /// <exception cref="IOException"/>
  389. public virtual void ProcessServerSupplementalData(IList<SupplementalDataEntry> serverSupplementalData)
  390. {
  391. if (serverSupplementalData != null)
  392. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  393. }
  394. public abstract TlsAuthentication GetAuthentication();
  395. /// <exception cref="IOException"/>
  396. public virtual IList<SupplementalDataEntry> GetClientSupplementalData()
  397. {
  398. return null;
  399. }
  400. /// <exception cref="IOException"/>
  401. public virtual void NotifyNewSessionTicket(NewSessionTicket newSessionTicket)
  402. {
  403. }
  404. }
  405. }
  406. #pragma warning restore
  407. #endif