@@ -216,7 +216,9 @@ private async Task RenegotiateAsync<TIOAdapter>(CancellationToken cancellationTo
216
216
ProtocolToken message ;
217
217
do
218
218
{
219
- message = await ReceiveBlobAsync < TIOAdapter > ( cancellationToken ) . ConfigureAwait ( false ) ;
219
+ int frameSize = await ReceiveTlsFrameAsync < TIOAdapter > ( cancellationToken ) . ConfigureAwait ( false ) ;
220
+ ProcessTlsFrame ( frameSize , out message ) ;
221
+
220
222
if ( message . Size > 0 )
221
223
{
222
224
await TIOAdapter . WriteAsync ( InnerStream , new ReadOnlyMemory < byte > ( message . Payload ! , 0 , message . Size ) , cancellationToken ) . ConfigureAwait ( false ) ;
@@ -245,7 +247,7 @@ private async Task RenegotiateAsync<TIOAdapter>(CancellationToken cancellationTo
245
247
private async Task ForceAuthenticationAsync < TIOAdapter > ( bool receiveFirst , byte [ ] ? reAuthenticationData , CancellationToken cancellationToken )
246
248
where TIOAdapter : IReadWriteAdapter
247
249
{
248
- ProtocolToken message ;
250
+ ProtocolToken message = default ;
249
251
bool handshakeCompleted = false ;
250
252
251
253
if ( reAuthenticationData == null )
@@ -256,12 +258,12 @@ private async Task ForceAuthenticationAsync<TIOAdapter>(bool receiveFirst, byte[
256
258
throw new InvalidOperationException ( SR . Format ( SR . net_io_invalidnestedcall , "authenticate" ) ) ;
257
259
}
258
260
}
259
-
260
261
try
261
262
{
262
263
if ( ! receiveFirst )
263
264
{
264
- message = NextMessage ( reAuthenticationData ) ;
265
+ NextMessage ( reAuthenticationData , out message ) ;
266
+
265
267
if ( message . Size > 0 )
266
268
{
267
269
await TIOAdapter . WriteAsync ( InnerStream , new ReadOnlyMemory < byte > ( message . Payload ! , 0 , message . Size ) , cancellationToken ) . ConfigureAwait ( false ) ;
@@ -289,7 +291,8 @@ private async Task ForceAuthenticationAsync<TIOAdapter>(bool receiveFirst, byte[
289
291
290
292
while ( ! handshakeCompleted )
291
293
{
292
- message = await ReceiveBlobAsync < TIOAdapter > ( cancellationToken ) . ConfigureAwait ( false ) ;
294
+ int frameSize = await ReceiveTlsFrameAsync < TIOAdapter > ( cancellationToken ) . ConfigureAwait ( false ) ;
295
+ ProcessTlsFrame ( frameSize , out message ) ;
293
296
294
297
ReadOnlyMemory < byte > payload = default ;
295
298
if ( message . Size > 0 )
@@ -355,7 +358,8 @@ private async Task ForceAuthenticationAsync<TIOAdapter>(bool receiveFirst, byte[
355
358
356
359
}
357
360
358
- private async ValueTask < ProtocolToken > ReceiveBlobAsync < TIOAdapter > ( CancellationToken cancellationToken )
361
+ // This method will make sure we have at least one full TLS frame buffered.
362
+ private async ValueTask < int > ReceiveTlsFrameAsync < TIOAdapter > ( CancellationToken cancellationToken )
359
363
where TIOAdapter : IReadWriteAdapter
360
364
{
361
365
int frameSize = await EnsureFullTlsFrameAsync < TIOAdapter > ( cancellationToken ) . ConfigureAwait ( false ) ;
@@ -430,11 +434,11 @@ private async ValueTask<ProtocolToken> ReceiveBlobAsync<TIOAdapter>(Cancellation
430
434
431
435
}
432
436
433
- return ProcessBlob ( frameSize ) ;
437
+ return frameSize ;
434
438
}
435
439
436
440
// Calls crypto on received data. No IO inside.
437
- private ProtocolToken ProcessBlob ( int frameSize )
441
+ private void ProcessTlsFrame ( int frameSize , out ProtocolToken message )
438
442
{
439
443
int chunkSize = frameSize ;
440
444
@@ -467,26 +471,26 @@ private ProtocolToken ProcessBlob(int frameSize)
467
471
_buffer . DiscardEncrypted ( frameSize ) ;
468
472
}
469
473
470
- return NextMessage ( availableData . Slice ( 0 , chunkSize ) ) ;
474
+ NextMessage ( availableData . Slice ( 0 , chunkSize ) , out message ) ;
471
475
}
472
476
473
477
//
474
478
// This is to reset auth state on remote side.
475
479
// If this write succeeds we will allow auth retrying.
476
480
//
477
- private void SendAuthResetSignal ( ProtocolToken ? message , ExceptionDispatchInfo exception )
481
+ private void SendAuthResetSignal ( ReadOnlySpan < byte > alert , ExceptionDispatchInfo exception )
478
482
{
479
483
SetException ( exception . SourceException ) ;
480
484
481
- if ( message == null || message . Size == 0 )
485
+ if ( alert . Length == 0 )
482
486
{
483
487
//
484
488
// We don't have an alert to send so cannot retry and fail prematurely.
485
489
//
486
490
exception . Throw ( ) ;
487
491
}
488
492
489
- InnerStream . Write ( message . Payload ! , 0 , message . Size ) ;
493
+ InnerStream . Write ( alert ) ;
490
494
491
495
exception . Throw ( ) ;
492
496
}
@@ -499,7 +503,7 @@ private void SendAuthResetSignal(ProtocolToken? message, ExceptionDispatchInfo e
499
503
//
500
504
// - Returns false if failed to verify the Remote Cert
501
505
//
502
- private bool CompleteHandshake ( ref ProtocolToken ? alertToken , out SslPolicyErrors sslPolicyErrors , out X509ChainStatusFlags chainStatus )
506
+ private bool CompleteHandshake ( ref ProtocolToken alertToken , out SslPolicyErrors sslPolicyErrors , out X509ChainStatusFlags chainStatus )
503
507
{
504
508
ProcessHandshakeSuccess ( ) ;
505
509
@@ -527,7 +531,7 @@ private bool CompleteHandshake(ref ProtocolToken? alertToken, out SslPolicyError
527
531
// The Java TrustManager callback is called only when the peer has a certificate. It's possible that
528
532
// the peer didn't provide any certificate (for example when the peer is the client) and the validation
529
533
// result hasn't been set. In that case we still need to run the verification at this point.
530
- if ( TryGetRemoteCertificateValidationResult ( out sslPolicyErrors , out chainStatus , out alertToken , out bool isValid ) )
534
+ if ( TryGetRemoteCertificateValidationResult ( out sslPolicyErrors , out chainStatus , ref alertToken , out bool isValid ) )
531
535
{
532
536
_handshakeCompleted = isValid ;
533
537
return isValid ;
@@ -546,23 +550,23 @@ private bool CompleteHandshake(ref ProtocolToken? alertToken, out SslPolicyError
546
550
547
551
private void CompleteHandshake ( SslAuthenticationOptions sslAuthenticationOptions )
548
552
{
549
- ProtocolToken ? alertToken = null ;
553
+ ProtocolToken alertToken = default ;
550
554
if ( ! CompleteHandshake ( ref alertToken , out SslPolicyErrors sslPolicyErrors , out X509ChainStatusFlags chainStatus ) )
551
555
{
552
556
if ( sslAuthenticationOptions ! . CertValidationDelegate != null )
553
557
{
554
558
// there may be some chain errors but the decision was made by custom callback. Details should be tracing if enabled.
555
- SendAuthResetSignal ( alertToken , ExceptionDispatchInfo . Capture ( new AuthenticationException ( SR . net_ssl_io_cert_custom_validation , null ) ) ) ;
559
+ SendAuthResetSignal ( new ReadOnlySpan < byte > ( alertToken . Payload ) , ExceptionDispatchInfo . Capture ( new AuthenticationException ( SR . net_ssl_io_cert_custom_validation , null ) ) ) ;
556
560
}
557
561
else if ( sslPolicyErrors == SslPolicyErrors . RemoteCertificateChainErrors && chainStatus != X509ChainStatusFlags . NoError )
558
562
{
559
563
// We failed only because of chain and we have some insight.
560
- SendAuthResetSignal ( alertToken , ExceptionDispatchInfo . Capture ( new AuthenticationException ( SR . Format ( SR . net_ssl_io_cert_chain_validation , chainStatus ) , null ) ) ) ;
564
+ SendAuthResetSignal ( new ReadOnlySpan < byte > ( alertToken . Payload ) , ExceptionDispatchInfo . Capture ( new AuthenticationException ( SR . Format ( SR . net_ssl_io_cert_chain_validation , chainStatus ) , null ) ) ) ;
561
565
}
562
566
else
563
567
{
564
568
// Simple add sslPolicyErrors as crude info.
565
- SendAuthResetSignal ( alertToken , ExceptionDispatchInfo . Capture ( new AuthenticationException ( SR . Format ( SR . net_ssl_io_cert_validation , sslPolicyErrors ) , null ) ) ) ;
569
+ SendAuthResetSignal ( new ReadOnlySpan < byte > ( alertToken . Payload ) , ExceptionDispatchInfo . Capture ( new AuthenticationException ( SR . Format ( SR . net_ssl_io_cert_validation , sslPolicyErrors ) , null ) ) ) ;
566
570
}
567
571
}
568
572
}
0 commit comments