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

TlsServerProtocol

using Org.BouncyCastle.Tls.Crypto; using Org.BouncyCastle.Utilities; using System; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Tls { public class TlsServerProtocol : TlsProtocol { protected TlsServer m_tlsServer; internal TlsServerContextImpl m_tlsServerContext; protected int[] m_offeredCipherSuites; protected TlsKeyExchange m_keyExchange; protected CertificateRequest m_certificateRequest; protected override TlsContext Context => m_tlsServerContext; internal override AbstractTlsContext ContextAdmin => m_tlsServerContext; protected override TlsPeer Peer => m_tlsServer; public TlsServerProtocol() { } public TlsServerProtocol(Stream stream) : base(stream) { } public TlsServerProtocol(Stream input, Stream output) : base(input, output) { } public void Accept(TlsServer tlsServer) { if (tlsServer == null) throw new ArgumentNullException("tlsServer"); if (m_tlsServer != null) throw new InvalidOperationException("'Accept' can only be called once"); m_tlsServer = tlsServer; m_tlsServerContext = new TlsServerContextImpl(tlsServer.Crypto); tlsServer.Init(m_tlsServerContext); tlsServer.NotifyCloseHandle(this); BeginHandshake(); if (m_blocking) BlockForHandshake(); } protected override void CleanupHandshake() { base.CleanupHandshake(); m_offeredCipherSuites = null; m_keyExchange = null; m_certificateRequest = null; } protected virtual bool ExpectCertificateVerifyMessage() { if (m_certificateRequest == null) return false; Certificate peerCertificate = m_tlsServerContext.SecurityParameters.PeerCertificate; if (peerCertificate != null && !peerCertificate.IsEmpty) { if (m_keyExchange != null) return m_keyExchange.RequiresCertificateVerify; return true; } return false; } protected virtual ServerHello Generate13HelloRetryRequest(ClientHello clientHello) { if (m_retryGroup < 0) throw new TlsFatalAlert(80); SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters; ProtocolVersion negotiatedVersion = securityParameters.NegotiatedVersion; Dictionary<int, byte[]> extensions = new Dictionary<int, byte[]>(); TlsExtensionsUtilities.AddSupportedVersionsExtensionServer(extensions, negotiatedVersion); if (m_retryGroup >= 0) TlsExtensionsUtilities.AddKeyShareHelloRetryRequest(extensions, m_retryGroup); if (m_retryCookie != null) TlsExtensionsUtilities.AddCookieExtension(extensions, m_retryCookie); TlsUtilities.CheckExtensionData13(extensions, 6, 80); return new ServerHello(clientHello.SessionID, securityParameters.CipherSuite, extensions); } protected virtual ServerHello Generate13ServerHello(ClientHello clientHello, HandshakeMessageInput clientHelloMessage, bool afterHelloRetryRequest) { SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters; byte[] sessionID = clientHello.SessionID; IDictionary<int, byte[]> extensions = clientHello.Extensions; if (extensions == null) throw new TlsFatalAlert(109); ProtocolVersion negotiatedVersion = securityParameters.NegotiatedVersion; TlsCrypto crypto = m_tlsServerContext.Crypto; OfferedPsks.SelectedConfig selectedConfig = TlsUtilities.SelectPreSharedKey(m_tlsServerContext, m_tlsServer, extensions, clientHelloMessage, m_handshakeHash, afterHelloRetryRequest); IList<KeyShareEntry> keyShareClientHello = TlsExtensionsUtilities.GetKeyShareClientHello(extensions); KeyShareEntry keyShareEntry = null; if (afterHelloRetryRequest) { if (m_retryGroup < 0) throw new TlsFatalAlert(80); if (selectedConfig == null) { if (securityParameters.ClientSigAlgs == null) throw new TlsFatalAlert(109); } else if (selectedConfig.m_psk.PrfAlgorithm != securityParameters.PrfAlgorithm) { throw new TlsFatalAlert(47); } byte[] cookieExtension = TlsExtensionsUtilities.GetCookieExtension(extensions); if (!Arrays.AreEqual(m_retryCookie, cookieExtension)) throw new TlsFatalAlert(47); m_retryCookie = null; keyShareEntry = TlsUtilities.SelectKeyShare(keyShareClientHello, m_retryGroup); if (keyShareEntry == null) throw new TlsFatalAlert(47); } else { securityParameters.m_serverRandom = TlsProtocol.CreateRandomBlock(false, m_tlsServerContext); if (!negotiatedVersion.Equals(ProtocolVersion.GetLatestTls(m_tlsServer.GetProtocolVersions()))) TlsUtilities.WriteDowngradeMarker(negotiatedVersion, securityParameters.ServerRandom); m_clientExtensions = extensions; securityParameters.m_secureRenegotiation = false; TlsExtensionsUtilities.GetPaddingExtension(extensions); securityParameters.m_clientServerNames = TlsExtensionsUtilities.GetServerNameExtensionClient(extensions); TlsUtilities.EstablishClientSigAlgs(securityParameters, extensions); if (selectedConfig == null && securityParameters.ClientSigAlgs == null) throw new TlsFatalAlert(109); m_tlsServer.ProcessClientExtensions(extensions); securityParameters.m_resumedSession = false; m_tlsSession = TlsUtilities.ImportSession(TlsUtilities.EmptyBytes, null); m_sessionParameters = null; m_sessionMasterSecret = null; securityParameters.m_sessionID = m_tlsSession.SessionID; m_tlsServer.NotifySession(m_tlsSession); TlsUtilities.NegotiatedVersionTlsServer(m_tlsServerContext); int selectedCipherSuite = m_tlsServer.GetSelectedCipherSuite(); if (!TlsUtilities.IsValidCipherSuiteSelection(m_offeredCipherSuites, selectedCipherSuite) || !TlsUtilities.IsValidVersionForCipherSuite(selectedCipherSuite, negotiatedVersion)) throw new TlsFatalAlert(80); TlsUtilities.NegotiatedCipherSuite(securityParameters, selectedCipherSuite); int[] clientSupportedGroups = securityParameters.ClientSupportedGroups; int[] serverSupportedGroups = securityParameters.ServerSupportedGroups; keyShareEntry = TlsUtilities.SelectKeyShare(crypto, negotiatedVersion, keyShareClientHello, clientSupportedGroups, serverSupportedGroups); if (keyShareEntry == null) { m_retryGroup = TlsUtilities.SelectKeyShareGroup(crypto, negotiatedVersion, clientSupportedGroups, serverSupportedGroups); if (m_retryGroup < 0) throw new TlsFatalAlert(40); m_retryCookie = m_tlsServerContext.NonceGenerator.GenerateNonce(16); return Generate13HelloRetryRequest(clientHello); } int namedGroup2 = keyShareEntry.NamedGroup; int num = serverSupportedGroups[0]; } Dictionary<int, byte[]> extensions2 = new Dictionary<int, byte[]>(); IDictionary<int, byte[]> dictionary = TlsExtensionsUtilities.EnsureExtensionsInitialised(m_tlsServer.GetServerExtensions()); m_tlsServer.GetServerExtensionsForConnection(dictionary); ProtocolVersion tLSv = ProtocolVersion.TLSv12; TlsExtensionsUtilities.AddSupportedVersionsExtensionServer(extensions2, negotiatedVersion); securityParameters.m_extendedMasterSecret = true; securityParameters.m_applicationProtocol = TlsExtensionsUtilities.GetAlpnExtensionServer(dictionary); securityParameters.m_applicationProtocolSet = true; if (dictionary.Count > 0) { securityParameters.m_maxFragmentLength = TlsUtilities.ProcessMaxFragmentLengthExtension(securityParameters.IsResumedSession ? null : extensions, dictionary, 80); if (!securityParameters.IsResumedSession) { securityParameters.m_clientCertificateType = TlsUtilities.ProcessClientCertificateTypeExtension13(extensions, dictionary, 80); securityParameters.m_serverCertificateType = TlsUtilities.ProcessServerCertificateTypeExtension13(extensions, dictionary, 80); } } securityParameters.m_encryptThenMac = false; securityParameters.m_truncatedHmac = false; securityParameters.m_statusRequestVersion = (extensions.ContainsKey(5) ? 1 : 0); m_expectSessionTicket = false; TlsSecret pskEarlySecret = null; if (selectedConfig != null) { pskEarlySecret = selectedConfig.m_earlySecret; m_selectedPsk13 = true; TlsExtensionsUtilities.AddPreSharedKeyServerHello(extensions2, selectedConfig.m_index); } int namedGroup = keyShareEntry.NamedGroup; TlsAgreement tlsAgreement; if (NamedGroup.RefersToASpecificCurve(namedGroup)) tlsAgreement = crypto.CreateECDomain(new TlsECConfig(namedGroup)).CreateECDH(); else { if (!NamedGroup.RefersToASpecificFiniteField(namedGroup)) throw new TlsFatalAlert(80); tlsAgreement = crypto.CreateDHDomain(new TlsDHConfig(namedGroup, true)).CreateDH(); } byte[] keyExchange = tlsAgreement.GenerateEphemeral(); KeyShareEntry serverShare = new KeyShareEntry(namedGroup, keyExchange); TlsExtensionsUtilities.AddKeyShareServerHello(extensions2, serverShare); tlsAgreement.ReceivePeerValue(keyShareEntry.KeyExchange); TlsUtilities.Establish13PhaseSecrets(sharedSecret: tlsAgreement.CalculateSecret(), context: m_tlsServerContext, pskEarlySecret: pskEarlySecret); m_serverExtensions = dictionary; ApplyMaxFragmentLengthExtension(securityParameters.MaxFragmentLength); TlsUtilities.CheckExtensionData13(extensions2, 2, 80); return new ServerHello(tLSv, securityParameters.ServerRandom, sessionID, securityParameters.CipherSuite, extensions2); } protected virtual ServerHello GenerateServerHello(ClientHello clientHello, HandshakeMessageInput clientHelloMessage) { ProtocolVersion version = clientHello.Version; if (!version.IsTls) throw new TlsFatalAlert(47); m_offeredCipherSuites = clientHello.CipherSuites; SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters; m_tlsServerContext.SetClientSupportedVersions(TlsExtensionsUtilities.GetSupportedVersionsExtensionClient(clientHello.Extensions)); ProtocolVersion protocolVersion = version; if (m_tlsServerContext.ClientSupportedVersions == null) { if (protocolVersion.IsLaterVersionOf(ProtocolVersion.TLSv12)) protocolVersion = ProtocolVersion.TLSv12; m_tlsServerContext.SetClientSupportedVersions(protocolVersion.DownTo(ProtocolVersion.SSLv3)); } else protocolVersion = ProtocolVersion.GetLatestTls(m_tlsServerContext.ClientSupportedVersions); m_recordStream.SetWriteVersion(protocolVersion); if (!ProtocolVersion.SERVER_EARLIEST_SUPPORTED_TLS.IsEqualOrEarlierVersionOf(protocolVersion)) throw new TlsFatalAlert(70); m_tlsServerContext.SetClientVersion(protocolVersion); m_tlsServer.NotifyClientVersion(m_tlsServerContext.ClientVersion); securityParameters.m_clientRandom = clientHello.Random; m_tlsServer.NotifyFallback(Arrays.Contains(m_offeredCipherSuites, 22016)); m_tlsServer.NotifyOfferedCipherSuites(m_offeredCipherSuites); ProtocolVersion serverVersion = m_tlsServer.GetServerVersion(); if (!ProtocolVersion.Contains(m_tlsServerContext.ClientSupportedVersions, serverVersion)) throw new TlsFatalAlert(80); securityParameters.m_negotiatedVersion = serverVersion; securityParameters.m_clientSupportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(clientHello.Extensions); securityParameters.m_serverSupportedGroups = m_tlsServer.GetSupportedGroups(); if (ProtocolVersion.TLSv13.IsEqualOrEarlierVersionOf(serverVersion)) { m_recordStream.SetIgnoreChangeCipherSpec(true); m_recordStream.SetWriteVersion(ProtocolVersion.TLSv12); return Generate13ServerHello(clientHello, clientHelloMessage, false); } m_recordStream.SetWriteVersion(serverVersion); bool useGmtUnixTime = m_tlsServer.ShouldUseGmtUnixTime(); securityParameters.m_serverRandom = TlsProtocol.CreateRandomBlock(useGmtUnixTime, m_tlsServerContext); if (!serverVersion.Equals(ProtocolVersion.GetLatestTls(m_tlsServer.GetProtocolVersions()))) TlsUtilities.WriteDowngradeMarker(serverVersion, securityParameters.ServerRandom); m_clientExtensions = clientHello.Extensions; byte[] extensionData = TlsUtilities.GetExtensionData(m_clientExtensions, 65281); if (Arrays.Contains(m_offeredCipherSuites, 255)) securityParameters.m_secureRenegotiation = true; if (extensionData != null) { securityParameters.m_secureRenegotiation = true; if (!Arrays.FixedTimeEquals(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) throw new TlsFatalAlert(40); } m_tlsServer.NotifySecureRenegotiation(securityParameters.IsSecureRenegotiation); if (m_clientExtensions != null) { TlsExtensionsUtilities.GetPaddingExtension(m_clientExtensions); securityParameters.m_clientServerNames = TlsExtensionsUtilities.GetServerNameExtensionClient(m_clientExtensions); if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(protocolVersion)) TlsUtilities.EstablishClientSigAlgs(securityParameters, m_clientExtensions); securityParameters.m_clientSupportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(m_clientExtensions); m_tlsServer.ProcessClientExtensions(m_clientExtensions); } TlsSession sessionToResume = m_tlsServer.GetSessionToResume(clientHello.SessionID); bool flag = EstablishSession(sessionToResume); if (flag && !serverVersion.Equals(m_sessionParameters.NegotiatedVersion)) flag = false; bool flag2 = false; if (TlsUtilities.IsExtendedMasterSecretOptional(serverVersion) && m_tlsServer.ShouldUseExtendedMasterSecret()) { if (TlsExtensionsUtilities.HasExtendedMasterSecretExtension(m_clientExtensions)) flag2 = true; else { if (m_tlsServer.RequiresExtendedMasterSecret()) throw new TlsFatalAlert(40, "Extended Master Secret extension is required"); if (flag) { if (m_sessionParameters.IsExtendedMasterSecret) throw new TlsFatalAlert(40, "Extended Master Secret extension is required for EMS session resumption"); if (!m_tlsServer.AllowLegacyResumption()) throw new TlsFatalAlert(40, "Extended Master Secret extension is required for legacy session resumption"); } } } if (flag && flag2 != m_sessionParameters.IsExtendedMasterSecret) flag = false; securityParameters.m_extendedMasterSecret = flag2; if (!flag) { CancelSession(); byte[] array = m_tlsServer.GetNewSessionID(); if (array == null) array = TlsUtilities.EmptyBytes; m_tlsSession = TlsUtilities.ImportSession(array, null); } securityParameters.m_resumedSession = flag; securityParameters.m_sessionID = m_tlsSession.SessionID; m_tlsServer.NotifySession(m_tlsSession); TlsUtilities.NegotiatedVersionTlsServer(m_tlsServerContext); int cipherSuite = flag ? m_sessionParameters.CipherSuite : m_tlsServer.GetSelectedCipherSuite(); if (!TlsUtilities.IsValidCipherSuiteSelection(m_offeredCipherSuites, cipherSuite) || !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, serverVersion)) throw new TlsFatalAlert(80); TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite); m_tlsServerContext.SetRsaPreMasterSecretVersion(version); IDictionary<int, byte[]> extensions = flag ? m_sessionParameters.ReadServerExtensions() : m_tlsServer.GetServerExtensions(); m_serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(extensions); m_tlsServer.GetServerExtensionsForConnection(m_serverExtensions); if (securityParameters.IsSecureRenegotiation) { byte[] extensionData2 = TlsUtilities.GetExtensionData(m_serverExtensions, 65281); if (extensionData2 == null) m_serverExtensions[65281] = TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes); } if (securityParameters.IsExtendedMasterSecret) TlsExtensionsUtilities.AddExtendedMasterSecretExtension(m_serverExtensions); else m_serverExtensions.Remove(23); securityParameters.m_applicationProtocol = TlsExtensionsUtilities.GetAlpnExtensionServer(m_serverExtensions); securityParameters.m_applicationProtocolSet = true; if (m_serverExtensions.Count > 0) { securityParameters.m_encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(m_serverExtensions); securityParameters.m_maxFragmentLength = TlsUtilities.ProcessMaxFragmentLengthExtension(flag ? null : m_clientExtensions, m_serverExtensions, 80); securityParameters.m_truncatedHmac = TlsExtensionsUtilities.HasTruncatedHmacExtension(m_serverExtensions); if (!flag) { if (TlsUtilities.HasExpectedEmptyExtensionData(m_serverExtensions, 17, 80)) securityParameters.m_statusRequestVersion = 2; else if (TlsUtilities.HasExpectedEmptyExtensionData(m_serverExtensions, 5, 80)) { securityParameters.m_statusRequestVersion = 1; } securityParameters.m_clientCertificateType = TlsUtilities.ProcessClientCertificateTypeExtension(m_clientExtensions, m_serverExtensions, 80); securityParameters.m_serverCertificateType = TlsUtilities.ProcessServerCertificateTypeExtension(m_clientExtensions, m_serverExtensions, 80); m_expectSessionTicket = TlsUtilities.HasExpectedEmptyExtensionData(m_serverExtensions, 35, 80); } } ApplyMaxFragmentLengthExtension(securityParameters.MaxFragmentLength); return new ServerHello(serverVersion, securityParameters.ServerRandom, securityParameters.SessionID, securityParameters.CipherSuite, m_serverExtensions); } protected virtual void Handle13HandshakeMessage(short type, HandshakeMessageInput buf) { if (!IsTlsV13ConnectionState()) throw new TlsFatalAlert(80); switch (type) { case 11: if (m_connectionState != 20) throw new TlsFatalAlert(10); Receive13ClientCertificate(buf); m_connectionState = 15; break; case 15: if (m_connectionState != 15) throw new TlsFatalAlert(10); Receive13ClientCertificateVerify(buf); buf.UpdateHash(m_handshakeHash); m_connectionState = 17; break; case 1: switch (m_connectionState) { case 0: throw new TlsFatalAlert(80); case 2: { ClientHello clientHello = ReceiveClientHelloMessage(buf); m_connectionState = 3; ServerHello serverHello = Generate13ServerHello(clientHello, buf, true); SendServerHelloMessage(serverHello); m_connectionState = 4; Send13ServerHelloCoda(serverHello, true); break; } default: throw new TlsFatalAlert(10); } break; case 20: { short connectionState = m_connectionState; if (connectionState != 15 && connectionState != 17 && connectionState != 20) throw new TlsFatalAlert(10); if (m_connectionState == 20) Skip13ClientCertificate(); if (m_connectionState != 17) Skip13ClientCertificateVerify(); Receive13ClientFinished(buf); m_connectionState = 18; m_recordStream.SetIgnoreChangeCipherSpec(false); m_recordStream.EnablePendingCipherRead(false); CompleteHandshake(); break; } case 24: Receive13KeyUpdate(buf); break; default: throw new TlsFatalAlert(10); } } protected override void HandleHandshakeMessage(short type, HandshakeMessageInput buf) { SecurityParameters securityParameters = m_tlsServerContext.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 == 20) { ProcessFinishedMessage(buf); m_connectionState = 18; CompleteHandshake(); return; } goto default; default: throw new TlsFatalAlert(10); case 1: break; } } switch (type) { case 1: if (!base.IsApplicationDataReady) { switch (m_connectionState) { case 21: throw new TlsFatalAlert(80); case 0: { ClientHello clientHello = ReceiveClientHelloMessage(buf); m_connectionState = 1; ServerHello serverHello = GenerateServerHello(clientHello, buf); m_handshakeHash.NotifyPrfDetermined(); if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion)) { m_handshakeHash.SealHashAlgorithms(); if (serverHello.IsHelloRetryRequest()) { TlsUtilities.AdjustTranscriptForRetry(m_handshakeHash); SendServerHelloMessage(serverHello); m_connectionState = 2; SendChangeCipherSpecMessage(); } else { SendServerHelloMessage(serverHello); m_connectionState = 4; SendChangeCipherSpecMessage(); Send13ServerHelloCoda(serverHello, false); } } else { buf.UpdateHash(m_handshakeHash); SendServerHelloMessage(serverHello); m_connectionState = 4; if (securityParameters.IsResumedSession) { securityParameters.m_masterSecret = m_sessionMasterSecret; m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsServerContext)); SendChangeCipherSpec(); SendFinishedMessage(); m_connectionState = 20; } else { IList<SupplementalDataEntry> serverSupplementalData = m_tlsServer.GetServerSupplementalData(); if (serverSupplementalData != null) { SendSupplementalDataMessage(serverSupplementalData); m_connectionState = 6; } m_keyExchange = TlsUtilities.InitKeyExchangeServer(m_tlsServerContext, m_tlsServer); TlsCredentials tlsCredentials = null; if (!KeyExchangeAlgorithm.IsAnonymous(securityParameters.KeyExchangeAlgorithm)) tlsCredentials = TlsUtilities.EstablishServerCredentials(m_tlsServer); Certificate certificate = null; MemoryStream memoryStream = new MemoryStream(); if (tlsCredentials == null) m_keyExchange.SkipServerCredentials(); else { m_keyExchange.ProcessServerCredentials(tlsCredentials); certificate = tlsCredentials.Certificate; SendCertificateMessage(certificate, memoryStream); m_connectionState = 7; } securityParameters.m_tlsServerEndPoint = memoryStream.ToArray(); if (certificate == null || certificate.IsEmpty) securityParameters.m_statusRequestVersion = 0; if (securityParameters.StatusRequestVersion > 0) { CertificateStatus certificateStatus = m_tlsServer.GetCertificateStatus(); if (certificateStatus != null) { SendCertificateStatusMessage(certificateStatus); m_connectionState = 8; } } byte[] array = m_keyExchange.GenerateServerKeyExchange(); if (array != null) { SendServerKeyExchangeMessage(array); m_connectionState = 10; } if (tlsCredentials != null) { m_certificateRequest = m_tlsServer.GetCertificateRequest(); if (m_certificateRequest == null) { if (!m_keyExchange.RequiresCertificateVerify) throw new TlsFatalAlert(80); } else { if (TlsUtilities.IsTlsV12(m_tlsServerContext) != (m_certificateRequest.SupportedSignatureAlgorithms != null)) throw new TlsFatalAlert(80); m_certificateRequest = TlsUtilities.ValidateCertificateRequest(m_certificateRequest, m_keyExchange); TlsUtilities.EstablishServerSigAlgs(securityParameters, m_certificateRequest); if (ProtocolVersion.TLSv12.Equals(securityParameters.NegotiatedVersion)) { TlsUtilities.TrackHashAlgorithms(m_handshakeHash, securityParameters.ServerSigAlgs); if (m_tlsServerContext.Crypto.HasAnyStreamVerifiers(securityParameters.ServerSigAlgs)) m_handshakeHash.ForceBuffering(); } else if (m_tlsServerContext.Crypto.HasAnyStreamVerifiersLegacy(m_certificateRequest.CertificateTypes)) { m_handshakeHash.ForceBuffering(); } } } m_handshakeHash.SealHashAlgorithms(); if (m_certificateRequest != null) { SendCertificateRequestMessage(m_certificateRequest); m_connectionState = 11; } SendServerHelloDoneMessage(); m_connectionState = 12; } } break; } default: throw new TlsFatalAlert(10); } } else RefuseRenegotiation(); break; case 23: if (m_connectionState != 12) throw new TlsFatalAlert(10); m_tlsServer.ProcessClientSupplementalData(TlsProtocol.ReadSupplementalDataMessage(buf)); m_connectionState = 14; break; case 11: { short connectionState = m_connectionState; if (connectionState != 12 && connectionState != 14) throw new TlsFatalAlert(10); if (m_connectionState != 14) m_tlsServer.ProcessClientSupplementalData(null); ReceiveCertificateMessage(buf); m_connectionState = 15; break; } case 16: { short connectionState = m_connectionState; if (connectionState != 12 && (uint)(connectionState - 14) > 1) throw new TlsFatalAlert(10); if (m_connectionState == 12) m_tlsServer.ProcessClientSupplementalData(null); if (m_connectionState != 15) { if (m_certificateRequest == null) m_keyExchange.SkipClientCredentials(); else { if (TlsUtilities.IsTlsV12(m_tlsServerContext)) throw new TlsFatalAlert(10); if (TlsUtilities.IsSsl(m_tlsServerContext)) throw new TlsFatalAlert(10); NotifyClientCertificate(Certificate.EmptyChain); } } ReceiveClientKeyExchangeMessage(buf); m_connectionState = 16; break; } case 15: if (m_connectionState != 16) throw new TlsFatalAlert(10); if (!ExpectCertificateVerifyMessage()) throw new TlsFatalAlert(10); ReceiveCertificateVerifyMessage(buf); buf.UpdateHash(m_handshakeHash); m_connectionState = 17; break; case 20: { short connectionState = m_connectionState; if ((uint)(connectionState - 16) > 1) throw new TlsFatalAlert(10); if (m_connectionState != 17 && ExpectCertificateVerifyMessage()) throw new TlsFatalAlert(10); ProcessFinishedMessage(buf); buf.UpdateHash(m_handshakeHash); m_connectionState = 18; if (m_expectSessionTicket) { SendNewSessionTicketMessage(m_tlsServer.GetNewSessionTicket()); m_connectionState = 19; } SendChangeCipherSpec(); SendFinishedMessage(); m_connectionState = 20; CompleteHandshake(); break; } default: throw new TlsFatalAlert(10); } } } protected override void HandleAlertWarningMessage(short alertDescription) { if (41 == alertDescription && m_certificateRequest != null && TlsUtilities.IsSsl(m_tlsServerContext)) { short connectionState = m_connectionState; if (connectionState == 12 || connectionState == 14) { if (m_connectionState != 14) m_tlsServer.ProcessClientSupplementalData(null); NotifyClientCertificate(Certificate.EmptyChain); m_connectionState = 15; return; } } base.HandleAlertWarningMessage(alertDescription); } protected virtual void NotifyClientCertificate(Certificate clientCertificate) { if (m_certificateRequest == null) throw new TlsFatalAlert(80); TlsUtilities.ProcessClientCertificate(m_tlsServerContext, clientCertificate, m_keyExchange, m_tlsServer); } protected virtual void Receive13ClientCertificate(MemoryStream buf) { if (m_certificateRequest == null) throw new TlsFatalAlert(10); Certificate clientCertificate = Certificate.Parse(new Certificate.ParseOptions { CertificateType = m_tlsServerContext.SecurityParameters.ClientCertificateType, MaxChainLength = m_tlsServer.GetMaxCertificateChainLength() }, m_tlsServerContext, buf, null); TlsProtocol.AssertEmpty(buf); NotifyClientCertificate(clientCertificate); } protected void Receive13ClientCertificateVerify(MemoryStream buf) { Certificate peerCertificate = m_tlsServerContext.SecurityParameters.PeerCertificate; if (peerCertificate == null || peerCertificate.IsEmpty) throw new TlsFatalAlert(80); CertificateVerify certificateVerify = CertificateVerify.Parse(m_tlsServerContext, buf); TlsProtocol.AssertEmpty(buf); TlsUtilities.Verify13CertificateVerifyClient(m_tlsServerContext, m_handshakeHash, certificateVerify); } protected virtual void Receive13ClientFinished(MemoryStream buf) { Process13FinishedMessage(buf); } protected virtual void ReceiveCertificateMessage(MemoryStream buf) { if (m_certificateRequest == null) throw new TlsFatalAlert(10); Certificate clientCertificate = Certificate.Parse(new Certificate.ParseOptions { CertificateType = m_tlsServerContext.SecurityParameters.ClientCertificateType, MaxChainLength = m_tlsServer.GetMaxCertificateChainLength() }, m_tlsServerContext, buf, null); TlsProtocol.AssertEmpty(buf); NotifyClientCertificate(clientCertificate); } protected virtual void ReceiveCertificateVerifyMessage(MemoryStream buf) { DigitallySigned certificateVerify = DigitallySigned.Parse(m_tlsServerContext, buf); TlsProtocol.AssertEmpty(buf); TlsUtilities.VerifyCertificateVerifyClient(m_tlsServerContext, m_certificateRequest, certificateVerify, m_handshakeHash); m_handshakeHash.StopTracking(); } protected virtual ClientHello ReceiveClientHelloMessage(MemoryStream buf) { return ClientHello.Parse(buf, null); } protected virtual void ReceiveClientKeyExchangeMessage(MemoryStream buf) { m_keyExchange.ProcessClientKeyExchange(buf); TlsProtocol.AssertEmpty(buf); bool num = TlsUtilities.IsSsl(m_tlsServerContext); if (num) TlsProtocol.EstablishMasterSecret(m_tlsServerContext, m_keyExchange); m_tlsServerContext.SecurityParameters.m_sessionHash = TlsUtilities.GetCurrentPrfHash(m_handshakeHash); if (!num) TlsProtocol.EstablishMasterSecret(m_tlsServerContext, m_keyExchange); m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsServerContext)); if (!ExpectCertificateVerifyMessage()) m_handshakeHash.StopTracking(); } protected virtual void Send13EncryptedExtensionsMessage(IDictionary<int, byte[]> serverExtensions) { byte[] buf = TlsProtocol.WriteExtensionsData(serverExtensions); HandshakeMessageOutput handshakeMessageOutput = new HandshakeMessageOutput(8); TlsUtilities.WriteOpaque16(buf, handshakeMessageOutput); handshakeMessageOutput.Send(this); } protected virtual void Send13ServerHelloCoda(ServerHello serverHello, bool afterHelloRetryRequest) { SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters; byte[] currentPrfHash = TlsUtilities.GetCurrentPrfHash(m_handshakeHash); TlsUtilities.Establish13PhaseHandshake(m_tlsServerContext, currentPrfHash, m_recordStream); m_recordStream.EnablePendingCipherWrite(); m_recordStream.EnablePendingCipherRead(true); Send13EncryptedExtensionsMessage(m_serverExtensions); m_connectionState = 5; if (!m_selectedPsk13) { m_certificateRequest = m_tlsServer.GetCertificateRequest(); if (m_certificateRequest != null) { if (!m_certificateRequest.HasCertificateRequestContext(TlsUtilities.EmptyBytes)) throw new TlsFatalAlert(80); TlsUtilities.EstablishServerSigAlgs(securityParameters, m_certificateRequest); SendCertificateRequestMessage(m_certificateRequest); m_connectionState = 11; } TlsCredentialedSigner tlsCredentialedSigner = TlsUtilities.Establish13ServerCredentials(m_tlsServer); if (tlsCredentialedSigner == null) throw new TlsFatalAlert(80); Certificate certificate = tlsCredentialedSigner.Certificate; Send13CertificateMessage(certificate); securityParameters.m_tlsServerEndPoint = null; m_connectionState = 7; DigitallySigned certificateVerify = TlsUtilities.Generate13CertificateVerify(m_tlsServerContext, tlsCredentialedSigner, m_handshakeHash); Send13CertificateVerifyMessage(certificateVerify); m_connectionState = 17; } Send13FinishedMessage(); m_connectionState = 20; byte[] currentPrfHash2 = TlsUtilities.GetCurrentPrfHash(m_handshakeHash); TlsUtilities.Establish13PhaseApplication(m_tlsServerContext, currentPrfHash2, m_recordStream); m_recordStream.EnablePendingCipherWrite(); } protected virtual void SendCertificateRequestMessage(CertificateRequest certificateRequest) { HandshakeMessageOutput handshakeMessageOutput = new HandshakeMessageOutput(13); certificateRequest.Encode(m_tlsServerContext, handshakeMessageOutput); handshakeMessageOutput.Send(this); } protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus) { HandshakeMessageOutput handshakeMessageOutput = new HandshakeMessageOutput(22); certificateStatus.Encode(handshakeMessageOutput); handshakeMessageOutput.Send(this); } protected virtual void SendHelloRequestMessage() { HandshakeMessageOutput.Send(this, 0, TlsUtilities.EmptyBytes); } protected virtual void SendNewSessionTicketMessage(NewSessionTicket newSessionTicket) { if (newSessionTicket == null) throw new TlsFatalAlert(80); HandshakeMessageOutput handshakeMessageOutput = new HandshakeMessageOutput(4); newSessionTicket.Encode(handshakeMessageOutput); handshakeMessageOutput.Send(this); } protected virtual void SendServerHelloDoneMessage() { HandshakeMessageOutput.Send(this, 14, TlsUtilities.EmptyBytes); } protected virtual void SendServerHelloMessage(ServerHello serverHello) { HandshakeMessageOutput handshakeMessageOutput = new HandshakeMessageOutput(2); serverHello.Encode(m_tlsServerContext, handshakeMessageOutput); handshakeMessageOutput.Send(this); } protected virtual void SendServerKeyExchangeMessage(byte[] serverKeyExchange) { HandshakeMessageOutput.Send(this, 12, serverKeyExchange); } protected virtual void Skip13ClientCertificate() { if (m_certificateRequest != null) throw new TlsFatalAlert(10); } protected virtual void Skip13ClientCertificateVerify() { if (ExpectCertificateVerifyMessage()) throw new TlsFatalAlert(10); } } }