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

1173 lines
26 KiB
C#

using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class TlsProtocol
{
internal class HandshakeMessage : MemoryStream
{
internal HandshakeMessage(byte handshakeType)
: this(handshakeType, 60)
{
}
internal HandshakeMessage(byte handshakeType, int length)
: base(length + 4)
{
TlsUtilities.WriteUint8(handshakeType, this);
TlsUtilities.WriteUint24(0, this);
}
internal void Write(byte[] data)
{
Write(data, 0, data.Length);
}
internal void WriteToRecordStream(TlsProtocol protocol)
{
long num = Length - 4;
TlsUtilities.CheckUint24(num);
Position = 1L;
TlsUtilities.WriteUint24((int)num, this);
byte[] buffer = GetBuffer();
int len = (int)Length;
protocol.WriteHandshakeMessage(buffer, 0, len);
Platform.Dispose(this);
}
}
protected const short CS_START = 0;
protected const short CS_CLIENT_HELLO = 1;
protected const short CS_SERVER_HELLO = 2;
protected const short CS_SERVER_SUPPLEMENTAL_DATA = 3;
protected const short CS_SERVER_CERTIFICATE = 4;
protected const short CS_CERTIFICATE_STATUS = 5;
protected const short CS_SERVER_KEY_EXCHANGE = 6;
protected const short CS_CERTIFICATE_REQUEST = 7;
protected const short CS_SERVER_HELLO_DONE = 8;
protected const short CS_CLIENT_SUPPLEMENTAL_DATA = 9;
protected const short CS_CLIENT_CERTIFICATE = 10;
protected const short CS_CLIENT_KEY_EXCHANGE = 11;
protected const short CS_CERTIFICATE_VERIFY = 12;
protected const short CS_CLIENT_FINISHED = 13;
protected const short CS_SERVER_SESSION_TICKET = 14;
protected const short CS_SERVER_FINISHED = 15;
protected const short CS_END = 16;
protected const short ADS_MODE_1_Nsub1 = 0;
protected const short ADS_MODE_0_N = 1;
protected const short ADS_MODE_0_N_FIRSTONLY = 2;
private ByteQueue mApplicationDataQueue = new ByteQueue(0);
private ByteQueue mAlertQueue = new ByteQueue(2);
private ByteQueue mHandshakeQueue = new ByteQueue(0);
internal RecordStream mRecordStream;
protected SecureRandom mSecureRandom;
private TlsStream mTlsStream = null;
private volatile bool mClosed = false;
private volatile bool mFailedWithError = false;
private volatile bool mAppDataReady = false;
private volatile bool mAppDataSplitEnabled = true;
private volatile int mAppDataSplitMode = 0;
private byte[] mExpectedVerifyData = null;
protected TlsSession mTlsSession = null;
protected SessionParameters mSessionParameters = null;
protected SecurityParameters mSecurityParameters = null;
protected Certificate mPeerCertificate = null;
protected int[] mOfferedCipherSuites = null;
protected byte[] mOfferedCompressionMethods = null;
protected IDictionary mClientExtensions = null;
protected IDictionary mServerExtensions = null;
protected short mConnectionState = 0;
protected bool mResumedSession = false;
protected bool mReceivedChangeCipherSpec = false;
protected bool mSecureRenegotiation = false;
protected bool mAllowCertificateStatus = false;
protected bool mExpectSessionTicket = false;
protected bool mBlocking = true;
protected ByteQueueStream mInputBuffers = null;
protected ByteQueueStream mOutputBuffer = null;
protected abstract TlsContext Context { get; }
internal abstract AbstractTlsContext ContextAdmin { get; }
protected abstract TlsPeer Peer { get; }
public virtual Stream Stream
{
get
{
if (!mBlocking)
{
throw new InvalidOperationException("Cannot use Stream in non-blocking mode! Use OfferInput()/OfferOutput() instead.");
}
return mTlsStream;
}
}
public virtual bool IsClosed => mClosed;
public TlsProtocol(Stream stream, SecureRandom secureRandom)
: this(stream, stream, secureRandom)
{
}
public TlsProtocol(Stream input, Stream output, SecureRandom secureRandom)
{
mRecordStream = new RecordStream(this, input, output);
mSecureRandom = secureRandom;
}
public TlsProtocol(SecureRandom secureRandom)
{
mBlocking = false;
mInputBuffers = new ByteQueueStream();
mOutputBuffer = new ByteQueueStream();
mRecordStream = new RecordStream(this, mInputBuffers, mOutputBuffer);
mSecureRandom = secureRandom;
}
protected virtual void HandleAlertMessage(byte alertLevel, byte alertDescription)
{
Peer.NotifyAlertReceived(alertLevel, alertDescription);
if (alertLevel == 1)
{
HandleAlertWarningMessage(alertDescription);
return;
}
HandleFailure();
throw new TlsFatalAlertReceived(alertDescription);
}
protected virtual void HandleAlertWarningMessage(byte alertDescription)
{
if (alertDescription == 0)
{
if (!mAppDataReady)
{
throw new TlsFatalAlert(40);
}
HandleClose(user_canceled: false);
}
}
protected virtual void HandleChangeCipherSpecMessage()
{
}
protected virtual void HandleClose(bool user_canceled)
{
if (!mClosed)
{
mClosed = true;
if (user_canceled && !mAppDataReady)
{
RaiseAlertWarning(90, "User canceled handshake");
}
RaiseAlertWarning(0, "Connection closed");
mRecordStream.SafeClose();
if (!mAppDataReady)
{
CleanupHandshake();
}
}
}
protected virtual void HandleException(byte alertDescription, string message, Exception cause)
{
if (!mClosed)
{
RaiseAlertFatal(alertDescription, message, cause);
HandleFailure();
}
}
protected virtual void HandleFailure()
{
mClosed = true;
mFailedWithError = true;
InvalidateSession();
mRecordStream.SafeClose();
if (!mAppDataReady)
{
CleanupHandshake();
}
}
protected abstract void HandleHandshakeMessage(byte type, MemoryStream buf);
protected virtual void ApplyMaxFragmentLengthExtension()
{
if (mSecurityParameters.maxFragmentLength >= 0)
{
if (!MaxFragmentLength.IsValid((byte)mSecurityParameters.maxFragmentLength))
{
throw new TlsFatalAlert(80);
}
int plaintextLimit = 1 << 8 + mSecurityParameters.maxFragmentLength;
mRecordStream.SetPlaintextLimit(plaintextLimit);
}
}
protected virtual void CheckReceivedChangeCipherSpec(bool expected)
{
if (expected != mReceivedChangeCipherSpec)
{
throw new TlsFatalAlert(10);
}
}
protected virtual void CleanupHandshake()
{
if (mExpectedVerifyData != null)
{
Arrays.Fill(mExpectedVerifyData, 0);
mExpectedVerifyData = null;
}
mSecurityParameters.Clear();
mPeerCertificate = null;
mOfferedCipherSuites = null;
mOfferedCompressionMethods = null;
mClientExtensions = null;
mServerExtensions = null;
mResumedSession = false;
mReceivedChangeCipherSpec = false;
mSecureRenegotiation = false;
mAllowCertificateStatus = false;
mExpectSessionTicket = false;
}
protected virtual void BlockForHandshake()
{
if (!mBlocking)
{
return;
}
while (mConnectionState != 16)
{
if (mClosed)
{
throw new TlsFatalAlert(80);
}
SafeReadRecord();
}
}
protected virtual void CompleteHandshake()
{
try
{
mConnectionState = 16;
mAlertQueue.Shrink();
mHandshakeQueue.Shrink();
mRecordStream.FinaliseHandshake();
mAppDataSplitEnabled = !TlsUtilities.IsTlsV11(Context);
if (!mAppDataReady)
{
mAppDataReady = true;
if (mBlocking)
{
mTlsStream = new TlsStream(this);
}
}
if (mTlsSession != null)
{
if (mSessionParameters == null)
{
mSessionParameters = new SessionParameters.Builder().SetCipherSuite(mSecurityParameters.CipherSuite).SetCompressionAlgorithm(mSecurityParameters.CompressionAlgorithm).SetExtendedMasterSecret(mSecurityParameters.IsExtendedMasterSecret)
.SetMasterSecret(mSecurityParameters.MasterSecret)
.SetPeerCertificate(mPeerCertificate)
.SetPskIdentity(mSecurityParameters.PskIdentity)
.SetSrpIdentity(mSecurityParameters.SrpIdentity)
.SetServerExtensions(mServerExtensions)
.Build();
mTlsSession = new TlsSessionImpl(mTlsSession.SessionID, mSessionParameters);
}
ContextAdmin.SetResumableSession(mTlsSession);
}
Peer.NotifyHandshakeComplete();
}
finally
{
CleanupHandshake();
}
}
protected internal void ProcessRecord(byte protocol, byte[] buf, int off, int len)
{
switch (protocol)
{
case 21:
mAlertQueue.AddData(buf, off, len);
ProcessAlertQueue();
break;
case 23:
if (!mAppDataReady)
{
throw new TlsFatalAlert(10);
}
mApplicationDataQueue.AddData(buf, off, len);
ProcessApplicationDataQueue();
break;
case 20:
ProcessChangeCipherSpec(buf, off, len);
break;
case 22:
{
if (mHandshakeQueue.Available > 0)
{
mHandshakeQueue.AddData(buf, off, len);
ProcessHandshakeQueue(mHandshakeQueue);
break;
}
ByteQueue byteQueue = new ByteQueue(buf, off, len);
ProcessHandshakeQueue(byteQueue);
int available = byteQueue.Available;
if (available > 0)
{
mHandshakeQueue.AddData(buf, off + len - available, available);
}
break;
}
default:
throw new TlsFatalAlert(80);
}
}
private void ProcessHandshakeQueue(ByteQueue queue)
{
while (queue.Available >= 4)
{
byte[] buf = new byte[4];
queue.Read(buf, 0, 4, 0);
byte b = TlsUtilities.ReadUint8(buf, 0);
int num = TlsUtilities.ReadUint24(buf, 1);
int num2 = 4 + num;
if (queue.Available < num2)
{
break;
}
if (b != 0)
{
if (20 == b)
{
CheckReceivedChangeCipherSpec(expected: true);
TlsContext context = Context;
if (mExpectedVerifyData == null && context.SecurityParameters.MasterSecret != null)
{
mExpectedVerifyData = CreateVerifyData(!context.IsServer);
}
}
else
{
CheckReceivedChangeCipherSpec(mConnectionState == 16);
}
queue.CopyTo(mRecordStream.HandshakeHashUpdater, num2);
}
queue.RemoveData(4);
MemoryStream buf2 = queue.ReadFrom(num);
HandleHandshakeMessage(b, buf2);
}
}
private void ProcessApplicationDataQueue()
{
}
private void ProcessAlertQueue()
{
while (mAlertQueue.Available >= 2)
{
byte[] array = mAlertQueue.RemoveData(2, 0);
byte alertLevel = array[0];
byte alertDescription = array[1];
HandleAlertMessage(alertLevel, alertDescription);
}
}
private void ProcessChangeCipherSpec(byte[] buf, int off, int len)
{
for (int i = 0; i < len; i++)
{
byte b = TlsUtilities.ReadUint8(buf, off + i);
if (b != 1)
{
throw new TlsFatalAlert(50);
}
if (mReceivedChangeCipherSpec || mAlertQueue.Available > 0 || mHandshakeQueue.Available > 0)
{
throw new TlsFatalAlert(10);
}
mRecordStream.ReceivedReadCipherSpec();
mReceivedChangeCipherSpec = true;
HandleChangeCipherSpecMessage();
}
}
protected internal virtual int ApplicationDataAvailable()
{
return mApplicationDataQueue.Available;
}
protected internal virtual int ReadApplicationData(byte[] buf, int offset, int len)
{
if (len < 1)
{
return 0;
}
while (mApplicationDataQueue.Available == 0)
{
if (mClosed)
{
if (mFailedWithError)
{
throw new IOException("Cannot read application data on failed TLS connection");
}
if (!mAppDataReady)
{
throw new InvalidOperationException("Cannot read application data until initial handshake completed.");
}
return 0;
}
SafeReadRecord();
}
len = System.Math.Min(len, mApplicationDataQueue.Available);
mApplicationDataQueue.RemoveData(buf, offset, len, 0);
return len;
}
protected virtual void SafeCheckRecordHeader(byte[] recordHeader)
{
try
{
mRecordStream.CheckRecordHeader(recordHeader);
}
catch (TlsFatalAlert tlsFatalAlert)
{
HandleException(tlsFatalAlert.AlertDescription, "Failed to read record", tlsFatalAlert);
throw tlsFatalAlert;
}
catch (IOException ex)
{
HandleException(80, "Failed to read record", ex);
throw ex;
}
catch (Exception ex2)
{
HandleException(80, "Failed to read record", ex2);
throw new TlsFatalAlert(80, ex2);
}
}
protected virtual void SafeReadRecord()
{
try
{
if (mRecordStream.ReadRecord())
{
return;
}
if (!mAppDataReady)
{
throw new TlsFatalAlert(40);
}
}
catch (TlsFatalAlertReceived tlsFatalAlertReceived)
{
throw tlsFatalAlertReceived;
}
catch (TlsFatalAlert tlsFatalAlert)
{
HandleException(tlsFatalAlert.AlertDescription, "Failed to read record", tlsFatalAlert);
throw tlsFatalAlert;
}
catch (IOException ex)
{
HandleException(80, "Failed to read record", ex);
throw ex;
}
catch (Exception ex2)
{
HandleException(80, "Failed to read record", ex2);
throw new TlsFatalAlert(80, ex2);
}
HandleFailure();
throw new TlsNoCloseNotifyException();
}
protected virtual void SafeWriteRecord(byte type, byte[] buf, int offset, int len)
{
try
{
mRecordStream.WriteRecord(type, buf, offset, len);
}
catch (TlsFatalAlert tlsFatalAlert)
{
HandleException(tlsFatalAlert.AlertDescription, "Failed to write record", tlsFatalAlert);
throw tlsFatalAlert;
}
catch (IOException ex)
{
HandleException(80, "Failed to write record", ex);
throw ex;
}
catch (Exception ex2)
{
HandleException(80, "Failed to write record", ex2);
throw new TlsFatalAlert(80, ex2);
}
}
protected internal virtual void WriteData(byte[] buf, int offset, int len)
{
if (mClosed)
{
throw new IOException("Cannot write application data on closed/failed TLS connection");
}
while (len > 0)
{
if (mAppDataSplitEnabled)
{
switch (mAppDataSplitMode)
{
case 1:
SafeWriteRecord(23, TlsUtilities.EmptyBytes, 0, 0);
break;
case 2:
mAppDataSplitEnabled = false;
SafeWriteRecord(23, TlsUtilities.EmptyBytes, 0, 0);
break;
default:
SafeWriteRecord(23, buf, offset, 1);
offset++;
len--;
break;
}
}
if (len > 0)
{
int num = System.Math.Min(len, mRecordStream.GetPlaintextLimit());
SafeWriteRecord(23, buf, offset, num);
offset += num;
len -= num;
}
}
}
protected virtual void SetAppDataSplitMode(int appDataSplitMode)
{
if (appDataSplitMode < 0 || appDataSplitMode > 2)
{
throw new ArgumentException("Illegal appDataSplitMode mode: " + appDataSplitMode, "appDataSplitMode");
}
mAppDataSplitMode = appDataSplitMode;
}
protected virtual void WriteHandshakeMessage(byte[] buf, int off, int len)
{
if (len < 4)
{
throw new TlsFatalAlert(80);
}
if (TlsUtilities.ReadUint8(buf, off) != 0)
{
mRecordStream.HandshakeHashUpdater.Write(buf, off, len);
}
int num = 0;
do
{
int num2 = System.Math.Min(len - num, mRecordStream.GetPlaintextLimit());
SafeWriteRecord(22, buf, off + num, num2);
num += num2;
}
while (num < len);
}
public virtual void CloseInput()
{
if (mBlocking)
{
throw new InvalidOperationException("Cannot use CloseInput() in blocking mode!");
}
if (mClosed)
{
return;
}
if (mInputBuffers.Available > 0)
{
throw new EndOfStreamException();
}
if (!mAppDataReady)
{
throw new TlsFatalAlert(40);
}
throw new TlsNoCloseNotifyException();
}
public virtual void OfferInput(byte[] input)
{
if (mBlocking)
{
throw new InvalidOperationException("Cannot use OfferInput() in blocking mode! Use Stream instead.");
}
if (mClosed)
{
throw new IOException("Connection is closed, cannot accept any more input");
}
mInputBuffers.Write(input);
while (mInputBuffers.Available >= 5)
{
byte[] array = new byte[5];
mInputBuffers.Peek(array);
int num = TlsUtilities.ReadUint16(array, 3) + 5;
if (mInputBuffers.Available < num)
{
SafeCheckRecordHeader(array);
break;
}
SafeReadRecord();
if (mClosed)
{
if (mConnectionState != 16)
{
throw new TlsFatalAlert(80);
}
break;
}
}
}
public virtual int GetAvailableInputBytes()
{
if (mBlocking)
{
throw new InvalidOperationException("Cannot use GetAvailableInputBytes() in blocking mode! Use ApplicationDataAvailable() instead.");
}
return ApplicationDataAvailable();
}
public virtual int ReadInput(byte[] buffer, int offset, int length)
{
if (mBlocking)
{
throw new InvalidOperationException("Cannot use ReadInput() in blocking mode! Use Stream instead.");
}
return ReadApplicationData(buffer, offset, System.Math.Min(length, ApplicationDataAvailable()));
}
public virtual void OfferOutput(byte[] buffer, int offset, int length)
{
if (mBlocking)
{
throw new InvalidOperationException("Cannot use OfferOutput() in blocking mode! Use Stream instead.");
}
if (!mAppDataReady)
{
throw new IOException("Application data cannot be sent until the handshake is complete!");
}
WriteData(buffer, offset, length);
}
public virtual int GetAvailableOutputBytes()
{
if (mBlocking)
{
throw new InvalidOperationException("Cannot use GetAvailableOutputBytes() in blocking mode! Use Stream instead.");
}
return mOutputBuffer.Available;
}
public virtual int ReadOutput(byte[] buffer, int offset, int length)
{
if (mBlocking)
{
throw new InvalidOperationException("Cannot use ReadOutput() in blocking mode! Use Stream instead.");
}
return mOutputBuffer.Read(buffer, offset, length);
}
protected virtual void InvalidateSession()
{
if (mSessionParameters != null)
{
mSessionParameters.Clear();
mSessionParameters = null;
}
if (mTlsSession != null)
{
mTlsSession.Invalidate();
mTlsSession = null;
}
}
protected virtual void ProcessFinishedMessage(MemoryStream buf)
{
if (mExpectedVerifyData == null)
{
throw new TlsFatalAlert(80);
}
byte[] b = TlsUtilities.ReadFully(mExpectedVerifyData.Length, buf);
AssertEmpty(buf);
if (!Arrays.ConstantTimeAreEqual(mExpectedVerifyData, b))
{
throw new TlsFatalAlert(51);
}
}
protected virtual void RaiseAlertFatal(byte alertDescription, string message, Exception cause)
{
Peer.NotifyAlertRaised(2, alertDescription, message, cause);
byte[] plaintext = new byte[2] { 2, alertDescription };
try
{
mRecordStream.WriteRecord(21, plaintext, 0, 2);
}
catch (Exception)
{
}
}
protected virtual void RaiseAlertWarning(byte alertDescription, string message)
{
Peer.NotifyAlertRaised(1, alertDescription, message, null);
byte[] buf = new byte[2] { 1, alertDescription };
SafeWriteRecord(21, buf, 0, 2);
}
protected virtual void SendCertificateMessage(Certificate certificate)
{
if (certificate == null)
{
certificate = Certificate.EmptyChain;
}
if (certificate.IsEmpty)
{
TlsContext context = Context;
if (!context.IsServer)
{
ProtocolVersion serverVersion = Context.ServerVersion;
if (serverVersion.IsSsl)
{
string message = serverVersion.ToString() + " client didn't provide credentials";
RaiseAlertWarning(41, message);
return;
}
}
}
HandshakeMessage handshakeMessage = new HandshakeMessage(11);
certificate.Encode(handshakeMessage);
handshakeMessage.WriteToRecordStream(this);
}
protected virtual void SendChangeCipherSpecMessage()
{
byte[] array = new byte[1] { 1 };
SafeWriteRecord(20, array, 0, array.Length);
mRecordStream.SentWriteCipherSpec();
}
protected virtual void SendFinishedMessage()
{
byte[] array = CreateVerifyData(Context.IsServer);
HandshakeMessage handshakeMessage = new HandshakeMessage(20, array.Length);
handshakeMessage.Write(array, 0, array.Length);
handshakeMessage.WriteToRecordStream(this);
}
protected virtual void SendSupplementalDataMessage(IList supplementalData)
{
HandshakeMessage handshakeMessage = new HandshakeMessage(23);
WriteSupplementalData(handshakeMessage, supplementalData);
handshakeMessage.WriteToRecordStream(this);
}
protected virtual byte[] CreateVerifyData(bool isServer)
{
TlsContext context = Context;
string asciiLabel = (isServer ? "server finished" : "client finished");
byte[] sslSender = (isServer ? TlsUtilities.SSL_SERVER : TlsUtilities.SSL_CLIENT);
byte[] currentPrfHash = GetCurrentPrfHash(context, mRecordStream.HandshakeHash, sslSender);
return TlsUtilities.CalculateVerifyData(context, asciiLabel, currentPrfHash);
}
public virtual void Close()
{
HandleClose(user_canceled: true);
}
protected internal virtual void Flush()
{
mRecordStream.Flush();
}
protected virtual short ProcessMaxFragmentLengthExtension(IDictionary clientExtensions, IDictionary serverExtensions, byte alertDescription)
{
short maxFragmentLengthExtension = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions);
if (maxFragmentLengthExtension >= 0 && (!MaxFragmentLength.IsValid((byte)maxFragmentLengthExtension) || (!mResumedSession && maxFragmentLengthExtension != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions))))
{
throw new TlsFatalAlert(alertDescription);
}
return maxFragmentLengthExtension;
}
protected virtual void RefuseRenegotiation()
{
if (TlsUtilities.IsSsl(Context))
{
throw new TlsFatalAlert(40);
}
RaiseAlertWarning(100, "Renegotiation not supported");
}
protected internal static void AssertEmpty(MemoryStream buf)
{
if (buf.Position < buf.Length)
{
throw new TlsFatalAlert(50);
}
}
protected internal static byte[] CreateRandomBlock(bool useGmtUnixTime, IRandomGenerator randomGenerator)
{
byte[] array = new byte[32];
randomGenerator.NextBytes(array);
if (useGmtUnixTime)
{
TlsUtilities.WriteGmtUnixTime(array, 0);
}
return array;
}
protected internal static byte[] CreateRenegotiationInfo(byte[] renegotiated_connection)
{
return TlsUtilities.EncodeOpaque8(renegotiated_connection);
}
protected internal static void EstablishMasterSecret(TlsContext context, TlsKeyExchange keyExchange)
{
byte[] array = keyExchange.GeneratePremasterSecret();
try
{
context.SecurityParameters.masterSecret = TlsUtilities.CalculateMasterSecret(context, array);
}
finally
{
if (array != null)
{
Arrays.Fill(array, 0);
}
}
}
protected internal static byte[] GetCurrentPrfHash(TlsContext context, TlsHandshakeHash handshakeHash, byte[] sslSender)
{
IDigest digest = handshakeHash.ForkPrfHash();
if (sslSender != null && TlsUtilities.IsSsl(context))
{
digest.BlockUpdate(sslSender, 0, sslSender.Length);
}
return DigestUtilities.DoFinal(digest);
}
protected internal static IDictionary ReadExtensions(MemoryStream input)
{
if (input.Position >= input.Length)
{
return null;
}
byte[] buffer = TlsUtilities.ReadOpaque16(input);
AssertEmpty(input);
MemoryStream memoryStream = new MemoryStream(buffer, writable: false);
IDictionary dictionary = Platform.CreateHashtable();
while (memoryStream.Position < memoryStream.Length)
{
int num = TlsUtilities.ReadUint16(memoryStream);
byte[] value = TlsUtilities.ReadOpaque16(memoryStream);
if (dictionary.Contains(num))
{
throw new TlsFatalAlert(47);
}
dictionary.Add(num, value);
}
return dictionary;
}
protected internal static IList ReadSupplementalDataMessage(MemoryStream input)
{
byte[] buffer = TlsUtilities.ReadOpaque24(input);
AssertEmpty(input);
MemoryStream memoryStream = new MemoryStream(buffer, writable: false);
IList list = Platform.CreateArrayList();
while (memoryStream.Position < memoryStream.Length)
{
int dataType = TlsUtilities.ReadUint16(memoryStream);
byte[] data = TlsUtilities.ReadOpaque16(memoryStream);
list.Add(new SupplementalDataEntry(dataType, data));
}
return list;
}
protected internal static void WriteExtensions(Stream output, IDictionary extensions)
{
MemoryStream memoryStream = new MemoryStream();
WriteSelectedExtensions(memoryStream, extensions, selectEmpty: true);
WriteSelectedExtensions(memoryStream, extensions, selectEmpty: false);
byte[] buf = memoryStream.ToArray();
TlsUtilities.WriteOpaque16(buf, output);
}
protected internal static void WriteSelectedExtensions(Stream output, IDictionary extensions, bool selectEmpty)
{
foreach (object key in extensions.Keys)
{
int num = (int)key;
byte[] array = (byte[])extensions[num];
if (selectEmpty == (array.Length == 0))
{
TlsUtilities.CheckUint16(num);
TlsUtilities.WriteUint16(num, output);
TlsUtilities.WriteOpaque16(array, output);
}
}
}
protected internal static void WriteSupplementalData(Stream output, IList supplementalData)
{
MemoryStream memoryStream = new MemoryStream();
foreach (SupplementalDataEntry supplementalDatum in supplementalData)
{
int dataType = supplementalDatum.DataType;
TlsUtilities.CheckUint16(dataType);
TlsUtilities.WriteUint16(dataType, memoryStream);
TlsUtilities.WriteOpaque16(supplementalDatum.Data, memoryStream);
}
byte[] buf = memoryStream.ToArray();
TlsUtilities.WriteOpaque24(buf, output);
}
protected internal static int GetPrfAlgorithm(TlsContext context, int ciphersuite)
{
bool flag = TlsUtilities.IsTlsV12(context);
switch (ciphersuite)
{
case 59:
case 60:
case 61:
case 62:
case 63:
case 64:
case 103:
case 104:
case 105:
case 106:
case 107:
case 108:
case 109:
case 156:
case 158:
case 160:
case 162:
case 164:
case 166:
case 168:
case 170:
case 172:
case 186:
case 187:
case 188:
case 189:
case 190:
case 191:
case 192:
case 193:
case 194:
case 195:
case 196:
case 197:
case 49187:
case 49189:
case 49191:
case 49193:
case 49195:
case 49197:
case 49199:
case 49201:
case 49266:
case 49268:
case 49270:
case 49272:
case 49274:
case 49276:
case 49278:
case 49280:
case 49282:
case 49284:
case 49286:
case 49288:
case 49290:
case 49292:
case 49294:
case 49296:
case 49298:
case 49308:
case 49309:
case 49310:
case 49311:
case 49312:
case 49313:
case 49314:
case 49315:
case 49316:
case 49317:
case 49318:
case 49319:
case 49320:
case 49321:
case 49322:
case 49323:
case 49324:
case 49325:
case 49326:
case 49327:
case 52392:
case 52393:
case 52394:
case 52395:
case 52396:
case 52397:
case 52398:
case 65280:
case 65281:
case 65282:
case 65283:
case 65284:
case 65285:
case 65296:
case 65297:
case 65298:
case 65299:
case 65300:
case 65301:
if (flag)
{
return 1;
}
throw new TlsFatalAlert(47);
case 157:
case 159:
case 161:
case 163:
case 165:
case 167:
case 169:
case 171:
case 173:
case 49188:
case 49190:
case 49192:
case 49194:
case 49196:
case 49198:
case 49200:
case 49202:
case 49267:
case 49269:
case 49271:
case 49273:
case 49275:
case 49277:
case 49279:
case 49281:
case 49283:
case 49285:
case 49287:
case 49289:
case 49291:
case 49293:
case 49295:
case 49297:
case 49299:
if (flag)
{
return 2;
}
throw new TlsFatalAlert(47);
case 175:
case 177:
case 179:
case 181:
case 183:
case 185:
case 49208:
case 49211:
case 49301:
case 49303:
case 49305:
case 49307:
if (flag)
{
return 2;
}
return 0;
default:
if (flag)
{
return 1;
}
return 0;
}
}
}