12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- 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
- {
- private static readonly string TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
-
- 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();
- private ByteQueue mAlertQueue = new ByteQueue(2);
- private ByteQueue mHandshakeQueue = new ByteQueue();
-
-
- 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 = ADS_MODE_1_Nsub1;
- 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 = CS_START;
- 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;
- public TlsProtocol(Stream stream, SecureRandom secureRandom)
- : this(stream, stream, secureRandom)
- {
- }
- public TlsProtocol(Stream input, Stream output, SecureRandom secureRandom)
- {
- this.mRecordStream = new RecordStream(this, input, output);
- this.mSecureRandom = secureRandom;
- }
- public TlsProtocol(SecureRandom secureRandom)
- {
- this.mBlocking = false;
- this.mInputBuffers = new ByteQueueStream();
- this.mOutputBuffer = new ByteQueueStream();
- this.mRecordStream = new RecordStream(this, mInputBuffers, mOutputBuffer);
- this.mSecureRandom = secureRandom;
- }
- protected abstract TlsContext Context { get; }
- internal abstract AbstractTlsContext ContextAdmin { get; }
- protected abstract TlsPeer Peer { get; }
- protected virtual void HandleChangeCipherSpecMessage()
- {
- }
- protected abstract void HandleHandshakeMessage(byte type, byte[] buf);
- protected virtual void HandleWarningMessage(byte description)
- {
- }
- protected virtual void ApplyMaxFragmentLengthExtension()
- {
- if (mSecurityParameters.maxFragmentLength >= 0)
- {
- if (!MaxFragmentLength.IsValid((byte)mSecurityParameters.maxFragmentLength))
- throw new TlsFatalAlert(AlertDescription.internal_error);
- int plainTextLimit = 1 << (8 + mSecurityParameters.maxFragmentLength);
- mRecordStream.SetPlaintextLimit(plainTextLimit);
- }
- }
- protected virtual void CheckReceivedChangeCipherSpec(bool expected)
- {
- if (expected != mReceivedChangeCipherSpec)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- protected virtual void CleanupHandshake()
- {
- if (this.mExpectedVerifyData != null)
- {
- Arrays.Fill(this.mExpectedVerifyData, (byte)0);
- this.mExpectedVerifyData = null;
- }
- this.mSecurityParameters.Clear();
- this.mPeerCertificate = null;
- this.mOfferedCipherSuites = null;
- this.mOfferedCompressionMethods = null;
- this.mClientExtensions = null;
- this.mServerExtensions = null;
- this.mResumedSession = false;
- this.mReceivedChangeCipherSpec = false;
- this.mSecureRenegotiation = false;
- this.mAllowCertificateStatus = false;
- this.mExpectSessionTicket = false;
- }
- protected virtual void BlockForHandshake()
- {
- if (mBlocking)
- {
- while (this.mConnectionState != CS_END)
- {
- if (this.mClosed)
- {
-
- }
- SafeReadRecord();
- }
- }
- }
- protected virtual void CompleteHandshake()
- {
- try
- {
- this.mRecordStream.FinaliseHandshake();
- this.mAppDataSplitEnabled = !TlsUtilities.IsTlsV11(Context);
-
- if (!mAppDataReady)
- {
- this.mAppDataReady = true;
- if (mBlocking)
- {
- this.mTlsStream = new TlsStream(this);
- }
- }
- if (this.mTlsSession != null)
- {
- if (this.mSessionParameters == null)
- {
- this.mSessionParameters = new SessionParameters.Builder()
- .SetCipherSuite(this.mSecurityParameters.CipherSuite)
- .SetCompressionAlgorithm(this.mSecurityParameters.CompressionAlgorithm)
- .SetMasterSecret(this.mSecurityParameters.MasterSecret)
- .SetPeerCertificate(this.mPeerCertificate)
- .SetPskIdentity(this.mSecurityParameters.PskIdentity)
- .SetSrpIdentity(this.mSecurityParameters.SrpIdentity)
-
- .SetServerExtensions(this.mServerExtensions)
- .Build();
- this.mTlsSession = new TlsSessionImpl(this.mTlsSession.SessionID, this.mSessionParameters);
- }
- ContextAdmin.SetResumableSession(this.mTlsSession);
- }
- Peer.NotifyHandshakeComplete();
- }
- finally
- {
- CleanupHandshake();
- }
- }
- protected internal void ProcessRecord(byte protocol, byte[] buf, int offset, int len)
- {
-
- switch (protocol)
- {
- case ContentType.alert:
- {
- mAlertQueue.AddData(buf, offset, len);
- ProcessAlert();
- break;
- }
- case ContentType.application_data:
- {
- if (!mAppDataReady)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- mApplicationDataQueue.AddData(buf, offset, len);
- ProcessApplicationData();
- break;
- }
- case ContentType.change_cipher_spec:
- {
- ProcessChangeCipherSpec(buf, offset, len);
- break;
- }
- case ContentType.handshake:
- {
- mHandshakeQueue.AddData(buf, offset, len);
- ProcessHandshake();
- break;
- }
- case ContentType.heartbeat:
- {
- if (!mAppDataReady)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
-
-
-
- break;
- }
- default:
-
- break;
- }
- }
- private void ProcessHandshake()
- {
- bool read;
- do
- {
- read = false;
-
- if (mHandshakeQueue.Available >= 4)
- {
- byte[] beginning = new byte[4];
- mHandshakeQueue.Read(beginning, 0, 4, 0);
- byte type = TlsUtilities.ReadUint8(beginning, 0);
- int len = TlsUtilities.ReadUint24(beginning, 1);
-
- if (mHandshakeQueue.Available >= (len + 4))
- {
-
- byte[] buf = mHandshakeQueue.RemoveData(len, 4);
- CheckReceivedChangeCipherSpec(mConnectionState == CS_END || type == HandshakeType.finished);
-
- switch (type)
- {
- case HandshakeType.hello_request:
- break;
- case HandshakeType.finished:
- default:
- {
- TlsContext ctx = Context;
- if (type == HandshakeType.finished
- && this.mExpectedVerifyData == null
- && ctx.SecurityParameters.MasterSecret != null)
- {
- this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer);
- }
- mRecordStream.UpdateHandshakeData(beginning, 0, 4);
- mRecordStream.UpdateHandshakeData(buf, 0, len);
- break;
- }
- }
-
- HandleHandshakeMessage(type, buf);
- read = true;
- }
- }
- }
- while (read);
- }
- private void ProcessApplicationData()
- {
-
- }
- private void ProcessAlert()
- {
- while (mAlertQueue.Available >= 2)
- {
-
- byte[] tmp = mAlertQueue.RemoveData(2, 0);
- byte level = tmp[0];
- byte description = tmp[1];
- Peer.NotifyAlertReceived(level, description);
- if (level == AlertLevel.fatal)
- {
-
- InvalidateSession();
- this.mFailedWithError = true;
- this.mClosed = true;
- mRecordStream.SafeClose();
- throw new IOException(TLS_ERROR_MESSAGE);
- }
- else
- {
-
-
- if (description == AlertDescription.close_notify)
- {
- HandleClose(false);
- }
-
- HandleWarningMessage(description);
- }
- }
- }
-
- private void ProcessChangeCipherSpec(byte[] buf, int off, int len)
- {
- for (int i = 0; i < len; ++i)
- {
- byte message = TlsUtilities.ReadUint8(buf, off + i);
- if (message != ChangeCipherSpec.change_cipher_spec)
- throw new TlsFatalAlert(AlertDescription.decode_error);
- if (this.mReceivedChangeCipherSpec
- || mAlertQueue.Available > 0
- || mHandshakeQueue.Available > 0)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- mRecordStream.ReceivedReadCipherSpec();
- this.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 (this.mClosed)
- {
- if (this.mFailedWithError)
- {
-
- throw new IOException(TLS_ERROR_MESSAGE);
- }
-
- return 0;
- }
- SafeReadRecord();
- }
- len = System.Math.Min(len, mApplicationDataQueue.Available);
- mApplicationDataQueue.RemoveData(buf, offset, len, 0);
- return len;
- }
- protected virtual void SafeReadRecord()
- {
- try
- {
- if (!mRecordStream.ReadRecord())
- {
-
-
- throw new EndOfStreamException();
- }
- }
- catch (TlsFatalAlert e)
- {
- if (!mClosed)
- {
- this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to read record", e);
- }
- throw e;
- }
- catch (Exception e)
- {
- if (!mClosed)
- {
- this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
- }
- throw e;
- }
- }
- protected virtual void SafeWriteRecord(byte type, byte[] buf, int offset, int len)
- {
- try
- {
- mRecordStream.WriteRecord(type, buf, offset, len);
- }
- catch (TlsFatalAlert e)
- {
- if (!mClosed)
- {
- this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to write record", e);
- }
- throw e;
- }
- catch (Exception e)
- {
- if (!mClosed)
- {
- this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
- }
- throw e;
- }
- }
-
- protected internal virtual void WriteData(byte[] buf, int offset, int len)
- {
- if (this.mClosed)
- {
- if (this.mFailedWithError)
- throw new IOException(TLS_ERROR_MESSAGE);
- throw new IOException("Sorry, connection has been closed, you cannot write more data");
- }
- while (len > 0)
- {
-
- if (this.mAppDataSplitEnabled)
- {
-
- switch (mAppDataSplitMode)
- {
- case ADS_MODE_0_N:
- SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
- break;
- case ADS_MODE_0_N_FIRSTONLY:
- this.mAppDataSplitEnabled = false;
- SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
- break;
- case ADS_MODE_1_Nsub1:
- default:
- SafeWriteRecord(ContentType.application_data, buf, offset, 1);
- ++offset;
- --len;
- break;
- }
- }
- if (len > 0)
- {
-
- int toWrite = System.Math.Min(len, mRecordStream.GetPlaintextLimit());
- SafeWriteRecord(ContentType.application_data, buf, offset, toWrite);
- offset += toWrite;
- len -= toWrite;
- }
- }
- }
- protected virtual void SetAppDataSplitMode(int appDataSplitMode)
- {
- if (appDataSplitMode < ADS_MODE_1_Nsub1 || appDataSplitMode > ADS_MODE_0_N_FIRSTONLY)
- throw new ArgumentException("Illegal appDataSplitMode mode: " + appDataSplitMode, "appDataSplitMode");
- this.mAppDataSplitMode = appDataSplitMode;
- }
- protected virtual void WriteHandshakeMessage(byte[] buf, int off, int len)
- {
- while (len > 0)
- {
-
- int toWrite = System.Math.Min(len, mRecordStream.GetPlaintextLimit());
- SafeWriteRecord(ContentType.handshake, buf, off, toWrite);
- off += toWrite;
- len -= toWrite;
- }
- }
-
-
- public virtual Stream Stream
- {
- get
- {
- if (!mBlocking)
- throw new InvalidOperationException("Cannot use Stream in non-blocking mode! Use OfferInput()/OfferOutput() instead.");
- return this.mTlsStream;
- }
- }
-
- 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 >= RecordStream.TLS_HEADER_SIZE)
- {
- byte[] header = new byte[RecordStream.TLS_HEADER_SIZE];
- mInputBuffers.Peek(header);
- int totalLength = TlsUtilities.ReadUint16(header, RecordStream.TLS_HEADER_LENGTH_OFFSET) + RecordStream.TLS_HEADER_SIZE;
- if (mInputBuffers.Available < totalLength)
- {
-
- break;
- }
- SafeReadRecord();
- }
- }
-
- 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 FailWithError(byte alertLevel, byte alertDescription, string message, Exception cause)
- {
-
- if (!mClosed)
- {
-
- this.mClosed = true;
- if (alertLevel == AlertLevel.fatal)
- {
-
-
- InvalidateSession();
- this.mFailedWithError = true;
- }
- RaiseAlert(alertLevel, alertDescription, message, cause);
- mRecordStream.SafeClose();
- if (alertLevel != AlertLevel.fatal)
- {
- return;
- }
- }
- throw new IOException(TLS_ERROR_MESSAGE);
- }
- protected virtual void InvalidateSession()
- {
- if (this.mSessionParameters != null)
- {
- this.mSessionParameters.Clear();
- this.mSessionParameters = null;
- }
- if (this.mTlsSession != null)
- {
- this.mTlsSession.Invalidate();
- this.mTlsSession = null;
- }
- }
- protected virtual void ProcessFinishedMessage(MemoryStream buf)
- {
- if (mExpectedVerifyData == null)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- byte[] verify_data = TlsUtilities.ReadFully(mExpectedVerifyData.Length, buf);
- AssertEmpty(buf);
-
- if (!Arrays.ConstantTimeAreEqual(mExpectedVerifyData, verify_data))
- {
-
- throw new TlsFatalAlert(AlertDescription.decrypt_error);
- }
- }
- protected virtual void RaiseAlert(byte alertLevel, byte alertDescription, string message, Exception cause)
- {
- Peer.NotifyAlertRaised(alertLevel, alertDescription, message, cause);
- byte[] error = new byte[]{ alertLevel, alertDescription };
- SafeWriteRecord(ContentType.alert, error, 0, 2);
- }
- protected virtual void RaiseWarning(byte alertDescription, string message)
- {
- RaiseAlert(AlertLevel.warning, alertDescription, message, null);
- }
- 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 errorMessage = serverVersion.ToString() + " client didn't provide credentials";
- RaiseWarning(AlertDescription.no_certificate, errorMessage);
- return;
- }
- }
- }
- HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate);
- certificate.Encode(message);
- message.WriteToRecordStream(this);
- }
- protected virtual void SendChangeCipherSpecMessage()
- {
- byte[] message = new byte[]{ 1 };
- SafeWriteRecord(ContentType.change_cipher_spec, message, 0, message.Length);
- mRecordStream.SentWriteCipherSpec();
- }
- protected virtual void SendFinishedMessage()
- {
- byte[] verify_data = CreateVerifyData(Context.IsServer);
- HandshakeMessage message = new HandshakeMessage(HandshakeType.finished, verify_data.Length);
- message.Write(verify_data, 0, verify_data.Length);
- message.WriteToRecordStream(this);
- }
- protected virtual void SendSupplementalDataMessage(IList supplementalData)
- {
- HandshakeMessage message = new HandshakeMessage(HandshakeType.supplemental_data);
- WriteSupplementalData(message, supplementalData);
- message.WriteToRecordStream(this);
- }
- protected virtual byte[] CreateVerifyData(bool isServer)
- {
- TlsContext context = Context;
- string asciiLabel = isServer ? ExporterLabel.server_finished : ExporterLabel.client_finished;
- byte[] sslSender = isServer ? TlsUtilities.SSL_SERVER : TlsUtilities.SSL_CLIENT;
- byte[] hash = GetCurrentPrfHash(context, mRecordStream.HandshakeHash, sslSender);
- return TlsUtilities.CalculateVerifyData(context, asciiLabel, hash);
- }
-
- public virtual void Close()
- {
- HandleClose(true);
- }
- protected virtual void HandleClose(bool user_canceled)
- {
- if (!mClosed)
- {
- if (user_canceled && !mAppDataReady)
- {
- RaiseWarning(AlertDescription.user_canceled, "User canceled handshake");
- }
- this.FailWithError(AlertLevel.warning, AlertDescription.close_notify, "Connection closed", null);
- }
- }
- protected internal virtual void Flush()
- {
- mRecordStream.Flush();
- }
- public virtual bool IsClosed
- {
- get { return mClosed; }
- }
- protected virtual short ProcessMaxFragmentLengthExtension(IDictionary clientExtensions, IDictionary serverExtensions,
- byte alertDescription)
- {
- short maxFragmentLength = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions);
- if (maxFragmentLength >= 0)
- {
- if (!MaxFragmentLength.IsValid((byte)maxFragmentLength)
- || (!this.mResumedSession && maxFragmentLength != TlsExtensionsUtilities
- .GetMaxFragmentLengthExtension(clientExtensions)))
- {
- throw new TlsFatalAlert(alertDescription);
- }
- }
- return maxFragmentLength;
- }
- protected virtual void RefuseRenegotiation()
- {
-
- if (TlsUtilities.IsSsl(Context))
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- RaiseWarning(AlertDescription.no_renegotiation, "Renegotiation not supported");
- }
-
- protected internal static void AssertEmpty(MemoryStream buf)
- {
- if (buf.Position < buf.Length)
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- protected internal static byte[] CreateRandomBlock(bool useGmtUnixTime, IRandomGenerator randomGenerator)
- {
- byte[] result = new byte[32];
- randomGenerator.NextBytes(result);
- if (useGmtUnixTime)
- {
- TlsUtilities.WriteGmtUnixTime(result, 0);
- }
- return result;
- }
- protected internal static byte[] CreateRenegotiationInfo(byte[] renegotiated_connection)
- {
- return TlsUtilities.EncodeOpaque8(renegotiated_connection);
- }
- protected internal static void EstablishMasterSecret(TlsContext context, TlsKeyExchange keyExchange)
- {
- byte[] pre_master_secret = keyExchange.GeneratePremasterSecret();
- try
- {
- context.SecurityParameters.masterSecret = TlsUtilities.CalculateMasterSecret(context, pre_master_secret);
- }
- finally
- {
-
-
- if (pre_master_secret != null)
- {
- Arrays.Fill(pre_master_secret, (byte)0);
- }
- }
- }
-
- protected internal static byte[] GetCurrentPrfHash(TlsContext context, TlsHandshakeHash handshakeHash, byte[] sslSender)
- {
- IDigest d = handshakeHash.ForkPrfHash();
- if (sslSender != null && TlsUtilities.IsSsl(context))
- {
- d.BlockUpdate(sslSender, 0, sslSender.Length);
- }
- return DigestUtilities.DoFinal(d);
- }
- protected internal static IDictionary ReadExtensions(MemoryStream input)
- {
- if (input.Position >= input.Length)
- return null;
- byte[] extBytes = TlsUtilities.ReadOpaque16(input);
- AssertEmpty(input);
- MemoryStream buf = new MemoryStream(extBytes, false);
-
- IDictionary extensions = Org.BouncyCastle.Utilities.Platform.CreateHashtable();
- while (buf.Position < buf.Length)
- {
- int extension_type = TlsUtilities.ReadUint16(buf);
- byte[] extension_data = TlsUtilities.ReadOpaque16(buf);
-
- if (extensions.Contains(extension_type))
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- extensions.Add(extension_type, extension_data);
- }
- return extensions;
- }
- protected internal static IList ReadSupplementalDataMessage(MemoryStream input)
- {
- byte[] supp_data = TlsUtilities.ReadOpaque24(input);
- AssertEmpty(input);
- MemoryStream buf = new MemoryStream(supp_data, false);
- IList supplementalData = Org.BouncyCastle.Utilities.Platform.CreateArrayList();
- while (buf.Position < buf.Length)
- {
- int supp_data_type = TlsUtilities.ReadUint16(buf);
- byte[] data = TlsUtilities.ReadOpaque16(buf);
- supplementalData.Add(new SupplementalDataEntry(supp_data_type, data));
- }
- return supplementalData;
- }
- protected internal static void WriteExtensions(Stream output, IDictionary extensions)
- {
- MemoryStream buf = new MemoryStream();
-
- WriteSelectedExtensions(buf, extensions, true);
- WriteSelectedExtensions(buf, extensions, false);
- byte[] extBytes = buf.ToArray();
- TlsUtilities.WriteOpaque16(extBytes, output);
- }
- protected internal static void WriteSelectedExtensions(Stream output, IDictionary extensions, bool selectEmpty)
- {
- foreach (int extension_type in extensions.Keys)
- {
- byte[] extension_data = (byte[])extensions[extension_type];
- if (selectEmpty == (extension_data.Length == 0))
- {
- TlsUtilities.CheckUint16(extension_type);
- TlsUtilities.WriteUint16(extension_type, output);
- TlsUtilities.WriteOpaque16(extension_data, output);
- }
- }
- }
- protected internal static void WriteSupplementalData(Stream output, IList supplementalData)
- {
- MemoryStream buf = new MemoryStream();
- foreach (SupplementalDataEntry entry in supplementalData)
- {
- int supp_data_type = entry.DataType;
- TlsUtilities.CheckUint16(supp_data_type);
- TlsUtilities.WriteUint16(supp_data_type, buf);
- TlsUtilities.WriteOpaque16(entry.Data, buf);
- }
- byte[] supp_data = buf.ToArray();
- TlsUtilities.WriteOpaque24(supp_data, output);
- }
- protected internal static int GetPrfAlgorithm(TlsContext context, int ciphersuite)
- {
- bool isTLSv12 = TlsUtilities.IsTlsV12(context);
- switch (ciphersuite)
- {
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
- case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
- case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
- case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB:
- case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB:
- case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB:
- case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
- case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
- case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
- case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
- case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB:
- case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
- case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
- case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
- case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
- case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
- case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
- {
- if (isTLSv12)
- {
- return PrfAlgorithm.tls_prf_sha256;
- }
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- {
- if (isTLSv12)
- {
- return PrfAlgorithm.tls_prf_sha384;
- }
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
- case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
- case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
- {
- if (isTLSv12)
- {
- return PrfAlgorithm.tls_prf_sha384;
- }
- return PrfAlgorithm.tls_prf_legacy;
- }
- default:
- {
- if (isTLSv12)
- {
- return PrfAlgorithm.tls_prf_sha256;
- }
- return PrfAlgorithm.tls_prf_legacy;
- }
- }
- }
- 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 length = Length - 4;
- TlsUtilities.CheckUint24(length);
- this.Position = 1;
- TlsUtilities.WriteUint24((int)length, this);
- #if PORTABLE || NETFX_CORE
- byte[] buf = ToArray();
- int bufLen = buf.Length;
- #else
- byte[] buf = GetBuffer();
- int bufLen = (int)Length;
- #endif
- protocol.WriteHandshakeMessage(buf, 0, bufLen);
- Org.BouncyCastle.Utilities.Platform.Dispose(this);
- }
- }
- }
- }
- #endif
|