TlsProtocol.cs 82 KB

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