TlsProtocol.cs 83 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203
  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 BestHTTP.Connections.TLS;
  7. using BestHTTP.PlatformSupport.Threading;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  11. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
  12. {
  13. public abstract class TlsProtocol
  14. : TlsCloseable
  15. {
  16. /*
  17. * Connection States.
  18. *
  19. * NOTE: Redirection of handshake messages to TLS 1.3 handlers assumes CS_START, CS_CLIENT_HELLO
  20. * are lower than any of the other values.
  21. */
  22. protected const short CS_START = 0;
  23. protected const short CS_CLIENT_HELLO = 1;
  24. protected const short CS_SERVER_HELLO_RETRY_REQUEST = 2;
  25. protected const short CS_CLIENT_HELLO_RETRY = 3;
  26. protected const short CS_SERVER_HELLO = 4;
  27. protected const short CS_SERVER_ENCRYPTED_EXTENSIONS = 5;
  28. protected const short CS_SERVER_SUPPLEMENTAL_DATA = 6;
  29. protected const short CS_SERVER_CERTIFICATE = 7;
  30. protected const short CS_SERVER_CERTIFICATE_STATUS = 8;
  31. protected const short CS_SERVER_CERTIFICATE_VERIFY = 9;
  32. protected const short CS_SERVER_KEY_EXCHANGE = 10;
  33. protected const short CS_SERVER_CERTIFICATE_REQUEST = 11;
  34. protected const short CS_SERVER_HELLO_DONE = 12;
  35. protected const short CS_CLIENT_END_OF_EARLY_DATA = 13;
  36. protected const short CS_CLIENT_SUPPLEMENTAL_DATA = 14;
  37. protected const short CS_CLIENT_CERTIFICATE = 15;
  38. protected const short CS_CLIENT_KEY_EXCHANGE = 16;
  39. protected const short CS_CLIENT_CERTIFICATE_VERIFY = 17;
  40. protected const short CS_CLIENT_FINISHED = 18;
  41. protected const short CS_SERVER_SESSION_TICKET = 19;
  42. protected const short CS_SERVER_FINISHED = 20;
  43. protected const short CS_END = 21;
  44. protected bool IsLegacyConnectionState()
  45. {
  46. switch (m_connectionState)
  47. {
  48. case CS_START:
  49. case CS_CLIENT_HELLO:
  50. case CS_SERVER_HELLO:
  51. case CS_SERVER_SUPPLEMENTAL_DATA:
  52. case CS_SERVER_CERTIFICATE:
  53. case CS_SERVER_CERTIFICATE_STATUS:
  54. case CS_SERVER_KEY_EXCHANGE:
  55. case CS_SERVER_CERTIFICATE_REQUEST:
  56. case CS_SERVER_HELLO_DONE:
  57. case CS_CLIENT_SUPPLEMENTAL_DATA:
  58. case CS_CLIENT_CERTIFICATE:
  59. case CS_CLIENT_KEY_EXCHANGE:
  60. case CS_CLIENT_CERTIFICATE_VERIFY:
  61. case CS_CLIENT_FINISHED:
  62. case CS_SERVER_SESSION_TICKET:
  63. case CS_SERVER_FINISHED:
  64. case CS_END:
  65. return true;
  66. case CS_SERVER_HELLO_RETRY_REQUEST:
  67. case CS_CLIENT_HELLO_RETRY:
  68. case CS_SERVER_ENCRYPTED_EXTENSIONS:
  69. case CS_SERVER_CERTIFICATE_VERIFY:
  70. case CS_CLIENT_END_OF_EARLY_DATA:
  71. default:
  72. return false;
  73. }
  74. }
  75. protected bool IsTlsV13ConnectionState()
  76. {
  77. switch (m_connectionState)
  78. {
  79. case CS_START:
  80. case CS_CLIENT_HELLO:
  81. case CS_SERVER_HELLO_RETRY_REQUEST:
  82. case CS_CLIENT_HELLO_RETRY:
  83. case CS_SERVER_HELLO:
  84. case CS_SERVER_ENCRYPTED_EXTENSIONS:
  85. case CS_SERVER_CERTIFICATE_REQUEST:
  86. case CS_SERVER_CERTIFICATE:
  87. case CS_SERVER_CERTIFICATE_VERIFY:
  88. case CS_SERVER_FINISHED:
  89. case CS_CLIENT_END_OF_EARLY_DATA:
  90. case CS_CLIENT_CERTIFICATE:
  91. case CS_CLIENT_CERTIFICATE_VERIFY:
  92. case CS_CLIENT_FINISHED:
  93. case CS_END:
  94. return true;
  95. case CS_SERVER_SUPPLEMENTAL_DATA:
  96. case CS_SERVER_CERTIFICATE_STATUS:
  97. case CS_SERVER_KEY_EXCHANGE:
  98. case CS_SERVER_HELLO_DONE:
  99. case CS_CLIENT_SUPPLEMENTAL_DATA:
  100. case CS_CLIENT_KEY_EXCHANGE:
  101. case CS_SERVER_SESSION_TICKET:
  102. default:
  103. return false;
  104. }
  105. }
  106. /*
  107. * Different modes to handle the known IV weakness
  108. */
  109. protected const short ADS_MODE_1_Nsub1 = 0; // 1/n-1 record splitting
  110. protected const short ADS_MODE_0_N = 1; // 0/n record splitting
  111. protected const short ADS_MODE_0_N_FIRSTONLY = 2; // 0/n record splitting on first data fragment only
  112. /*
  113. * Queues for data from some protocols.
  114. */
  115. private readonly ByteQueue m_applicationDataQueue = new ByteQueue(0);
  116. private readonly ByteQueue m_alertQueue = new ByteQueue(2);
  117. private readonly ByteQueue m_handshakeQueue = new ByteQueue(0);
  118. //private readonly ByteQueue m_heartbeatQueue = new ByteQueue(0);
  119. internal readonly RecordStream m_recordStream;
  120. //internal readonly object m_recordWriteLock = new object();
  121. private int m_maxHandshakeMessageSize = -1;
  122. internal TlsHandshakeHash m_handshakeHash;
  123. private TlsStream m_tlsStream = null;
  124. private volatile bool m_closed = false;
  125. private volatile bool m_failedWithError = false;
  126. private volatile bool m_appDataReady = false;
  127. private volatile bool m_appDataSplitEnabled = true;
  128. private volatile bool m_keyUpdateEnabled = false;
  129. //private volatile bool m_keyUpdatePendingReceive = false;
  130. private volatile bool m_keyUpdatePendingSend = false;
  131. private volatile bool m_resumableHandshake = false;
  132. private volatile int m_appDataSplitMode = ADS_MODE_1_Nsub1;
  133. protected TlsSession m_tlsSession = null;
  134. protected SessionParameters m_sessionParameters = null;
  135. protected TlsSecret m_sessionMasterSecret = null;
  136. protected byte[] m_retryCookie = null;
  137. protected int m_retryGroup = -1;
  138. protected IDictionary<int, byte[]> m_clientExtensions = null;
  139. protected IDictionary<int, byte[]> m_serverExtensions = null;
  140. protected short m_connectionState = CS_START;
  141. protected bool m_selectedPsk13 = false;
  142. protected bool m_receivedChangeCipherSpec = false;
  143. protected bool m_expectSessionTicket = false;
  144. protected readonly bool m_blocking;
  145. protected readonly ByteQueueInputStream m_inputBuffers;
  146. protected readonly ByteQueueOutputStream m_outputBuffer;
  147. protected TlsProtocol()
  148. {
  149. this.m_blocking = false;
  150. this.m_inputBuffers = new ByteQueueInputStream();
  151. this.m_outputBuffer = new ByteQueueOutputStream();
  152. this.m_recordStream = new RecordStream(this, m_inputBuffers, m_outputBuffer);
  153. }
  154. public TlsProtocol(Stream stream)
  155. : this(stream, stream)
  156. {
  157. }
  158. public TlsProtocol(Stream input, Stream output)
  159. {
  160. this.m_blocking = true;
  161. this.m_inputBuffers = null;
  162. this.m_outputBuffer = null;
  163. this.m_recordStream = new RecordStream(this, input, output);
  164. }
  165. /// <exception cref="IOException"/>
  166. public virtual void ResumeHandshake()
  167. {
  168. if (!m_blocking)
  169. throw new InvalidOperationException("Cannot use ResumeHandshake() in non-blocking mode!");
  170. if (!IsHandshaking)
  171. throw new InvalidOperationException("No handshake in progress");
  172. BlockForHandshake();
  173. }
  174. /// <exception cref="IOException"/>
  175. protected virtual void CloseConnection()
  176. {
  177. m_recordStream.Close();
  178. }
  179. protected abstract TlsContext Context { get; }
  180. internal abstract AbstractTlsContext ContextAdmin { get; }
  181. protected abstract TlsPeer Peer { get; }
  182. /// <exception cref="IOException"/>
  183. protected virtual void HandleAlertMessage(short alertLevel, short alertDescription)
  184. {
  185. Peer.NotifyAlertReceived(alertLevel, alertDescription);
  186. if (alertLevel == AlertLevel.warning)
  187. {
  188. HandleAlertWarningMessage(alertDescription);
  189. }
  190. else
  191. {
  192. HandleFailure();
  193. throw new TlsFatalAlertReceived(alertDescription);
  194. }
  195. }
  196. /// <exception cref="IOException"/>
  197. protected virtual void HandleAlertWarningMessage(short alertDescription)
  198. {
  199. switch (alertDescription)
  200. {
  201. /*
  202. * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own
  203. * and close down the connection immediately, discarding any pending writes.
  204. */
  205. case AlertDescription.close_notify:
  206. {
  207. if (!m_appDataReady)
  208. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  209. HandleClose(false);
  210. break;
  211. }
  212. case AlertDescription.no_certificate:
  213. {
  214. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  215. }
  216. case AlertDescription.no_renegotiation:
  217. {
  218. // TODO[reneg] Give peer the option to tolerate this
  219. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  220. }
  221. }
  222. }
  223. /// <exception cref="IOException"/>
  224. protected virtual void HandleChangeCipherSpecMessage()
  225. {
  226. }
  227. /// <exception cref="IOException"/>
  228. protected virtual void HandleClose(bool user_canceled)
  229. {
  230. if (!m_closed)
  231. {
  232. this.m_closed = true;
  233. if (!m_appDataReady)
  234. {
  235. CleanupHandshake();
  236. if (user_canceled)
  237. {
  238. RaiseAlertWarning(AlertDescription.user_canceled, "User canceled handshake");
  239. }
  240. }
  241. RaiseAlertWarning(AlertDescription.close_notify, "Connection closed");
  242. CloseConnection();
  243. }
  244. }
  245. /// <exception cref="IOException"/>
  246. protected virtual void HandleException(short alertDescription, string message, Exception e)
  247. {
  248. // TODO[tls-port] Can we support interrupted IO on .NET?
  249. //if ((m_appDataReady || IsResumableHandshake()) && (e is InterruptedIOException))
  250. // return;
  251. if (!m_closed)
  252. {
  253. RaiseAlertFatal(alertDescription, message, e);
  254. HandleFailure();
  255. }
  256. }
  257. /// <exception cref="IOException"/>
  258. protected virtual void HandleFailure()
  259. {
  260. this.m_closed = true;
  261. this.m_failedWithError = true;
  262. /*
  263. * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
  264. * without proper close_notify messages with level equal to warning.
  265. */
  266. // TODO This isn't quite in the right place. Also, as of TLS 1.1 the above is obsolete.
  267. InvalidateSession();
  268. if (!m_appDataReady)
  269. {
  270. CleanupHandshake();
  271. }
  272. CloseConnection();
  273. }
  274. /// <exception cref="IOException"/>
  275. protected abstract void HandleHandshakeMessage(short type, HandshakeMessageInput buf);
  276. /// <exception cref="IOException"/>
  277. protected virtual void ApplyMaxFragmentLengthExtension(short maxFragmentLength)
  278. {
  279. if (maxFragmentLength >= 0)
  280. {
  281. if (!MaxFragmentLength.IsValid(maxFragmentLength))
  282. throw new TlsFatalAlert(AlertDescription.internal_error);
  283. int plainTextLimit = 1 << (8 + maxFragmentLength);
  284. m_recordStream.SetPlaintextLimit(plainTextLimit);
  285. }
  286. }
  287. /// <exception cref="IOException"/>
  288. protected virtual void CheckReceivedChangeCipherSpec(bool expected)
  289. {
  290. if (expected != m_receivedChangeCipherSpec)
  291. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  292. }
  293. /// <exception cref="IOException"/>
  294. protected virtual void BlockForHandshake()
  295. {
  296. while (m_connectionState != CS_END)
  297. {
  298. if (IsClosed)
  299. {
  300. // NOTE: Any close during the handshake should have raised an exception.
  301. throw new TlsFatalAlert(AlertDescription.internal_error);
  302. }
  303. using (new WriteLock(this.applicationDataLock))
  304. SafeReadRecord();
  305. }
  306. }
  307. protected virtual void handleRenegotiation()
  308. {
  309. // TODO: check whether renegotiation is enabled or not and call BeginHandshake/RefuseRenegotiation accordingly.
  310. BeginHandshake(true);
  311. }
  312. /// <exception cref="IOException"/>
  313. protected virtual void BeginHandshake(bool renegotiation)
  314. {
  315. AbstractTlsContext context = ContextAdmin;
  316. TlsPeer peer = Peer;
  317. this.m_maxHandshakeMessageSize = System.Math.Max(1024, peer.GetMaxHandshakeMessageSize());
  318. this.m_handshakeHash = new DeferredHash(context);
  319. this.m_connectionState = CS_START;
  320. this.m_selectedPsk13 = false;
  321. context.HandshakeBeginning(peer);
  322. SecurityParameters securityParameters = context.SecurityParameters;
  323. if (renegotiation != securityParameters.IsRenegotiating)
  324. {
  325. throw new TlsFatalAlert(AlertDescription.internal_error);
  326. }
  327. securityParameters.m_extendedPadding = peer.ShouldUseExtendedPadding();
  328. }
  329. protected virtual void CleanupHandshake()
  330. {
  331. TlsContext context = Context;
  332. if (null != context)
  333. {
  334. SecurityParameters securityParameters = context.SecurityParameters;
  335. if (null != securityParameters)
  336. {
  337. securityParameters.Clear();
  338. }
  339. }
  340. this.m_tlsSession = null;
  341. this.m_sessionParameters = null;
  342. this.m_sessionMasterSecret = null;
  343. this.m_retryCookie = null;
  344. this.m_retryGroup = -1;
  345. this.m_clientExtensions = null;
  346. this.m_serverExtensions = null;
  347. this.m_selectedPsk13 = false;
  348. this.m_receivedChangeCipherSpec = false;
  349. this.m_expectSessionTicket = false;
  350. }
  351. /// <exception cref="IOException"/>
  352. protected virtual void CompleteHandshake()
  353. {
  354. try
  355. {
  356. AbstractTlsContext context = ContextAdmin;
  357. SecurityParameters securityParameters = context.SecurityParameters;
  358. if ((!context.IsHandshaking && !securityParameters.IsRenegotiating) ||
  359. null == securityParameters.LocalVerifyData ||
  360. null == securityParameters.PeerVerifyData)
  361. {
  362. throw new TlsFatalAlert(AlertDescription.internal_error);
  363. }
  364. m_recordStream.FinaliseHandshake();
  365. this.m_connectionState = CS_END;
  366. // TODO Prefer to set to null, but would need guards elsewhere
  367. this.m_handshakeHash = new DeferredHash(context);
  368. m_alertQueue.Shrink();
  369. m_handshakeQueue.Shrink();
  370. ProtocolVersion negotiatedVersion = securityParameters.NegotiatedVersion;
  371. this.m_appDataSplitEnabled = !TlsUtilities.IsTlsV11(negotiatedVersion);
  372. this.m_appDataReady = true;
  373. this.m_keyUpdateEnabled = TlsUtilities.IsTlsV13(negotiatedVersion);
  374. if (m_blocking)
  375. {
  376. this.m_tlsStream = new TlsStream(this);
  377. }
  378. if (m_sessionParameters == null)
  379. {
  380. this.m_sessionMasterSecret = securityParameters.MasterSecret;
  381. this.m_sessionParameters = new SessionParameters.Builder()
  382. .SetCipherSuite(securityParameters.CipherSuite)
  383. .SetExtendedMasterSecret(securityParameters.IsExtendedMasterSecret)
  384. .SetLocalCertificate(securityParameters.LocalCertificate)
  385. .SetMasterSecret(context.Crypto.AdoptSecret(m_sessionMasterSecret))
  386. .SetNegotiatedVersion(securityParameters.NegotiatedVersion)
  387. .SetPeerCertificate(securityParameters.PeerCertificate)
  388. .SetPskIdentity(securityParameters.PskIdentity)
  389. .SetSrpIdentity(securityParameters.SrpIdentity)
  390. // TODO Consider filtering extensions that aren't relevant to resumed sessions
  391. .SetServerExtensions(m_serverExtensions)
  392. .Build();
  393. this.m_tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, m_sessionParameters);
  394. }
  395. else
  396. {
  397. securityParameters.m_localCertificate = m_sessionParameters.LocalCertificate;
  398. securityParameters.m_peerCertificate = m_sessionParameters.PeerCertificate;
  399. securityParameters.m_pskIdentity = m_sessionParameters.PskIdentity;
  400. securityParameters.m_srpIdentity = m_sessionParameters.SrpIdentity;
  401. }
  402. context.HandshakeComplete(Peer, m_tlsSession);
  403. }
  404. finally
  405. {
  406. CleanupHandshake();
  407. }
  408. }
  409. /// <exception cref="IOException"/>
  410. internal void ProcessRecord(short protocol, byte[] buf, int off, int len)
  411. {
  412. /*
  413. * Have a look at the protocol type, and add it to the correct queue.
  414. */
  415. switch (protocol)
  416. {
  417. case ContentType.alert:
  418. {
  419. m_alertQueue.AddData(buf, off, len);
  420. ProcessAlertQueue();
  421. break;
  422. }
  423. case ContentType.application_data:
  424. {
  425. if (!m_appDataReady)
  426. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  427. m_applicationDataQueue.AddData(buf, off, len);
  428. ProcessApplicationDataQueue();
  429. break;
  430. }
  431. case ContentType.change_cipher_spec:
  432. {
  433. ProcessChangeCipherSpec(buf, off, len);
  434. break;
  435. }
  436. case ContentType.handshake:
  437. {
  438. if (m_handshakeQueue.Available > 0)
  439. {
  440. m_handshakeQueue.AddData(buf, off, len);
  441. ProcessHandshakeQueue(m_handshakeQueue);
  442. }
  443. else
  444. {
  445. ByteQueue tmpQueue = new ByteQueue(buf, off, len);
  446. ProcessHandshakeQueue(tmpQueue);
  447. int remaining = tmpQueue.Available;
  448. if (remaining > 0)
  449. {
  450. m_handshakeQueue.AddData(buf, off + len - remaining, remaining);
  451. }
  452. }
  453. break;
  454. }
  455. //case ContentType.heartbeat:
  456. //{
  457. // if (!m_appDataReady)
  458. // throw new TlsFatalAlert(AlertDescription.unexpected_message);
  459. // // TODO[RFC 6520]
  460. // m_heartbeatQueue.addData(buf, off, len);
  461. // ProcessHeartbeatQueue();
  462. // break;
  463. //}
  464. default:
  465. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  466. }
  467. }
  468. /// <exception cref="IOException"/>
  469. private void ProcessHandshakeQueue(ByteQueue queue)
  470. {
  471. /*
  472. * We need the first 4 bytes, they contain type and length of the message.
  473. */
  474. while (queue.Available >= 4)
  475. {
  476. int header = queue.ReadInt32();
  477. short type = (short)((uint)header >> 24);
  478. if (!HandshakeType.IsRecognized(type))
  479. {
  480. throw new TlsFatalAlert(AlertDescription.unexpected_message,
  481. "Handshake message of unrecognized type: " + type);
  482. }
  483. int length = header & 0x00FFFFFF;
  484. if (length > m_maxHandshakeMessageSize)
  485. {
  486. throw new TlsFatalAlert(AlertDescription.internal_error,
  487. "Handshake message length exceeds the maximum: " + HandshakeType.GetText(type) + ", " + length
  488. + " > " + m_maxHandshakeMessageSize);
  489. }
  490. int totalLength = 4 + length;
  491. if (queue.Available < totalLength)
  492. {
  493. // Not enough bytes in the buffer to read the full message.
  494. break;
  495. }
  496. /*
  497. * Check ChangeCipherSpec status
  498. */
  499. switch (type)
  500. {
  501. case HandshakeType.hello_request:
  502. break;
  503. default:
  504. {
  505. ProtocolVersion negotiatedVersion = Context.ServerVersion;
  506. if (null != negotiatedVersion && TlsUtilities.IsTlsV13(negotiatedVersion))
  507. break;
  508. CheckReceivedChangeCipherSpec(HandshakeType.finished == type);
  509. break;
  510. }
  511. }
  512. HandshakeMessageInput buf = queue.ReadHandshakeMessage(totalLength);
  513. switch (type)
  514. {
  515. /*
  516. * These message types aren't included in the transcript.
  517. */
  518. case HandshakeType.hello_request:
  519. case HandshakeType.key_update:
  520. break;
  521. /*
  522. * Not included in the transcript for (D)TLS 1.3+
  523. */
  524. case HandshakeType.new_session_ticket:
  525. {
  526. ProtocolVersion negotiatedVersion = Context.ServerVersion;
  527. if (null != negotiatedVersion && !TlsUtilities.IsTlsV13(negotiatedVersion))
  528. {
  529. buf.UpdateHash(m_handshakeHash);
  530. }
  531. break;
  532. }
  533. /*
  534. * These message types are deferred to the handler to explicitly update the transcript.
  535. */
  536. case HandshakeType.certificate_verify:
  537. case HandshakeType.client_hello:
  538. case HandshakeType.finished:
  539. case HandshakeType.server_hello:
  540. break;
  541. /*
  542. * For all others we automatically update the transcript immediately.
  543. */
  544. default:
  545. {
  546. buf.UpdateHash(m_handshakeHash);
  547. break;
  548. }
  549. }
  550. buf.Seek(4L, SeekOrigin.Current);
  551. HandleHandshakeMessage(type, buf);
  552. }
  553. }
  554. private void ProcessApplicationDataQueue()
  555. {
  556. /*
  557. * There is nothing we need to do here.
  558. *
  559. * This function could be used for callbacks when application data arrives in the future.
  560. */
  561. }
  562. /// <exception cref="IOException"/>
  563. private void ProcessAlertQueue()
  564. {
  565. while (m_alertQueue.Available >= 2)
  566. {
  567. /*
  568. * An alert is always 2 bytes. Read the alert.
  569. */
  570. byte[] alert = m_alertQueue.RemoveData(2, 0);
  571. short alertLevel = alert[0];
  572. short alertDescription = alert[1];
  573. HandleAlertMessage(alertLevel, alertDescription);
  574. }
  575. }
  576. /// <summary>This method is called, when a change cipher spec message is received.</summary>
  577. /// <exception cref="IOException">If the message has an invalid content or the handshake is not in the correct
  578. /// state.</exception>
  579. private void ProcessChangeCipherSpec(byte[] buf, int off, int len)
  580. {
  581. ProtocolVersion negotiatedVersion = Context.ServerVersion;
  582. if (null == negotiatedVersion || TlsUtilities.IsTlsV13(negotiatedVersion))
  583. {
  584. // See RFC 8446 D.4.
  585. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  586. }
  587. for (int i = 0; i < len; ++i)
  588. {
  589. short message = TlsUtilities.ReadUint8(buf, off + i);
  590. if (message != ChangeCipherSpec.change_cipher_spec)
  591. throw new TlsFatalAlert(AlertDescription.decode_error);
  592. if (this.m_receivedChangeCipherSpec
  593. || m_alertQueue.Available > 0
  594. || m_handshakeQueue.Available > 0)
  595. {
  596. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  597. }
  598. m_recordStream.NotifyChangeCipherSpecReceived();
  599. this.m_receivedChangeCipherSpec = true;
  600. HandleChangeCipherSpecMessage();
  601. }
  602. }
  603. public virtual int ApplicationDataAvailable
  604. {
  605. get { return m_applicationDataQueue.Available; }
  606. }
  607. /// <summary>Read data from the network.</summary>
  608. /// <remarks>
  609. /// The method will return immediately, if there is still some data left in the buffer, or block until some
  610. /// application data has been read from the network.
  611. /// </remarks>
  612. /// <param name="buffer">The buffer where the data will be copied to.</param>
  613. /// <param name="offset">The position where the data will be placed in the buffer.</param>
  614. /// <param name="count">The maximum number of bytes to read.</param>
  615. /// <returns>The number of bytes read.</returns>
  616. /// <exception cref="IOException">If something goes wrong during reading data.</exception>
  617. public virtual int ReadApplicationData(byte[] buffer, int offset, int count)
  618. {
  619. Streams.ValidateBufferArguments(buffer, offset, count);
  620. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
  621. return ReadApplicationData(buffer.AsSpan(offset, count));
  622. #else
  623. if (!m_appDataReady)
  624. throw new InvalidOperationException("Cannot read application data until initial handshake completed.");
  625. using (new WriteLock(this.applicationDataLock))
  626. {
  627. while (m_applicationDataQueue.Available < 1)
  628. {
  629. if (this.m_closed)
  630. {
  631. if (this.m_failedWithError)
  632. throw new IOException("Cannot read application data on failed TLS connection");
  633. return 0;
  634. }
  635. /*
  636. * NOTE: Only called more than once when empty records are received, so no special
  637. * InterruptedIOException handling is necessary.
  638. */
  639. SafeReadRecord();
  640. }
  641. if (count > 0)
  642. {
  643. count = System.Math.Min(count, m_applicationDataQueue.Available);
  644. m_applicationDataQueue.RemoveData(buffer, offset, count, 0);
  645. }
  646. return count;
  647. }
  648. #endif
  649. }
  650. System.Threading.ReaderWriterLockSlim applicationDataLock = new System.Threading.ReaderWriterLockSlim();
  651. public bool TryEnterApplicationDataLock(int millisecondsTimeout)
  652. {
  653. return this.applicationDataLock.TryEnterWriteLock(millisecondsTimeout);
  654. }
  655. public void ExitApplicationDataLock()
  656. {
  657. this.applicationDataLock.ExitWriteLock();
  658. }
  659. public int TestApplicationData()
  660. {
  661. using (new WriteLock(this.applicationDataLock))
  662. {
  663. while (m_applicationDataQueue.Available == 0)
  664. {
  665. if (this.m_closed)
  666. {
  667. if (this.m_failedWithError)
  668. throw new IOException("Cannot read application data on failed TLS connection");
  669. return -1;
  670. }
  671. if (!m_appDataReady)
  672. throw new InvalidOperationException("Cannot read application data until initial handshake completed.");
  673. /*
  674. * NOTE: Only called more than once when empty records are received, so no special
  675. * InterruptedIOException handling is necessary.
  676. */
  677. SafeReadRecord();
  678. }
  679. return m_applicationDataQueue.Available;
  680. }
  681. }
  682. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
  683. public virtual int ReadApplicationData(Span<byte> buffer)
  684. {
  685. if (!m_appDataReady)
  686. throw new InvalidOperationException("Cannot read application data until initial handshake completed.");
  687. while (m_applicationDataQueue.Available < 1)
  688. {
  689. if (this.m_closed)
  690. {
  691. if (this.m_failedWithError)
  692. throw new IOException("Cannot read application data on failed TLS connection");
  693. return 0;
  694. }
  695. /*
  696. * NOTE: Only called more than once when empty records are received, so no special
  697. * InterruptedIOException handling is necessary.
  698. */
  699. SafeReadRecord();
  700. }
  701. int count = buffer.Length;
  702. if (count > 0)
  703. {
  704. count = System.Math.Min(count, m_applicationDataQueue.Available);
  705. m_applicationDataQueue.RemoveData(buffer[..count], 0);
  706. }
  707. return count;
  708. }
  709. #endif
  710. /// <exception cref="IOException"/>
  711. protected virtual RecordPreview SafePreviewRecordHeader(byte[] recordHeader)
  712. {
  713. try
  714. {
  715. return m_recordStream.PreviewRecordHeader(recordHeader);
  716. }
  717. catch (TlsFatalAlert e)
  718. {
  719. HandleException(e.AlertDescription, "Failed to read record", e);
  720. throw e;
  721. }
  722. catch (IOException e)
  723. {
  724. HandleException(AlertDescription.internal_error, "Failed to read record", e);
  725. throw e;
  726. }
  727. catch (Exception e)
  728. {
  729. HandleException(AlertDescription.internal_error, "Failed to read record", e);
  730. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  731. }
  732. }
  733. /// <exception cref="IOException"/>
  734. protected virtual void SafeReadRecord()
  735. {
  736. try
  737. {
  738. if (m_recordStream.ReadRecord())
  739. return;
  740. if (!m_appDataReady)
  741. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  742. if (!Peer.RequiresCloseNotify())
  743. {
  744. HandleClose(false);
  745. return;
  746. }
  747. }
  748. catch (TlsFatalAlertReceived e)
  749. {
  750. // Connection failure already handled at source
  751. throw;
  752. }
  753. catch (TlsFatalAlert e)
  754. {
  755. HandleException(e.AlertDescription, "Failed to read record", e);
  756. throw;
  757. }
  758. catch (IOException e)
  759. {
  760. HandleException(AlertDescription.internal_error, "Failed to read record", e);
  761. throw;
  762. }
  763. catch (Exception e)
  764. {
  765. HandleException(AlertDescription.internal_error, "Failed to read record", e);
  766. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  767. }
  768. HandleFailure();
  769. throw new TlsNoCloseNotifyException();
  770. }
  771. /// <exception cref="IOException"/>
  772. protected virtual bool SafeReadFullRecord(byte[] input, int inputOff, int inputLen)
  773. {
  774. try
  775. {
  776. return m_recordStream.ReadFullRecord(input, inputOff, inputLen);
  777. }
  778. catch (TlsFatalAlert e)
  779. {
  780. HandleException(e.AlertDescription, "Failed to process record", e);
  781. throw e;
  782. }
  783. catch (IOException e)
  784. {
  785. HandleException(AlertDescription.internal_error, "Failed to process record", e);
  786. throw e;
  787. }
  788. catch (Exception e)
  789. {
  790. HandleException(AlertDescription.internal_error, "Failed to process record", e);
  791. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  792. }
  793. }
  794. /// <exception cref="IOException"/>
  795. protected virtual void SafeWriteRecord(short type, byte[] buf, int offset, int len)
  796. {
  797. try
  798. {
  799. m_recordStream.WriteRecord(type, buf, offset, len);
  800. }
  801. catch (TlsFatalAlert e)
  802. {
  803. HandleException(e.AlertDescription, "Failed to write record", e);
  804. throw e;
  805. }
  806. catch (IOException e)
  807. {
  808. HandleException(AlertDescription.internal_error, "Failed to write record", e);
  809. throw e;
  810. }
  811. catch (Exception e)
  812. {
  813. HandleException(AlertDescription.internal_error, "Failed to write record", e);
  814. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  815. }
  816. }
  817. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
  818. /// <exception cref="IOException"/>
  819. protected virtual void SafeWriteRecord(short type, ReadOnlySpan<byte> buffer)
  820. {
  821. try
  822. {
  823. m_recordStream.WriteRecord(type, buffer);
  824. }
  825. catch (TlsFatalAlert e)
  826. {
  827. HandleException(e.AlertDescription, "Failed to write record", e);
  828. throw e;
  829. }
  830. catch (IOException e)
  831. {
  832. HandleException(AlertDescription.internal_error, "Failed to write record", e);
  833. throw e;
  834. }
  835. catch (Exception e)
  836. {
  837. HandleException(AlertDescription.internal_error, "Failed to write record", e);
  838. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  839. }
  840. }
  841. #endif
  842. /// <summary>Write some application data.</summary>
  843. /// <remarks>
  844. /// Fragmentation is handled internally. Usable in both blocking/non-blocking modes.<br/><br/>
  845. /// In blocking mode, the output will be automatically sent via the underlying transport. In non-blocking mode,
  846. /// call <see cref="ReadOutput(byte[], int, int)"/> to get the output bytes to send to the peer.<br/><br/>
  847. /// This method must not be called until after the initial handshake is complete. Attempting to call it earlier
  848. /// will result in an <see cref="InvalidOperationException"/>.
  849. /// </remarks>
  850. /// <param name="buffer">The buffer containing application data to send.</param>
  851. /// <param name="offset">The offset at which the application data begins</param>
  852. /// <param name="count">The number of bytes of application data.</param>
  853. /// <exception cref="InvalidOperationException">If called before the initial handshake has completed.
  854. /// </exception>
  855. /// <exception cref="IOException">If connection is already closed, or for encryption or transport errors.
  856. /// </exception>
  857. public virtual void WriteApplicationData(byte[] buffer, int offset, int count)
  858. {
  859. Streams.ValidateBufferArguments(buffer, offset, count);
  860. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
  861. WriteApplicationData(buffer.AsSpan(offset, count));
  862. #else
  863. if (!m_appDataReady)
  864. throw new InvalidOperationException(
  865. "Cannot write application data until initial handshake completed.");
  866. //lock (m_recordWriteLock)
  867. {
  868. while (count > 0)
  869. {
  870. if (m_closed)
  871. throw new IOException("Cannot write application data on closed/failed TLS connection");
  872. /*
  873. * RFC 5246 6.2.1. Zero-length fragments of Application data MAY be sent as they are
  874. * potentially useful as a traffic analysis countermeasure.
  875. *
  876. * NOTE: Actually, implementations appear to have settled on 1/n-1 record splitting.
  877. */
  878. if (m_appDataSplitEnabled)
  879. {
  880. /*
  881. * Protect against known IV attack!
  882. *
  883. * DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
  884. */
  885. switch (m_appDataSplitMode)
  886. {
  887. case ADS_MODE_0_N_FIRSTONLY:
  888. {
  889. this.m_appDataSplitEnabled = false;
  890. SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
  891. break;
  892. }
  893. case ADS_MODE_0_N:
  894. {
  895. SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
  896. break;
  897. }
  898. case ADS_MODE_1_Nsub1:
  899. default:
  900. {
  901. if (count > 1)
  902. {
  903. SafeWriteRecord(ContentType.application_data, buffer, offset, 1);
  904. ++offset;
  905. --count;
  906. }
  907. break;
  908. }
  909. }
  910. }
  911. else if (m_keyUpdateEnabled)
  912. {
  913. if (m_keyUpdatePendingSend)
  914. {
  915. Send13KeyUpdate(false);
  916. }
  917. else if (m_recordStream.NeedsKeyUpdate())
  918. {
  919. Send13KeyUpdate(true);
  920. }
  921. }
  922. // Fragment data according to the current fragment limit.
  923. int toWrite = System.Math.Min(count, m_recordStream.PlaintextLimit);
  924. SafeWriteRecord(ContentType.application_data, buffer, offset, toWrite);
  925. offset += toWrite;
  926. count -= toWrite;
  927. }
  928. }
  929. #endif
  930. }
  931. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
  932. public virtual void WriteApplicationData(ReadOnlySpan<byte> buffer)
  933. {
  934. if (!m_appDataReady)
  935. throw new InvalidOperationException(
  936. "Cannot write application data until initial handshake completed.");
  937. //lock (m_recordWriteLock)
  938. {
  939. while (!buffer.IsEmpty)
  940. {
  941. if (m_closed)
  942. throw new IOException("Cannot write application data on closed/failed TLS connection");
  943. /*
  944. * RFC 5246 6.2.1. Zero-length fragments of Application data MAY be sent as they are
  945. * potentially useful as a traffic analysis countermeasure.
  946. *
  947. * NOTE: Actually, implementations appear to have settled on 1/n-1 record splitting.
  948. */
  949. if (m_appDataSplitEnabled)
  950. {
  951. /*
  952. * Protect against known IV attack!
  953. *
  954. * DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
  955. */
  956. switch (m_appDataSplitMode)
  957. {
  958. case ADS_MODE_0_N_FIRSTONLY:
  959. {
  960. this.m_appDataSplitEnabled = false;
  961. SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
  962. break;
  963. }
  964. case ADS_MODE_0_N:
  965. {
  966. SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
  967. break;
  968. }
  969. case ADS_MODE_1_Nsub1:
  970. default:
  971. {
  972. if (buffer.Length > 1)
  973. {
  974. SafeWriteRecord(ContentType.application_data, buffer[..1]);
  975. buffer = buffer[1..];
  976. }
  977. break;
  978. }
  979. }
  980. }
  981. else if (m_keyUpdateEnabled)
  982. {
  983. if (m_keyUpdatePendingSend)
  984. {
  985. Send13KeyUpdate(false);
  986. }
  987. else if (m_recordStream.NeedsKeyUpdate())
  988. {
  989. Send13KeyUpdate(true);
  990. }
  991. }
  992. // Fragment data according to the current fragment limit.
  993. int toWrite = System.Math.Min(buffer.Length, m_recordStream.PlaintextLimit);
  994. SafeWriteRecord(ContentType.application_data, buffer[..toWrite]);
  995. buffer = buffer[toWrite..];
  996. }
  997. }
  998. }
  999. #endif
  1000. public virtual int AppDataSplitMode
  1001. {
  1002. get { return m_appDataSplitMode; }
  1003. set
  1004. {
  1005. if (value < ADS_MODE_1_Nsub1 || value > ADS_MODE_0_N_FIRSTONLY)
  1006. throw new InvalidOperationException("Illegal appDataSplitMode mode: " + value);
  1007. this.m_appDataSplitMode = value;
  1008. }
  1009. }
  1010. public virtual bool IsResumableHandshake
  1011. {
  1012. get { return m_resumableHandshake; }
  1013. set { this.m_resumableHandshake = value; }
  1014. }
  1015. /// <exception cref="IOException"/>
  1016. internal void WriteHandshakeMessage(byte[] buf, int off, int len)
  1017. {
  1018. if (len < 4)
  1019. throw new TlsFatalAlert(AlertDescription.internal_error);
  1020. short type = TlsUtilities.ReadUint8(buf, off);
  1021. switch (type)
  1022. {
  1023. /*
  1024. * These message types aren't included in the transcript.
  1025. */
  1026. case HandshakeType.hello_request:
  1027. case HandshakeType.key_update:
  1028. break;
  1029. /*
  1030. * Not included in the transcript for (D)TLS 1.3+
  1031. */
  1032. case HandshakeType.new_session_ticket:
  1033. {
  1034. ProtocolVersion negotiatedVersion = Context.ServerVersion;
  1035. if (null != negotiatedVersion && !TlsUtilities.IsTlsV13(negotiatedVersion))
  1036. {
  1037. m_handshakeHash.Update(buf, off, len);
  1038. }
  1039. break;
  1040. }
  1041. /*
  1042. * These message types are deferred to the writer to explicitly update the transcript.
  1043. */
  1044. case HandshakeType.client_hello:
  1045. break;
  1046. /*
  1047. * For all others we automatically update the transcript.
  1048. */
  1049. default:
  1050. {
  1051. m_handshakeHash.Update(buf, off, len);
  1052. break;
  1053. }
  1054. }
  1055. int total = 0;
  1056. do
  1057. {
  1058. // Fragment data according to the current fragment limit.
  1059. int toWrite = System.Math.Min(len - total, m_recordStream.PlaintextLimit);
  1060. SafeWriteRecord(ContentType.handshake, buf, off + total, toWrite);
  1061. total += toWrite;
  1062. }
  1063. while (total < len);
  1064. }
  1065. /// <summary>The secure bidirectional stream for this connection</summary>
  1066. /// <remarks>Only allowed in blocking mode.</remarks>
  1067. public virtual Stream Stream
  1068. {
  1069. get
  1070. {
  1071. if (!m_blocking)
  1072. throw new InvalidOperationException(
  1073. "Cannot use Stream in non-blocking mode! Use OfferInput()/OfferOutput() instead.");
  1074. return this.m_tlsStream;
  1075. }
  1076. }
  1077. /// <summary>Should be called in non-blocking mode when the input data reaches EOF.</summary>
  1078. /// <exception cref="IOException"/>
  1079. public virtual void CloseInput()
  1080. {
  1081. if (m_blocking)
  1082. throw new InvalidOperationException("Cannot use CloseInput() in blocking mode!");
  1083. if (m_closed)
  1084. return;
  1085. if (m_inputBuffers.Available > 0)
  1086. throw new EndOfStreamException();
  1087. if (!m_appDataReady)
  1088. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  1089. if (!Peer.RequiresCloseNotify())
  1090. {
  1091. HandleClose(false);
  1092. return;
  1093. }
  1094. HandleFailure();
  1095. throw new TlsNoCloseNotifyException();
  1096. }
  1097. /// <exception cref="IOException"/>
  1098. public virtual RecordPreview PreviewInputRecord(byte[] recordHeader)
  1099. {
  1100. if (m_blocking)
  1101. throw new InvalidOperationException("Cannot use PreviewInputRecord() in blocking mode!");
  1102. if (m_inputBuffers.Available != 0)
  1103. throw new InvalidOperationException("Can only use PreviewInputRecord() for record-aligned input.");
  1104. if (m_closed)
  1105. throw new IOException("Connection is closed, cannot accept any more input");
  1106. return SafePreviewRecordHeader(recordHeader);
  1107. }
  1108. public virtual int PreviewOutputRecord()
  1109. {
  1110. if (m_blocking)
  1111. throw new InvalidOperationException("Cannot use PreviewOutputRecord() in blocking mode!");
  1112. ByteQueue buffer = m_outputBuffer.Buffer;
  1113. int available = buffer.Available;
  1114. if (available < 1)
  1115. return 0;
  1116. if (available >= RecordFormat.FragmentOffset)
  1117. {
  1118. int length = buffer.ReadUint16(RecordFormat.LengthOffset);
  1119. int recordSize = RecordFormat.FragmentOffset + length;
  1120. if (available >= recordSize)
  1121. return recordSize;
  1122. }
  1123. throw new InvalidOperationException("Can only use PreviewOutputRecord() for record-aligned output.");
  1124. }
  1125. /// <exception cref="IOException"/>
  1126. public virtual RecordPreview PreviewOutputRecord(int applicationDataSize)
  1127. {
  1128. if (!m_appDataReady)
  1129. throw new InvalidOperationException(
  1130. "Cannot use PreviewOutputRecord() until initial handshake completed.");
  1131. if (m_blocking)
  1132. throw new InvalidOperationException("Cannot use PreviewOutputRecord() in blocking mode!");
  1133. if (m_outputBuffer.Buffer.Available != 0)
  1134. throw new InvalidOperationException("Can only use PreviewOutputRecord() for record-aligned output.");
  1135. if (m_closed)
  1136. throw new IOException("Connection is closed, cannot produce any more output");
  1137. if (applicationDataSize < 1)
  1138. return new RecordPreview(0, 0);
  1139. if (m_appDataSplitEnabled)
  1140. {
  1141. switch (m_appDataSplitMode)
  1142. {
  1143. case ADS_MODE_0_N_FIRSTONLY:
  1144. case ADS_MODE_0_N:
  1145. {
  1146. RecordPreview a = m_recordStream.PreviewOutputRecord(0);
  1147. RecordPreview b = m_recordStream.PreviewOutputRecord(applicationDataSize);
  1148. return RecordPreview.CombineAppData(a, b);
  1149. }
  1150. case ADS_MODE_1_Nsub1:
  1151. default:
  1152. {
  1153. RecordPreview a = m_recordStream.PreviewOutputRecord(1);
  1154. if (applicationDataSize > 1)
  1155. {
  1156. RecordPreview b = m_recordStream.PreviewOutputRecord(applicationDataSize - 1);
  1157. a = RecordPreview.CombineAppData(a, b);
  1158. }
  1159. return a;
  1160. }
  1161. }
  1162. }
  1163. else
  1164. {
  1165. RecordPreview a = m_recordStream.PreviewOutputRecord(applicationDataSize);
  1166. if (m_keyUpdateEnabled && (m_keyUpdatePendingSend || m_recordStream.NeedsKeyUpdate()))
  1167. {
  1168. int keyUpdateLength = HandshakeMessageOutput.GetLength(1);
  1169. int recordSize = m_recordStream.PreviewOutputRecordSize(keyUpdateLength);
  1170. a = RecordPreview.ExtendRecordSize(a, recordSize);
  1171. }
  1172. return a;
  1173. }
  1174. }
  1175. /// <summary>Equivalent to <code>OfferInput(input, 0, input.Length)</code>.</summary>
  1176. /// <param name="input">The input buffer to offer.</param>
  1177. /// <exception cref="IOException"/>
  1178. /// <seealso cref="OfferInput(byte[], int, int)"/>
  1179. public virtual void OfferInput(byte[] input)
  1180. {
  1181. OfferInput(input, 0, input.Length);
  1182. }
  1183. /// <summary>Offer input from an arbitrary source.</summary>
  1184. /// <remarks>Only allowed in non-blocking mode.<br/><br/>
  1185. /// This method will decrypt and process all records that are fully available. If only part of a record is
  1186. /// available, the buffer will be retained until the remainder of the record is offered.<br/><br/>
  1187. /// If any records containing application data were processed, the decrypted data can be obtained using
  1188. /// <see cref="ReadInput(byte[], int, int)"/>. If any records containing protocol data were processed, a
  1189. /// response may have been generated. You should always check to see if there is any available output after
  1190. /// calling this method by calling <see cref="GetAvailableOutputBytes"/>.
  1191. /// </remarks>
  1192. /// <param name="input">The input buffer to offer.</param>
  1193. /// <param name="inputOff">The offset within the input buffer that input begins.</param>
  1194. /// <param name="inputLen">The number of bytes of input being offered.</param>
  1195. /// <exception cref="IOException">If an error occurs while decrypting or processing a record.</exception>
  1196. public virtual void OfferInput(byte[] input, int inputOff, int inputLen)
  1197. {
  1198. if (m_blocking)
  1199. throw new InvalidOperationException("Cannot use OfferInput() in blocking mode! Use Stream instead.");
  1200. if (m_closed)
  1201. throw new IOException("Connection is closed, cannot accept any more input");
  1202. // Fast path if the input is arriving one record at a time
  1203. if (m_inputBuffers.Available == 0 && SafeReadFullRecord(input, inputOff, inputLen))
  1204. {
  1205. if (m_closed)
  1206. {
  1207. if (!m_appDataReady)
  1208. {
  1209. // NOTE: Any close during the handshake should have raised an exception.
  1210. throw new TlsFatalAlert(AlertDescription.internal_error);
  1211. }
  1212. }
  1213. return;
  1214. }
  1215. m_inputBuffers.AddBytes(input, inputOff, inputLen);
  1216. // loop while there are enough bytes to read the length of the next record
  1217. while (m_inputBuffers.Available >= RecordFormat.FragmentOffset)
  1218. {
  1219. byte[] recordHeader = new byte[RecordFormat.FragmentOffset];
  1220. if (RecordFormat.FragmentOffset != m_inputBuffers.Peek(recordHeader))
  1221. throw new TlsFatalAlert(AlertDescription.internal_error);
  1222. RecordPreview preview = SafePreviewRecordHeader(recordHeader);
  1223. if (m_inputBuffers.Available < preview.RecordSize)
  1224. {
  1225. // not enough bytes to read a whole record
  1226. break;
  1227. }
  1228. // NOTE: This is actually reading from inputBuffers, so InterruptedIOException shouldn't be possible
  1229. SafeReadRecord();
  1230. if (m_closed)
  1231. {
  1232. if (!m_appDataReady)
  1233. {
  1234. // NOTE: Any close during the handshake should have raised an exception.
  1235. throw new TlsFatalAlert(AlertDescription.internal_error);
  1236. }
  1237. break;
  1238. }
  1239. }
  1240. }
  1241. public virtual int ApplicationDataLimit
  1242. {
  1243. get { return m_recordStream.PlaintextLimit; }
  1244. }
  1245. /// <summary>Gets the amount of received application data.</summary>
  1246. /// <remarks>A call to <see cref="ReadInput(byte[], int, int)"/> is guaranteed to be able to return at least
  1247. /// this much data.<br/><br/>
  1248. /// Only allowed in non-blocking mode.
  1249. /// </remarks>
  1250. /// <returns>The number of bytes of available application data.</returns>
  1251. public virtual int GetAvailableInputBytes()
  1252. {
  1253. if (m_blocking)
  1254. throw new InvalidOperationException("Cannot use GetAvailableInputBytes() in blocking mode!");
  1255. return ApplicationDataAvailable;
  1256. }
  1257. /// <summary>Retrieves received application data.</summary>
  1258. /// <remarks>
  1259. /// Use <see cref="GetAvailableInputBytes"/> to check how much application data is currently available. This
  1260. /// method functions similarly to <see cref="Stream.Read(byte[], int, int)"/>, except that it never blocks. If
  1261. /// no data is available, nothing will be copied and zero will be returned.<br/><br/>
  1262. /// Only allowed in non-blocking mode.
  1263. /// </remarks>
  1264. /// <param name="buf">The buffer to hold the application data.</param>
  1265. /// <param name="off">The start offset in the buffer at which the data is written.</param>
  1266. /// <param name="len">The maximum number of bytes to read.</param>
  1267. /// <returns>The total number of bytes copied to the buffer. May be less than the length specified if the
  1268. /// length was greater than the amount of available data.</returns>
  1269. public virtual int ReadInput(byte[] buf, int off, int len)
  1270. {
  1271. if (m_blocking)
  1272. throw new InvalidOperationException("Cannot use ReadInput() in blocking mode! Use Stream instead.");
  1273. len = System.Math.Min(len, ApplicationDataAvailable);
  1274. if (len < 1)
  1275. return 0;
  1276. m_applicationDataQueue.RemoveData(buf, off, len, 0);
  1277. return len;
  1278. }
  1279. /// <summary>Gets the amount of encrypted data available to be sent.</summary>
  1280. /// <remarks>
  1281. /// A call to <see cref="ReadOutput(byte[], int, int)"/> is guaranteed to be able to return at least this much
  1282. /// data. Only allowed in non-blocking mode.
  1283. /// </remarks>
  1284. /// <returns>The number of bytes of available encrypted data.</returns>
  1285. public virtual int GetAvailableOutputBytes()
  1286. {
  1287. if (m_blocking)
  1288. throw new InvalidOperationException("Cannot use GetAvailableOutputBytes() in blocking mode! Use Stream instead.");
  1289. return m_outputBuffer.Buffer.Available;
  1290. }
  1291. /// <summary>Retrieves encrypted data to be sent.</summary>
  1292. /// <remarks>
  1293. /// Use <see cref="GetAvailableOutputBytes"/> to check how much encrypted data is currently available. This
  1294. /// method functions similarly to <see cref="Stream.Read(byte[], int, int)"/>, except that it never blocks. If
  1295. /// no data is available, nothing will be copied and zero will be returned. Only allowed in non-blocking mode.
  1296. /// </remarks>
  1297. /// <param name="buffer">The buffer to hold the encrypted data.</param>
  1298. /// <param name="offset">The start offset in the buffer at which the data is written.</param>
  1299. /// <param name="length">The maximum number of bytes to read.</param>
  1300. /// <returns>The total number of bytes copied to the buffer. May be less than the length specified if the
  1301. /// length was greater than the amount of available data.</returns>
  1302. public virtual int ReadOutput(byte[] buffer, int offset, int length)
  1303. {
  1304. if (m_blocking)
  1305. throw new InvalidOperationException("Cannot use ReadOutput() in blocking mode! Use 'Stream() instead.");
  1306. int bytesToRead = System.Math.Min(GetAvailableOutputBytes(), length);
  1307. m_outputBuffer.Buffer.RemoveData(buffer, offset, bytesToRead, 0);
  1308. return bytesToRead;
  1309. }
  1310. protected virtual bool EstablishSession(TlsSession sessionToResume)
  1311. {
  1312. this.m_tlsSession = null;
  1313. this.m_sessionParameters = null;
  1314. this.m_sessionMasterSecret = null;
  1315. if (null == sessionToResume || !sessionToResume.IsResumable)
  1316. return false;
  1317. SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
  1318. if (null == sessionParameters)
  1319. return false;
  1320. if (!sessionParameters.IsExtendedMasterSecret)
  1321. {
  1322. TlsPeer peer = Peer;
  1323. if (!peer.AllowLegacyResumption() || peer.RequiresExtendedMasterSecret())
  1324. return false;
  1325. /*
  1326. * NOTE: For session resumption without extended_master_secret, renegotiation MUST be disabled
  1327. * (see RFC 7627 5.4).
  1328. */
  1329. }
  1330. TlsSecret sessionMasterSecret = TlsUtilities.GetSessionMasterSecret(Context.Crypto,
  1331. sessionParameters.MasterSecret);
  1332. if (null == sessionMasterSecret)
  1333. return false;
  1334. this.m_tlsSession = sessionToResume;
  1335. this.m_sessionParameters = sessionParameters;
  1336. this.m_sessionMasterSecret = sessionMasterSecret;
  1337. return true;
  1338. }
  1339. protected virtual void InvalidateSession()
  1340. {
  1341. if (m_sessionMasterSecret != null)
  1342. {
  1343. m_sessionMasterSecret.Destroy();
  1344. this.m_sessionMasterSecret = null;
  1345. }
  1346. if (m_sessionParameters != null)
  1347. {
  1348. m_sessionParameters.Clear();
  1349. this.m_sessionParameters = null;
  1350. }
  1351. if (m_tlsSession != null)
  1352. {
  1353. m_tlsSession.Invalidate();
  1354. this.m_tlsSession = null;
  1355. }
  1356. }
  1357. /// <exception cref="IOException"/>
  1358. protected virtual void ProcessFinishedMessage(MemoryStream buf)
  1359. {
  1360. TlsContext context = Context;
  1361. SecurityParameters securityParameters = context.SecurityParameters;
  1362. bool isServerContext = context.IsServer;
  1363. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
  1364. Span<byte> verify_data = stackalloc byte[securityParameters.VerifyDataLength];
  1365. TlsUtilities.ReadFully(verify_data, buf);
  1366. #else
  1367. byte[] verify_data = TlsUtilities.ReadFully(securityParameters.VerifyDataLength, buf);
  1368. #endif
  1369. AssertEmpty(buf);
  1370. byte[] expected_verify_data = TlsUtilities.CalculateVerifyData(context, m_handshakeHash, !isServerContext);
  1371. /*
  1372. * Compare both checksums.
  1373. */
  1374. if (!Arrays.ConstantTimeAreEqual(expected_verify_data, verify_data))
  1375. {
  1376. /*
  1377. * Wrong checksum in the finished message.
  1378. */
  1379. throw new TlsFatalAlert(AlertDescription.decrypt_error);
  1380. }
  1381. securityParameters.m_peerVerifyData = expected_verify_data;
  1382. if (!securityParameters.IsResumedSession || securityParameters.IsExtendedMasterSecret)
  1383. {
  1384. if (null == securityParameters.LocalVerifyData)
  1385. {
  1386. securityParameters.m_tlsUnique = expected_verify_data;
  1387. }
  1388. }
  1389. }
  1390. /// <exception cref="IOException"/>
  1391. protected virtual void Process13FinishedMessage(MemoryStream buf)
  1392. {
  1393. TlsContext context = Context;
  1394. SecurityParameters securityParameters = context.SecurityParameters;
  1395. bool isServerContext = context.IsServer;
  1396. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || _UNITY_2021_2_OR_NEWER_
  1397. Span<byte> verify_data = stackalloc byte[securityParameters.VerifyDataLength];
  1398. TlsUtilities.ReadFully(verify_data, buf);
  1399. #else
  1400. byte[] verify_data = TlsUtilities.ReadFully(securityParameters.VerifyDataLength, buf);
  1401. #endif
  1402. AssertEmpty(buf);
  1403. byte[] expected_verify_data = TlsUtilities.CalculateVerifyData(context, m_handshakeHash, !isServerContext);
  1404. /*
  1405. * Compare both checksums.
  1406. */
  1407. if (!Arrays.ConstantTimeAreEqual(expected_verify_data, verify_data))
  1408. {
  1409. /*
  1410. * Wrong checksum in the finished message.
  1411. */
  1412. throw new TlsFatalAlert(AlertDescription.decrypt_error);
  1413. }
  1414. securityParameters.m_peerVerifyData = expected_verify_data;
  1415. securityParameters.m_tlsUnique = null;
  1416. }
  1417. /// <exception cref="IOException"/>
  1418. protected virtual void RaiseAlertFatal(short alertDescription, string message, Exception cause)
  1419. {
  1420. Peer.NotifyAlertRaised(AlertLevel.fatal, alertDescription, message, cause);
  1421. byte[] alert = new byte[]{ (byte)AlertLevel.fatal, (byte)alertDescription };
  1422. try
  1423. {
  1424. m_recordStream.WriteRecord(ContentType.alert, alert, 0, 2);
  1425. }
  1426. catch (Exception)
  1427. {
  1428. // We are already processing an exception, so just ignore this
  1429. }
  1430. }
  1431. /// <exception cref="IOException"/>
  1432. protected virtual void RaiseAlertWarning(short alertDescription, string message)
  1433. {
  1434. Peer.NotifyAlertRaised(AlertLevel.warning, alertDescription, message, null);
  1435. byte[] alert = new byte[]{ (byte)AlertLevel.warning, (byte)alertDescription };
  1436. SafeWriteRecord(ContentType.alert, alert, 0, 2);
  1437. }
  1438. /// <exception cref="IOException"/>
  1439. protected virtual void Receive13KeyUpdate(MemoryStream buf)
  1440. {
  1441. // TODO[tls13] This is interesting enough to notify the TlsPeer for possible logging/vetting
  1442. if (!(m_appDataReady && m_keyUpdateEnabled))
  1443. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  1444. short requestUpdate = TlsUtilities.ReadUint8(buf);
  1445. AssertEmpty(buf);
  1446. if (!KeyUpdateRequest.IsValid(requestUpdate))
  1447. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  1448. bool updateRequested = (KeyUpdateRequest.update_requested == requestUpdate);
  1449. TlsUtilities.Update13TrafficSecretPeer(Context);
  1450. m_recordStream.NotifyKeyUpdateReceived();
  1451. //this.m_keyUpdatePendingReceive &= updateRequested;
  1452. this.m_keyUpdatePendingSend |= updateRequested;
  1453. }
  1454. /// <exception cref="IOException"/>
  1455. protected virtual void SendCertificateMessage(Certificate certificate, Stream endPointHash)
  1456. {
  1457. TlsContext context = Context;
  1458. SecurityParameters securityParameters = context.SecurityParameters;
  1459. if (null != securityParameters.LocalCertificate)
  1460. throw new TlsFatalAlert(AlertDescription.internal_error);
  1461. if (null == certificate)
  1462. {
  1463. certificate = Certificate.EmptyChain;
  1464. }
  1465. if (certificate.IsEmpty && !context.IsServer && securityParameters.NegotiatedVersion.IsSsl)
  1466. {
  1467. string message = "SSLv3 client didn't provide credentials";
  1468. RaiseAlertWarning(AlertDescription.no_certificate, message);
  1469. }
  1470. else
  1471. {
  1472. HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.certificate);
  1473. certificate.Encode(context, message, endPointHash);
  1474. message.Send(this);
  1475. }
  1476. securityParameters.m_localCertificate = certificate;
  1477. }
  1478. /// <exception cref="IOException"/>
  1479. protected virtual void Send13CertificateMessage(Certificate certificate)
  1480. {
  1481. if (null == certificate)
  1482. throw new TlsFatalAlert(AlertDescription.internal_error);
  1483. TlsContext context = Context;
  1484. SecurityParameters securityParameters = context.SecurityParameters;
  1485. if (null != securityParameters.LocalCertificate)
  1486. throw new TlsFatalAlert(AlertDescription.internal_error);
  1487. HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.certificate);
  1488. certificate.Encode(context, message, null);
  1489. message.Send(this);
  1490. securityParameters.m_localCertificate = certificate;
  1491. }
  1492. /// <exception cref="IOException"/>
  1493. protected virtual void Send13CertificateVerifyMessage(DigitallySigned certificateVerify)
  1494. {
  1495. HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.certificate_verify);
  1496. certificateVerify.Encode(message);
  1497. message.Send(this);
  1498. }
  1499. /// <exception cref="IOException"/>
  1500. protected virtual void SendChangeCipherSpec()
  1501. {
  1502. SendChangeCipherSpecMessage();
  1503. m_recordStream.EnablePendingCipherWrite();
  1504. }
  1505. /// <exception cref="IOException"/>
  1506. protected virtual void SendChangeCipherSpecMessage()
  1507. {
  1508. byte[] message = new byte[]{ 1 };
  1509. SafeWriteRecord(ContentType.change_cipher_spec, message, 0, message.Length);
  1510. }
  1511. /// <exception cref="IOException"/>
  1512. protected virtual void SendFinishedMessage()
  1513. {
  1514. TlsContext context = Context;
  1515. SecurityParameters securityParameters = context.SecurityParameters;
  1516. bool isServerContext = context.IsServer;
  1517. byte[] verify_data = TlsUtilities.CalculateVerifyData(context, m_handshakeHash, isServerContext);
  1518. securityParameters.m_localVerifyData = verify_data;
  1519. if (!securityParameters.IsResumedSession || securityParameters.IsExtendedMasterSecret)
  1520. {
  1521. if (null == securityParameters.PeerVerifyData)
  1522. {
  1523. securityParameters.m_tlsUnique = verify_data;
  1524. }
  1525. }
  1526. HandshakeMessageOutput.Send(this, HandshakeType.finished, verify_data);
  1527. }
  1528. /// <exception cref="IOException"/>
  1529. protected virtual void Send13FinishedMessage()
  1530. {
  1531. TlsContext context = Context;
  1532. SecurityParameters securityParameters = context.SecurityParameters;
  1533. bool isServerContext = context.IsServer;
  1534. byte[] verify_data = TlsUtilities.CalculateVerifyData(context, m_handshakeHash, isServerContext);
  1535. securityParameters.m_localVerifyData = verify_data;
  1536. securityParameters.m_tlsUnique = null;
  1537. HandshakeMessageOutput.Send(this, HandshakeType.finished, verify_data);
  1538. }
  1539. /// <exception cref="IOException"/>
  1540. protected virtual void Send13KeyUpdate(bool updateRequested)
  1541. {
  1542. // TODO[tls13] This is interesting enough to notify the TlsPeer for possible logging/vetting
  1543. if (!(m_appDataReady && m_keyUpdateEnabled))
  1544. throw new TlsFatalAlert(AlertDescription.internal_error);
  1545. short requestUpdate = updateRequested
  1546. ? KeyUpdateRequest.update_requested
  1547. : KeyUpdateRequest.update_not_requested;
  1548. HandshakeMessageOutput.Send(this, HandshakeType.key_update, TlsUtilities.EncodeUint8(requestUpdate));
  1549. TlsUtilities.Update13TrafficSecretLocal(Context);
  1550. m_recordStream.NotifyKeyUpdateSent();
  1551. //this.m_keyUpdatePendingReceive |= updateRequested;
  1552. this.m_keyUpdatePendingSend &= updateRequested;
  1553. }
  1554. /// <exception cref="IOException"/>
  1555. protected virtual void SendSupplementalDataMessage(IList<SupplementalDataEntry> supplementalData)
  1556. {
  1557. HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.supplemental_data);
  1558. WriteSupplementalData(message, supplementalData);
  1559. message.Send(this);
  1560. }
  1561. public virtual void Close()
  1562. {
  1563. applicationDataLock?.Dispose();
  1564. applicationDataLock = null;
  1565. HandleClose(true);
  1566. }
  1567. public virtual void Flush()
  1568. {
  1569. }
  1570. internal bool IsApplicationDataReady
  1571. {
  1572. get { return m_appDataReady; }
  1573. }
  1574. public virtual bool IsClosed
  1575. {
  1576. get { return m_closed; }
  1577. }
  1578. public virtual bool IsConnected
  1579. {
  1580. get
  1581. {
  1582. if (m_closed)
  1583. return false;
  1584. AbstractTlsContext context = ContextAdmin;
  1585. return null != context && context.IsConnected;
  1586. }
  1587. }
  1588. public virtual bool IsHandshaking
  1589. {
  1590. get
  1591. {
  1592. if (m_closed)
  1593. return false;
  1594. AbstractTlsContext context = ContextAdmin;
  1595. return null != context && context.IsHandshaking;
  1596. }
  1597. }
  1598. /// <exception cref="IOException"/>
  1599. protected virtual short ProcessMaxFragmentLengthExtension(IDictionary<int, byte[]> clientExtensions,
  1600. IDictionary<int, byte[]> serverExtensions, short alertDescription)
  1601. {
  1602. short maxFragmentLength = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions);
  1603. if (maxFragmentLength >= 0)
  1604. {
  1605. if (!MaxFragmentLength.IsValid(maxFragmentLength) ||
  1606. (clientExtensions != null &&
  1607. maxFragmentLength != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions)))
  1608. {
  1609. throw new TlsFatalAlert(alertDescription);
  1610. }
  1611. }
  1612. return maxFragmentLength;
  1613. }
  1614. /// <exception cref="IOException"/>
  1615. protected virtual void RefuseRenegotiation()
  1616. {
  1617. /*
  1618. * RFC 5746 4.5 SSLv3 clients [..] SHOULD use a fatal handshake_failure alert.
  1619. */
  1620. if (TlsUtilities.IsSsl(Context))
  1621. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  1622. RaiseAlertWarning(AlertDescription.no_renegotiation, "Renegotiation not supported");
  1623. }
  1624. /// <summary>Make sure the <see cref="Stream"/> 'buf' is now empty. Fail otherwise.</summary>
  1625. /// <param name="buf">The <see cref="Stream"/> to check.</param>
  1626. /// <exception cref="IOException"/>
  1627. internal static void AssertEmpty(MemoryStream buf)
  1628. {
  1629. if (buf.Position < buf.Length)
  1630. throw new TlsFatalAlert(AlertDescription.decode_error);
  1631. }
  1632. internal static byte[] CreateRandomBlock(bool useGmtUnixTime, TlsContext context)
  1633. {
  1634. byte[] result = context.NonceGenerator.GenerateNonce(32);
  1635. if (useGmtUnixTime)
  1636. {
  1637. TlsUtilities.WriteGmtUnixTime(result, 0);
  1638. }
  1639. return result;
  1640. }
  1641. /// <exception cref="IOException"/>
  1642. internal static byte[] CreateRenegotiationInfo(byte[] renegotiated_connection)
  1643. {
  1644. return TlsUtilities.EncodeOpaque8(renegotiated_connection);
  1645. }
  1646. /// <exception cref="IOException"/>
  1647. internal static void EstablishMasterSecret(TlsContext context, TlsKeyExchange keyExchange)
  1648. {
  1649. TlsSecret preMasterSecret = keyExchange.GeneratePreMasterSecret();
  1650. if (preMasterSecret == null)
  1651. throw new TlsFatalAlert(AlertDescription.internal_error);
  1652. try
  1653. {
  1654. context.SecurityParameters.m_masterSecret = TlsUtilities.CalculateMasterSecret(context,
  1655. preMasterSecret);
  1656. if (context.SecurityParameters.NegotiatedVersion != ProtocolVersion.TLSv13)
  1657. KeyLogFileWriter.WriteLabel(Labels.CLIENT_RANDOM, context.SecurityParameters);
  1658. }
  1659. finally
  1660. {
  1661. /*
  1662. * RFC 2246 8.1. The pre_master_secret should be deleted from memory once the
  1663. * master_secret has been computed.
  1664. */
  1665. preMasterSecret.Destroy();
  1666. }
  1667. }
  1668. /// <exception cref="IOException"/>
  1669. internal static IDictionary<int, byte[]> ReadExtensions(MemoryStream input)
  1670. {
  1671. if (input.Position >= input.Length)
  1672. return null;
  1673. byte[] extBytes = TlsUtilities.ReadOpaque16(input);
  1674. AssertEmpty(input);
  1675. return ReadExtensionsData(extBytes);
  1676. }
  1677. /// <exception cref="IOException"/>
  1678. internal static IDictionary<int, byte[]> ReadExtensionsData(byte[] extBytes)
  1679. {
  1680. // Int32 -> byte[]
  1681. var extensions = new Dictionary<int, byte[]>();
  1682. if (extBytes.Length > 0)
  1683. {
  1684. MemoryStream buf = new MemoryStream(extBytes, false);
  1685. do
  1686. {
  1687. int extension_type = TlsUtilities.ReadUint16(buf);
  1688. byte[] extension_data = TlsUtilities.ReadOpaque16(buf);
  1689. /*
  1690. * RFC 3546 2.3 There MUST NOT be more than one extension of the same type.
  1691. */
  1692. if (extensions.ContainsKey(extension_type))
  1693. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1694. "Repeated extension: " + ExtensionType.GetText(extension_type));
  1695. extensions.Add(extension_type, extension_data);
  1696. }
  1697. while (buf.Position < buf.Length);
  1698. }
  1699. return extensions;
  1700. }
  1701. /// <exception cref="IOException"/>
  1702. internal static IDictionary<int, byte[]> ReadExtensionsData13(int handshakeType, byte[] extBytes)
  1703. {
  1704. // Int32 -> byte[]
  1705. var extensions = new Dictionary<int, byte[]>();
  1706. if (extBytes.Length > 0)
  1707. {
  1708. MemoryStream buf = new MemoryStream(extBytes, false);
  1709. do
  1710. {
  1711. int extension_type = TlsUtilities.ReadUint16(buf);
  1712. if (!TlsUtilities.IsPermittedExtensionType13(handshakeType, extension_type))
  1713. {
  1714. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1715. "Invalid extension: " + ExtensionType.GetText(extension_type));
  1716. }
  1717. byte[] extension_data = TlsUtilities.ReadOpaque16(buf);
  1718. /*
  1719. * RFC 3546 2.3 There MUST NOT be more than one extension of the same type.
  1720. */
  1721. if (extensions.ContainsKey(extension_type))
  1722. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1723. "Repeated extension: " + ExtensionType.GetText(extension_type));
  1724. extensions.Add(extension_type, extension_data);
  1725. }
  1726. while (buf.Position < buf.Length);
  1727. }
  1728. return extensions;
  1729. }
  1730. /// <exception cref="IOException"/>
  1731. internal static IDictionary<int, byte[]> ReadExtensionsDataClientHello(byte[] extBytes)
  1732. {
  1733. /*
  1734. * TODO[tls13] We are currently allowing any extensions to appear in ClientHello. It is
  1735. * somewhat complicated to restrict what can appear based on the specific set of versions
  1736. * the client is offering, and anyway could be fragile since clients may take a
  1737. * "kitchen sink" approach to adding extensions independently of the offered versions.
  1738. */
  1739. // Int32 -> byte[]
  1740. var extensions = new Dictionary<int, byte[]>();
  1741. if (extBytes.Length > 0)
  1742. {
  1743. MemoryStream buf = new MemoryStream(extBytes, false);
  1744. int extension_type;
  1745. bool pre_shared_key_found = false;
  1746. do
  1747. {
  1748. extension_type = TlsUtilities.ReadUint16(buf);
  1749. byte[] extension_data = TlsUtilities.ReadOpaque16(buf);
  1750. /*
  1751. * RFC 3546 2.3 There MUST NOT be more than one extension of the same type.
  1752. */
  1753. if (extensions.ContainsKey(extension_type))
  1754. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1755. "Repeated extension: " + ExtensionType.GetText(extension_type));
  1756. extensions.Add(extension_type, extension_data);
  1757. pre_shared_key_found |= (ExtensionType.pre_shared_key == extension_type);
  1758. }
  1759. while (buf.Position < buf.Length);
  1760. if (pre_shared_key_found && (ExtensionType.pre_shared_key != extension_type))
  1761. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1762. "'pre_shared_key' MUST be last in ClientHello");
  1763. }
  1764. return extensions;
  1765. }
  1766. /// <exception cref="IOException"/>
  1767. internal static IList<SupplementalDataEntry> ReadSupplementalDataMessage(MemoryStream input)
  1768. {
  1769. byte[] supp_data = TlsUtilities.ReadOpaque24(input, 1);
  1770. AssertEmpty(input);
  1771. MemoryStream buf = new MemoryStream(supp_data, false);
  1772. var supplementalData = new List<SupplementalDataEntry>();
  1773. while (buf.Position < buf.Length)
  1774. {
  1775. int supp_data_type = TlsUtilities.ReadUint16(buf);
  1776. byte[] data = TlsUtilities.ReadOpaque16(buf);
  1777. supplementalData.Add(new SupplementalDataEntry(supp_data_type, data));
  1778. }
  1779. return supplementalData;
  1780. }
  1781. /// <exception cref="IOException"/>
  1782. internal static void WriteExtensions(Stream output, IDictionary<int, byte[]> extensions)
  1783. {
  1784. WriteExtensions(output, extensions, 0);
  1785. }
  1786. /// <exception cref="IOException"/>
  1787. internal static void WriteExtensions(Stream output, IDictionary<int, byte[]> extensions, int bindersSize)
  1788. {
  1789. if (null == extensions || extensions.Count < 1)
  1790. return;
  1791. byte[] extBytes = WriteExtensionsData(extensions, bindersSize);
  1792. int lengthWithBinders = extBytes.Length + bindersSize;
  1793. TlsUtilities.CheckUint16(lengthWithBinders);
  1794. TlsUtilities.WriteUint16(lengthWithBinders, output);
  1795. output.Write(extBytes, 0, extBytes.Length);
  1796. }
  1797. /// <exception cref="IOException"/>
  1798. internal static byte[] WriteExtensionsData(IDictionary<int, byte[]> extensions)
  1799. {
  1800. return WriteExtensionsData(extensions, 0);
  1801. }
  1802. /// <exception cref="IOException"/>
  1803. internal static byte[] WriteExtensionsData(IDictionary<int, byte[]> extensions, int bindersSize)
  1804. {
  1805. MemoryStream buf = new MemoryStream();
  1806. WriteExtensionsData(extensions, buf, bindersSize);
  1807. return buf.ToArray();
  1808. }
  1809. /// <exception cref="IOException"/>
  1810. internal static void WriteExtensionsData(IDictionary<int, byte[]> extensions, MemoryStream buf)
  1811. {
  1812. WriteExtensionsData(extensions, buf, 0);
  1813. }
  1814. /// <exception cref="IOException"/>
  1815. internal static void WriteExtensionsData(IDictionary<int, byte[]> extensions, MemoryStream buf, int bindersSize)
  1816. {
  1817. /*
  1818. * NOTE: There are reports of servers that don't accept a zero-length extension as the last
  1819. * one, so we write out any zero-length ones first as a best-effort workaround.
  1820. */
  1821. WriteSelectedExtensions(buf, extensions, true);
  1822. WriteSelectedExtensions(buf, extensions, false);
  1823. WritePreSharedKeyExtension(buf, extensions, bindersSize);
  1824. }
  1825. /// <exception cref="IOException"/>
  1826. internal static void WritePreSharedKeyExtension(MemoryStream buf, IDictionary<int, byte[]> extensions,
  1827. int bindersSize)
  1828. {
  1829. if (extensions.TryGetValue(ExtensionType.pre_shared_key, out var extension_data))
  1830. {
  1831. TlsUtilities.CheckUint16(ExtensionType.pre_shared_key);
  1832. TlsUtilities.WriteUint16(ExtensionType.pre_shared_key, buf);
  1833. int lengthWithBinders = extension_data.Length + bindersSize;
  1834. TlsUtilities.CheckUint16(lengthWithBinders);
  1835. TlsUtilities.WriteUint16(lengthWithBinders, buf);
  1836. buf.Write(extension_data, 0, extension_data.Length);
  1837. }
  1838. }
  1839. /// <exception cref="IOException"/>
  1840. internal static void WriteSelectedExtensions(Stream output, IDictionary<int, byte[]> extensions,
  1841. bool selectEmpty)
  1842. {
  1843. foreach (var extension in extensions)
  1844. {
  1845. int extension_type = extension.Key;
  1846. // NOTE: Must be last; handled by 'WritePreSharedKeyExtension'
  1847. if (ExtensionType.pre_shared_key == extension_type)
  1848. continue;
  1849. byte[] extension_data = extension.Value;
  1850. if (selectEmpty == (extension_data.Length == 0))
  1851. {
  1852. TlsUtilities.CheckUint16(extension_type);
  1853. TlsUtilities.WriteUint16(extension_type, output);
  1854. TlsUtilities.WriteOpaque16(extension_data, output);
  1855. }
  1856. }
  1857. }
  1858. /// <exception cref="IOException"/>
  1859. internal static void WriteSupplementalData(Stream output, IList<SupplementalDataEntry> supplementalData)
  1860. {
  1861. MemoryStream buf = new MemoryStream();
  1862. foreach (SupplementalDataEntry entry in supplementalData)
  1863. {
  1864. int supp_data_type = entry.DataType;
  1865. TlsUtilities.CheckUint16(supp_data_type);
  1866. TlsUtilities.WriteUint16(supp_data_type, buf);
  1867. TlsUtilities.WriteOpaque16(entry.Data, buf);
  1868. }
  1869. byte[] supp_data = buf.ToArray();
  1870. TlsUtilities.WriteOpaque24(supp_data, output);
  1871. }
  1872. }
  1873. }
  1874. #pragma warning restore
  1875. #endif