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

TlsClientProtocol

using Org.BouncyCastle.Tls.Crypto; using Org.BouncyCastle.Utilities; using System; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Tls { public class TlsClientProtocol : TlsProtocol { protected TlsClient m_tlsClient; internal TlsClientContextImpl m_tlsClientContext; protected IDictionary<int, TlsAgreement> m_clientAgreements; internal OfferedPsks.BindersConfig m_clientBinders; protected ClientHello m_clientHello; protected TlsKeyExchange m_keyExchange; protected TlsAuthentication m_authentication; protected CertificateStatus m_certificateStatus; protected CertificateRequest m_certificateRequest; protected override TlsContext Context => m_tlsClientContext; internal override AbstractTlsContext ContextAdmin => m_tlsClientContext; protected override TlsPeer Peer => m_tlsClient; public TlsClientProtocol() { } public TlsClientProtocol(Stream stream) : base(stream) { } public TlsClientProtocol(Stream input, Stream output) : base(input, output) { } public virtual void Connect(TlsClient tlsClient) { if (tlsClient == null) throw new ArgumentNullException("tlsClient"); if (m_tlsClient != null) throw new InvalidOperationException("'Connect' can only be called once"); m_tlsClient = tlsClient; m_tlsClientContext = new TlsClientContextImpl(tlsClient.Crypto); tlsClient.Init(m_tlsClientContext); tlsClient.NotifyCloseHandle(this); BeginHandshake(); if (m_blocking) BlockForHandshake(); } protected override void BeginHandshake() { base.BeginHandshake(); SendClientHello(); m_connectionState = 1; } protected override void CleanupHandshake() { base.CleanupHandshake(); m_clientAgreements = null; m_clientBinders = null; m_clientHello = null; m_keyExchange = null; m_authentication = null; m_certificateStatus = null; m_certificateRequest = null; } protected virtual void Handle13HandshakeMessage(short type, HandshakeMessageInput buf) { if (!IsTlsV13ConnectionState()) throw new TlsFatalAlert(80); switch (type) { case 11: { short connectionState = m_connectionState; if (connectionState != 5 && connectionState != 11) throw new TlsFatalAlert(10); if (m_connectionState != 11) Skip13CertificateRequest(); Receive13ServerCertificate(buf); m_connectionState = 7; break; } case 13: { short connectionState = m_connectionState; if (connectionState != 5) throw new TlsFatalAlert(10); Receive13CertificateRequest(buf, false); m_connectionState = 11; break; } case 15: if (m_connectionState != 7) throw new TlsFatalAlert(10); Receive13ServerCertificateVerify(buf); buf.UpdateHash(m_handshakeHash); m_connectionState = 9; break; case 8: if (m_connectionState != 4) throw new TlsFatalAlert(10); Receive13EncryptedExtensions(buf); m_connectionState = 5; break; case 20: { short connectionState = m_connectionState; if (connectionState != 5 && connectionState != 9 && connectionState != 11) throw new TlsFatalAlert(10); if (m_connectionState == 5) Skip13CertificateRequest(); if (m_connectionState != 9) Skip13ServerCertificate(); Receive13ServerFinished(buf); buf.UpdateHash(m_handshakeHash); m_connectionState = 20; byte[] currentPrfHash = TlsUtilities.GetCurrentPrfHash(m_handshakeHash); m_recordStream.SetIgnoreChangeCipherSpec(false); if (m_certificateRequest != null) { TlsCredentialedSigner tlsCredentialedSigner = TlsUtilities.Establish13ClientCredentials(m_authentication, m_certificateRequest); Certificate certificate = null; if (tlsCredentialedSigner != null) certificate = tlsCredentialedSigner.Certificate; if (certificate == null) certificate = Certificate.EmptyChainTls13; Send13CertificateMessage(certificate); m_connectionState = 15; if (tlsCredentialedSigner != null) { DigitallySigned certificateVerify = TlsUtilities.Generate13CertificateVerify(m_tlsClientContext, tlsCredentialedSigner, m_handshakeHash); Send13CertificateVerifyMessage(certificateVerify); m_connectionState = 17; } } Send13FinishedMessage(); m_connectionState = 18; TlsUtilities.Establish13PhaseApplication(m_tlsClientContext, currentPrfHash, m_recordStream); m_recordStream.EnablePendingCipherWrite(); m_recordStream.EnablePendingCipherRead(false); CompleteHandshake(); break; } case 24: Receive13KeyUpdate(buf); break; case 4: Receive13NewSessionTicket(buf); break; case 2: switch (m_connectionState) { case 1: throw new TlsFatalAlert(80); case 3: { ServerHello serverHello = ReceiveServerHelloMessage(buf); if (serverHello.IsHelloRetryRequest()) throw new TlsFatalAlert(10); Process13ServerHello(serverHello, true); buf.UpdateHash(m_handshakeHash); m_connectionState = 4; Process13ServerHelloCoda(serverHello, true); break; } default: throw new TlsFatalAlert(10); } break; default: throw new TlsFatalAlert(10); } } protected override void HandleHandshakeMessage(short type, HandshakeMessageInput buf) { SecurityParameters securityParameters = m_tlsClientContext.SecurityParameters; if (m_connectionState > 1 && TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion)) { if (securityParameters.IsResumedSession) throw new TlsFatalAlert(80); Handle13HandshakeMessage(type, buf); } else { if (!IsLegacyConnectionState()) throw new TlsFatalAlert(80); if (securityParameters.IsResumedSession) { switch (type) { case 20: if (m_connectionState == 4) { ProcessFinishedMessage(buf); buf.UpdateHash(m_handshakeHash); m_connectionState = 20; SendChangeCipherSpec(); SendFinishedMessage(); m_connectionState = 18; CompleteHandshake(); return; } goto default; default: throw new TlsFatalAlert(10); case 0: break; } } switch (type) { case 11: { short connectionState = m_connectionState; if (connectionState != 4 && connectionState != 6) throw new TlsFatalAlert(10); if (m_connectionState != 6) HandleSupplementalData(null); m_authentication = TlsUtilities.ReceiveServerCertificate(m_tlsClientContext, m_tlsClient, buf, m_serverExtensions); m_connectionState = 7; break; } case 22: if (m_connectionState != 7) throw new TlsFatalAlert(10); if (securityParameters.StatusRequestVersion < 1) throw new TlsFatalAlert(10); m_certificateStatus = CertificateStatus.Parse(m_tlsClientContext, buf); TlsProtocol.AssertEmpty(buf); m_connectionState = 8; break; case 20: { short connectionState = m_connectionState; if ((uint)(connectionState - 18) > 1) throw new TlsFatalAlert(10); if (m_connectionState != 19 && m_expectSessionTicket) throw new TlsFatalAlert(10); ProcessFinishedMessage(buf); m_connectionState = 20; CompleteHandshake(); break; } case 2: { if (m_connectionState != 1) throw new TlsFatalAlert(10); ServerHello serverHello = ReceiveServerHelloMessage(buf); if (serverHello.IsHelloRetryRequest()) { Process13HelloRetryRequest(serverHello); m_handshakeHash.NotifyPrfDetermined(); m_handshakeHash.SealHashAlgorithms(); TlsUtilities.AdjustTranscriptForRetry(m_handshakeHash); buf.UpdateHash(m_handshakeHash); m_connectionState = 2; Send13ClientHelloRetry(); m_connectionState = 3; } else { ProcessServerHello(serverHello); m_handshakeHash.NotifyPrfDetermined(); if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion)) m_handshakeHash.SealHashAlgorithms(); buf.UpdateHash(m_handshakeHash); m_connectionState = 4; if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion)) Process13ServerHelloCoda(serverHello, false); } break; } case 23: if (m_connectionState != 4) throw new TlsFatalAlert(10); HandleSupplementalData(TlsProtocol.ReadSupplementalDataMessage(buf)); break; case 14: switch (m_connectionState) { case 4: case 6: case 7: case 8: case 10: case 11: { if (m_connectionState == 4) HandleSupplementalData(null); if (m_connectionState == 4 || m_connectionState == 6) m_authentication = null; if (m_connectionState != 10 && m_connectionState != 11) { HandleServerCertificate(); m_keyExchange.SkipServerKeyExchange(); } TlsProtocol.AssertEmpty(buf); m_connectionState = 12; TlsCredentials tlsCredentials = null; TlsCredentialedSigner tlsCredentialedSigner = null; Certificate certificate = null; SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; TlsStreamSigner tlsStreamSigner = null; if (m_certificateRequest != null) { tlsCredentials = TlsUtilities.EstablishClientCredentials(m_authentication, m_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.TLSv12.Equals(securityParameters.NegotiatedVersion)) { TlsUtilities.VerifySupportedSignatureAlgorithm(securityParameters.ServerSigAlgs, signatureAndHashAlgorithm, 80); if (tlsStreamSigner == null) TlsUtilities.TrackHashAlgorithmClient(m_handshakeHash, signatureAndHashAlgorithm); } if (tlsStreamSigner != null) m_handshakeHash.ForceBuffering(); } } } m_handshakeHash.SealHashAlgorithms(); if (tlsCredentials == null) m_keyExchange.SkipClientCredentials(); else m_keyExchange.ProcessClientCredentials(tlsCredentials); IList<SupplementalDataEntry> clientSupplementalData = m_tlsClient.GetClientSupplementalData(); if (clientSupplementalData != null) { SendSupplementalDataMessage(clientSupplementalData); m_connectionState = 14; } if (m_certificateRequest != null) { SendCertificateMessage(certificate, null); m_connectionState = 15; } SendClientKeyExchange(); m_connectionState = 16; bool num = TlsUtilities.IsSsl(m_tlsClientContext); if (num) TlsProtocol.EstablishMasterSecret(m_tlsClientContext, m_keyExchange); securityParameters.m_sessionHash = TlsUtilities.GetCurrentPrfHash(m_handshakeHash); if (!num) TlsProtocol.EstablishMasterSecret(m_tlsClientContext, m_keyExchange); m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsClientContext)); if (tlsCredentialedSigner != null) { DigitallySigned certificateVerify = TlsUtilities.GenerateCertificateVerifyClient(m_tlsClientContext, tlsCredentialedSigner, signatureAndHashAlgorithm, tlsStreamSigner, m_handshakeHash); SendCertificateVerifyMessage(certificateVerify); m_connectionState = 17; } m_handshakeHash.StopTracking(); SendChangeCipherSpec(); SendFinishedMessage(); m_connectionState = 18; break; } default: throw new TlsFatalAlert(10); } break; case 12: { short connectionState = m_connectionState; if (connectionState != 4 && (uint)(connectionState - 6) > 2) throw new TlsFatalAlert(10); if (m_connectionState == 4) HandleSupplementalData(null); if (m_connectionState != 7 && m_connectionState != 8) m_authentication = null; HandleServerCertificate(); m_keyExchange.ProcessServerKeyExchange(buf); TlsProtocol.AssertEmpty(buf); m_connectionState = 10; break; } case 13: { short connectionState = m_connectionState; if ((uint)(connectionState - 7) > 1 && connectionState != 10) throw new TlsFatalAlert(10); if (m_connectionState != 10) { HandleServerCertificate(); m_keyExchange.SkipServerKeyExchange(); } ReceiveCertificateRequest(buf); TlsUtilities.EstablishServerSigAlgs(securityParameters, m_certificateRequest); m_connectionState = 11; break; } case 4: if (m_connectionState != 18) throw new TlsFatalAlert(10); if (!m_expectSessionTicket) throw new TlsFatalAlert(10); securityParameters.m_sessionID = TlsUtilities.EmptyBytes; InvalidateSession(); m_tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, null); ReceiveNewSessionTicket(buf); m_connectionState = 19; break; case 0: TlsProtocol.AssertEmpty(buf); if (base.IsApplicationDataReady) RefuseRenegotiation(); break; default: throw new TlsFatalAlert(10); } } } protected virtual void HandleServerCertificate() { TlsUtilities.ProcessServerCertificate(m_tlsClientContext, m_certificateStatus, m_keyExchange, m_authentication, m_clientExtensions, m_serverExtensions); } protected virtual void HandleSupplementalData(IList<SupplementalDataEntry> serverSupplementalData) { m_tlsClient.ProcessServerSupplementalData(serverSupplementalData); m_connectionState = 6; m_keyExchange = TlsUtilities.InitKeyExchangeClient(m_tlsClientContext, m_tlsClient); } protected virtual void Process13HelloRetryRequest(ServerHello helloRetryRequest) { ProtocolVersion tLSv = ProtocolVersion.TLSv12; m_recordStream.SetWriteVersion(tLSv); SecurityParameters securityParameters = m_tlsClientContext.SecurityParameters; ProtocolVersion version = helloRetryRequest.Version; byte[] sessionID = helloRetryRequest.SessionID; int cipherSuite = helloRetryRequest.CipherSuite; if (!ProtocolVersion.TLSv12.Equals(version) || !Arrays.AreEqual(m_clientHello.SessionID, sessionID) || !TlsUtilities.IsValidCipherSuiteSelection(m_clientHello.CipherSuites, cipherSuite)) throw new TlsFatalAlert(47); IDictionary<int, byte[]> extensions = helloRetryRequest.Extensions; if (extensions == null) throw new TlsFatalAlert(47); TlsUtilities.CheckExtensionData13(extensions, 6, 47); foreach (int key in extensions.Keys) { if (44 != key && TlsUtilities.GetExtensionData(m_clientExtensions, key) == null) throw new TlsFatalAlert(110); } ProtocolVersion supportedVersionsExtensionServer = TlsExtensionsUtilities.GetSupportedVersionsExtensionServer(extensions); if (supportedVersionsExtensionServer == null) throw new TlsFatalAlert(109); if (!ProtocolVersion.TLSv13.IsEqualOrEarlierVersionOf(supportedVersionsExtensionServer) || !ProtocolVersion.Contains(m_tlsClientContext.ClientSupportedVersions, supportedVersionsExtensionServer) || !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, supportedVersionsExtensionServer)) throw new TlsFatalAlert(47); if (m_clientBinders != null && !Arrays.Contains(m_clientBinders.m_pskKeyExchangeModes, 1)) { m_clientBinders = null; m_tlsClient.NotifySelectedPsk(null); } int keyShareHelloRetryRequest = TlsExtensionsUtilities.GetKeyShareHelloRetryRequest(extensions); if (!TlsUtilities.IsValidKeyShareSelection(supportedVersionsExtensionServer, securityParameters.ClientSupportedGroups, m_clientAgreements, keyShareHelloRetryRequest)) throw new TlsFatalAlert(47); byte[] cookieExtension = TlsExtensionsUtilities.GetCookieExtension(extensions); securityParameters.m_negotiatedVersion = supportedVersionsExtensionServer; TlsUtilities.NegotiatedVersionTlsClient(m_tlsClientContext, m_tlsClient); securityParameters.m_resumedSession = false; securityParameters.m_sessionID = TlsUtilities.EmptyBytes; m_tlsClient.NotifySessionID(TlsUtilities.EmptyBytes); TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite); m_tlsClient.NotifySelectedCipherSuite(cipherSuite); m_clientAgreements = null; m_retryCookie = cookieExtension; m_retryGroup = keyShareHelloRetryRequest; } protected virtual void Process13ServerHello(ServerHello serverHello, bool afterHelloRetryRequest) { SecurityParameters securityParameters = m_tlsClientContext.SecurityParameters; ProtocolVersion version = serverHello.Version; byte[] sessionID = serverHello.SessionID; int cipherSuite = serverHello.CipherSuite; if (!ProtocolVersion.TLSv12.Equals(version) || !Arrays.AreEqual(m_clientHello.SessionID, sessionID)) throw new TlsFatalAlert(47); IDictionary<int, byte[]> extensions = serverHello.Extensions; if (extensions == null) throw new TlsFatalAlert(47); TlsUtilities.CheckExtensionData13(extensions, 2, 47); if (afterHelloRetryRequest) { ProtocolVersion supportedVersionsExtensionServer = TlsExtensionsUtilities.GetSupportedVersionsExtensionServer(extensions); if (supportedVersionsExtensionServer == null) throw new TlsFatalAlert(109); if (!securityParameters.NegotiatedVersion.Equals(supportedVersionsExtensionServer) || securityParameters.CipherSuite != cipherSuite) throw new TlsFatalAlert(47); } else { if (!TlsUtilities.IsValidCipherSuiteSelection(m_clientHello.CipherSuites, cipherSuite) || !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, securityParameters.NegotiatedVersion)) throw new TlsFatalAlert(47); securityParameters.m_resumedSession = false; securityParameters.m_sessionID = TlsUtilities.EmptyBytes; m_tlsClient.NotifySessionID(TlsUtilities.EmptyBytes); TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite); m_tlsClient.NotifySelectedCipherSuite(cipherSuite); } m_clientHello = null; securityParameters.m_serverRandom = serverHello.Random; securityParameters.m_secureRenegotiation = false; securityParameters.m_extendedMasterSecret = true; securityParameters.m_statusRequestVersion = (m_clientExtensions.ContainsKey(5) ? 1 : 0); TlsSecret tlsSecret = null; int preSharedKeyServerHello = TlsExtensionsUtilities.GetPreSharedKeyServerHello(extensions); TlsPsk tlsPsk = null; if (preSharedKeyServerHello >= 0) { if (m_clientBinders == null || preSharedKeyServerHello >= m_clientBinders.m_psks.Length) throw new TlsFatalAlert(47); tlsPsk = m_clientBinders.m_psks[preSharedKeyServerHello]; if (tlsPsk.PrfAlgorithm != securityParameters.PrfAlgorithm) throw new TlsFatalAlert(47); tlsSecret = m_clientBinders.m_earlySecrets[preSharedKeyServerHello]; m_selectedPsk13 = true; } m_tlsClient.NotifySelectedPsk(tlsPsk); TlsSecret sharedSecret = null; KeyShareEntry keyShareServerHello = TlsExtensionsUtilities.GetKeyShareServerHello(extensions); if (keyShareServerHello == null) { if (afterHelloRetryRequest || tlsSecret == null || !Arrays.Contains(m_clientBinders.m_pskKeyExchangeModes, 0)) throw new TlsFatalAlert(47); } else { if (tlsSecret != null && !Arrays.Contains(m_clientBinders.m_pskKeyExchangeModes, 1)) throw new TlsFatalAlert(47); if (!m_clientAgreements.TryGetValue(keyShareServerHello.NamedGroup, out TlsAgreement value)) throw new TlsFatalAlert(47); value.ReceivePeerValue(keyShareServerHello.KeyExchange); sharedSecret = value.CalculateSecret(); } m_clientAgreements = null; m_clientBinders = null; TlsUtilities.Establish13PhaseSecrets(m_tlsClientContext, tlsSecret, sharedSecret); InvalidateSession(); m_tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, null); } protected virtual void Process13ServerHelloCoda(ServerHello serverHello, bool afterHelloRetryRequest) { byte[] currentPrfHash = TlsUtilities.GetCurrentPrfHash(m_handshakeHash); TlsUtilities.Establish13PhaseHandshake(m_tlsClientContext, currentPrfHash, m_recordStream); if (!afterHelloRetryRequest) { m_recordStream.SetIgnoreChangeCipherSpec(true); SendChangeCipherSpecMessage(); } m_recordStream.EnablePendingCipherWrite(); m_recordStream.EnablePendingCipherRead(false); } protected virtual void ProcessServerHello(ServerHello serverHello) { 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.TLSv12.Equals(version) || !ProtocolVersion.TLSv13.IsEqualOrEarlierVersionOf(supportedVersionsExtensionServer)) throw new TlsFatalAlert(47); protocolVersion = supportedVersionsExtensionServer; } SecurityParameters securityParameters = m_tlsClientContext.SecurityParameters; if (!ProtocolVersion.Contains(m_tlsClientContext.ClientSupportedVersions, protocolVersion)) throw new TlsFatalAlert(70); ProtocolVersion writeVersion = protocolVersion.IsLaterVersionOf(ProtocolVersion.TLSv12) ? ProtocolVersion.TLSv12 : protocolVersion; m_recordStream.SetWriteVersion(writeVersion); securityParameters.m_negotiatedVersion = protocolVersion; TlsUtilities.NegotiatedVersionTlsClient(m_tlsClientContext, m_tlsClient); if (ProtocolVersion.TLSv13.IsEqualOrEarlierVersionOf(protocolVersion)) Process13ServerHello(serverHello, false); else { int[] cipherSuites = m_clientHello.CipherSuites; m_clientHello = null; m_retryCookie = null; m_retryGroup = -1; securityParameters.m_serverRandom = serverHello.Random; if (!m_tlsClientContext.ClientVersion.Equals(protocolVersion)) TlsUtilities.CheckDowngradeMarker(protocolVersion, securityParameters.ServerRandom); byte[] array = securityParameters.m_sessionID = serverHello.SessionID; m_tlsClient.NotifySessionID(array); securityParameters.m_resumedSession = (array.Length != 0 && m_tlsSession != null && Arrays.AreEqual(array, m_tlsSession.SessionID)); if (securityParameters.IsResumedSession && (serverHello.CipherSuite != m_sessionParameters.CipherSuite || !securityParameters.NegotiatedVersion.Equals(m_sessionParameters.NegotiatedVersion))) throw new TlsFatalAlert(47, "ServerHello parameters do not match resumed session"); int cipherSuite = serverHello.CipherSuite; if (!TlsUtilities.IsValidCipherSuiteSelection(cipherSuites, cipherSuite) || !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, securityParameters.NegotiatedVersion)) throw new TlsFatalAlert(47, "ServerHello selected invalid cipher suite"); TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite); m_tlsClient.NotifySelectedCipherSuite(cipherSuite); m_serverExtensions = extensions; if (extensions != null) { foreach (int key in extensions.Keys) { if (65281 != key) { if (TlsUtilities.GetExtensionData(m_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); } m_tlsClient.NotifySecureRenegotiation(securityParameters.IsSecureRenegotiation); bool flag = false; if (TlsExtensionsUtilities.HasExtendedMasterSecretExtension(m_clientExtensions)) { flag = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(extensions); if (TlsUtilities.IsExtendedMasterSecretOptional(protocolVersion)) { if (!flag && m_tlsClient.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 != m_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; IDictionary<int, byte[]> dictionary = m_clientExtensions; IDictionary<int, byte[]> dictionary2 = extensions; if (securityParameters.IsResumedSession) { dictionary = null; dictionary2 = m_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); m_expectSessionTicket = TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 35, 47); } } if (dictionary != null) m_tlsClient.ProcessServerExtensions(dictionary2); ApplyMaxFragmentLengthExtension(securityParameters.MaxFragmentLength); if (securityParameters.IsResumedSession) { securityParameters.m_masterSecret = m_sessionMasterSecret; m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsClientContext)); } else { InvalidateSession(); m_tlsSession = TlsUtilities.ImportSession(securityParameters.SessionID, null); } } } protected virtual void Receive13CertificateRequest(MemoryStream buf, bool postHandshakeAuth) { if (postHandshakeAuth) throw new TlsFatalAlert(80); if (m_selectedPsk13) throw new TlsFatalAlert(10); CertificateRequest certificateRequest = CertificateRequest.Parse(m_tlsClientContext, buf); TlsProtocol.AssertEmpty(buf); if (!certificateRequest.HasCertificateRequestContext(TlsUtilities.EmptyBytes)) throw new TlsFatalAlert(47); m_certificateRequest = certificateRequest; TlsUtilities.EstablishServerSigAlgs(m_tlsClientContext.SecurityParameters, certificateRequest); } protected virtual void Receive13EncryptedExtensions(MemoryStream buf) { byte[] extBytes = TlsUtilities.ReadOpaque16(buf); TlsProtocol.AssertEmpty(buf); m_serverExtensions = TlsProtocol.ReadExtensionsData13(8, extBytes); foreach (int key in m_serverExtensions.Keys) { if (TlsUtilities.GetExtensionData(m_clientExtensions, key) == null) throw new TlsFatalAlert(110); } SecurityParameters securityParameters = m_tlsClientContext.SecurityParameters; ProtocolVersion negotiatedVersion = securityParameters.NegotiatedVersion; securityParameters.m_applicationProtocol = TlsExtensionsUtilities.GetAlpnExtensionServer(m_serverExtensions); securityParameters.m_applicationProtocolSet = true; IDictionary<int, byte[]> dictionary = m_clientExtensions; IDictionary<int, byte[]> serverExtensions = m_serverExtensions; if (securityParameters.IsResumedSession) { dictionary = null; serverExtensions = m_sessionParameters.ReadServerExtensions(); } securityParameters.m_maxFragmentLength = TlsUtilities.ProcessMaxFragmentLengthExtension(dictionary, serverExtensions, 47); securityParameters.m_encryptThenMac = false; securityParameters.m_truncatedHmac = false; if (!securityParameters.IsResumedSession) { securityParameters.m_statusRequestVersion = (m_clientExtensions.ContainsKey(5) ? 1 : 0); securityParameters.m_clientCertificateType = TlsUtilities.ProcessClientCertificateTypeExtension13(dictionary, serverExtensions, 47); securityParameters.m_serverCertificateType = TlsUtilities.ProcessServerCertificateTypeExtension13(dictionary, serverExtensions, 47); } m_expectSessionTicket = false; if (dictionary != null) m_tlsClient.ProcessServerExtensions(m_serverExtensions); ApplyMaxFragmentLengthExtension(securityParameters.MaxFragmentLength); } protected virtual void Receive13NewSessionTicket(MemoryStream buf) { if (!base.IsApplicationDataReady) throw new TlsFatalAlert(10); TlsUtilities.ReadUint32(buf); TlsUtilities.ReadUint32(buf); TlsUtilities.ReadOpaque8(buf); TlsUtilities.ReadOpaque16(buf); TlsUtilities.ReadOpaque16(buf); TlsProtocol.AssertEmpty(buf); } protected virtual void Receive13ServerCertificate(MemoryStream buf) { if (m_selectedPsk13) throw new TlsFatalAlert(10); m_authentication = TlsUtilities.Receive13ServerCertificate(m_tlsClientContext, m_tlsClient, buf, m_serverExtensions); HandleServerCertificate(); } protected virtual void Receive13ServerCertificateVerify(MemoryStream buf) { Certificate peerCertificate = m_tlsClientContext.SecurityParameters.PeerCertificate; if (peerCertificate == null || peerCertificate.IsEmpty) throw new TlsFatalAlert(80); CertificateVerify certificateVerify = CertificateVerify.Parse(m_tlsClientContext, buf); TlsProtocol.AssertEmpty(buf); TlsUtilities.Verify13CertificateVerifyServer(m_tlsClientContext, m_handshakeHash, certificateVerify); } protected virtual void Receive13ServerFinished(MemoryStream buf) { Process13FinishedMessage(buf); } protected virtual void ReceiveCertificateRequest(MemoryStream buf) { if (m_authentication == null) throw new TlsFatalAlert(40); CertificateRequest certificateRequest = CertificateRequest.Parse(m_tlsClientContext, buf); TlsProtocol.AssertEmpty(buf); m_certificateRequest = TlsUtilities.ValidateCertificateRequest(certificateRequest, m_keyExchange); } protected virtual void ReceiveNewSessionTicket(MemoryStream buf) { NewSessionTicket newSessionTicket = NewSessionTicket.Parse(buf); TlsProtocol.AssertEmpty(buf); m_tlsClient.NotifyNewSessionTicket(newSessionTicket); } protected virtual ServerHello ReceiveServerHelloMessage(MemoryStream buf) { return ServerHello.Parse(buf); } protected virtual void Send13ClientHelloRetry() { IDictionary<int, byte[]> extensions = m_clientHello.Extensions; extensions.Remove(44); extensions.Remove(42); extensions.Remove(51); extensions.Remove(41); if (m_retryCookie != null) { TlsExtensionsUtilities.AddCookieExtension(extensions, m_retryCookie); m_retryCookie = null; } if (m_clientBinders != null) { m_clientBinders = TlsUtilities.AddPreSharedKeyToClientHelloRetry(m_tlsClientContext, m_clientBinders, extensions); if (m_clientBinders == null) m_tlsClient.NotifySelectedPsk(null); } if (m_retryGroup < 0) throw new TlsFatalAlert(80); m_clientAgreements = TlsUtilities.AddKeyShareToClientHelloRetry(m_tlsClientContext, extensions, m_retryGroup); m_recordStream.SetIgnoreChangeCipherSpec(true); SendChangeCipherSpecMessage(); SendClientHelloMessage(); } protected virtual void SendCertificateVerifyMessage(DigitallySigned certificateVerify) { HandshakeMessageOutput handshakeMessageOutput = new HandshakeMessageOutput(15); certificateVerify.Encode(handshakeMessageOutput); handshakeMessageOutput.Send(this); } protected virtual void SendClientHello() { SecurityParameters securityParameters = m_tlsClientContext.SecurityParameters; ProtocolVersion[] protocolVersions = m_tlsClient.GetProtocolVersions(); if (ProtocolVersion.Contains(protocolVersions, ProtocolVersion.SSLv3)) m_recordStream.SetWriteVersion(ProtocolVersion.SSLv3); else m_recordStream.SetWriteVersion(ProtocolVersion.TLSv10); ProtocolVersion earliestTls = ProtocolVersion.GetEarliestTls(protocolVersions); ProtocolVersion latestTls = ProtocolVersion.GetLatestTls(protocolVersions); if (!ProtocolVersion.IsSupportedTlsVersionClient(latestTls)) throw new TlsFatalAlert(80); m_tlsClientContext.SetClientVersion(latestTls); m_tlsClientContext.SetClientSupportedVersions(protocolVersions); bool num = ProtocolVersion.TLSv12.IsEqualOrLaterVersionOf(earliestTls); bool flag = ProtocolVersion.TLSv13.IsEqualOrEarlierVersionOf(latestTls); bool useGmtUnixTime = !flag && m_tlsClient.ShouldUseGmtUnixTime(); securityParameters.m_clientRandom = TlsProtocol.CreateRandomBlock(useGmtUnixTime, m_tlsClientContext); TlsSession sessionToResume = num ? m_tlsClient.GetSessionToResume() : null; bool num2 = m_tlsClient.IsFallback(); int[] array = m_tlsClient.GetCipherSuites(); m_clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(m_tlsClient.GetClientExtensions()); bool flag2 = m_tlsClient.ShouldUseExtendedMasterSecret(); EstablishSession(sessionToResume); byte[] array2 = TlsUtilities.GetSessionID(m_tlsSession); if (array2.Length != 0 && !Arrays.Contains(array, m_sessionParameters.CipherSuite)) array2 = TlsUtilities.EmptyBytes; ProtocolVersion protocolVersion = null; if (array2.Length != 0) { protocolVersion = m_sessionParameters.NegotiatedVersion; if (!ProtocolVersion.Contains(protocolVersions, protocolVersion)) array2 = TlsUtilities.EmptyBytes; } if (array2.Length != 0 && TlsUtilities.IsExtendedMasterSecretOptional(protocolVersion)) { if (flag2) { if (!m_sessionParameters.IsExtendedMasterSecret && !m_tlsClient.AllowLegacyResumption()) array2 = TlsUtilities.EmptyBytes; } else if (m_sessionParameters.IsExtendedMasterSecret) { array2 = TlsUtilities.EmptyBytes; } } if (array2.Length < 1) CancelSession(); m_tlsClient.NotifySessionToResume(m_tlsSession); ProtocolVersion protocolVersion2 = latestTls; if (flag) { protocolVersion2 = ProtocolVersion.TLSv12; TlsExtensionsUtilities.AddSupportedVersionsExtensionClient(m_clientExtensions, protocolVersions); if (array2.Length < 1 && TlsUtilities.ShouldUseCompatibilityMode(m_tlsClient)) array2 = m_tlsClientContext.NonceGenerator.GenerateNonce(32); } m_tlsClientContext.SetRsaPreMasterSecretVersion(protocolVersion2); securityParameters.m_clientServerNames = TlsExtensionsUtilities.GetServerNameExtensionClient(m_clientExtensions); if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(latestTls)) TlsUtilities.EstablishClientSigAlgs(securityParameters, m_clientExtensions); securityParameters.m_clientSupportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(m_clientExtensions); m_clientBinders = TlsUtilities.AddPreSharedKeyToClientHello(m_tlsClientContext, m_tlsClient, m_clientExtensions, array); m_clientAgreements = TlsUtilities.AddKeyShareToClientHello(m_tlsClientContext, m_tlsClient, m_clientExtensions); if (flag2 && TlsUtilities.IsExtendedMasterSecretOptional(protocolVersions)) TlsExtensionsUtilities.AddExtendedMasterSecretExtension(m_clientExtensions); else m_clientExtensions.Remove(23); bool num3 = TlsUtilities.GetExtensionData(m_clientExtensions, 65281) == null; bool flag3 = !Arrays.Contains(array, 255); if (num3 & flag3) array = Arrays.Append(array, 255); if (num2 && !Arrays.Contains(array, 22016)) array = Arrays.Append(array, 22016); int bindersSize = (m_clientBinders != null) ? m_clientBinders.m_bindersSize : 0; m_clientHello = new ClientHello(protocolVersion2, securityParameters.ClientRandom, array2, null, array, m_clientExtensions, bindersSize); SendClientHelloMessage(); } protected virtual void SendClientHelloMessage() { HandshakeMessageOutput handshakeMessageOutput = new HandshakeMessageOutput(1); m_clientHello.Encode(m_tlsClientContext, handshakeMessageOutput); handshakeMessageOutput.PrepareClientHello(m_handshakeHash, m_clientHello.BindersSize); if (m_clientBinders != null) OfferedPsks.EncodeBinders(handshakeMessageOutput, m_tlsClientContext.Crypto, m_handshakeHash, m_clientBinders); handshakeMessageOutput.SendClientHello(this, m_handshakeHash, m_clientHello.BindersSize); } protected virtual void SendClientKeyExchange() { HandshakeMessageOutput handshakeMessageOutput = new HandshakeMessageOutput(16); m_keyExchange.GenerateClientKeyExchange(handshakeMessageOutput); handshakeMessageOutput.Send(this); } protected virtual void Skip13CertificateRequest() { m_certificateRequest = null; } protected virtual void Skip13ServerCertificate() { if (!m_selectedPsk13) throw new TlsFatalAlert(10); m_authentication = TlsUtilities.Skip13ServerCertificate(m_tlsClientContext); } } }