// This will initiate renegotiation or PHA for Tls1.3
private async Task RenegotiateAsync <TIOAdapter>(CancellationToken cancellationToken)
where TIOAdapter : IReadWriteAdapter
{
if (Interlocked.Exchange(ref _nestedAuth, 1) == 1)
{
throw new InvalidOperationException(SR.Format(SR.net_io_invalidnestedcall, "authenticate"));
}
if (Interlocked.Exchange(ref _nestedRead, 1) == 1)
{
throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, "read"));
}
if (Interlocked.Exchange(ref _nestedWrite, 1) == 1)
{
_nestedRead = 0;
throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, "write"));
}
try
{
if (_buffer.ActiveLength > 0)
{
throw new InvalidOperationException(SR.net_ssl_renegotiate_buffer);
}
_sslAuthenticationOptions !.RemoteCertRequired = true;
_isRenego = true;
SecurityStatusPal status = Renegotiate(out byte[]? nextmsg);
if (nextmsg is { Length : > 0 })
{
await TIOAdapter.WriteAsync(InnerStream, nextmsg, 0, nextmsg.Length, cancellationToken).ConfigureAwait(false);
await TIOAdapter.FlushAsync(InnerStream, cancellationToken).ConfigureAwait(false);
}
if (status.ErrorCode != SecurityStatusPalErrorCode.OK)
{
if (status.ErrorCode == SecurityStatusPalErrorCode.NoRenegotiation)
{
// Peer does not want to renegotiate. That should keep session usable.
return;
}
throw SslStreamPal.GetException(status);
}
_buffer.EnsureAvailableSpace(InitialHandshakeBufferSize);
ProtocolToken message;
do
{
message = await ReceiveBlobAsync <TIOAdapter>(cancellationToken).ConfigureAwait(false);
if (message.Size > 0)
{
await TIOAdapter.WriteAsync(InnerStream, message.Payload !, 0, message.Size, cancellationToken).ConfigureAwait(false);
await TIOAdapter.FlushAsync(InnerStream, cancellationToken).ConfigureAwait(false);
}
}while (message.Status.ErrorCode == SecurityStatusPalErrorCode.ContinueNeeded);
CompleteHandshake(_sslAuthenticationOptions !);
}