DtlsClientProtocol.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  8. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
  9. {
  10. public class DtlsClientProtocol
  11. : DtlsProtocol
  12. {
  13. public DtlsClientProtocol()
  14. : base()
  15. {
  16. }
  17. /// <exception cref="IOException"/>
  18. public virtual DtlsTransport Connect(TlsClient client, DatagramTransport transport)
  19. {
  20. if (client == null)
  21. throw new ArgumentNullException("client");
  22. if (transport == null)
  23. throw new ArgumentNullException("transport");
  24. ClientHandshakeState state = new ClientHandshakeState();
  25. state.client = client;
  26. state.clientContext = new TlsClientContextImpl(client.Crypto);
  27. client.Init(state.clientContext);
  28. state.clientContext.HandshakeBeginning(client);
  29. SecurityParameters securityParameters = state.clientContext.SecurityParameters;
  30. securityParameters.m_extendedPadding = client.ShouldUseExtendedPadding();
  31. TlsSession sessionToResume = state.client.GetSessionToResume();
  32. if (sessionToResume != null && sessionToResume.IsResumable)
  33. {
  34. SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
  35. /*
  36. * NOTE: If we ever enable session resumption without extended_master_secret, then
  37. * renegotiation MUST be disabled (see RFC 7627 5.4).
  38. */
  39. if (sessionParameters != null
  40. && (sessionParameters.IsExtendedMasterSecret
  41. || (!state.client.RequiresExtendedMasterSecret() && state.client.AllowLegacyResumption())))
  42. {
  43. TlsSecret masterSecret = sessionParameters.MasterSecret;
  44. lock (masterSecret)
  45. {
  46. if (masterSecret.IsAlive())
  47. {
  48. state.tlsSession = sessionToResume;
  49. state.sessionParameters = sessionParameters;
  50. state.sessionMasterSecret = state.clientContext.Crypto.AdoptSecret(masterSecret);
  51. }
  52. }
  53. }
  54. }
  55. DtlsRecordLayer recordLayer = new DtlsRecordLayer(state.clientContext, state.client, transport);
  56. client.NotifyCloseHandle(recordLayer);
  57. try
  58. {
  59. return ClientHandshake(state, recordLayer);
  60. }
  61. catch (TlsFatalAlert fatalAlert)
  62. {
  63. AbortClientHandshake(state, recordLayer, fatalAlert.AlertDescription);
  64. throw fatalAlert;
  65. }
  66. catch (IOException e)
  67. {
  68. AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
  69. throw e;
  70. }
  71. catch (Exception e)
  72. {
  73. AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
  74. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  75. }
  76. finally
  77. {
  78. securityParameters.Clear();
  79. }
  80. }
  81. internal virtual void AbortClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer,
  82. short alertDescription)
  83. {
  84. recordLayer.Fail(alertDescription);
  85. InvalidateSession(state);
  86. }
  87. /// <exception cref="IOException"/>
  88. internal virtual DtlsTransport ClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer)
  89. {
  90. SecurityParameters securityParameters = state.clientContext.SecurityParameters;
  91. DtlsReliableHandshake handshake = new DtlsReliableHandshake(state.clientContext, recordLayer,
  92. state.client.GetHandshakeTimeoutMillis(), null);
  93. byte[] clientHelloBody = GenerateClientHello(state);
  94. recordLayer.SetWriteVersion(ProtocolVersion.DTLSv10);
  95. handshake.SendMessage(HandshakeType.client_hello, clientHelloBody);
  96. DtlsReliableHandshake.Message serverMessage = handshake.ReceiveMessage();
  97. // TODO Consider stricter HelloVerifyRequest protocol
  98. //if (serverMessage.Type == HandshakeType.hello_verify_request)
  99. while (serverMessage.Type == HandshakeType.hello_verify_request)
  100. {
  101. byte[] cookie = ProcessHelloVerifyRequest(state, serverMessage.Body);
  102. byte[] patched = PatchClientHelloWithCookie(clientHelloBody, cookie);
  103. handshake.ResetAfterHelloVerifyRequestClient();
  104. handshake.SendMessage(HandshakeType.client_hello, patched);
  105. serverMessage = handshake.ReceiveMessage();
  106. }
  107. if (serverMessage.Type == HandshakeType.server_hello)
  108. {
  109. ProtocolVersion recordLayerVersion = recordLayer.ReadVersion;
  110. ReportServerVersion(state, recordLayerVersion);
  111. recordLayer.SetWriteVersion(recordLayerVersion);
  112. ProcessServerHello(state, serverMessage.Body);
  113. }
  114. else
  115. {
  116. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  117. }
  118. handshake.HandshakeHash.NotifyPrfDetermined();
  119. ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.MaxFragmentLength);
  120. if (state.resumedSession)
  121. {
  122. securityParameters.m_masterSecret = state.sessionMasterSecret;
  123. recordLayer.InitPendingEpoch(TlsUtilities.InitCipher(state.clientContext));
  124. // NOTE: Calculated exclusive of the actual Finished message from the server
  125. securityParameters.m_peerVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext,
  126. handshake.HandshakeHash, true);
  127. ProcessFinished(handshake.ReceiveMessageBody(HandshakeType.finished),
  128. securityParameters.PeerVerifyData);
  129. // NOTE: Calculated exclusive of the Finished message itself
  130. securityParameters.m_localVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext,
  131. handshake.HandshakeHash, false);
  132. handshake.SendMessage(HandshakeType.finished, securityParameters.LocalVerifyData);
  133. handshake.Finish();
  134. if (securityParameters.IsExtendedMasterSecret)
  135. {
  136. securityParameters.m_tlsUnique = securityParameters.PeerVerifyData;
  137. }
  138. securityParameters.m_localCertificate = state.sessionParameters.LocalCertificate;
  139. securityParameters.m_peerCertificate = state.sessionParameters.PeerCertificate;
  140. securityParameters.m_pskIdentity = state.sessionParameters.PskIdentity;
  141. securityParameters.m_srpIdentity = state.sessionParameters.SrpIdentity;
  142. state.clientContext.HandshakeComplete(state.client, state.tlsSession);
  143. recordLayer.InitHeartbeat(state.heartbeat,
  144. HeartbeatMode.peer_allowed_to_send == state.heartbeatPolicy);
  145. return new DtlsTransport(recordLayer);
  146. }
  147. InvalidateSession(state);
  148. state.tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, null);
  149. serverMessage = handshake.ReceiveMessage();
  150. if (serverMessage.Type == HandshakeType.supplemental_data)
  151. {
  152. ProcessServerSupplementalData(state, serverMessage.Body);
  153. serverMessage = handshake.ReceiveMessage();
  154. }
  155. else
  156. {
  157. state.client.ProcessServerSupplementalData(null);
  158. }
  159. state.keyExchange = TlsUtilities.InitKeyExchangeClient(state.clientContext, state.client);
  160. if (serverMessage.Type == HandshakeType.certificate)
  161. {
  162. ProcessServerCertificate(state, serverMessage.Body);
  163. serverMessage = handshake.ReceiveMessage();
  164. }
  165. else
  166. {
  167. // Okay, Certificate is optional
  168. state.authentication = null;
  169. }
  170. if (serverMessage.Type == HandshakeType.certificate_status)
  171. {
  172. if (securityParameters.StatusRequestVersion < 1)
  173. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  174. ProcessCertificateStatus(state, serverMessage.Body);
  175. serverMessage = handshake.ReceiveMessage();
  176. }
  177. else
  178. {
  179. // Okay, CertificateStatus is optional
  180. }
  181. TlsUtilities.ProcessServerCertificate(state.clientContext, state.certificateStatus, state.keyExchange,
  182. state.authentication, state.clientExtensions, state.serverExtensions);
  183. if (serverMessage.Type == HandshakeType.server_key_exchange)
  184. {
  185. ProcessServerKeyExchange(state, serverMessage.Body);
  186. serverMessage = handshake.ReceiveMessage();
  187. }
  188. else
  189. {
  190. // Okay, ServerKeyExchange is optional
  191. state.keyExchange.SkipServerKeyExchange();
  192. }
  193. if (serverMessage.Type == HandshakeType.certificate_request)
  194. {
  195. ProcessCertificateRequest(state, serverMessage.Body);
  196. TlsUtilities.EstablishServerSigAlgs(securityParameters, state.certificateRequest);
  197. /*
  198. * TODO Give the client a chance to immediately select the CertificateVerify hash
  199. * algorithm here to avoid tracking the other hash algorithms unnecessarily?
  200. */
  201. TlsUtilities.TrackHashAlgorithms(handshake.HandshakeHash, securityParameters.ServerSigAlgs);
  202. serverMessage = handshake.ReceiveMessage();
  203. }
  204. else
  205. {
  206. // Okay, CertificateRequest is optional
  207. }
  208. if (serverMessage.Type == HandshakeType.server_hello_done)
  209. {
  210. if (serverMessage.Body.Length != 0)
  211. {
  212. throw new TlsFatalAlert(AlertDescription.decode_error);
  213. }
  214. }
  215. else
  216. {
  217. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  218. }
  219. IList clientSupplementalData = state.client.GetClientSupplementalData();
  220. if (clientSupplementalData != null)
  221. {
  222. byte[] supplementalDataBody = GenerateSupplementalData(clientSupplementalData);
  223. handshake.SendMessage(HandshakeType.supplemental_data, supplementalDataBody);
  224. }
  225. if (null != state.certificateRequest)
  226. {
  227. state.clientCredentials = TlsUtilities.EstablishClientCredentials(state.authentication,
  228. state.certificateRequest);
  229. /*
  230. * RFC 5246 If no suitable certificate is available, the client MUST send a certificate
  231. * message containing no certificates.
  232. *
  233. * NOTE: In previous RFCs, this was SHOULD instead of MUST.
  234. */
  235. Certificate clientCertificate = null;
  236. if (null != state.clientCredentials)
  237. {
  238. clientCertificate = state.clientCredentials.Certificate;
  239. }
  240. SendCertificateMessage(state.clientContext, handshake, clientCertificate, null);
  241. }
  242. TlsCredentialedSigner credentialedSigner = null;
  243. TlsStreamSigner streamSigner = null;
  244. if (null != state.clientCredentials)
  245. {
  246. state.keyExchange.ProcessClientCredentials(state.clientCredentials);
  247. if (state.clientCredentials is TlsCredentialedSigner)
  248. {
  249. credentialedSigner = (TlsCredentialedSigner)state.clientCredentials;
  250. streamSigner = credentialedSigner.GetStreamSigner();
  251. }
  252. }
  253. else
  254. {
  255. state.keyExchange.SkipClientCredentials();
  256. }
  257. bool forceBuffering = streamSigner != null;
  258. TlsUtilities.SealHandshakeHash(state.clientContext, handshake.HandshakeHash, forceBuffering);
  259. byte[] clientKeyExchangeBody = GenerateClientKeyExchange(state);
  260. handshake.SendMessage(HandshakeType.client_key_exchange, clientKeyExchangeBody);
  261. securityParameters.m_sessionHash = TlsUtilities.GetCurrentPrfHash(handshake.HandshakeHash);
  262. TlsProtocol.EstablishMasterSecret(state.clientContext, state.keyExchange);
  263. recordLayer.InitPendingEpoch(TlsUtilities.InitCipher(state.clientContext));
  264. {
  265. if (credentialedSigner != null)
  266. {
  267. DigitallySigned certificateVerify = TlsUtilities.GenerateCertificateVerifyClient(
  268. state.clientContext, credentialedSigner, streamSigner, handshake.HandshakeHash);
  269. byte[] certificateVerifyBody = GenerateCertificateVerify(state, certificateVerify);
  270. handshake.SendMessage(HandshakeType.certificate_verify, certificateVerifyBody);
  271. }
  272. handshake.PrepareToFinish();
  273. }
  274. securityParameters.m_localVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext,
  275. handshake.HandshakeHash, false);
  276. handshake.SendMessage(HandshakeType.finished, securityParameters.LocalVerifyData);
  277. if (state.expectSessionTicket)
  278. {
  279. serverMessage = handshake.ReceiveMessage();
  280. if (serverMessage.Type == HandshakeType.new_session_ticket)
  281. {
  282. /*
  283. * RFC 5077 3.4. If the client receives a session ticket from the server, then it
  284. * discards any Session ID that was sent in the ServerHello.
  285. */
  286. securityParameters.m_sessionID = TlsUtilities.EmptyBytes;
  287. InvalidateSession(state);
  288. state.tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, null);
  289. ProcessNewSessionTicket(state, serverMessage.Body);
  290. }
  291. else
  292. {
  293. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  294. }
  295. }
  296. // NOTE: Calculated exclusive of the actual Finished message from the server
  297. securityParameters.m_peerVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext,
  298. handshake.HandshakeHash, true);
  299. ProcessFinished(handshake.ReceiveMessageBody(HandshakeType.finished), securityParameters.PeerVerifyData);
  300. handshake.Finish();
  301. state.sessionMasterSecret = securityParameters.MasterSecret;
  302. state.sessionParameters = new SessionParameters.Builder()
  303. .SetCipherSuite(securityParameters.CipherSuite)
  304. .SetExtendedMasterSecret(securityParameters.IsExtendedMasterSecret)
  305. .SetLocalCertificate(securityParameters.LocalCertificate)
  306. .SetMasterSecret(state.clientContext.Crypto.AdoptSecret(state.sessionMasterSecret))
  307. .SetNegotiatedVersion(securityParameters.NegotiatedVersion)
  308. .SetPeerCertificate(securityParameters.PeerCertificate)
  309. .SetPskIdentity(securityParameters.PskIdentity)
  310. .SetSrpIdentity(securityParameters.SrpIdentity)
  311. // TODO Consider filtering extensions that aren't relevant to resumed sessions
  312. .SetServerExtensions(state.serverExtensions)
  313. .Build();
  314. state.tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, state.sessionParameters);
  315. securityParameters.m_tlsUnique = securityParameters.LocalVerifyData;
  316. state.clientContext.HandshakeComplete(state.client, state.tlsSession);
  317. recordLayer.InitHeartbeat(state.heartbeat, HeartbeatMode.peer_allowed_to_send == state.heartbeatPolicy);
  318. return new DtlsTransport(recordLayer);
  319. }
  320. /// <exception cref="IOException"/>
  321. protected virtual byte[] GenerateCertificateVerify(ClientHandshakeState state,
  322. DigitallySigned certificateVerify)
  323. {
  324. MemoryStream buf = new MemoryStream();
  325. certificateVerify.Encode(buf);
  326. return buf.ToArray();
  327. }
  328. /// <exception cref="IOException"/>
  329. protected virtual byte[] GenerateClientHello(ClientHandshakeState state)
  330. {
  331. TlsClientContextImpl context = state.clientContext;
  332. SecurityParameters securityParameters = context.SecurityParameters;
  333. context.SetClientSupportedVersions(state.client.GetProtocolVersions());
  334. ProtocolVersion client_version = ProtocolVersion.GetLatestDtls(context.ClientSupportedVersions);
  335. if (!ProtocolVersion.IsSupportedDtlsVersionClient(client_version))
  336. throw new TlsFatalAlert(AlertDescription.internal_error);
  337. context.SetClientVersion(client_version);
  338. byte[] session_id = TlsUtilities.GetSessionID(state.tlsSession);
  339. bool fallback = state.client.IsFallback();
  340. state.offeredCipherSuites = state.client.GetCipherSuites();
  341. if (session_id.Length > 0 && state.sessionParameters != null)
  342. {
  343. if (!Arrays.Contains(state.offeredCipherSuites, state.sessionParameters.CipherSuite))
  344. {
  345. session_id = TlsUtilities.EmptyBytes;
  346. }
  347. }
  348. state.clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(
  349. state.client.GetClientExtensions());
  350. ProtocolVersion legacy_version = client_version;
  351. if (client_version.IsLaterVersionOf(ProtocolVersion.DTLSv12))
  352. {
  353. legacy_version = ProtocolVersion.DTLSv12;
  354. TlsExtensionsUtilities.AddSupportedVersionsExtensionClient(state.clientExtensions,
  355. context.ClientSupportedVersions);
  356. }
  357. context.SetRsaPreMasterSecretVersion(legacy_version);
  358. securityParameters.m_clientServerNames = TlsExtensionsUtilities.GetServerNameExtensionClient(
  359. state.clientExtensions);
  360. if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(client_version))
  361. {
  362. TlsUtilities.EstablishClientSigAlgs(securityParameters, state.clientExtensions);
  363. }
  364. securityParameters.m_clientSupportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(
  365. state.clientExtensions);
  366. state.clientAgreements = TlsUtilities.AddKeyShareToClientHello(state.clientContext, state.client,
  367. state.clientExtensions);
  368. if (TlsUtilities.IsExtendedMasterSecretOptionalDtls(context.ClientSupportedVersions)
  369. && state.client.ShouldUseExtendedMasterSecret())
  370. {
  371. TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.clientExtensions);
  372. }
  373. else if (!TlsUtilities.IsTlsV13(client_version)
  374. && state.client.RequiresExtendedMasterSecret())
  375. {
  376. throw new TlsFatalAlert(AlertDescription.internal_error);
  377. }
  378. {
  379. bool useGmtUnixTime = ProtocolVersion.DTLSv12.IsEqualOrLaterVersionOf(client_version)
  380. && state.client.ShouldUseGmtUnixTime();
  381. securityParameters.m_clientRandom = TlsProtocol.CreateRandomBlock(useGmtUnixTime, state.clientContext);
  382. }
  383. // Cipher Suites (and SCSV)
  384. {
  385. /*
  386. * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
  387. * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
  388. * ClientHello. Including both is NOT RECOMMENDED.
  389. */
  390. bool noRenegExt = (null == TlsUtilities.GetExtensionData(state.clientExtensions,
  391. ExtensionType.renegotiation_info));
  392. bool noRenegScsv = !Arrays.Contains(state.offeredCipherSuites,
  393. CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
  394. if (noRenegExt && noRenegScsv)
  395. {
  396. state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites,
  397. CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
  398. }
  399. }
  400. /* (Fallback SCSV)
  401. * RFC 7507 4. If a client sends a ClientHello.client_version containing a lower value
  402. * than the latest (highest-valued) version supported by the client, it SHOULD include
  403. * the TLS_FALLBACK_SCSV cipher suite value in ClientHello.cipher_suites [..]. (The
  404. * client SHOULD put TLS_FALLBACK_SCSV after all cipher suites that it actually intends
  405. * to negotiate.)
  406. */
  407. if (fallback && !Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV))
  408. {
  409. state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV);
  410. }
  411. // Heartbeats
  412. {
  413. state.heartbeat = state.client.GetHeartbeat();
  414. state.heartbeatPolicy = state.client.GetHeartbeatPolicy();
  415. if (null != state.heartbeat || HeartbeatMode.peer_allowed_to_send == state.heartbeatPolicy)
  416. {
  417. TlsExtensionsUtilities.AddHeartbeatExtension(state.clientExtensions,
  418. new HeartbeatExtension(state.heartbeatPolicy));
  419. }
  420. }
  421. ClientHello clientHello = new ClientHello(legacy_version, securityParameters.ClientRandom, session_id,
  422. TlsUtilities.EmptyBytes, state.offeredCipherSuites, state.clientExtensions, 0);
  423. MemoryStream buf = new MemoryStream();
  424. clientHello.Encode(state.clientContext, buf);
  425. return buf.ToArray();
  426. }
  427. /// <exception cref="IOException"/>
  428. protected virtual byte[] GenerateClientKeyExchange(ClientHandshakeState state)
  429. {
  430. MemoryStream buf = new MemoryStream();
  431. state.keyExchange.GenerateClientKeyExchange(buf);
  432. return buf.ToArray();
  433. }
  434. protected virtual void InvalidateSession(ClientHandshakeState state)
  435. {
  436. if (state.sessionMasterSecret != null)
  437. {
  438. state.sessionMasterSecret.Destroy();
  439. state.sessionMasterSecret = null;
  440. }
  441. if (state.sessionParameters != null)
  442. {
  443. state.sessionParameters.Clear();
  444. state.sessionParameters = null;
  445. }
  446. if (state.tlsSession != null)
  447. {
  448. state.tlsSession.Invalidate();
  449. state.tlsSession = null;
  450. }
  451. }
  452. /// <exception cref="IOException"/>
  453. protected virtual void ProcessCertificateRequest(ClientHandshakeState state, byte[] body)
  454. {
  455. if (null == state.authentication)
  456. {
  457. /*
  458. * RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server to
  459. * request client identification.
  460. */
  461. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  462. }
  463. MemoryStream buf = new MemoryStream(body, false);
  464. CertificateRequest certificateRequest = CertificateRequest.Parse(state.clientContext, buf);
  465. TlsProtocol.AssertEmpty(buf);
  466. state.certificateRequest = TlsUtilities.ValidateCertificateRequest(certificateRequest, state.keyExchange);
  467. }
  468. /// <exception cref="IOException"/>
  469. protected virtual void ProcessCertificateStatus(ClientHandshakeState state, byte[] body)
  470. {
  471. MemoryStream buf = new MemoryStream(body, false);
  472. // TODO[tls13] Ensure this cannot happen for (D)TLS1.3+
  473. state.certificateStatus = CertificateStatus.Parse(state.clientContext, buf);
  474. TlsProtocol.AssertEmpty(buf);
  475. }
  476. /// <exception cref="IOException"/>
  477. protected virtual byte[] ProcessHelloVerifyRequest(ClientHandshakeState state, byte[] body)
  478. {
  479. MemoryStream buf = new MemoryStream(body, false);
  480. ProtocolVersion server_version = TlsUtilities.ReadVersion(buf);
  481. /*
  482. * RFC 6347 This specification increases the cookie size limit to 255 bytes for greater
  483. * future flexibility. The limit remains 32 for previous versions of DTLS.
  484. */
  485. int maxCookieLength = ProtocolVersion.DTLSv12.IsEqualOrEarlierVersionOf(server_version) ? 255 : 32;
  486. byte[] cookie = TlsUtilities.ReadOpaque8(buf, 0, maxCookieLength);
  487. TlsProtocol.AssertEmpty(buf);
  488. // TODO Seems this behaviour is not yet in line with OpenSSL for DTLS 1.2
  489. //ReportServerVersion(state, server_version);
  490. if (!server_version.IsEqualOrEarlierVersionOf(state.clientContext.ClientVersion))
  491. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  492. return cookie;
  493. }
  494. /// <exception cref="IOException"/>
  495. protected virtual void ProcessNewSessionTicket(ClientHandshakeState state, byte[] body)
  496. {
  497. MemoryStream buf = new MemoryStream(body, false);
  498. NewSessionTicket newSessionTicket = NewSessionTicket.Parse(buf);
  499. TlsProtocol.AssertEmpty(buf);
  500. state.client.NotifyNewSessionTicket(newSessionTicket);
  501. }
  502. /// <exception cref="IOException"/>
  503. protected virtual void ProcessServerCertificate(ClientHandshakeState state, byte[] body)
  504. {
  505. state.authentication = TlsUtilities.ReceiveServerCertificate(state.clientContext, state.client,
  506. new MemoryStream(body, false));
  507. }
  508. /// <exception cref="IOException"/>
  509. protected virtual void ProcessServerHello(ClientHandshakeState state, byte[] body)
  510. {
  511. MemoryStream buf = new MemoryStream(body, false);
  512. ServerHello serverHello = ServerHello.Parse(buf);
  513. ProtocolVersion server_version = serverHello.Version;
  514. state.serverExtensions = serverHello.Extensions;
  515. SecurityParameters securityParameters = state.clientContext.SecurityParameters;
  516. // TODO[dtls13] Check supported_version extension for negotiated version
  517. ReportServerVersion(state, server_version);
  518. securityParameters.m_serverRandom = serverHello.Random;
  519. if (!state.clientContext.ClientVersion.Equals(server_version))
  520. {
  521. TlsUtilities.CheckDowngradeMarker(server_version, securityParameters.ServerRandom);
  522. }
  523. {
  524. byte[] selectedSessionID = serverHello.SessionID;
  525. securityParameters.m_sessionID = selectedSessionID;
  526. state.client.NotifySessionID(selectedSessionID);
  527. state.resumedSession = selectedSessionID.Length > 0 && state.tlsSession != null
  528. && Arrays.AreEqual(selectedSessionID, state.tlsSession.SessionID);
  529. }
  530. /*
  531. * Find out which CipherSuite the server has chosen and check that it was one of the offered
  532. * ones, and is a valid selection for the negotiated version.
  533. */
  534. {
  535. int cipherSuite = ValidateSelectedCipherSuite(serverHello.CipherSuite,
  536. AlertDescription.illegal_parameter);
  537. if (!TlsUtilities.IsValidCipherSuiteSelection(state.offeredCipherSuites, cipherSuite) ||
  538. !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, securityParameters.NegotiatedVersion))
  539. {
  540. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  541. }
  542. TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite);
  543. state.client.NotifySelectedCipherSuite(cipherSuite);
  544. }
  545. /*
  546. * RFC3546 2.2 The extended server hello message format MAY be sent in place of the server
  547. * hello message when the client has requested extended functionality via the extended
  548. * client hello message specified in Section 2.1. ... Note that the extended server hello
  549. * message is only sent in response to an extended client hello message. This prevents the
  550. * possibility that the extended server hello message could "break" existing TLS 1.0
  551. * clients.
  552. */
  553. /*
  554. * TODO RFC 3546 2.3 If [...] the older session is resumed, then the server MUST ignore
  555. * extensions appearing in the client hello, and send a server hello containing no
  556. * extensions.
  557. */
  558. /*
  559. * RFC 7627 4. Clients and servers SHOULD NOT accept handshakes that do not use the extended
  560. * master secret [..]. (and see 5.2, 5.3)
  561. *
  562. * RFC 8446 Appendix D. Because TLS 1.3 always hashes in the transcript up to the server
  563. * Finished, implementations which support both TLS 1.3 and earlier versions SHOULD indicate
  564. * the use of the Extended Master Secret extension in their APIs whenever TLS 1.3 is used.
  565. */
  566. if (TlsUtilities.IsTlsV13(server_version))
  567. {
  568. securityParameters.m_extendedMasterSecret = true;
  569. }
  570. else
  571. {
  572. bool acceptedExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(
  573. state.serverExtensions);
  574. if (acceptedExtendedMasterSecret)
  575. {
  576. if (!state.resumedSession && !state.client.ShouldUseExtendedMasterSecret())
  577. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  578. }
  579. else
  580. {
  581. if (state.client.RequiresExtendedMasterSecret()
  582. || (state.resumedSession && !state.client.AllowLegacyResumption()))
  583. {
  584. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  585. }
  586. }
  587. securityParameters.m_extendedMasterSecret = acceptedExtendedMasterSecret;
  588. }
  589. /*
  590. *
  591. * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an
  592. * extended client hello message. However, see RFC 5746 exception below. We always include
  593. * the SCSV, so an Extended Server Hello is always allowed.
  594. */
  595. if (state.serverExtensions != null)
  596. {
  597. foreach (int extType in state.serverExtensions.Keys)
  598. {
  599. /*
  600. * RFC 5746 3.6. Note that sending a "renegotiation_info" extension in response to a
  601. * ClientHello containing only the SCSV is an explicit exception to the prohibition
  602. * in RFC 5246, Section 7.4.1.4, on the server sending unsolicited extensions and is
  603. * only allowed because the client is signaling its willingness to receive the
  604. * extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
  605. */
  606. if (extType == ExtensionType.renegotiation_info)
  607. continue;
  608. /*
  609. * RFC 5246 7.4.1.4 An extension type MUST NOT appear in the ServerHello unless the
  610. * same extension type appeared in the corresponding ClientHello. If a client
  611. * receives an extension type in ServerHello that it did not request in the
  612. * associated ClientHello, it MUST abort the handshake with an unsupported_extension
  613. * fatal alert.
  614. */
  615. if (null == TlsUtilities.GetExtensionData(state.clientExtensions, extType))
  616. throw new TlsFatalAlert(AlertDescription.unsupported_extension);
  617. /*
  618. * RFC 3546 2.3. If [...] the older session is resumed, then the server MUST ignore
  619. * extensions appearing in the client hello, and send a server hello containing no
  620. * extensions[.]
  621. */
  622. if (state.resumedSession)
  623. {
  624. // TODO[compat-gnutls] GnuTLS test server sends server extensions e.g. ec_point_formats
  625. // TODO[compat-openssl] OpenSSL test server sends server extensions e.g. ec_point_formats
  626. // TODO[compat-polarssl] PolarSSL test server sends server extensions e.g. ec_point_formats
  627. //throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  628. }
  629. }
  630. }
  631. /*
  632. * RFC 5746 3.4. Client Behavior: Initial Handshake
  633. */
  634. {
  635. /*
  636. * When a ServerHello is received, the client MUST check if it includes the
  637. * "renegotiation_info" extension:
  638. */
  639. byte[] renegExtData = TlsUtilities.GetExtensionData(state.serverExtensions,
  640. ExtensionType.renegotiation_info);
  641. if (renegExtData != null)
  642. {
  643. /*
  644. * If the extension is present, set the secure_renegotiation flag to TRUE. The
  645. * client MUST then verify that the length of the "renegotiated_connection"
  646. * field is zero, and if it is not, MUST abort the handshake (by sending a fatal
  647. * handshake_failure alert).
  648. */
  649. securityParameters.m_secureRenegotiation = true;
  650. if (!Arrays.ConstantTimeAreEqual(renegExtData,
  651. TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
  652. {
  653. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  654. }
  655. }
  656. }
  657. // TODO[compat-gnutls] GnuTLS test server fails to send renegotiation_info extension when resuming
  658. state.client.NotifySecureRenegotiation(securityParameters.IsSecureRenegotiation);
  659. /*
  660. * RFC 7301 3.1. When session resumption or session tickets [...] are used, the previous
  661. * contents of this extension are irrelevant, and only the values in the new handshake
  662. * messages are considered.
  663. */
  664. securityParameters.m_applicationProtocol = TlsExtensionsUtilities.GetAlpnExtensionServer(
  665. state.serverExtensions);
  666. securityParameters.m_applicationProtocolSet = true;
  667. // Heartbeats
  668. {
  669. HeartbeatExtension heartbeatExtension = TlsExtensionsUtilities.GetHeartbeatExtension(
  670. state.serverExtensions);
  671. if (null == heartbeatExtension)
  672. {
  673. state.heartbeat = null;
  674. state.heartbeatPolicy = HeartbeatMode.peer_not_allowed_to_send;
  675. }
  676. else if (HeartbeatMode.peer_allowed_to_send != heartbeatExtension.Mode)
  677. {
  678. state.heartbeat = null;
  679. }
  680. }
  681. IDictionary sessionClientExtensions = state.clientExtensions,
  682. sessionServerExtensions = state.serverExtensions;
  683. if (state.resumedSession)
  684. {
  685. if (securityParameters.CipherSuite != state.sessionParameters.CipherSuite
  686. || !server_version.Equals(state.sessionParameters.NegotiatedVersion))
  687. {
  688. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  689. }
  690. sessionClientExtensions = null;
  691. sessionServerExtensions = state.sessionParameters.ReadServerExtensions();
  692. }
  693. if (sessionServerExtensions != null && sessionServerExtensions.Count > 0)
  694. {
  695. {
  696. /*
  697. * RFC 7366 3. If a server receives an encrypt-then-MAC request extension from a client
  698. * and then selects a stream or Authenticated Encryption with Associated Data (AEAD)
  699. * ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the
  700. * client.
  701. */
  702. bool serverSentEncryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(
  703. sessionServerExtensions);
  704. if (serverSentEncryptThenMac && !TlsUtilities.IsBlockCipherSuite(securityParameters.CipherSuite))
  705. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  706. securityParameters.m_encryptThenMac = serverSentEncryptThenMac;
  707. }
  708. securityParameters.m_maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.resumedSession,
  709. sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter);
  710. securityParameters.m_truncatedHmac = TlsExtensionsUtilities.HasTruncatedHmacExtension(
  711. sessionServerExtensions);
  712. if (!state.resumedSession)
  713. {
  714. // TODO[tls13] See RFC 8446 4.4.2.1
  715. if (TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions,
  716. ExtensionType.status_request_v2, AlertDescription.illegal_parameter))
  717. {
  718. securityParameters.m_statusRequestVersion = 2;
  719. }
  720. else if (TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions,
  721. ExtensionType.status_request, AlertDescription.illegal_parameter))
  722. {
  723. securityParameters.m_statusRequestVersion = 1;
  724. }
  725. }
  726. state.expectSessionTicket = !state.resumedSession
  727. && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions,
  728. ExtensionType.session_ticket, AlertDescription.illegal_parameter);
  729. }
  730. if (sessionClientExtensions != null)
  731. {
  732. state.client.ProcessServerExtensions(sessionServerExtensions);
  733. }
  734. }
  735. /// <exception cref="IOException"/>
  736. protected virtual void ProcessServerKeyExchange(ClientHandshakeState state, byte[] body)
  737. {
  738. MemoryStream buf = new MemoryStream(body, false);
  739. state.keyExchange.ProcessServerKeyExchange(buf);
  740. TlsProtocol.AssertEmpty(buf);
  741. }
  742. /// <exception cref="IOException"/>
  743. protected virtual void ProcessServerSupplementalData(ClientHandshakeState state, byte[] body)
  744. {
  745. MemoryStream buf = new MemoryStream(body, false);
  746. IList serverSupplementalData = TlsProtocol.ReadSupplementalDataMessage(buf);
  747. state.client.ProcessServerSupplementalData(serverSupplementalData);
  748. }
  749. /// <exception cref="IOException"/>
  750. protected virtual void ReportServerVersion(ClientHandshakeState state, ProtocolVersion server_version)
  751. {
  752. TlsClientContextImpl context = state.clientContext;
  753. SecurityParameters securityParameters = context.SecurityParameters;
  754. ProtocolVersion currentServerVersion = securityParameters.NegotiatedVersion;
  755. if (null != currentServerVersion)
  756. {
  757. if (!currentServerVersion.Equals(server_version))
  758. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  759. return;
  760. }
  761. if (!ProtocolVersion.Contains(context.ClientSupportedVersions, server_version))
  762. throw new TlsFatalAlert(AlertDescription.protocol_version);
  763. securityParameters.m_negotiatedVersion = server_version;
  764. TlsUtilities.NegotiatedVersionDtlsClient(state.clientContext, state.client);
  765. }
  766. /// <exception cref="IOException"/>
  767. protected static byte[] PatchClientHelloWithCookie(byte[] clientHelloBody, byte[] cookie)
  768. {
  769. int sessionIDPos = 34;
  770. int sessionIDLength = TlsUtilities.ReadUint8(clientHelloBody, sessionIDPos);
  771. int cookieLengthPos = sessionIDPos + 1 + sessionIDLength;
  772. int cookiePos = cookieLengthPos + 1;
  773. byte[] patched = new byte[clientHelloBody.Length + cookie.Length];
  774. Array.Copy(clientHelloBody, 0, patched, 0, cookieLengthPos);
  775. TlsUtilities.CheckUint8(cookie.Length);
  776. TlsUtilities.WriteUint8(cookie.Length, patched, cookieLengthPos);
  777. Array.Copy(cookie, 0, patched, cookiePos, cookie.Length);
  778. Array.Copy(clientHelloBody, cookiePos, patched, cookiePos + cookie.Length,
  779. clientHelloBody.Length - cookiePos);
  780. return patched;
  781. }
  782. protected internal class ClientHandshakeState
  783. {
  784. internal TlsClient client = null;
  785. internal TlsClientContextImpl clientContext = null;
  786. internal TlsSession tlsSession = null;
  787. internal SessionParameters sessionParameters = null;
  788. internal TlsSecret sessionMasterSecret = null;
  789. internal SessionParameters.Builder sessionParametersBuilder = null;
  790. internal int[] offeredCipherSuites = null;
  791. internal IDictionary clientExtensions = null;
  792. internal IDictionary serverExtensions = null;
  793. internal bool resumedSession = false;
  794. internal bool expectSessionTicket = false;
  795. internal IDictionary clientAgreements = null;
  796. internal TlsKeyExchange keyExchange = null;
  797. internal TlsAuthentication authentication = null;
  798. internal CertificateStatus certificateStatus = null;
  799. internal CertificateRequest certificateRequest = null;
  800. internal TlsCredentials clientCredentials = null;
  801. internal TlsHeartbeat heartbeat = null;
  802. internal short heartbeatPolicy = HeartbeatMode.peer_not_allowed_to_send;
  803. }
  804. }
  805. }
  806. #pragma warning restore
  807. #endif