<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />

DtlsClientProtocol

using Org.BouncyCastle.Tls.Crypto; using Org.BouncyCastle.Utilities; using System; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Tls { public class DtlsClientProtocol : DtlsProtocol { protected internal class ClientHandshakeState { internal TlsClient client; internal TlsClientContextImpl clientContext; internal TlsSession tlsSession; internal SessionParameters sessionParameters; internal TlsSecret sessionMasterSecret; internal SessionParameters.Builder sessionParametersBuilder; internal int[] offeredCipherSuites; internal IDictionary<int, byte[]> clientExtensions; internal IDictionary<int, byte[]> serverExtensions; internal bool expectSessionTicket; internal IDictionary<int, TlsAgreement> clientAgreements; internal OfferedPsks.BindersConfig clientBinders; internal TlsKeyExchange keyExchange; internal TlsAuthentication authentication; internal CertificateStatus certificateStatus; internal CertificateRequest certificateRequest; internal TlsHeartbeat heartbeat; internal short heartbeatPolicy = 2; } public virtual DtlsTransport Connect(TlsClient client, DatagramTransport transport) { if (client == null) throw new ArgumentNullException("client"); if (transport != null) { TlsClientContextImpl tlsClientContextImpl = new TlsClientContextImpl(client.Crypto); ClientHandshakeState clientHandshakeState = new ClientHandshakeState(); clientHandshakeState.client = client; clientHandshakeState.clientContext = tlsClientContextImpl; client.Init(tlsClientContextImpl); tlsClientContextImpl.HandshakeBeginning(client); SecurityParameters securityParameters = tlsClientContextImpl.SecurityParameters; securityParameters.m_extendedPadding = client.ShouldUseExtendedPadding(); DtlsRecordLayer dtlsRecordLayer = new DtlsRecordLayer(tlsClientContextImpl, client, transport); client.NotifyCloseHandle(dtlsRecordLayer); try { return ClientHandshake(clientHandshakeState, dtlsRecordLayer); } catch (TlsFatalAlert tlsFatalAlert) { AbortClientHandshake(clientHandshakeState, dtlsRecordLayer, tlsFatalAlert.AlertDescription); throw; } catch (IOException) { AbortClientHandshake(clientHandshakeState, dtlsRecordLayer, 80); throw; } catch (Exception alertCause) { AbortClientHandshake(clientHandshakeState, dtlsRecordLayer, 80); throw new TlsFatalAlert(80, alertCause); } finally { securityParameters.Clear(); } } throw new ArgumentNullException("transport"); } internal virtual void AbortClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer, short alertDescription) { recordLayer.Fail(alertDescription); InvalidateSession(state); } internal virtual DtlsTransport ClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer) { TlsClient client = state.client; TlsClientContextImpl clientContext = state.clientContext; SecurityParameters securityParameters = clientContext.SecurityParameters; DtlsReliableHandshake dtlsReliableHandshake = new DtlsReliableHandshake(clientContext, recordLayer, client.GetHandshakeTimeoutMillis(), TlsUtilities.GetHandshakeResendTimeMillis(client), null); byte[] array = GenerateClientHello(state); recordLayer.SetWriteVersion(ProtocolVersion.DTLSv10); dtlsReliableHandshake.SendMessage(1, array); DtlsReliableHandshake.Message message = dtlsReliableHandshake.ReceiveMessage(); while (message.Type == 3) { byte[] cookie = ProcessHelloVerifyRequest(state, message.Body); byte[] body = PatchClientHelloWithCookie(array, cookie); dtlsReliableHandshake.ResetAfterHelloVerifyRequestClient(); dtlsReliableHandshake.SendMessage(1, body); message = dtlsReliableHandshake.ReceiveMessage(); } if (message.Type != 2) throw new TlsFatalAlert(10); ProtocolVersion readVersion = recordLayer.ReadVersion; ReportServerVersion(state, readVersion); recordLayer.SetWriteVersion(readVersion); ProcessServerHello(state, message.Body); DtlsProtocol.ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.MaxFragmentLength); dtlsReliableHandshake.HandshakeHash.NotifyPrfDetermined(); if (securityParameters.IsResumedSession) { securityParameters.m_masterSecret = state.sessionMasterSecret; recordLayer.InitPendingEpoch(TlsUtilities.InitCipher(clientContext)); securityParameters.m_peerVerifyData = TlsUtilities.CalculateVerifyData(clientContext, dtlsReliableHandshake.HandshakeHash, true); ProcessFinished(dtlsReliableHandshake.ReceiveMessageBody(20), securityParameters.PeerVerifyData); securityParameters.m_localVerifyData = TlsUtilities.CalculateVerifyData(clientContext, dtlsReliableHandshake.HandshakeHash, false); dtlsReliableHandshake.SendMessage(20, securityParameters.LocalVerifyData); dtlsReliableHandshake.Finish(); if (securityParameters.IsExtendedMasterSecret) securityParameters.m_tlsUnique = securityParameters.PeerVerifyData; securityParameters.m_localCertificate = state.sessionParameters.LocalCertificate; securityParameters.m_peerCertificate = state.sessionParameters.PeerCertificate; securityParameters.m_pskIdentity = state.sessionParameters.PskIdentity; securityParameters.m_srpIdentity = state.sessionParameters.SrpIdentity; clientContext.HandshakeComplete(client, state.tlsSession); recordLayer.InitHeartbeat(state.heartbeat, 1 == state.heartbeatPolicy); return new DtlsTransport(recordLayer, client.IgnoreCorruptDtlsRecords); } InvalidateSession(state); state.tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, null); message = dtlsReliableHandshake.ReceiveMessage(); if (message.Type == 23) { ProcessServerSupplementalData(state, message.Body); message = dtlsReliableHandshake.ReceiveMessage(); } else client.ProcessServerSupplementalData(null); state.keyExchange = TlsUtilities.InitKeyExchangeClient(clientContext, client); if (message.Type == 11) { ProcessServerCertificate(state, message.Body); message = dtlsReliableHandshake.ReceiveMessage(); } else state.authentication = null; if (message.Type == 22) { if (securityParameters.StatusRequestVersion < 1) throw new TlsFatalAlert(10); ProcessCertificateStatus(state, message.Body); message = dtlsReliableHandshake.ReceiveMessage(); } TlsUtilities.ProcessServerCertificate(clientContext, state.certificateStatus, state.keyExchange, state.authentication, state.clientExtensions, state.serverExtensions); if (message.Type == 12) { ProcessServerKeyExchange(state, message.Body); message = dtlsReliableHandshake.ReceiveMessage(); } else state.keyExchange.SkipServerKeyExchange(); if (message.Type == 13) { ProcessCertificateRequest(state, message.Body); TlsUtilities.EstablishServerSigAlgs(securityParameters, state.certificateRequest); message = dtlsReliableHandshake.ReceiveMessage(); } if (message.Type != 14) throw new TlsFatalAlert(10); if (message.Body.Length != 0) throw new TlsFatalAlert(50); TlsCredentials tlsCredentials = null; TlsCredentialedSigner tlsCredentialedSigner = null; Certificate certificate = null; SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; TlsStreamSigner tlsStreamSigner = null; if (state.certificateRequest != null) { tlsCredentials = TlsUtilities.EstablishClientCredentials(state.authentication, state.certificateRequest); if (tlsCredentials != null) { certificate = tlsCredentials.Certificate; if (tlsCredentials is TlsCredentialedSigner) { tlsCredentialedSigner = (TlsCredentialedSigner)tlsCredentials; signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm(securityParameters.NegotiatedVersion, tlsCredentialedSigner); tlsStreamSigner = tlsCredentialedSigner.GetStreamSigner(); if (ProtocolVersion.DTLSv12.Equals(securityParameters.NegotiatedVersion)) { TlsUtilities.VerifySupportedSignatureAlgorithm(securityParameters.ServerSigAlgs, signatureAndHashAlgorithm, 80); if (tlsStreamSigner == null) TlsUtilities.TrackHashAlgorithmClient(dtlsReliableHandshake.HandshakeHash, signatureAndHashAlgorithm); } if (tlsStreamSigner != null) dtlsReliableHandshake.HandshakeHash.ForceBuffering(); } } } dtlsReliableHandshake.HandshakeHash.SealHashAlgorithms(); if (tlsCredentials == null) state.keyExchange.SkipClientCredentials(); else state.keyExchange.ProcessClientCredentials(tlsCredentials); IList<SupplementalDataEntry> clientSupplementalData = client.GetClientSupplementalData(); if (clientSupplementalData != null) { byte[] body2 = DtlsProtocol.GenerateSupplementalData(clientSupplementalData); dtlsReliableHandshake.SendMessage(23, body2); } if (state.certificateRequest != null) DtlsProtocol.SendCertificateMessage(clientContext, dtlsReliableHandshake, certificate, null); byte[] body3 = GenerateClientKeyExchange(state); dtlsReliableHandshake.SendMessage(16, body3); securityParameters.m_sessionHash = TlsUtilities.GetCurrentPrfHash(dtlsReliableHandshake.HandshakeHash); TlsProtocol.EstablishMasterSecret(clientContext, state.keyExchange); recordLayer.InitPendingEpoch(TlsUtilities.InitCipher(clientContext)); if (tlsCredentialedSigner != null) { DigitallySigned certificateVerify = TlsUtilities.GenerateCertificateVerifyClient(clientContext, tlsCredentialedSigner, signatureAndHashAlgorithm, tlsStreamSigner, dtlsReliableHandshake.HandshakeHash); byte[] body4 = GenerateCertificateVerify(state, certificateVerify); dtlsReliableHandshake.SendMessage(15, body4); } dtlsReliableHandshake.PrepareToFinish(); securityParameters.m_localVerifyData = TlsUtilities.CalculateVerifyData(clientContext, dtlsReliableHandshake.HandshakeHash, false); dtlsReliableHandshake.SendMessage(20, securityParameters.LocalVerifyData); if (state.expectSessionTicket) { message = dtlsReliableHandshake.ReceiveMessage(); if (message.Type != 4) throw new TlsFatalAlert(10); securityParameters.m_sessionID = TlsUtilities.EmptyBytes; InvalidateSession(state); state.tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, null); ProcessNewSessionTicket(state, message.Body); } securityParameters.m_peerVerifyData = TlsUtilities.CalculateVerifyData(clientContext, dtlsReliableHandshake.HandshakeHash, true); ProcessFinished(dtlsReliableHandshake.ReceiveMessageBody(20), securityParameters.PeerVerifyData); dtlsReliableHandshake.Finish(); state.sessionMasterSecret = securityParameters.MasterSecret; state.sessionParameters = new SessionParameters.Builder().SetCipherSuite(securityParameters.CipherSuite).SetExtendedMasterSecret(securityParameters.IsExtendedMasterSecret).SetLocalCertificate(securityParameters.LocalCertificate) .SetMasterSecret(clientContext.Crypto.AdoptSecret(state.sessionMasterSecret)) .SetNegotiatedVersion(securityParameters.NegotiatedVersion) .SetPeerCertificate(securityParameters.PeerCertificate) .SetPskIdentity(securityParameters.PskIdentity) .SetSrpIdentity(securityParameters.SrpIdentity) .SetServerExtensions(state.serverExtensions) .Build(); state.tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, state.sessionParameters); securityParameters.m_tlsUnique = securityParameters.LocalVerifyData; clientContext.HandshakeComplete(client, state.tlsSession); recordLayer.InitHeartbeat(state.heartbeat, 1 == state.heartbeatPolicy); return new DtlsTransport(recordLayer, client.IgnoreCorruptDtlsRecords); } protected virtual byte[] GenerateCertificateVerify(ClientHandshakeState state, DigitallySigned certificateVerify) { MemoryStream memoryStream = new MemoryStream(); certificateVerify.Encode(memoryStream); return memoryStream.ToArray(); } protected virtual byte[] GenerateClientHello(ClientHandshakeState state) { TlsClient client = state.client; TlsClientContextImpl clientContext = state.clientContext; SecurityParameters securityParameters = clientContext.SecurityParameters; ProtocolVersion[] protocolVersions = client.GetProtocolVersions(); ProtocolVersion earliestDtls = ProtocolVersion.GetEarliestDtls(protocolVersions); ProtocolVersion latestDtls = ProtocolVersion.GetLatestDtls(protocolVersions); if (!ProtocolVersion.IsSupportedDtlsVersionClient(latestDtls)) throw new TlsFatalAlert(80); clientContext.SetClientVersion(latestDtls); clientContext.SetClientSupportedVersions(protocolVersions); bool num = ProtocolVersion.DTLSv12.IsEqualOrLaterVersionOf(earliestDtls); bool flag = ProtocolVersion.DTLSv13.IsEqualOrEarlierVersionOf(latestDtls); bool useGmtUnixTime = !flag && client.ShouldUseGmtUnixTime(); securityParameters.m_clientRandom = TlsProtocol.CreateRandomBlock(useGmtUnixTime, clientContext); TlsSession sessionToResume = num ? client.GetSessionToResume() : null; bool num2 = client.IsFallback(); state.offeredCipherSuites = client.GetCipherSuites(); state.clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(client.GetClientExtensions()); bool flag2 = client.ShouldUseExtendedMasterSecret(); EstablishSession(state, sessionToResume); byte[] array = TlsUtilities.GetSessionID(state.tlsSession); if (array.Length != 0 && !Arrays.Contains(state.offeredCipherSuites, state.sessionParameters.CipherSuite)) array = TlsUtilities.EmptyBytes; ProtocolVersion protocolVersion = null; if (array.Length != 0) { protocolVersion = state.sessionParameters.NegotiatedVersion; if (!ProtocolVersion.Contains(protocolVersions, protocolVersion)) array = TlsUtilities.EmptyBytes; } if (array.Length != 0 && TlsUtilities.IsExtendedMasterSecretOptional(protocolVersion)) { if (flag2) { if (!state.sessionParameters.IsExtendedMasterSecret && !client.AllowLegacyResumption()) array = TlsUtilities.EmptyBytes; } else if (state.sessionParameters.IsExtendedMasterSecret) { array = TlsUtilities.EmptyBytes; } } if (array.Length < 1) CancelSession(state); client.NotifySessionToResume(state.tlsSession); ProtocolVersion protocolVersion2 = latestDtls; if (flag) { protocolVersion2 = ProtocolVersion.DTLSv12; TlsExtensionsUtilities.AddSupportedVersionsExtensionClient(state.clientExtensions, protocolVersions); } clientContext.SetRsaPreMasterSecretVersion(protocolVersion2); securityParameters.m_clientServerNames = TlsExtensionsUtilities.GetServerNameExtensionClient(state.clientExtensions); if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(latestDtls)) TlsUtilities.EstablishClientSigAlgs(securityParameters, state.clientExtensions); securityParameters.m_clientSupportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(state.clientExtensions); state.clientBinders = null; state.clientAgreements = TlsUtilities.AddKeyShareToClientHello(clientContext, client, state.clientExtensions); if (flag2 && TlsUtilities.IsExtendedMasterSecretOptional(protocolVersions)) TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.clientExtensions); else state.clientExtensions.Remove(23); bool num3 = TlsUtilities.GetExtensionData(state.clientExtensions, 65281) == null; bool flag3 = !Arrays.Contains(state.offeredCipherSuites, 255); if (num3 & flag3) state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, 255); if (num2 && !Arrays.Contains(state.offeredCipherSuites, 22016)) state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, 22016); state.heartbeat = client.GetHeartbeat(); state.heartbeatPolicy = client.GetHeartbeatPolicy(); if (state.heartbeat != null || 1 == state.heartbeatPolicy) TlsExtensionsUtilities.AddHeartbeatExtension(state.clientExtensions, new HeartbeatExtension(state.heartbeatPolicy)); int bindersSize = (state.clientBinders != null) ? state.clientBinders.m_bindersSize : 0; ClientHello clientHello = new ClientHello(protocolVersion2, securityParameters.ClientRandom, array, TlsUtilities.EmptyBytes, state.offeredCipherSuites, state.clientExtensions, bindersSize); MemoryStream memoryStream = new MemoryStream(); clientHello.Encode(clientContext, memoryStream); return memoryStream.ToArray(); } protected virtual byte[] GenerateClientKeyExchange(ClientHandshakeState state) { MemoryStream memoryStream = new MemoryStream(); state.keyExchange.GenerateClientKeyExchange(memoryStream); return memoryStream.ToArray(); } protected virtual void CancelSession(ClientHandshakeState state) { if (state.sessionMasterSecret != null) { state.sessionMasterSecret.Destroy(); state.sessionMasterSecret = null; } if (state.sessionParameters != null) { state.sessionParameters.Clear(); state.sessionParameters = null; } state.tlsSession = null; } protected virtual bool EstablishSession(ClientHandshakeState state, TlsSession sessionToResume) { state.tlsSession = null; state.sessionParameters = null; state.sessionMasterSecret = null; if (sessionToResume == null || !sessionToResume.IsResumable) return false; SessionParameters sessionParameters = sessionToResume.ExportSessionParameters(); if (sessionParameters == null) return false; ProtocolVersion negotiatedVersion = sessionParameters.NegotiatedVersion; if (negotiatedVersion == null || !negotiatedVersion.IsDtls) return false; if (!sessionParameters.IsExtendedMasterSecret && !TlsUtilities.IsExtendedMasterSecretOptional(negotiatedVersion)) return false; TlsSecret sessionMasterSecret = TlsUtilities.GetSessionMasterSecret(state.clientContext.Crypto, sessionParameters.MasterSecret); if (sessionMasterSecret == null) return false; state.tlsSession = sessionToResume; state.sessionParameters = sessionParameters; state.sessionMasterSecret = sessionMasterSecret; return true; } protected virtual void InvalidateSession(ClientHandshakeState state) { if (state.tlsSession != null) state.tlsSession.Invalidate(); CancelSession(state); } protected virtual void ProcessCertificateRequest(ClientHandshakeState state, byte[] body) { if (state.authentication == null) throw new TlsFatalAlert(40); MemoryStream memoryStream = new MemoryStream(body, false); CertificateRequest certificateRequest = CertificateRequest.Parse(state.clientContext, memoryStream); TlsProtocol.AssertEmpty(memoryStream); state.certificateRequest = TlsUtilities.ValidateCertificateRequest(certificateRequest, state.keyExchange); } protected virtual void ProcessCertificateStatus(ClientHandshakeState state, byte[] body) { MemoryStream memoryStream = new MemoryStream(body, false); state.certificateStatus = CertificateStatus.Parse(state.clientContext, memoryStream); TlsProtocol.AssertEmpty(memoryStream); } protected virtual byte[] ProcessHelloVerifyRequest(ClientHandshakeState state, byte[] body) { MemoryStream memoryStream = new MemoryStream(body, false); ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(memoryStream); int maxLength = ProtocolVersion.DTLSv12.IsEqualOrEarlierVersionOf(protocolVersion) ? 255 : 32; byte[] result = TlsUtilities.ReadOpaque8(memoryStream, 0, maxLength); TlsProtocol.AssertEmpty(memoryStream); if (!protocolVersion.IsEqualOrEarlierVersionOf(state.clientContext.ClientVersion)) throw new TlsFatalAlert(47); return result; } protected virtual void ProcessNewSessionTicket(ClientHandshakeState state, byte[] body) { MemoryStream memoryStream = new MemoryStream(body, false); NewSessionTicket newSessionTicket = NewSessionTicket.Parse(memoryStream); TlsProtocol.AssertEmpty(memoryStream); state.client.NotifyNewSessionTicket(newSessionTicket); } protected virtual void ProcessServerCertificate(ClientHandshakeState state, byte[] body) { state.authentication = TlsUtilities.ReceiveServerCertificate(state.clientContext, state.client, new MemoryStream(body, false), state.serverExtensions); } protected virtual void ProcessServerHello(ClientHandshakeState state, byte[] body) { TlsClient client = state.client; TlsClientContextImpl clientContext = state.clientContext; SecurityParameters securityParameters = clientContext.SecurityParameters; ServerHello serverHello = ServerHello.Parse(new MemoryStream(body, false)); IDictionary<int, byte[]> extensions = serverHello.Extensions; ProtocolVersion version = serverHello.Version; ProtocolVersion supportedVersionsExtensionServer = TlsExtensionsUtilities.GetSupportedVersionsExtensionServer(extensions); ProtocolVersion protocolVersion; if (supportedVersionsExtensionServer == null) protocolVersion = version; else { if (!ProtocolVersion.DTLSv12.Equals(version) || !ProtocolVersion.DTLSv13.IsEqualOrEarlierVersionOf(supportedVersionsExtensionServer)) throw new TlsFatalAlert(47); protocolVersion = supportedVersionsExtensionServer; } ReportServerVersion(state, protocolVersion); int[] offeredCipherSuites = state.offeredCipherSuites; securityParameters.m_serverRandom = serverHello.Random; if (!clientContext.ClientVersion.Equals(protocolVersion)) TlsUtilities.CheckDowngradeMarker(protocolVersion, securityParameters.ServerRandom); byte[] array = securityParameters.m_sessionID = serverHello.SessionID; client.NotifySessionID(array); securityParameters.m_resumedSession = (array.Length != 0 && state.tlsSession != null && Arrays.AreEqual(array, state.tlsSession.SessionID)); if (securityParameters.IsResumedSession && (serverHello.CipherSuite != state.sessionParameters.CipherSuite || !securityParameters.NegotiatedVersion.Equals(state.sessionParameters.NegotiatedVersion))) throw new TlsFatalAlert(47, "ServerHello parameters do not match resumed session"); int num = DtlsProtocol.ValidateSelectedCipherSuite(serverHello.CipherSuite, 47); if (!TlsUtilities.IsValidCipherSuiteSelection(offeredCipherSuites, num) || !TlsUtilities.IsValidVersionForCipherSuite(num, securityParameters.NegotiatedVersion)) throw new TlsFatalAlert(47, "ServerHello selected invalid cipher suite"); TlsUtilities.NegotiatedCipherSuite(securityParameters, num); client.NotifySelectedCipherSuite(num); state.serverExtensions = extensions; if (extensions != null) { foreach (int key in extensions.Keys) { if (key != 65281) { if (TlsUtilities.GetExtensionData(state.clientExtensions, key) == null) throw new TlsFatalAlert(110); bool isResumedSession = securityParameters.IsResumedSession; } } } byte[] extensionData = TlsUtilities.GetExtensionData(extensions, 65281); if (extensionData == null) securityParameters.m_secureRenegotiation = false; else { securityParameters.m_secureRenegotiation = true; if (!Arrays.FixedTimeEquals(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) throw new TlsFatalAlert(40); } client.NotifySecureRenegotiation(securityParameters.IsSecureRenegotiation); bool flag = false; if (TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions)) { flag = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(extensions); if (TlsUtilities.IsExtendedMasterSecretOptional(protocolVersion)) { if (!flag && client.RequiresExtendedMasterSecret()) throw new TlsFatalAlert(40, "Extended Master Secret extension is required"); } else if (flag) { throw new TlsFatalAlert(47, "Server sent an unexpected extended_master_secret extension negotiating " + protocolVersion?.ToString()); } } securityParameters.m_extendedMasterSecret = flag; if (securityParameters.IsResumedSession && securityParameters.IsExtendedMasterSecret != state.sessionParameters.IsExtendedMasterSecret) throw new TlsFatalAlert(40, "Server resumed session with mismatched extended_master_secret negotiation"); securityParameters.m_applicationProtocol = TlsExtensionsUtilities.GetAlpnExtensionServer(extensions); securityParameters.m_applicationProtocolSet = true; if (ProtocolVersion.DTLSv12.Equals(securityParameters.NegotiatedVersion)) { byte[] connectionIDExtension = TlsExtensionsUtilities.GetConnectionIDExtension(extensions); if (connectionIDExtension != null) { byte[] connectionIDExtension2 = TlsExtensionsUtilities.GetConnectionIDExtension(state.clientExtensions); if (connectionIDExtension2 == null) throw new TlsFatalAlert(80); byte[] connectionIDPeer = connectionIDExtension2; securityParameters.m_connectionIDLocal = connectionIDExtension; securityParameters.m_connectionIDPeer = connectionIDPeer; } } HeartbeatExtension heartbeatExtension = TlsExtensionsUtilities.GetHeartbeatExtension(extensions); if (heartbeatExtension == null) { state.heartbeat = null; state.heartbeatPolicy = 2; } else if (1 != heartbeatExtension.Mode) { state.heartbeat = null; } IDictionary<int, byte[]> dictionary = state.clientExtensions; IDictionary<int, byte[]> dictionary2 = extensions; if (securityParameters.IsResumedSession) { dictionary = null; dictionary2 = state.sessionParameters.ReadServerExtensions(); } if (dictionary2 != null && dictionary2.Count > 0) { bool flag2 = TlsExtensionsUtilities.HasEncryptThenMacExtension(dictionary2); if (flag2 && !TlsUtilities.IsBlockCipherSuite(securityParameters.CipherSuite)) throw new TlsFatalAlert(47); securityParameters.m_encryptThenMac = flag2; securityParameters.m_maxFragmentLength = TlsUtilities.ProcessMaxFragmentLengthExtension(dictionary, dictionary2, 47); securityParameters.m_truncatedHmac = TlsExtensionsUtilities.HasTruncatedHmacExtension(dictionary2); if (!securityParameters.IsResumedSession) { if (TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 17, 47)) securityParameters.m_statusRequestVersion = 2; else if (TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 5, 47)) { securityParameters.m_statusRequestVersion = 1; } securityParameters.m_clientCertificateType = TlsUtilities.ProcessClientCertificateTypeExtension(dictionary, dictionary2, 47); securityParameters.m_serverCertificateType = TlsUtilities.ProcessServerCertificateTypeExtension(dictionary, dictionary2, 47); state.expectSessionTicket = TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 35, 47); } } if (dictionary != null) client.ProcessServerExtensions(dictionary2); } protected virtual void ProcessServerKeyExchange(ClientHandshakeState state, byte[] body) { MemoryStream memoryStream = new MemoryStream(body, false); state.keyExchange.ProcessServerKeyExchange(memoryStream); TlsProtocol.AssertEmpty(memoryStream); } protected virtual void ProcessServerSupplementalData(ClientHandshakeState state, byte[] body) { IList<SupplementalDataEntry> serverSupplementalData = TlsProtocol.ReadSupplementalDataMessage(new MemoryStream(body, false)); state.client.ProcessServerSupplementalData(serverSupplementalData); } protected virtual void ReportServerVersion(ClientHandshakeState state, ProtocolVersion server_version) { TlsClientContextImpl clientContext = state.clientContext; SecurityParameters securityParameters = clientContext.SecurityParameters; ProtocolVersion negotiatedVersion = securityParameters.NegotiatedVersion; if (negotiatedVersion != null) { if (!negotiatedVersion.Equals(server_version)) throw new TlsFatalAlert(47); } else { if (!ProtocolVersion.Contains(clientContext.ClientSupportedVersions, server_version)) throw new TlsFatalAlert(70); securityParameters.m_negotiatedVersion = server_version; TlsUtilities.NegotiatedVersionDtlsClient(clientContext, state.client); } } protected static byte[] PatchClientHelloWithCookie(byte[] clientHelloBody, byte[] cookie) { int num = 34; int num2 = TlsUtilities.ReadUint8(clientHelloBody, num); int num3 = num + 1 + num2; int num4 = num3 + 1; byte[] array = new byte[clientHelloBody.Length + cookie.Length]; Array.Copy(clientHelloBody, 0, array, 0, num3); TlsUtilities.CheckUint8(cookie.Length); TlsUtilities.WriteUint8(cookie.Length, array, num3); Array.Copy(cookie, 0, array, num4, cookie.Length); Array.Copy(clientHelloBody, num4, array, num4 + cookie.Length, clientHelloBody.Length - num4); return array; } } }