@@ -23,6 +23,7 @@ internal async Task OnTlsClientHelloAsync(ConnectionContext connection, Cancella
2323 {
2424 var input = connection . Transport . Input ;
2525 ClientHelloParseState parseState = ClientHelloParseState . NotEnoughData ;
26+ short recordLength = - 1 ; // remembers the length of TLS record to not re-parse header on every iteration
2627
2728 while ( true )
2829 {
@@ -38,7 +39,7 @@ internal async Task OnTlsClientHelloAsync(ConnectionContext connection, Cancella
3839 break ;
3940 }
4041
41- parseState = TryParseClientHello ( buffer , out var clientHelloBytes ) ;
42+ parseState = TryParseClientHello ( buffer , ref recordLength , out var clientHelloBytes ) ;
4243 if ( parseState == ClientHelloParseState . NotEnoughData )
4344 {
4445 // if no data will be added, and we still lack enough bytes
@@ -81,10 +82,18 @@ internal async Task OnTlsClientHelloAsync(ConnectionContext connection, Cancella
8182 /// TLS 1.2: https://datatracker.ietf.org/doc/html/rfc5246#section-6.2
8283 /// TLS 1.3: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
8384 /// </summary>
84- private static ClientHelloParseState TryParseClientHello ( ReadOnlySequence < byte > buffer , out ReadOnlySequence < byte > clientHelloBytes )
85+ private static ClientHelloParseState TryParseClientHello ( ReadOnlySequence < byte > buffer , ref short recordLength , out ReadOnlySequence < byte > clientHelloBytes )
8586 {
8687 clientHelloBytes = default ;
8788
89+ // in case bad actor will be sending a TLS client hello one byte at a time
90+ // and we know the expected length of TLS client hello,
91+ // we can check and fail fastly here instead of re-parsing the TLS client hello "header" on each iteration
92+ if ( recordLength != - 1 && buffer . Length < 5 + recordLength )
93+ {
94+ return ClientHelloParseState . NotEnoughData ;
95+ }
96+
8897 if ( buffer . Length < 6 )
8998 {
9099 return ClientHelloParseState . NotEnoughData ;
@@ -105,7 +114,7 @@ private static ClientHelloParseState TryParseClientHello(ReadOnlySequence<byte>
105114 }
106115
107116 // Record length
108- if ( ! reader . TryReadBigEndian ( out short recordLength ) )
117+ if ( ! reader . TryReadBigEndian ( out recordLength ) )
109118 {
110119 return ClientHelloParseState . NotTlsClientHello ;
111120 }
0 commit comments