TlsProtocol.cs 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using BestHTTP.Connections.TLS;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  9. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
  10. {
  11. public abstract class TlsProtocol
  12. : TlsCloseable
  13. {
  14. /*
  15. * Connection States.
  16. *
  17. * NOTE: Redirection of handshake messages to TLS 1.3 handlers assumes CS_START, CS_CLIENT_HELLO
  18. * are lower than any of the other values.
  19. */
  20. protected const short CS_START = 0;
  21. protected const short CS_CLIENT_HELLO = 1;
  22. protected const short CS_SERVER_HELLO_RETRY_REQUEST = 2;
  23. protected const short CS_CLIENT_HELLO_RETRY = 3;
  24. protected const short CS_SERVER_HELLO = 4;
  25. protected const short CS_SERVER_ENCRYPTED_EXTENSIONS = 5;
  26. protected const short CS_SERVER_SUPPLEMENTAL_DATA = 6;
  27. protected const short CS_SERVER_CERTIFICATE = 7;
  28. protected const short CS_SERVER_CERTIFICATE_STATUS = 8;
  29. protected const short CS_SERVER_CERTIFICATE_VERIFY = 9;
  30. protected const short CS_SERVER_KEY_EXCHANGE = 10;
  31. protected const short CS_SERVER_CERTIFICATE_REQUEST = 11;
  32. protected const short CS_SERVER_HELLO_DONE = 12;
  33. protected const short CS_CLIENT_END_OF_EARLY_DATA = 13;
  34. protected const short CS_CLIENT_SUPPLEMENTAL_DATA = 14;
  35. protected const short CS_CLIENT_CERTIFICATE = 15;
  36. protected const short CS_CLIENT_KEY_EXCHANGE = 16;
  37. protected const short CS_CLIENT_CERTIFICATE_VERIFY = 17;
  38. protected const short CS_CLIENT_FINISHED = 18;
  39. protected const short CS_SERVER_SESSION_TICKET = 19;
  40. protected const short CS_SERVER_FINISHED = 20;
  41. protected const short CS_END = 21;
  42. protected bool IsLegacyConnectionState()
  43. {
  44. switch (m_connectionState)
  45. {
  46. case CS_START:
  47. case CS_CLIENT_HELLO:
  48. case CS_SERVER_HELLO:
  49. case CS_SERVER_SUPPLEMENTAL_DATA:
  50. case CS_SERVER_CERTIFICATE:
  51. case CS_SERVER_CERTIFICATE_STATUS:
  52. case CS_SERVER_KEY_EXCHANGE:
  53. case CS_SERVER_CERTIFICATE_REQUEST:
  54. case CS_SERVER_HELLO_DONE:
  55. case CS_CLIENT_SUPPLEMENTAL_DATA:
  56. case CS_CLIENT_CERTIFICATE:
  57. case CS_CLIENT_KEY_EXCHANGE:
  58. case CS_CLIENT_CERTIFICATE_VERIFY:
  59. case CS_CLIENT_FINISHED:
  60. case CS_SERVER_SESSION_TICKET:
  61. case CS_SERVER_FINISHED:
  62. case CS_END:
  63. return true;
  64. case CS_SERVER_HELLO_RETRY_REQUEST:
  65. case CS_CLIENT_HELLO_RETRY:
  66. case CS_SERVER_ENCRYPTED_EXTENSIONS:
  67. case CS_SERVER_CERTIFICATE_VERIFY:
  68. case CS_CLIENT_END_OF_EARLY_DATA:
  69. default:
  70. return false;
  71. }
  72. }
  73. protected bool IsTlsV13ConnectionState()
  74. {
  75. switch (m_connectionState)
  76. {
  77. case CS_START:
  78. case CS_CLIENT_HELLO:
  79. case CS_SERVER_HELLO_RETRY_REQUEST:
  80. case CS_CLIENT_HELLO_RETRY:
  81. case CS_SERVER_HELLO:
  82. case CS_SERVER_ENCRYPTED_EXTENSIONS:
  83. case CS_SERVER_CERTIFICATE_REQUEST:
  84. case CS_SERVER_CERTIFICATE:
  85. case CS_SERVER_CERTIFICATE_VERIFY:
  86. case CS_SERVER_FINISHED:
  87. case CS_CLIENT_END_OF_EARLY_DATA:
  88. case CS_CLIENT_CERTIFICATE:
  89. case CS_CLIENT_CERTIFICATE_VERIFY:
  90. case CS_CLIENT_FINISHED:
  91. case CS_END:
  92. return true;
  93. case CS_SERVER_SUPPLEMENTAL_DATA:
  94. case CS_SERVER_CERTIFICATE_STATUS:
  95. case CS_SERVER_KEY_EXCHANGE:
  96. case CS_SERVER_HELLO_DONE:
  97. case CS_CLIENT_SUPPLEMENTAL_DATA:
  98. case CS_CLIENT_KEY_EXCHANGE:
  99. case CS_SERVER_SESSION_TICKET:
  100. default:
  101. return false;
  102. }
  103. }
  104. /*
  105. * Different modes to handle the known IV weakness
  106. */
  107. protected const short ADS_MODE_1_Nsub1 = 0; // 1/n-1 record splitting
  108. protected const short ADS_MODE_0_N = 1; // 0/n record splitting
  109. protected const short ADS_MODE_0_N_FIRSTONLY = 2; // 0/n record splitting on first data fragment only
  110. /*
  111. * Queues for data from some protocols.
  112. */
  113. private readonly ByteQueue m_applicationDataQueue = new ByteQueue(0);
  114. private readonly ByteQueue m_alertQueue = new ByteQueue(2);
  115. private readonly ByteQueue m_handshakeQueue = new ByteQueue(0);
  116. //private readonly ByteQueue m_heartbeatQueue = new ByteQueue(0);
  117. internal readonly RecordStream m_recordStream;
  118. internal readonly object m_recordWriteLock = new object();
  119. private int m_maxHandshakeMessageSize = -1;
  120. internal TlsHandshakeHash m_handshakeHash;
  121. private TlsStream m_tlsStream = null;
  122. private volatile bool m_closed = false;
  123. private volatile bool m_failedWithError = false;
  124. private volatile bool m_appDataReady = false;
  125. private volatile bool m_appDataSplitEnabled = true;
  126. private volatile bool m_keyUpdateEnabled = false;
  127. //private volatile bool m_keyUpdatePendingReceive = false;
  128. private volatile bool m_keyUpdatePendingSend = false;
  129. private volatile bool m_resumableHandshake = false;
  130. private volatile int m_appDataSplitMode = ADS_MODE_1_Nsub1;
  131. protected TlsSession m_tlsSession = null;
  132. protected SessionParameters m_sessionParameters = null;
  133. protected TlsSecret m_sessionMasterSecret = null;
  134. protected byte[] m_retryCookie = null;
  135. protected int m_retryGroup = -1;
  136. protected IDictionary m_clientExtensions = null;
  137. protected IDictionary m_serverExtensions = null;
  138. protected short m_connectionState = CS_START;
  139. protected bool m_resumedSession = false;
  140. protected bool m_selectedPsk13 = false;
  141. protected bool m_receivedChangeCipherSpec = false;
  142. protected bool m_expectSessionTicket = false;
  143. protected readonly bool m_blocking;
  144. protected readonly ByteQueueInputStream m_inputBuffers;
  145. protected readonly ByteQueueOutputStream m_outputBuffer;
  146. protected TlsProtocol()
  147. {
  148. this.m_blocking = false;
  149. this.m_inputBuffers = new ByteQueueInputStream();
  150. this.m_outputBuffer = new ByteQueueOutputStream();
  151. this.m_recordStream = new RecordStream(this, m_inputBuffers, m_outputBuffer);
  152. }
  153. public TlsProtocol(Stream stream)
  154. : this(stream, stream)
  155. {
  156. }
  157. public TlsProtocol(Stream input, Stream output)
  158. {
  159. this.m_blocking = true;
  160. this.m_inputBuffers = null;
  161. this.m_outputBuffer = null;
  162. this.m_recordStream = new RecordStream(this, input, output);
  163. }
  164. /// <exception cref="IOException"/>
  165. public virtual void ResumeHandshake()
  166. {
  167. if (!m_blocking)
  168. throw new InvalidOperationException("Cannot use ResumeHandshake() in non-blocking mode!");
  169. if (!IsHandshaking)
  170. throw new InvalidOperationException("No handshake in progress");
  171. BlockForHandshake();
  172. }
  173. /// <exception cref="IOException"/>
  174. protected virtual void CloseConnection()
  175. {
  176. m_recordStream.Close();
  177. }
  178. protected abstract TlsContext Context { get; }
  179. internal abstract AbstractTlsContext ContextAdmin { get; }
  180. protected abstract TlsPeer Peer { get; }
  181. /// <exception cref="IOException"/>
  182. protected virtual void HandleAlertMessage(short alertLevel, short alertDescription)
  183. {
  184. Peer.NotifyAlertReceived(alertLevel, alertDescription);
  185. if (alertLevel == AlertLevel.warning)
  186. {
  187. HandleAlertWarningMessage(alertDescription);
  188. }
  189. else
  190. {
  191. HandleFailure();
  192. throw new TlsFatalAlertReceived(alertDescription);
  193. }
  194. }
  195. /// <exception cref="IOException"/>
  196. protected virtual void HandleAlertWarningMessage(short alertDescription)
  197. {
  198. switch (alertDescription)
  199. {
  200. /*
  201. * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own
  202. * and close down the connection immediately, discarding any pending writes.
  203. */
  204. case AlertDescription.close_notify:
  205. {
  206. if (!m_appDataReady)
  207. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  208. HandleClose(false);
  209. break;
  210. }
  211. case AlertDescription.no_certificate:
  212. {
  213. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  214. }
  215. case AlertDescription.no_renegotiation:
  216. {
  217. // TODO[reneg] Give peer the option to tolerate this
  218. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  219. }
  220. }
  221. }
  222. /// <exception cref="IOException"/>
  223. protected virtual void HandleChangeCipherSpecMessage()
  224. {
  225. }
  226. /// <exception cref="IOException"/>
  227. protected virtual void HandleClose(bool user_canceled)
  228. {
  229. if (!m_closed)
  230. {
  231. this.m_closed = true;
  232. if (!m_appDataReady)
  233. {
  234. CleanupHandshake();
  235. if (user_canceled)
  236. {
  237. RaiseAlertWarning(AlertDescription.user_canceled, "User canceled handshake");
  238. }
  239. }
  240. RaiseAlertWarning(AlertDescription.close_notify, "Connection closed");
  241. CloseConnection();
  242. }
  243. }
  244. /// <exception cref="IOException"/>
  245. protected virtual void HandleException(short alertDescription, string message, Exception e)
  246. {
  247. // TODO[tls-port] Can we support interrupted IO on .NET?
  248. //if ((m_appDataReady || IsResumableHandshake()) && (e is InterruptedIOException))
  249. // return;
  250. if (!m_closed)
  251. {
  252. RaiseAlertFatal(alertDescription, message, e);
  253. HandleFailure();
  254. }
  255. }
  256. /// <exception cref="IOException"/>
  257. protected virtual void HandleFailure()
  258. {
  259. this.m_closed = true;
  260. this.m_failedWithError = true;
  261. /*
  262. * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
  263. * without proper close_notify messages with level equal to warning.
  264. */
  265. // TODO This isn't quite in the right place. Also, as of TLS 1.1 the above is obsolete.
  266. InvalidateSession();
  267. if (!m_appDataReady)
  268. {
  269. CleanupHandshake();
  270. }
  271. CloseConnection();
  272. }
  273. /// <exception cref="IOException"/>
  274. protected abstract void HandleHandshakeMessage(short type, HandshakeMessageInput buf);
  275. /// <exception cref="IOException"/>
  276. protected virtual void ApplyMaxFragmentLengthExtension(short maxFragmentLength)
  277. {
  278. if (maxFragmentLength >= 0)
  279. {
  280. if (!MaxFragmentLength.IsValid(maxFragmentLength))
  281. throw new TlsFatalAlert(AlertDescription.internal_error);
  282. int plainTextLimit = 1 << (8 + maxFragmentLength);
  283. m_recordStream.SetPlaintextLimit(plainTextLimit);
  284. }
  285. }
  286. /// <exception cref="IOException"/>
  287. protected virtual void CheckReceivedChangeCipherSpec(bool expected)
  288. {
  289. if (expected != m_receivedChangeCipherSpec)
  290. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  291. }
  292. /// <exception cref="IOException"/>
  293. protected virtual void BlockForHandshake()
  294. {
  295. while (m_connectionState != CS_END)
  296. {
  297. if (IsClosed)
  298. {
  299. // NOTE: Any close during the handshake should have raised an exception.
  300. throw new TlsFatalAlert(AlertDescription.internal_error);
  301. }
  302. SafeReadRecord();
  303. }
  304. }
  305. protected virtual void handleRenegotiation()
  306. {
  307. // TODO: check whether renegotiation is enabled or not and call BeginHandshake/RefuseRenegotiation accordingly.
  308. BeginHandshake(true);
  309. }
  310. /// <exception cref="IOException"/>
  311. protected virtual void BeginHandshake(bool renegotiation)
  312. {
  313. AbstractTlsContext context = ContextAdmin;
  314. TlsPeer peer = Peer;
  315. this.m_maxHandshakeMessageSize = System.Math.Max(1024, peer.GetMaxHandshakeMessageSize());
  316. this.m_handshakeHash = new DeferredHash(context);
  317. this.m_connectionState = CS_START;
  318. this.m_resumedSession = false;
  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_resumedSession = false;
  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="buf">The buffer where the data will be copied to.</param>
  613. /// <param name="off">The position where the data will be placed in the buffer.</param>
  614. /// <param name="len">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[] buf, int off, int len)
  618. {
  619. if (len < 1)
  620. return 0;
  621. while (m_applicationDataQueue.Available == 0)
  622. {
  623. if (this.m_closed)
  624. {
  625. if (this.m_failedWithError)
  626. throw new IOException("Cannot read application data on failed TLS connection");
  627. return -1;
  628. }
  629. if (!m_appDataReady)
  630. throw new InvalidOperationException("Cannot read application data until initial handshake completed.");
  631. /*
  632. * NOTE: Only called more than once when empty records are received, so no special
  633. * InterruptedIOException handling is necessary.
  634. */
  635. SafeReadRecord();
  636. }
  637. len = System.Math.Min(len, m_applicationDataQueue.Available);
  638. m_applicationDataQueue.RemoveData(buf, off, len, 0);
  639. return len;
  640. }
  641. public int TestApplicationData()
  642. {
  643. while (m_applicationDataQueue.Available == 0)
  644. {
  645. if (this.m_closed)
  646. {
  647. if (this.m_failedWithError)
  648. throw new IOException("Cannot read application data on failed TLS connection");
  649. return -1;
  650. }
  651. if (!m_appDataReady)
  652. throw new InvalidOperationException("Cannot read application data until initial handshake completed.");
  653. /*
  654. * NOTE: Only called more than once when empty records are received, so no special
  655. * InterruptedIOException handling is necessary.
  656. */
  657. SafeReadRecord();
  658. }
  659. return m_applicationDataQueue.Available;
  660. }
  661. /// <exception cref="IOException"/>
  662. protected virtual RecordPreview SafePreviewRecordHeader(byte[] recordHeader)
  663. {
  664. try
  665. {
  666. return m_recordStream.PreviewRecordHeader(recordHeader);
  667. }
  668. catch (TlsFatalAlert e)
  669. {
  670. HandleException(e.AlertDescription, "Failed to read record", e);
  671. throw e;
  672. }
  673. catch (IOException e)
  674. {
  675. HandleException(AlertDescription.internal_error, "Failed to read record", e);
  676. throw e;
  677. }
  678. catch (Exception e)
  679. {
  680. HandleException(AlertDescription.internal_error, "Failed to read record", e);
  681. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  682. }
  683. }
  684. /// <exception cref="IOException"/>
  685. protected virtual void SafeReadRecord()
  686. {
  687. try
  688. {
  689. if (m_recordStream.ReadRecord())
  690. return;
  691. if (!m_appDataReady)
  692. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  693. if (!Peer.RequiresCloseNotify())
  694. {
  695. HandleClose(false);
  696. return;
  697. }
  698. }
  699. catch (TlsFatalAlertReceived e)
  700. {
  701. // Connection failure already handled at source
  702. throw e;
  703. }
  704. catch (TlsFatalAlert e)
  705. {
  706. HandleException(e.AlertDescription, "Failed to read record", e);
  707. throw e;
  708. }
  709. catch (IOException e)
  710. {
  711. HandleException(AlertDescription.internal_error, "Failed to read record", e);
  712. throw e;
  713. }
  714. catch (Exception e)
  715. {
  716. HandleException(AlertDescription.internal_error, "Failed to read record", e);
  717. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  718. }
  719. HandleFailure();
  720. throw new TlsNoCloseNotifyException();
  721. }
  722. /// <exception cref="IOException"/>
  723. protected virtual bool SafeReadFullRecord(byte[] input, int inputOff, int inputLen)
  724. {
  725. try
  726. {
  727. return m_recordStream.ReadFullRecord(input, inputOff, inputLen);
  728. }
  729. catch (TlsFatalAlert e)
  730. {
  731. HandleException(e.AlertDescription, "Failed to process record", e);
  732. throw e;
  733. }
  734. catch (IOException e)
  735. {
  736. HandleException(AlertDescription.internal_error, "Failed to process record", e);
  737. throw e;
  738. }
  739. catch (Exception e)
  740. {
  741. HandleException(AlertDescription.internal_error, "Failed to process record", e);
  742. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  743. }
  744. }
  745. /// <exception cref="IOException"/>
  746. protected virtual void SafeWriteRecord(short type, byte[] buf, int offset, int len)
  747. {
  748. try
  749. {
  750. m_recordStream.WriteRecord(type, buf, offset, len);
  751. }
  752. catch (TlsFatalAlert e)
  753. {
  754. HandleException(e.AlertDescription, "Failed to write record", e);
  755. throw e;
  756. }
  757. catch (IOException e)
  758. {
  759. HandleException(AlertDescription.internal_error, "Failed to write record", e);
  760. throw e;
  761. }
  762. catch (Exception e)
  763. {
  764. HandleException(AlertDescription.internal_error, "Failed to write record", e);
  765. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  766. }
  767. }
  768. /// <summary>Write some application data.</summary>
  769. /// <remarks>
  770. /// Fragmentation is handled internally. Usable in both blocking/non-blocking modes.<br/><br/>
  771. /// In blocking mode, the output will be automatically sent via the underlying transport. In non-blocking mode,
  772. /// call <see cref="ReadOutput(byte[], int, int)"/> to get the output bytes to send to the peer.<br/><br/>
  773. /// This method must not be called until after the initial handshake is complete. Attempting to call it earlier
  774. /// will result in an <see cref="InvalidOperationException"/>.
  775. /// </remarks>
  776. /// <param name="buf">The buffer containing application data to send.</param>
  777. /// <param name="off">The offset at which the application data begins</param>
  778. /// <param name="len">The number of bytes of application data.</param>
  779. /// <exception cref="InvalidOperationException">If called before the initial handshake has completed.
  780. /// </exception>
  781. /// <exception cref="IOException">If connection is already closed, or for encryption or transport errors.
  782. /// </exception>
  783. public virtual void WriteApplicationData(byte[] buf, int off, int len)
  784. {
  785. if (!m_appDataReady)
  786. throw new InvalidOperationException(
  787. "Cannot write application data until initial handshake completed.");
  788. lock (m_recordWriteLock)
  789. {
  790. while (len > 0)
  791. {
  792. if (m_closed)
  793. throw new IOException("Cannot write application data on closed/failed TLS connection");
  794. /*
  795. * RFC 5246 6.2.1. Zero-length fragments of Application data MAY be sent as they are
  796. * potentially useful as a traffic analysis countermeasure.
  797. *
  798. * NOTE: Actually, implementations appear to have settled on 1/n-1 record splitting.
  799. */
  800. if (m_appDataSplitEnabled)
  801. {
  802. /*
  803. * Protect against known IV attack!
  804. *
  805. * DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
  806. */
  807. switch (m_appDataSplitMode)
  808. {
  809. case ADS_MODE_0_N_FIRSTONLY:
  810. {
  811. this.m_appDataSplitEnabled = false;
  812. SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
  813. break;
  814. }
  815. case ADS_MODE_0_N:
  816. {
  817. SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
  818. break;
  819. }
  820. case ADS_MODE_1_Nsub1:
  821. default:
  822. {
  823. if (len > 1)
  824. {
  825. SafeWriteRecord(ContentType.application_data, buf, off, 1);
  826. ++off;
  827. --len;
  828. }
  829. break;
  830. }
  831. }
  832. }
  833. else if (m_keyUpdateEnabled)
  834. {
  835. if (m_keyUpdatePendingSend)
  836. {
  837. Send13KeyUpdate(false);
  838. }
  839. else if (m_recordStream.NeedsKeyUpdate())
  840. {
  841. Send13KeyUpdate(true);
  842. }
  843. }
  844. // Fragment data according to the current fragment limit.
  845. int toWrite = System.Math.Min(len, m_recordStream.PlaintextLimit);
  846. SafeWriteRecord(ContentType.application_data, buf, off, toWrite);
  847. off += toWrite;
  848. len -= toWrite;
  849. }
  850. }
  851. }
  852. public virtual int AppDataSplitMode
  853. {
  854. get { return m_appDataSplitMode; }
  855. set
  856. {
  857. if (value < ADS_MODE_1_Nsub1 || value > ADS_MODE_0_N_FIRSTONLY)
  858. throw new InvalidOperationException("Illegal appDataSplitMode mode: " + value);
  859. this.m_appDataSplitMode = value;
  860. }
  861. }
  862. public virtual bool IsResumableHandshake
  863. {
  864. get { return m_resumableHandshake; }
  865. set { this.m_resumableHandshake = value; }
  866. }
  867. /// <exception cref="IOException"/>
  868. internal void WriteHandshakeMessage(byte[] buf, int off, int len)
  869. {
  870. if (len < 4)
  871. throw new TlsFatalAlert(AlertDescription.internal_error);
  872. short type = TlsUtilities.ReadUint8(buf, off);
  873. switch (type)
  874. {
  875. /*
  876. * These message types aren't included in the transcript.
  877. */
  878. case HandshakeType.hello_request:
  879. case HandshakeType.key_update:
  880. break;
  881. /*
  882. * Not included in the transcript for (D)TLS 1.3+
  883. */
  884. case HandshakeType.new_session_ticket:
  885. {
  886. ProtocolVersion negotiatedVersion = Context.ServerVersion;
  887. if (null != negotiatedVersion && !TlsUtilities.IsTlsV13(negotiatedVersion))
  888. {
  889. m_handshakeHash.Update(buf, off, len);
  890. }
  891. break;
  892. }
  893. /*
  894. * These message types are deferred to the writer to explicitly update the transcript.
  895. */
  896. case HandshakeType.client_hello:
  897. break;
  898. /*
  899. * For all others we automatically update the transcript.
  900. */
  901. default:
  902. {
  903. m_handshakeHash.Update(buf, off, len);
  904. break;
  905. }
  906. }
  907. int total = 0;
  908. do
  909. {
  910. // Fragment data according to the current fragment limit.
  911. int toWrite = System.Math.Min(len - total, m_recordStream.PlaintextLimit);
  912. SafeWriteRecord(ContentType.handshake, buf, off + total, toWrite);
  913. total += toWrite;
  914. }
  915. while (total < len);
  916. }
  917. /// <summary>The secure bidirectional stream for this connection</summary>
  918. /// <remarks>Only allowed in blocking mode.</remarks>
  919. public virtual Stream Stream
  920. {
  921. get
  922. {
  923. if (!m_blocking)
  924. throw new InvalidOperationException(
  925. "Cannot use Stream in non-blocking mode! Use OfferInput()/OfferOutput() instead.");
  926. return this.m_tlsStream;
  927. }
  928. }
  929. /// <summary>Should be called in non-blocking mode when the input data reaches EOF.</summary>
  930. /// <exception cref="IOException"/>
  931. public virtual void CloseInput()
  932. {
  933. if (m_blocking)
  934. throw new InvalidOperationException("Cannot use CloseInput() in blocking mode!");
  935. if (m_closed)
  936. return;
  937. if (m_inputBuffers.Available > 0)
  938. throw new EndOfStreamException();
  939. if (!m_appDataReady)
  940. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  941. if (!Peer.RequiresCloseNotify())
  942. {
  943. HandleClose(false);
  944. return;
  945. }
  946. HandleFailure();
  947. throw new TlsNoCloseNotifyException();
  948. }
  949. /// <exception cref="IOException"/>
  950. public virtual RecordPreview PreviewInputRecord(byte[] recordHeader)
  951. {
  952. if (m_blocking)
  953. throw new InvalidOperationException("Cannot use PreviewInputRecord() in blocking mode!");
  954. if (m_inputBuffers.Available != 0)
  955. throw new InvalidOperationException("Can only use PreviewInputRecord() for record-aligned input.");
  956. if (m_closed)
  957. throw new IOException("Connection is closed, cannot accept any more input");
  958. return SafePreviewRecordHeader(recordHeader);
  959. }
  960. /// <exception cref="IOException"/>
  961. public virtual RecordPreview PreviewOutputRecord(int applicationDataSize)
  962. {
  963. if (!m_appDataReady)
  964. throw new InvalidOperationException(
  965. "Cannot use PreviewOutputRecord() until initial handshake completed.");
  966. if (m_blocking)
  967. throw new InvalidOperationException("Cannot use PreviewOutputRecord() in blocking mode!");
  968. if (m_outputBuffer.Buffer.Available != 0)
  969. throw new InvalidOperationException("Can only use PreviewOutputRecord() for record-aligned output.");
  970. if (m_closed)
  971. throw new IOException("Connection is closed, cannot produce any more output");
  972. if (applicationDataSize < 1)
  973. return new RecordPreview(0, 0);
  974. if (m_appDataSplitEnabled)
  975. {
  976. switch (m_appDataSplitMode)
  977. {
  978. case ADS_MODE_0_N_FIRSTONLY:
  979. case ADS_MODE_0_N:
  980. {
  981. RecordPreview a = m_recordStream.PreviewOutputRecord(0);
  982. RecordPreview b = m_recordStream.PreviewOutputRecord(applicationDataSize);
  983. return RecordPreview.CombineAppData(a, b);
  984. }
  985. case ADS_MODE_1_Nsub1:
  986. default:
  987. {
  988. RecordPreview a = m_recordStream.PreviewOutputRecord(1);
  989. if (applicationDataSize > 1)
  990. {
  991. RecordPreview b = m_recordStream.PreviewOutputRecord(applicationDataSize - 1);
  992. a = RecordPreview.CombineAppData(a, b);
  993. }
  994. return a;
  995. }
  996. }
  997. }
  998. else
  999. {
  1000. RecordPreview a = m_recordStream.PreviewOutputRecord(applicationDataSize);
  1001. if (m_keyUpdateEnabled && (m_keyUpdatePendingSend || m_recordStream.NeedsKeyUpdate()))
  1002. {
  1003. int keyUpdateLength = HandshakeMessageOutput.GetLength(1);
  1004. int recordSize = m_recordStream.PreviewOutputRecordSize(keyUpdateLength);
  1005. a = RecordPreview.ExtendRecordSize(a, recordSize);
  1006. }
  1007. return a;
  1008. }
  1009. }
  1010. /// <summary>Equivalent to <code>OfferInput(input, 0, input.Length)</code>.</summary>
  1011. /// <param name="input">The input buffer to offer.</param>
  1012. /// <exception cref="IOException"/>
  1013. /// <seealso cref="OfferInput(byte[], int, int)"/>
  1014. public virtual void OfferInput(byte[] input)
  1015. {
  1016. OfferInput(input, 0, input.Length);
  1017. }
  1018. /// <summary>Offer input from an arbitrary source.</summary>
  1019. /// <remarks>Only allowed in non-blocking mode.<br/><br/>
  1020. /// This method will decrypt and process all records that are fully available. If only part of a record is
  1021. /// available, the buffer will be retained until the remainder of the record is offered.<br/><br/>
  1022. /// If any records containing application data were processed, the decrypted data can be obtained using
  1023. /// <see cref="ReadInput(byte[], int, int)"/>. If any records containing protocol data were processed, a
  1024. /// response may have been generated. You should always check to see if there is any available output after
  1025. /// calling this method by calling <see cref="GetAvailableOutputBytes"/>.
  1026. /// </remarks>
  1027. /// <param name="input">The input buffer to offer.</param>
  1028. /// <param name="inputOff">The offset within the input buffer that input begins.</param>
  1029. /// <param name="inputLen">The number of bytes of input being offered.</param>
  1030. /// <exception cref="IOException">If an error occurs while decrypting or processing a record.</exception>
  1031. public virtual void OfferInput(byte[] input, int inputOff, int inputLen)
  1032. {
  1033. if (m_blocking)
  1034. throw new InvalidOperationException("Cannot use OfferInput() in blocking mode! Use Stream instead.");
  1035. if (m_closed)
  1036. throw new IOException("Connection is closed, cannot accept any more input");
  1037. // Fast path if the input is arriving one record at a time
  1038. if (m_inputBuffers.Available == 0 && SafeReadFullRecord(input, inputOff, inputLen))
  1039. {
  1040. if (m_closed)
  1041. {
  1042. if (!m_appDataReady)
  1043. {
  1044. // NOTE: Any close during the handshake should have raised an exception.
  1045. throw new TlsFatalAlert(AlertDescription.internal_error);
  1046. }
  1047. }
  1048. return;
  1049. }
  1050. m_inputBuffers.AddBytes(input, inputOff, inputLen);
  1051. // loop while there are enough bytes to read the length of the next record
  1052. while (m_inputBuffers.Available >= RecordFormat.FragmentOffset)
  1053. {
  1054. byte[] recordHeader = new byte[RecordFormat.FragmentOffset];
  1055. if (RecordFormat.FragmentOffset != m_inputBuffers.Peek(recordHeader))
  1056. throw new TlsFatalAlert(AlertDescription.internal_error);
  1057. RecordPreview preview = SafePreviewRecordHeader(recordHeader);
  1058. if (m_inputBuffers.Available < preview.RecordSize)
  1059. {
  1060. // not enough bytes to read a whole record
  1061. break;
  1062. }
  1063. // NOTE: This is actually reading from inputBuffers, so InterruptedIOException shouldn't be possible
  1064. SafeReadRecord();
  1065. if (m_closed)
  1066. {
  1067. if (!m_appDataReady)
  1068. {
  1069. // NOTE: Any close during the handshake should have raised an exception.
  1070. throw new TlsFatalAlert(AlertDescription.internal_error);
  1071. }
  1072. break;
  1073. }
  1074. }
  1075. }
  1076. public virtual int ApplicationDataLimit
  1077. {
  1078. get { return m_recordStream.PlaintextLimit; }
  1079. }
  1080. /// <summary>Gets the amount of received application data.</summary>
  1081. /// <remarks>A call to <see cref="readInput(byte[], int, int)"/> is guaranteed to be able to return at least
  1082. /// this much data.<br/><br/>
  1083. /// Only allowed in non-blocking mode.
  1084. /// </remarks>
  1085. /// <returns>The number of bytes of available application data.</returns>
  1086. public virtual int GetAvailableInputBytes()
  1087. {
  1088. if (m_blocking)
  1089. throw new InvalidOperationException("Cannot use GetAvailableInputBytes() in blocking mode!");
  1090. return ApplicationDataAvailable;
  1091. }
  1092. /// <summary>Retrieves received application data.</summary>
  1093. /// <remarks>
  1094. /// Use <see cref="GetAvailableInputBytes"/> to check how much application data is currently available. This
  1095. /// method functions similarly to <see cref="Stream.Read(byte[], int, int)"/>, except that it never blocks. If
  1096. /// no data is available, nothing will be copied and zero will be returned.<br/><br/>
  1097. /// Only allowed in non-blocking mode.
  1098. /// </remarks>
  1099. /// <param name="buf">The buffer to hold the application data.</param>
  1100. /// <param name="off">The start offset in the buffer at which the data is written.</param>
  1101. /// <param name="len">The maximum number of bytes to read.</param>
  1102. /// <returns>The total number of bytes copied to the buffer. May be less than the length specified if the
  1103. /// length was greater than the amount of available data.</returns>
  1104. public virtual int ReadInput(byte[] buf, int off, int len)
  1105. {
  1106. if (m_blocking)
  1107. throw new InvalidOperationException("Cannot use ReadInput() in blocking mode! Use Stream instead.");
  1108. len = System.Math.Min(len, ApplicationDataAvailable);
  1109. if (len < 1)
  1110. return 0;
  1111. m_applicationDataQueue.RemoveData(buf, off, len, 0);
  1112. return len;
  1113. }
  1114. /// <summary>Gets the amount of encrypted data available to be sent.</summary>
  1115. /// <remarks>
  1116. /// A call to <see cref="ReadOutput(byte[], int, int)"/> is guaranteed to be able to return at least this much
  1117. /// data. Only allowed in non-blocking mode.
  1118. /// </remarks>
  1119. /// <returns>The number of bytes of available encrypted data.</returns>
  1120. public virtual int GetAvailableOutputBytes()
  1121. {
  1122. if (m_blocking)
  1123. throw new InvalidOperationException("Cannot use GetAvailableOutputBytes() in blocking mode! Use Stream instead.");
  1124. return m_outputBuffer.Buffer.Available;
  1125. }
  1126. /// <summary>Retrieves encrypted data to be sent.</summary>
  1127. /// <remarks>
  1128. /// Use <see cref="GetAvailableOutputBytes"/> to check how much encrypted data is currently available. This
  1129. /// method functions similarly to <see cref="Stream.Read(byte[], int, int)"/>, except that it never blocks. If
  1130. /// no data is available, nothing will be copied and zero will be returned. Only allowed in non-blocking mode.
  1131. /// </remarks>
  1132. /// <param name="buffer">The buffer to hold the encrypted data.</param>
  1133. /// <param name="offset">The start offset in the buffer at which the data is written.</param>
  1134. /// <param name="length">The maximum number of bytes to read.</param>
  1135. /// <returns>The total number of bytes copied to the buffer. May be less than the length specified if the
  1136. /// length was greater than the amount of available data.</returns>
  1137. public virtual int ReadOutput(byte[] buffer, int offset, int length)
  1138. {
  1139. if (m_blocking)
  1140. throw new InvalidOperationException("Cannot use ReadOutput() in blocking mode! Use 'Stream() instead.");
  1141. int bytesToRead = System.Math.Min(GetAvailableOutputBytes(), length);
  1142. m_outputBuffer.Buffer.RemoveData(buffer, offset, bytesToRead, 0);
  1143. return bytesToRead;
  1144. }
  1145. protected virtual bool EstablishSession(TlsSession sessionToResume)
  1146. {
  1147. this.m_tlsSession = null;
  1148. this.m_sessionParameters = null;
  1149. this.m_sessionMasterSecret = null;
  1150. if (null == sessionToResume || !sessionToResume.IsResumable)
  1151. return false;
  1152. SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
  1153. if (null == sessionParameters)
  1154. return false;
  1155. if (!sessionParameters.IsExtendedMasterSecret)
  1156. {
  1157. TlsPeer peer = Peer;
  1158. if (!peer.AllowLegacyResumption() || peer.RequiresExtendedMasterSecret())
  1159. return false;
  1160. /*
  1161. * NOTE: For session resumption without extended_master_secret, renegotiation MUST be
  1162. * disabled (see RFC 7627 5.4). We currently do not implement renegotiation and it is
  1163. * unlikely we ever would since it was removed in TLS 1.3.
  1164. */
  1165. }
  1166. TlsSecret sessionMasterSecret = TlsUtilities.GetSessionMasterSecret(Context.Crypto,
  1167. sessionParameters.MasterSecret);
  1168. if (null == sessionMasterSecret)
  1169. return false;
  1170. this.m_tlsSession = sessionToResume;
  1171. this.m_sessionParameters = sessionParameters;
  1172. this.m_sessionMasterSecret = sessionMasterSecret;
  1173. return true;
  1174. }
  1175. protected virtual void InvalidateSession()
  1176. {
  1177. if (m_sessionMasterSecret != null)
  1178. {
  1179. m_sessionMasterSecret.Destroy();
  1180. this.m_sessionMasterSecret = null;
  1181. }
  1182. if (m_sessionParameters != null)
  1183. {
  1184. m_sessionParameters.Clear();
  1185. this.m_sessionParameters = null;
  1186. }
  1187. if (m_tlsSession != null)
  1188. {
  1189. m_tlsSession.Invalidate();
  1190. this.m_tlsSession = null;
  1191. }
  1192. }
  1193. /// <exception cref="IOException"/>
  1194. protected virtual void ProcessFinishedMessage(MemoryStream buf)
  1195. {
  1196. TlsContext context = Context;
  1197. SecurityParameters securityParameters = context.SecurityParameters;
  1198. bool isServerContext = context.IsServer;
  1199. byte[] verify_data = TlsUtilities.ReadFully(securityParameters.VerifyDataLength, buf);
  1200. AssertEmpty(buf);
  1201. byte[] expected_verify_data = TlsUtilities.CalculateVerifyData(context, m_handshakeHash, !isServerContext);
  1202. /*
  1203. * Compare both checksums.
  1204. */
  1205. if (!Arrays.ConstantTimeAreEqual(expected_verify_data, verify_data))
  1206. {
  1207. /*
  1208. * Wrong checksum in the finished message.
  1209. */
  1210. throw new TlsFatalAlert(AlertDescription.decrypt_error);
  1211. }
  1212. securityParameters.m_peerVerifyData = expected_verify_data;
  1213. if (!m_resumedSession || securityParameters.IsExtendedMasterSecret)
  1214. {
  1215. if (null == securityParameters.LocalVerifyData)
  1216. {
  1217. securityParameters.m_tlsUnique = expected_verify_data;
  1218. }
  1219. }
  1220. }
  1221. /// <exception cref="IOException"/>
  1222. protected virtual void Process13FinishedMessage(MemoryStream buf)
  1223. {
  1224. TlsContext context = Context;
  1225. SecurityParameters securityParameters = context.SecurityParameters;
  1226. bool isServerContext = context.IsServer;
  1227. byte[] verify_data = TlsUtilities.ReadFully(securityParameters.VerifyDataLength, buf);
  1228. AssertEmpty(buf);
  1229. byte[] expected_verify_data = TlsUtilities.CalculateVerifyData(context, m_handshakeHash, !isServerContext);
  1230. /*
  1231. * Compare both checksums.
  1232. */
  1233. if (!Arrays.ConstantTimeAreEqual(expected_verify_data, verify_data))
  1234. {
  1235. /*
  1236. * Wrong checksum in the finished message.
  1237. */
  1238. throw new TlsFatalAlert(AlertDescription.decrypt_error);
  1239. }
  1240. securityParameters.m_peerVerifyData = expected_verify_data;
  1241. securityParameters.m_tlsUnique = null;
  1242. }
  1243. /// <exception cref="IOException"/>
  1244. protected virtual void RaiseAlertFatal(short alertDescription, string message, Exception cause)
  1245. {
  1246. Peer.NotifyAlertRaised(AlertLevel.fatal, alertDescription, message, cause);
  1247. byte[] alert = new byte[]{ (byte)AlertLevel.fatal, (byte)alertDescription };
  1248. try
  1249. {
  1250. m_recordStream.WriteRecord(ContentType.alert, alert, 0, 2);
  1251. }
  1252. catch (Exception)
  1253. {
  1254. // We are already processing an exception, so just ignore this
  1255. }
  1256. }
  1257. /// <exception cref="IOException"/>
  1258. protected virtual void RaiseAlertWarning(short alertDescription, string message)
  1259. {
  1260. Peer.NotifyAlertRaised(AlertLevel.warning, alertDescription, message, null);
  1261. byte[] alert = new byte[]{ (byte)AlertLevel.warning, (byte)alertDescription };
  1262. SafeWriteRecord(ContentType.alert, alert, 0, 2);
  1263. }
  1264. /// <exception cref="IOException"/>
  1265. protected virtual void Receive13KeyUpdate(MemoryStream buf)
  1266. {
  1267. // TODO[tls13] This is interesting enough to notify the TlsPeer for possible logging/vetting
  1268. if (!(m_appDataReady && m_keyUpdateEnabled))
  1269. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  1270. short requestUpdate = TlsUtilities.ReadUint8(buf);
  1271. AssertEmpty(buf);
  1272. if (!KeyUpdateRequest.IsValid(requestUpdate))
  1273. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  1274. bool updateRequested = (KeyUpdateRequest.update_requested == requestUpdate);
  1275. TlsUtilities.Update13TrafficSecretPeer(Context);
  1276. m_recordStream.NotifyKeyUpdateReceived();
  1277. //this.m_keyUpdatePendingReceive &= updateRequested;
  1278. this.m_keyUpdatePendingSend |= updateRequested;
  1279. }
  1280. /// <exception cref="IOException"/>
  1281. protected virtual void SendCertificateMessage(Certificate certificate, Stream endPointHash)
  1282. {
  1283. TlsContext context = Context;
  1284. SecurityParameters securityParameters = context.SecurityParameters;
  1285. if (null != securityParameters.LocalCertificate)
  1286. throw new TlsFatalAlert(AlertDescription.internal_error);
  1287. if (null == certificate)
  1288. {
  1289. certificate = Certificate.EmptyChain;
  1290. }
  1291. if (certificate.IsEmpty && !context.IsServer && securityParameters.NegotiatedVersion.IsSsl)
  1292. {
  1293. string message = "SSLv3 client didn't provide credentials";
  1294. RaiseAlertWarning(AlertDescription.no_certificate, message);
  1295. }
  1296. else
  1297. {
  1298. HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.certificate);
  1299. certificate.Encode(context, message, endPointHash);
  1300. message.Send(this);
  1301. }
  1302. securityParameters.m_localCertificate = certificate;
  1303. }
  1304. /// <exception cref="IOException"/>
  1305. protected virtual void Send13CertificateMessage(Certificate certificate)
  1306. {
  1307. if (null == certificate)
  1308. throw new TlsFatalAlert(AlertDescription.internal_error);
  1309. TlsContext context = Context;
  1310. SecurityParameters securityParameters = context.SecurityParameters;
  1311. if (null != securityParameters.LocalCertificate)
  1312. throw new TlsFatalAlert(AlertDescription.internal_error);
  1313. HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.certificate);
  1314. certificate.Encode(context, message, null);
  1315. message.Send(this);
  1316. securityParameters.m_localCertificate = certificate;
  1317. }
  1318. /// <exception cref="IOException"/>
  1319. protected virtual void Send13CertificateVerifyMessage(DigitallySigned certificateVerify)
  1320. {
  1321. HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.certificate_verify);
  1322. certificateVerify.Encode(message);
  1323. message.Send(this);
  1324. }
  1325. /// <exception cref="IOException"/>
  1326. protected virtual void SendChangeCipherSpec()
  1327. {
  1328. SendChangeCipherSpecMessage();
  1329. m_recordStream.EnablePendingCipherWrite();
  1330. }
  1331. /// <exception cref="IOException"/>
  1332. protected virtual void SendChangeCipherSpecMessage()
  1333. {
  1334. byte[] message = new byte[]{ 1 };
  1335. SafeWriteRecord(ContentType.change_cipher_spec, message, 0, message.Length);
  1336. }
  1337. /// <exception cref="IOException"/>
  1338. protected virtual void SendFinishedMessage()
  1339. {
  1340. TlsContext context = Context;
  1341. SecurityParameters securityParameters = context.SecurityParameters;
  1342. bool isServerContext = context.IsServer;
  1343. byte[] verify_data = TlsUtilities.CalculateVerifyData(context, m_handshakeHash, isServerContext);
  1344. securityParameters.m_localVerifyData = verify_data;
  1345. if (!m_resumedSession || securityParameters.IsExtendedMasterSecret)
  1346. {
  1347. if (null == securityParameters.PeerVerifyData)
  1348. {
  1349. securityParameters.m_tlsUnique = verify_data;
  1350. }
  1351. }
  1352. HandshakeMessageOutput.Send(this, HandshakeType.finished, verify_data);
  1353. }
  1354. /// <exception cref="IOException"/>
  1355. protected virtual void Send13FinishedMessage()
  1356. {
  1357. TlsContext context = Context;
  1358. SecurityParameters securityParameters = context.SecurityParameters;
  1359. bool isServerContext = context.IsServer;
  1360. byte[] verify_data = TlsUtilities.CalculateVerifyData(context, m_handshakeHash, isServerContext);
  1361. securityParameters.m_localVerifyData = verify_data;
  1362. securityParameters.m_tlsUnique = null;
  1363. HandshakeMessageOutput.Send(this, HandshakeType.finished, verify_data);
  1364. }
  1365. /// <exception cref="IOException"/>
  1366. protected virtual void Send13KeyUpdate(bool updateRequested)
  1367. {
  1368. // TODO[tls13] This is interesting enough to notify the TlsPeer for possible logging/vetting
  1369. if (!(m_appDataReady && m_keyUpdateEnabled))
  1370. throw new TlsFatalAlert(AlertDescription.internal_error);
  1371. short requestUpdate = updateRequested
  1372. ? KeyUpdateRequest.update_requested
  1373. : KeyUpdateRequest.update_not_requested;
  1374. HandshakeMessageOutput.Send(this, HandshakeType.key_update, TlsUtilities.EncodeUint8(requestUpdate));
  1375. TlsUtilities.Update13TrafficSecretLocal(Context);
  1376. m_recordStream.NotifyKeyUpdateSent();
  1377. //this.m_keyUpdatePendingReceive |= updateRequested;
  1378. this.m_keyUpdatePendingSend &= updateRequested;
  1379. }
  1380. /// <exception cref="IOException"/>
  1381. protected virtual void SendSupplementalDataMessage(IList supplementalData)
  1382. {
  1383. HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.supplemental_data);
  1384. WriteSupplementalData(message, supplementalData);
  1385. message.Send(this);
  1386. }
  1387. public virtual void Close()
  1388. {
  1389. HandleClose(true);
  1390. }
  1391. public virtual void Flush()
  1392. {
  1393. }
  1394. internal bool IsApplicationDataReady
  1395. {
  1396. get { return m_appDataReady; }
  1397. }
  1398. public virtual bool IsClosed
  1399. {
  1400. get { return m_closed; }
  1401. }
  1402. public virtual bool IsConnected
  1403. {
  1404. get
  1405. {
  1406. if (m_closed)
  1407. return false;
  1408. AbstractTlsContext context = ContextAdmin;
  1409. return null != context && context.IsConnected;
  1410. }
  1411. }
  1412. public virtual bool IsHandshaking
  1413. {
  1414. get
  1415. {
  1416. if (m_closed)
  1417. return false;
  1418. AbstractTlsContext context = ContextAdmin;
  1419. return null != context && context.IsHandshaking;
  1420. }
  1421. }
  1422. /// <exception cref="IOException"/>
  1423. protected virtual short ProcessMaxFragmentLengthExtension(IDictionary clientExtensions,
  1424. IDictionary serverExtensions, short alertDescription)
  1425. {
  1426. short maxFragmentLength = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions);
  1427. if (maxFragmentLength >= 0)
  1428. {
  1429. if (!MaxFragmentLength.IsValid(maxFragmentLength)
  1430. || (!m_resumedSession &&
  1431. maxFragmentLength != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions)))
  1432. {
  1433. throw new TlsFatalAlert(alertDescription);
  1434. }
  1435. }
  1436. return maxFragmentLength;
  1437. }
  1438. /// <exception cref="IOException"/>
  1439. protected virtual void RefuseRenegotiation()
  1440. {
  1441. /*
  1442. * RFC 5746 4.5 SSLv3 clients [..] SHOULD use a fatal handshake_failure alert.
  1443. */
  1444. if (TlsUtilities.IsSsl(Context))
  1445. throw new TlsFatalAlert(AlertDescription.handshake_failure);
  1446. RaiseAlertWarning(AlertDescription.no_renegotiation, "Renegotiation not supported");
  1447. }
  1448. /// <summary>Make sure the <see cref="Stream"/> 'buf' is now empty. Fail otherwise.</summary>
  1449. /// <param name="buf">The <see cref="Stream"/> to check.</param>
  1450. /// <exception cref="IOException"/>
  1451. internal static void AssertEmpty(MemoryStream buf)
  1452. {
  1453. if (buf.Position < buf.Length)
  1454. throw new TlsFatalAlert(AlertDescription.decode_error);
  1455. }
  1456. internal static byte[] CreateRandomBlock(bool useGmtUnixTime, TlsContext context)
  1457. {
  1458. byte[] result = context.NonceGenerator.GenerateNonce(32);
  1459. if (useGmtUnixTime)
  1460. {
  1461. TlsUtilities.WriteGmtUnixTime(result, 0);
  1462. }
  1463. return result;
  1464. }
  1465. /// <exception cref="IOException"/>
  1466. internal static byte[] CreateRenegotiationInfo(byte[] renegotiated_connection)
  1467. {
  1468. return TlsUtilities.EncodeOpaque8(renegotiated_connection);
  1469. }
  1470. /// <exception cref="IOException"/>
  1471. internal static void EstablishMasterSecret(TlsContext context, TlsKeyExchange keyExchange)
  1472. {
  1473. TlsSecret preMasterSecret = keyExchange.GeneratePreMasterSecret();
  1474. if (preMasterSecret == null)
  1475. throw new TlsFatalAlert(AlertDescription.internal_error);
  1476. try
  1477. {
  1478. context.SecurityParameters.m_masterSecret = TlsUtilities.CalculateMasterSecret(context,
  1479. preMasterSecret);
  1480. if (context.SecurityParameters.NegotiatedVersion != ProtocolVersion.TLSv13)
  1481. KeyLogFileWriter.WriteLabel(Labels.CLIENT_RANDOM, context.SecurityParameters);
  1482. }
  1483. finally
  1484. {
  1485. /*
  1486. * RFC 2246 8.1. The pre_master_secret should be deleted from memory once the
  1487. * master_secret has been computed.
  1488. */
  1489. preMasterSecret.Destroy();
  1490. }
  1491. }
  1492. /// <exception cref="IOException"/>
  1493. internal static IDictionary ReadExtensions(MemoryStream input)
  1494. {
  1495. if (input.Position >= input.Length)
  1496. return null;
  1497. byte[] extBytes = TlsUtilities.ReadOpaque16(input);
  1498. AssertEmpty(input);
  1499. return ReadExtensionsData(extBytes);
  1500. }
  1501. /// <exception cref="IOException"/>
  1502. internal static IDictionary ReadExtensionsData(byte[] extBytes)
  1503. {
  1504. // Int32 -> byte[]
  1505. IDictionary extensions = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
  1506. if (extBytes.Length > 0)
  1507. {
  1508. MemoryStream buf = new MemoryStream(extBytes, false);
  1509. do
  1510. {
  1511. int extension_type = TlsUtilities.ReadUint16(buf);
  1512. byte[] extension_data = TlsUtilities.ReadOpaque16(buf);
  1513. /*
  1514. * RFC 3546 2.3 There MUST NOT be more than one extension of the same type.
  1515. */
  1516. Int32 key = extension_type;
  1517. if (extensions.Contains(key))
  1518. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1519. "Repeated extension: " + ExtensionType.GetText(extension_type));
  1520. extensions.Add(key, extension_data);
  1521. }
  1522. while (buf.Position < buf.Length);
  1523. }
  1524. return extensions;
  1525. }
  1526. /// <exception cref="IOException"/>
  1527. internal static IDictionary ReadExtensionsData13(int handshakeType, byte[] extBytes)
  1528. {
  1529. // Int32 -> byte[]
  1530. IDictionary extensions = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
  1531. if (extBytes.Length > 0)
  1532. {
  1533. MemoryStream buf = new MemoryStream(extBytes, false);
  1534. do
  1535. {
  1536. int extension_type = TlsUtilities.ReadUint16(buf);
  1537. if (!TlsUtilities.IsPermittedExtensionType13(handshakeType, extension_type))
  1538. {
  1539. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1540. "Invalid extension: " + ExtensionType.GetText(extension_type));
  1541. }
  1542. byte[] extension_data = TlsUtilities.ReadOpaque16(buf);
  1543. /*
  1544. * RFC 3546 2.3 There MUST NOT be more than one extension of the same type.
  1545. */
  1546. Int32 key = extension_type;
  1547. if (extensions.Contains(key))
  1548. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1549. "Repeated extension: " + ExtensionType.GetText(extension_type));
  1550. extensions.Add(key, extension_data);
  1551. }
  1552. while (buf.Position < buf.Length);
  1553. }
  1554. return extensions;
  1555. }
  1556. /// <exception cref="IOException"/>
  1557. internal static IDictionary ReadExtensionsDataClientHello(byte[] extBytes)
  1558. {
  1559. /*
  1560. * TODO[tls13] We are currently allowing any extensions to appear in ClientHello. It is
  1561. * somewhat complicated to restrict what can appear based on the specific set of versions
  1562. * the client is offering, and anyway could be fragile since clients may take a
  1563. * "kitchen sink" approach to adding extensions independently of the offered versions.
  1564. */
  1565. // Int32 -> byte[]
  1566. IDictionary extensions = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
  1567. if (extBytes.Length > 0)
  1568. {
  1569. MemoryStream buf = new MemoryStream(extBytes, false);
  1570. int extension_type;
  1571. bool pre_shared_key_found = false;
  1572. do
  1573. {
  1574. extension_type = TlsUtilities.ReadUint16(buf);
  1575. byte[] extension_data = TlsUtilities.ReadOpaque16(buf);
  1576. /*
  1577. * RFC 3546 2.3 There MUST NOT be more than one extension of the same type.
  1578. */
  1579. Int32 key = extension_type;
  1580. if (extensions.Contains(key))
  1581. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1582. "Repeated extension: " + ExtensionType.GetText(extension_type));
  1583. extensions.Add(key, extension_data);
  1584. pre_shared_key_found |= (ExtensionType.pre_shared_key == extension_type);
  1585. }
  1586. while (buf.Position < buf.Length);
  1587. if (pre_shared_key_found && (ExtensionType.pre_shared_key != extension_type))
  1588. throw new TlsFatalAlert(AlertDescription.illegal_parameter,
  1589. "'pre_shared_key' MUST be last in ClientHello");
  1590. }
  1591. return extensions;
  1592. }
  1593. /// <exception cref="IOException"/>
  1594. internal static IList ReadSupplementalDataMessage(MemoryStream input)
  1595. {
  1596. byte[] supp_data = TlsUtilities.ReadOpaque24(input, 1);
  1597. AssertEmpty(input);
  1598. MemoryStream buf = new MemoryStream(supp_data, false);
  1599. IList supplementalData = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
  1600. while (buf.Position < buf.Length)
  1601. {
  1602. int supp_data_type = TlsUtilities.ReadUint16(buf);
  1603. byte[] data = TlsUtilities.ReadOpaque16(buf);
  1604. supplementalData.Add(new SupplementalDataEntry(supp_data_type, data));
  1605. }
  1606. return supplementalData;
  1607. }
  1608. /// <exception cref="IOException"/>
  1609. internal static void WriteExtensions(Stream output, IDictionary extensions)
  1610. {
  1611. WriteExtensions(output, extensions, 0);
  1612. }
  1613. /// <exception cref="IOException"/>
  1614. internal static void WriteExtensions(Stream output, IDictionary extensions, int bindersSize)
  1615. {
  1616. if (null == extensions || extensions.Count < 1)
  1617. return;
  1618. byte[] extBytes = WriteExtensionsData(extensions, bindersSize);
  1619. int lengthWithBinders = extBytes.Length + bindersSize;
  1620. TlsUtilities.CheckUint16(lengthWithBinders);
  1621. TlsUtilities.WriteUint16(lengthWithBinders, output);
  1622. output.Write(extBytes, 0, extBytes.Length);
  1623. }
  1624. /// <exception cref="IOException"/>
  1625. internal static byte[] WriteExtensionsData(IDictionary extensions)
  1626. {
  1627. return WriteExtensionsData(extensions, 0);
  1628. }
  1629. /// <exception cref="IOException"/>
  1630. internal static byte[] WriteExtensionsData(IDictionary extensions, int bindersSize)
  1631. {
  1632. MemoryStream buf = new MemoryStream();
  1633. WriteExtensionsData(extensions, buf, bindersSize);
  1634. return buf.ToArray();
  1635. }
  1636. /// <exception cref="IOException"/>
  1637. internal static void WriteExtensionsData(IDictionary extensions, MemoryStream buf)
  1638. {
  1639. WriteExtensionsData(extensions, buf, 0);
  1640. }
  1641. /// <exception cref="IOException"/>
  1642. internal static void WriteExtensionsData(IDictionary extensions, MemoryStream buf, int bindersSize)
  1643. {
  1644. /*
  1645. * NOTE: There are reports of servers that don't accept a zero-length extension as the last
  1646. * one, so we write out any zero-length ones first as a best-effort workaround.
  1647. */
  1648. WriteSelectedExtensions(buf, extensions, true);
  1649. WriteSelectedExtensions(buf, extensions, false);
  1650. WritePreSharedKeyExtension(buf, extensions, bindersSize);
  1651. }
  1652. /// <exception cref="IOException"/>
  1653. internal static void WritePreSharedKeyExtension(MemoryStream buf, IDictionary extensions, int bindersSize)
  1654. {
  1655. byte[] extension_data = (byte[])extensions[ExtensionType.pre_shared_key];
  1656. if (null != extension_data)
  1657. {
  1658. TlsUtilities.CheckUint16(ExtensionType.pre_shared_key);
  1659. TlsUtilities.WriteUint16(ExtensionType.pre_shared_key, buf);
  1660. int lengthWithBinders = extension_data.Length + bindersSize;
  1661. TlsUtilities.CheckUint16(lengthWithBinders);
  1662. TlsUtilities.WriteUint16(lengthWithBinders, buf);
  1663. buf.Write(extension_data, 0, extension_data.Length);
  1664. }
  1665. }
  1666. /// <exception cref="IOException"/>
  1667. internal static void WriteSelectedExtensions(Stream output, IDictionary extensions, bool selectEmpty)
  1668. {
  1669. foreach (Int32 key in extensions.Keys)
  1670. {
  1671. int extension_type = key;
  1672. // NOTE: Must be last; handled by 'WritePreSharedKeyExtension'
  1673. if (ExtensionType.pre_shared_key == extension_type)
  1674. continue;
  1675. byte[] extension_data = (byte[])extensions[key];
  1676. if (selectEmpty == (extension_data.Length == 0))
  1677. {
  1678. TlsUtilities.CheckUint16(extension_type);
  1679. TlsUtilities.WriteUint16(extension_type, output);
  1680. TlsUtilities.WriteOpaque16(extension_data, output);
  1681. }
  1682. }
  1683. }
  1684. /// <exception cref="IOException"/>
  1685. internal static void WriteSupplementalData(Stream output, IList supplementalData)
  1686. {
  1687. MemoryStream buf = new MemoryStream();
  1688. foreach (SupplementalDataEntry entry in supplementalData)
  1689. {
  1690. int supp_data_type = entry.DataType;
  1691. TlsUtilities.CheckUint16(supp_data_type);
  1692. TlsUtilities.WriteUint16(supp_data_type, buf);
  1693. TlsUtilities.WriteOpaque16(entry.Data, buf);
  1694. }
  1695. byte[] supp_data = buf.ToArray();
  1696. TlsUtilities.WriteOpaque24(supp_data, output);
  1697. }
  1698. }
  1699. }
  1700. #pragma warning restore
  1701. #endif