Files
SuperVPN/output/Libraries/BouncyCastle.Crypto/Org/BouncyCastle/Crypto/Tls/TlsClientProtocol.cs
2025-10-09 09:57:24 +09:00

541 lines
16 KiB
C#

using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls;
public class TlsClientProtocol : TlsProtocol
{
protected TlsClient mTlsClient = null;
internal TlsClientContextImpl mTlsClientContext = null;
protected byte[] mSelectedSessionID = null;
protected TlsKeyExchange mKeyExchange = null;
protected TlsAuthentication mAuthentication = null;
protected CertificateStatus mCertificateStatus = null;
protected CertificateRequest mCertificateRequest = null;
protected override TlsContext Context => mTlsClientContext;
internal override AbstractTlsContext ContextAdmin => mTlsClientContext;
protected override TlsPeer Peer => mTlsClient;
public TlsClientProtocol(Stream stream, SecureRandom secureRandom)
: base(stream, secureRandom)
{
}
public TlsClientProtocol(Stream input, Stream output, SecureRandom secureRandom)
: base(input, output, secureRandom)
{
}
public TlsClientProtocol(SecureRandom secureRandom)
: base(secureRandom)
{
}
public virtual void Connect(TlsClient tlsClient)
{
if (tlsClient == null)
{
throw new ArgumentNullException("tlsClient");
}
if (mTlsClient != null)
{
throw new InvalidOperationException("'Connect' can only be called once");
}
mTlsClient = tlsClient;
mSecurityParameters = new SecurityParameters();
mSecurityParameters.entity = 1;
mTlsClientContext = new TlsClientContextImpl(mSecureRandom, mSecurityParameters);
mSecurityParameters.clientRandom = TlsProtocol.CreateRandomBlock(tlsClient.ShouldUseGmtUnixTime(), mTlsClientContext.NonceRandomGenerator);
mTlsClient.Init(mTlsClientContext);
mRecordStream.Init(mTlsClientContext);
TlsSession sessionToResume = tlsClient.GetSessionToResume();
if (sessionToResume != null && sessionToResume.IsResumable)
{
SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
if (sessionParameters != null && sessionParameters.IsExtendedMasterSecret)
{
mTlsSession = sessionToResume;
mSessionParameters = sessionParameters;
}
}
SendClientHelloMessage();
mConnectionState = 1;
BlockForHandshake();
}
protected override void CleanupHandshake()
{
base.CleanupHandshake();
mSelectedSessionID = null;
mKeyExchange = null;
mAuthentication = null;
mCertificateStatus = null;
mCertificateRequest = null;
}
protected override void HandleHandshakeMessage(byte type, MemoryStream buf)
{
if (mResumedSession)
{
if (type != 20 || mConnectionState != 2)
{
throw new TlsFatalAlert(10);
}
ProcessFinishedMessage(buf);
mConnectionState = 15;
SendChangeCipherSpecMessage();
SendFinishedMessage();
mConnectionState = 13;
CompleteHandshake();
return;
}
switch (type)
{
case 11:
switch (mConnectionState)
{
case 2:
case 3:
if (mConnectionState == 2)
{
HandleSupplementalData(null);
}
mPeerCertificate = Certificate.Parse(buf);
TlsProtocol.AssertEmpty(buf);
if (mPeerCertificate == null || mPeerCertificate.IsEmpty)
{
mAllowCertificateStatus = false;
}
mKeyExchange.ProcessServerCertificate(mPeerCertificate);
mAuthentication = mTlsClient.GetAuthentication();
mAuthentication.NotifyServerCertificate(mPeerCertificate);
mConnectionState = 4;
break;
default:
throw new TlsFatalAlert(10);
}
break;
case 22:
{
short num = mConnectionState;
if (num == 4)
{
if (!mAllowCertificateStatus)
{
throw new TlsFatalAlert(10);
}
mCertificateStatus = CertificateStatus.Parse(buf);
TlsProtocol.AssertEmpty(buf);
mConnectionState = 5;
break;
}
throw new TlsFatalAlert(10);
}
case 20:
switch (mConnectionState)
{
case 13:
case 14:
if (mConnectionState == 13 && mExpectSessionTicket)
{
throw new TlsFatalAlert(10);
}
ProcessFinishedMessage(buf);
mConnectionState = 15;
CompleteHandshake();
break;
default:
throw new TlsFatalAlert(10);
}
break;
case 2:
{
short num = mConnectionState;
if (num == 1)
{
ReceiveServerHelloMessage(buf);
mConnectionState = 2;
mRecordStream.NotifyHelloComplete();
ApplyMaxFragmentLengthExtension();
if (mResumedSession)
{
mSecurityParameters.masterSecret = Arrays.Clone(mSessionParameters.MasterSecret);
mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher());
break;
}
InvalidateSession();
if (mSelectedSessionID.Length > 0)
{
mTlsSession = new TlsSessionImpl(mSelectedSessionID, null);
}
break;
}
throw new TlsFatalAlert(10);
}
case 23:
{
short num = mConnectionState;
if (num == 2)
{
HandleSupplementalData(TlsProtocol.ReadSupplementalDataMessage(buf));
break;
}
throw new TlsFatalAlert(10);
}
case 14:
switch (mConnectionState)
{
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
{
if (mConnectionState < 3)
{
HandleSupplementalData(null);
}
if (mConnectionState < 4)
{
mKeyExchange.SkipServerCredentials();
mAuthentication = null;
}
if (mConnectionState < 6)
{
mKeyExchange.SkipServerKeyExchange();
}
TlsProtocol.AssertEmpty(buf);
mConnectionState = 8;
mRecordStream.HandshakeHash.SealHashAlgorithms();
IList clientSupplementalData = mTlsClient.GetClientSupplementalData();
if (clientSupplementalData != null)
{
SendSupplementalDataMessage(clientSupplementalData);
}
mConnectionState = 9;
TlsCredentials tlsCredentials = null;
if (mCertificateRequest == null)
{
mKeyExchange.SkipClientCredentials();
}
else
{
tlsCredentials = mAuthentication.GetClientCredentials(mCertificateRequest);
if (tlsCredentials == null)
{
mKeyExchange.SkipClientCredentials();
SendCertificateMessage(Certificate.EmptyChain);
}
else
{
mKeyExchange.ProcessClientCredentials(tlsCredentials);
SendCertificateMessage(tlsCredentials.Certificate);
}
}
mConnectionState = 10;
SendClientKeyExchangeMessage();
mConnectionState = 11;
if (TlsUtilities.IsSsl(Context))
{
TlsProtocol.EstablishMasterSecret(Context, mKeyExchange);
}
TlsHandshakeHash tlsHandshakeHash = mRecordStream.PrepareToFinish();
mSecurityParameters.sessionHash = TlsProtocol.GetCurrentPrfHash(Context, tlsHandshakeHash, null);
if (!TlsUtilities.IsSsl(Context))
{
TlsProtocol.EstablishMasterSecret(Context, mKeyExchange);
}
mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher());
if (tlsCredentials != null && tlsCredentials is TlsSignerCredentials)
{
TlsSignerCredentials tlsSignerCredentials = (TlsSignerCredentials)tlsCredentials;
SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm(Context, tlsSignerCredentials);
byte[] hash = ((signatureAndHashAlgorithm != null) ? tlsHandshakeHash.GetFinalHash(signatureAndHashAlgorithm.Hash) : mSecurityParameters.SessionHash);
byte[] signature = tlsSignerCredentials.GenerateCertificateSignature(hash);
DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature);
SendCertificateVerifyMessage(certificateVerify);
mConnectionState = 12;
}
SendChangeCipherSpecMessage();
SendFinishedMessage();
mConnectionState = 13;
break;
}
default:
throw new TlsFatalAlert(10);
}
break;
case 12:
switch (mConnectionState)
{
case 2:
case 3:
case 4:
case 5:
if (mConnectionState < 3)
{
HandleSupplementalData(null);
}
if (mConnectionState < 4)
{
mKeyExchange.SkipServerCredentials();
mAuthentication = null;
}
mKeyExchange.ProcessServerKeyExchange(buf);
TlsProtocol.AssertEmpty(buf);
mConnectionState = 6;
break;
default:
throw new TlsFatalAlert(10);
}
break;
case 13:
switch (mConnectionState)
{
case 4:
case 5:
case 6:
if (mConnectionState != 6)
{
mKeyExchange.SkipServerKeyExchange();
}
if (mAuthentication == null)
{
throw new TlsFatalAlert(40);
}
mCertificateRequest = CertificateRequest.Parse(Context, buf);
TlsProtocol.AssertEmpty(buf);
mKeyExchange.ValidateCertificateRequest(mCertificateRequest);
TlsUtilities.TrackHashAlgorithms(mRecordStream.HandshakeHash, mCertificateRequest.SupportedSignatureAlgorithms);
mConnectionState = 7;
break;
default:
throw new TlsFatalAlert(10);
}
break;
case 4:
{
short num = mConnectionState;
if (num == 13)
{
if (!mExpectSessionTicket)
{
throw new TlsFatalAlert(10);
}
InvalidateSession();
ReceiveNewSessionTicketMessage(buf);
mConnectionState = 14;
break;
}
throw new TlsFatalAlert(10);
}
case 0:
TlsProtocol.AssertEmpty(buf);
if (mConnectionState == 16)
{
RefuseRenegotiation();
}
break;
default:
throw new TlsFatalAlert(10);
}
}
protected virtual void HandleSupplementalData(IList serverSupplementalData)
{
mTlsClient.ProcessServerSupplementalData(serverSupplementalData);
mConnectionState = 3;
mKeyExchange = mTlsClient.GetKeyExchange();
mKeyExchange.Init(Context);
}
protected virtual void ReceiveNewSessionTicketMessage(MemoryStream buf)
{
NewSessionTicket newSessionTicket = NewSessionTicket.Parse(buf);
TlsProtocol.AssertEmpty(buf);
mTlsClient.NotifyNewSessionTicket(newSessionTicket);
}
protected virtual void ReceiveServerHelloMessage(MemoryStream buf)
{
ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(buf);
if (protocolVersion.IsDtls)
{
throw new TlsFatalAlert(47);
}
if (!protocolVersion.Equals(mRecordStream.ReadVersion))
{
throw new TlsFatalAlert(47);
}
ProtocolVersion clientVersion = Context.ClientVersion;
if (!protocolVersion.IsEqualOrEarlierVersionOf(clientVersion))
{
throw new TlsFatalAlert(47);
}
mRecordStream.SetWriteVersion(protocolVersion);
ContextAdmin.SetServerVersion(protocolVersion);
mTlsClient.NotifyServerVersion(protocolVersion);
mSecurityParameters.serverRandom = TlsUtilities.ReadFully(32, buf);
mSelectedSessionID = TlsUtilities.ReadOpaque8(buf);
if (mSelectedSessionID.Length > 32)
{
throw new TlsFatalAlert(47);
}
mTlsClient.NotifySessionID(mSelectedSessionID);
mResumedSession = mSelectedSessionID.Length > 0 && mTlsSession != null && Arrays.AreEqual(mSelectedSessionID, mTlsSession.SessionID);
int num = TlsUtilities.ReadUint16(buf);
if (!Arrays.Contains(mOfferedCipherSuites, num) || num == 0 || CipherSuite.IsScsv(num) || !TlsUtilities.IsValidCipherSuiteForVersion(num, Context.ServerVersion))
{
throw new TlsFatalAlert(47);
}
mTlsClient.NotifySelectedCipherSuite(num);
byte b = TlsUtilities.ReadUint8(buf);
if (!Arrays.Contains(mOfferedCompressionMethods, b))
{
throw new TlsFatalAlert(47);
}
mTlsClient.NotifySelectedCompressionMethod(b);
mServerExtensions = TlsProtocol.ReadExtensions(buf);
mSecurityParameters.extendedMasterSecret = !TlsUtilities.IsSsl(mTlsClientContext) && TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mServerExtensions);
if (!mSecurityParameters.IsExtendedMasterSecret && (mResumedSession || mTlsClient.RequiresExtendedMasterSecret()))
{
throw new TlsFatalAlert(40);
}
if (mServerExtensions != null)
{
foreach (object key in mServerExtensions.Keys)
{
int num2 = (int)key;
if (num2 != 65281)
{
if (TlsUtilities.GetExtensionData(mClientExtensions, num2) == null)
{
throw new TlsFatalAlert(110);
}
_ = mResumedSession;
}
}
}
byte[] extensionData = TlsUtilities.GetExtensionData(mServerExtensions, 65281);
if (extensionData != null)
{
mSecureRenegotiation = true;
if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
{
throw new TlsFatalAlert(40);
}
}
mTlsClient.NotifySecureRenegotiation(mSecureRenegotiation);
IDictionary dictionary = mClientExtensions;
IDictionary dictionary2 = mServerExtensions;
if (mResumedSession)
{
if (num != mSessionParameters.CipherSuite || b != mSessionParameters.CompressionAlgorithm)
{
throw new TlsFatalAlert(47);
}
dictionary = null;
dictionary2 = mSessionParameters.ReadServerExtensions();
}
mSecurityParameters.cipherSuite = num;
mSecurityParameters.compressionAlgorithm = b;
if (dictionary2 != null && dictionary2.Count > 0)
{
bool flag = TlsExtensionsUtilities.HasEncryptThenMacExtension(dictionary2);
if (flag && !TlsUtilities.IsBlockCipherSuite(num))
{
throw new TlsFatalAlert(47);
}
mSecurityParameters.encryptThenMac = flag;
mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(dictionary, dictionary2, 47);
mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(dictionary2);
mAllowCertificateStatus = !mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 5, 47);
mExpectSessionTicket = !mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 35, 47);
}
if (dictionary != null)
{
mTlsClient.ProcessServerExtensions(dictionary2);
}
mSecurityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(Context, mSecurityParameters.CipherSuite);
mSecurityParameters.verifyDataLength = 12;
}
protected virtual void SendCertificateVerifyMessage(DigitallySigned certificateVerify)
{
HandshakeMessage handshakeMessage = new HandshakeMessage(15);
certificateVerify.Encode(handshakeMessage);
handshakeMessage.WriteToRecordStream(this);
}
protected virtual void SendClientHelloMessage()
{
mRecordStream.SetWriteVersion(mTlsClient.ClientHelloRecordLayerVersion);
ProtocolVersion clientVersion = mTlsClient.ClientVersion;
if (clientVersion.IsDtls)
{
throw new TlsFatalAlert(80);
}
ContextAdmin.SetClientVersion(clientVersion);
byte[] array = TlsUtilities.EmptyBytes;
if (mTlsSession != null)
{
array = mTlsSession.SessionID;
if (array == null || array.Length > 32)
{
array = TlsUtilities.EmptyBytes;
}
}
bool isFallback = mTlsClient.IsFallback;
mOfferedCipherSuites = mTlsClient.GetCipherSuites();
mOfferedCompressionMethods = mTlsClient.GetCompressionMethods();
if (array.Length > 0 && mSessionParameters != null && (!mSessionParameters.IsExtendedMasterSecret || !Arrays.Contains(mOfferedCipherSuites, mSessionParameters.CipherSuite) || !Arrays.Contains(mOfferedCompressionMethods, mSessionParameters.CompressionAlgorithm)))
{
array = TlsUtilities.EmptyBytes;
}
mClientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(mTlsClient.GetClientExtensions());
if (!clientVersion.IsSsl)
{
TlsExtensionsUtilities.AddExtendedMasterSecretExtension(mClientExtensions);
}
HandshakeMessage handshakeMessage = new HandshakeMessage(1);
TlsUtilities.WriteVersion(clientVersion, handshakeMessage);
handshakeMessage.Write(mSecurityParameters.ClientRandom);
TlsUtilities.WriteOpaque8(array, handshakeMessage);
byte[] extensionData = TlsUtilities.GetExtensionData(mClientExtensions, 65281);
bool flag = null == extensionData;
bool flag2 = !Arrays.Contains(mOfferedCipherSuites, 255);
if (flag && flag2)
{
mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, 255);
}
if (isFallback && !Arrays.Contains(mOfferedCipherSuites, 22016))
{
mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, 22016);
}
TlsUtilities.WriteUint16ArrayWithUint16Length(mOfferedCipherSuites, handshakeMessage);
TlsUtilities.WriteUint8ArrayWithUint8Length(mOfferedCompressionMethods, handshakeMessage);
TlsProtocol.WriteExtensions(handshakeMessage, mClientExtensions);
handshakeMessage.WriteToRecordStream(this);
}
protected virtual void SendClientKeyExchangeMessage()
{
HandshakeMessage handshakeMessage = new HandshakeMessage(16);
mKeyExchange.GenerateClientKeyExchange(handshakeMessage);
handshakeMessage.WriteToRecordStream(this);
}
}