123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.Collections;
- using System.IO;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
- {
- public class TlsServerProtocol
- : TlsProtocol
- {
- protected TlsServer m_tlsServer = null;
- internal TlsServerContextImpl m_tlsServerContext = null;
- protected int[] m_offeredCipherSuites = null;
- protected TlsKeyExchange m_keyExchange = null;
- protected CertificateRequest m_certificateRequest = null;
- /// <summary>Constructor for non-blocking mode.</summary>
- /// <remarks>
- /// When data is received, use <see cref="TlsProtocol.OfferInput(byte[])"/> to provide the received ciphertext,
- /// then use <see cref="TlsProtocol.ReadInput(byte[],int,int)"/> to read the corresponding cleartext.<br/><br/>
- /// Similarly, when data needs to be sent, use <see cref="TlsProtocol.WriteApplicationData(byte[],int,int)"/>
- /// to provide the cleartext, then use <see cref="TlsProtocol.ReadOutput(byte[],int,int)"/> to get the
- /// corresponding ciphertext.
- /// </remarks>
- public TlsServerProtocol()
- : base()
- {
- }
- /// <summary>Constructor for blocking mode.</summary>
- /// <param name="stream">The <see cref="Stream"/> of data to/from the server.</param>
- public TlsServerProtocol(Stream stream)
- : base(stream)
- {
- }
- /// <summary>Constructor for blocking mode.</summary>
- /// <param name="input">The <see cref="Stream"/> of data from the server.</param>
- /// <param name="output">The <see cref="Stream"/> of data to the server.</param>
- public TlsServerProtocol(Stream input, Stream output)
- : base(input, output)
- {
- }
- /// <summary>Receives a TLS handshake in the role of server.</summary>
- /// <remarks>
- /// In blocking mode, this will not return until the handshake is complete. In non-blocking mode, use
- /// <see cref="TlsPeer.NotifyHandshakeComplete"/> to receive a callback when the handshake is complete.
- /// </remarks>
- /// <param name="tlsServer">The <see cref="TlsServer"/> to use for the handshake.</param>
- /// <exception cref="IOException">If in blocking mode and handshake was not successful.</exception>
- 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");
- this.m_tlsServer = tlsServer;
- this.m_tlsServerContext = new TlsServerContextImpl(tlsServer.Crypto);
- tlsServer.Init(m_tlsServerContext);
- tlsServer.NotifyCloseHandle(this);
- BeginHandshake(false);
- if (m_blocking)
- {
- BlockForHandshake();
- }
- }
- protected override void CleanupHandshake()
- {
- base.CleanupHandshake();
- this.m_offeredCipherSuites = null;
- this.m_keyExchange = null;
- this.m_certificateRequest = null;
- }
- protected virtual bool ExpectCertificateVerifyMessage()
- {
- if (null == m_certificateRequest)
- return false;
- Certificate clientCertificate = m_tlsServerContext.SecurityParameters.PeerCertificate;
- return null != clientCertificate && !clientCertificate.IsEmpty
- && (null == m_keyExchange || m_keyExchange.RequiresCertificateVerify);
- }
- /// <exception cref="IOException"/>
- protected virtual ServerHello Generate13HelloRetryRequest(ClientHello clientHello)
- {
- // TODO[tls13] In future there might be other reasons for a HelloRetryRequest.
- if (m_retryGroup < 0)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters;
- ProtocolVersion serverVersion = securityParameters.NegotiatedVersion;
- IDictionary serverHelloExtensions = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
- TlsExtensionsUtilities.AddSupportedVersionsExtensionServer(serverHelloExtensions, serverVersion);
- if (m_retryGroup >= 0)
- {
- TlsExtensionsUtilities.AddKeyShareHelloRetryRequest(serverHelloExtensions, m_retryGroup);
- }
- if (null != m_retryCookie)
- {
- TlsExtensionsUtilities.AddCookieExtension(serverHelloExtensions, m_retryCookie);
- }
- TlsUtilities.CheckExtensionData13(serverHelloExtensions, HandshakeType.hello_retry_request,
- AlertDescription.internal_error);
- return new ServerHello(clientHello.SessionID, securityParameters.CipherSuite, serverHelloExtensions);
- }
- /// <exception cref="IOException"/>
- protected virtual ServerHello Generate13ServerHello(ClientHello clientHello,
- HandshakeMessageInput clientHelloMessage, bool afterHelloRetryRequest)
- {
- SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters;
- byte[] legacy_session_id = clientHello.SessionID;
- IDictionary clientHelloExtensions = clientHello.Extensions;
- if (null == clientHelloExtensions)
- throw new TlsFatalAlert(AlertDescription.missing_extension);
- ProtocolVersion serverVersion = securityParameters.NegotiatedVersion;
- TlsCrypto crypto = m_tlsServerContext.Crypto;
- // NOTE: Will only select for psk_dhe_ke
- OfferedPsks.SelectedConfig selectedPsk = TlsUtilities.SelectPreSharedKey(m_tlsServerContext, m_tlsServer,
- clientHelloExtensions, clientHelloMessage, m_handshakeHash, afterHelloRetryRequest);
- IList clientShares = TlsExtensionsUtilities.GetKeyShareClientHello(clientHelloExtensions);
- KeyShareEntry clientShare = null;
- if (afterHelloRetryRequest)
- {
- if (m_retryGroup < 0)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- if (null == selectedPsk)
- {
- /*
- * RFC 8446 4.2.3. If a server is authenticating via a certificate and the client has
- * not sent a "signature_algorithms" extension, then the server MUST abort the handshake
- * with a "missing_extension" alert.
- */
- if (null == securityParameters.ClientSigAlgs)
- throw new TlsFatalAlert(AlertDescription.missing_extension);
- }
- else
- {
- // TODO[tls13] Maybe filter the offered PSKs by PRF algorithm before server selection instead
- if (selectedPsk.m_psk.PrfAlgorithm != securityParameters.PrfAlgorithm)
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- /*
- * TODO[tls13] Confirm fields in the ClientHello haven't changed
- *
- * RFC 8446 4.1.2 [..] when the server has responded to its ClientHello with a
- * HelloRetryRequest [..] the client MUST send the same ClientHello without
- * modification, except as follows: [key_share, early_data, cookie, pre_shared_key,
- * padding].
- */
- byte[] cookie = TlsExtensionsUtilities.GetCookieExtension(clientHelloExtensions);
- if (!Arrays.AreEqual(m_retryCookie, cookie))
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- this.m_retryCookie = null;
- clientShare = TlsUtilities.SelectKeyShare(clientShares, m_retryGroup);
- if (null == clientShare)
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- else
- {
- this.m_clientExtensions = clientHelloExtensions;
- securityParameters.m_secureRenegotiation = false;
- // NOTE: Validates the padding extension data, if present
- TlsExtensionsUtilities.GetPaddingExtension(clientHelloExtensions);
- securityParameters.m_clientServerNames = TlsExtensionsUtilities
- .GetServerNameExtensionClient(clientHelloExtensions);
- TlsUtilities.EstablishClientSigAlgs(securityParameters, clientHelloExtensions);
- /*
- * RFC 8446 4.2.3. If a server is authenticating via a certificate and the client has
- * not sent a "signature_algorithms" extension, then the server MUST abort the handshake
- * with a "missing_extension" alert.
- */
- if (null == selectedPsk && null == securityParameters.ClientSigAlgs)
- throw new TlsFatalAlert(AlertDescription.missing_extension);
- m_tlsServer.ProcessClientExtensions(clientHelloExtensions);
- /*
- * NOTE: Currently no server support for session resumption
- *
- * If adding support, ensure securityParameters.tlsUnique is set to the localVerifyData, but
- * ONLY when extended_master_secret has been negotiated (otherwise NULL).
- */
- {
- // TODO[tls13] Resumption/PSK
- this.m_tlsSession = TlsUtilities.ImportSession(TlsUtilities.EmptyBytes, null);
- this.m_sessionParameters = null;
- this.m_sessionMasterSecret = null;
- }
- securityParameters.m_sessionID = m_tlsSession.SessionID;
- m_tlsServer.NotifySession(m_tlsSession);
- TlsUtilities.NegotiatedVersionTlsServer(m_tlsServerContext);
- {
- securityParameters.m_serverRandom = CreateRandomBlock(false, m_tlsServerContext);
- if (!serverVersion.Equals(ProtocolVersion.GetLatestTls(m_tlsServer.GetProtocolVersions())))
- {
- TlsUtilities.WriteDowngradeMarker(serverVersion, securityParameters.ServerRandom);
- }
- }
- {
- // TODO[tls13] Constrain selection when PSK selected
- int cipherSuite = m_tlsServer.GetSelectedCipherSuite();
- if (!TlsUtilities.IsValidCipherSuiteSelection(m_offeredCipherSuites, cipherSuite) ||
- !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, serverVersion))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite);
- }
- int[] clientSupportedGroups = securityParameters.ClientSupportedGroups;
- int[] serverSupportedGroups = securityParameters.ServerSupportedGroups;
- clientShare = TlsUtilities.SelectKeyShare(crypto, serverVersion, clientShares, clientSupportedGroups,
- serverSupportedGroups);
- if (null == clientShare)
- {
- this.m_retryGroup = TlsUtilities.SelectKeyShareGroup(crypto, serverVersion, clientSupportedGroups,
- serverSupportedGroups);
- if (m_retryGroup < 0)
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- this.m_retryCookie = m_tlsServerContext.NonceGenerator.GenerateNonce(16);
- return Generate13HelloRetryRequest(clientHello);
- }
- if (clientShare.NamedGroup != serverSupportedGroups[0])
- {
- /*
- * TODO[tls13] RFC 8446 4.2.7. As of TLS 1.3, servers are permitted to send the
- * "supported_groups" extension to the client. Clients MUST NOT act upon any
- * information found in "supported_groups" prior to successful completion of the
- * handshake but MAY use the information learned from a successfully completed
- * handshake to change what groups they use in their "key_share" extension in
- * subsequent connections. If the server has a group it prefers to the ones in the
- * "key_share" extension but is still willing to accept the ClientHello, it SHOULD
- * send "supported_groups" to update the client's view of its preferences; this
- * extension SHOULD contain all groups the server supports, regardless of whether
- * they are currently supported by the client.
- */
- }
- }
- IDictionary serverHelloExtensions = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
- IDictionary serverEncryptedExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(
- m_tlsServer.GetServerExtensions());
- m_tlsServer.GetServerExtensionsForConnection(serverEncryptedExtensions);
- ProtocolVersion serverLegacyVersion = ProtocolVersion.TLSv12;
- TlsExtensionsUtilities.AddSupportedVersionsExtensionServer(serverHelloExtensions, serverVersion);
- /*
- * RFC 8446 Appendix D. Because TLS 1.3 always hashes in the transcript up to the server
- * Finished, implementations which support both TLS 1.3 and earlier versions SHOULD indicate
- * the use of the Extended Master Secret extension in their APIs whenever TLS 1.3 is used.
- */
- securityParameters.m_extendedMasterSecret = true;
- /*
- * RFC 7301 3.1. When session resumption or session tickets [...] are used, the previous
- * contents of this extension are irrelevant, and only the values in the new handshake
- * messages are considered.
- */
- securityParameters.m_applicationProtocol = TlsExtensionsUtilities.GetAlpnExtensionServer(
- serverEncryptedExtensions);
- securityParameters.m_applicationProtocolSet = true;
- if (serverEncryptedExtensions.Count > 0)
- {
- securityParameters.m_maxFragmentLength = ProcessMaxFragmentLengthExtension(clientHelloExtensions,
- serverEncryptedExtensions, AlertDescription.internal_error);
- }
- securityParameters.m_encryptThenMac = false;
- securityParameters.m_truncatedHmac = false;
- /*
- * TODO[tls13] RFC 8446 4.4.2.1. OCSP Status and SCT Extensions.
- *
- * OCSP information is carried in an extension for a CertificateEntry.
- */
- securityParameters.m_statusRequestVersion = clientHelloExtensions.Contains(ExtensionType.status_request)
- ? 1 : 0;
- this.m_expectSessionTicket = false;
- TlsSecret pskEarlySecret = null;
- if (null != selectedPsk)
- {
- pskEarlySecret = selectedPsk.m_earlySecret;
- this.m_selectedPsk13 = true;
- TlsExtensionsUtilities.AddPreSharedKeyServerHello(serverHelloExtensions, selectedPsk.m_index);
- }
- TlsSecret sharedSecret;
- {
- int namedGroup = clientShare.NamedGroup;
- TlsAgreement agreement;
- if (NamedGroup.RefersToASpecificCurve(namedGroup))
- {
- agreement = crypto.CreateECDomain(new TlsECConfig(namedGroup)).CreateECDH();
- }
- else if (NamedGroup.RefersToASpecificFiniteField(namedGroup))
- {
- agreement = crypto.CreateDHDomain(new TlsDHConfig(namedGroup, true)).CreateDH();
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- byte[] key_exchange = agreement.GenerateEphemeral();
- KeyShareEntry serverShare = new KeyShareEntry(namedGroup, key_exchange);
- TlsExtensionsUtilities.AddKeyShareServerHello(serverHelloExtensions, serverShare);
- agreement.ReceivePeerValue(clientShare.KeyExchange);
- sharedSecret = agreement.CalculateSecret();
- }
- TlsUtilities.Establish13PhaseSecrets(m_tlsServerContext, pskEarlySecret, sharedSecret);
- this.m_serverExtensions = serverEncryptedExtensions;
- ApplyMaxFragmentLengthExtension(securityParameters.MaxFragmentLength);
- TlsUtilities.CheckExtensionData13(serverHelloExtensions, HandshakeType.server_hello,
- AlertDescription.internal_error);
- return new ServerHello(serverLegacyVersion, securityParameters.ServerRandom, legacy_session_id,
- securityParameters.CipherSuite, serverHelloExtensions);
- }
- /// <exception cref="IOException"/>
- protected virtual ServerHello GenerateServerHello(ClientHello clientHello,
- HandshakeMessageInput clientHelloMessage)
- {
- ProtocolVersion clientLegacyVersion = clientHello.Version;
- if (!clientLegacyVersion.IsTls)
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- this.m_offeredCipherSuites = clientHello.CipherSuites;
-
- SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters;
- m_tlsServerContext.SetClientSupportedVersions(
- TlsExtensionsUtilities.GetSupportedVersionsExtensionClient(clientHello.Extensions));
- ProtocolVersion clientVersion = clientLegacyVersion;
- if (null == m_tlsServerContext.ClientSupportedVersions)
- {
- if (clientVersion.IsLaterVersionOf(ProtocolVersion.TLSv12))
- {
- clientVersion = ProtocolVersion.TLSv12;
- }
- m_tlsServerContext.SetClientSupportedVersions(clientVersion.DownTo(ProtocolVersion.SSLv3));
- }
- else
- {
- clientVersion = ProtocolVersion.GetLatestTls(m_tlsServerContext.ClientSupportedVersions);
- }
- // Set the legacy_record_version to use for early alerts
- m_recordStream.SetWriteVersion(clientVersion);
- if (!ProtocolVersion.SERVER_EARLIEST_SUPPORTED_TLS.IsEqualOrEarlierVersionOf(clientVersion))
- throw new TlsFatalAlert(AlertDescription.protocol_version);
- // NOT renegotiating
- {
- m_tlsServerContext.SetClientVersion(clientVersion);
- }
- m_tlsServer.NotifyClientVersion(m_tlsServerContext.ClientVersion);
- securityParameters.m_clientRandom = clientHello.Random;
- m_tlsServer.NotifyFallback(Arrays.Contains(m_offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV));
- m_tlsServer.NotifyOfferedCipherSuites(m_offeredCipherSuites);
- // TODO[tls13] Negotiate cipher suite first?
- ProtocolVersion serverVersion;
- // NOT renegotiating
- {
- serverVersion = m_tlsServer.GetServerVersion();
- if (!ProtocolVersion.Contains(m_tlsServerContext.ClientSupportedVersions, serverVersion))
- throw new TlsFatalAlert(AlertDescription.internal_error);
- securityParameters.m_negotiatedVersion = serverVersion;
- }
- securityParameters.m_clientSupportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(
- clientHello.Extensions);
- securityParameters.m_serverSupportedGroups = m_tlsServer.GetSupportedGroups();
- if (ProtocolVersion.TLSv13.IsEqualOrEarlierVersionOf(serverVersion))
- {
- // See RFC 8446 D.4.
- m_recordStream.SetIgnoreChangeCipherSpec(true);
- m_recordStream.SetWriteVersion(ProtocolVersion.TLSv12);
- return Generate13ServerHello(clientHello, clientHelloMessage, false);
- }
- m_recordStream.SetWriteVersion(serverVersion);
- this.m_clientExtensions = clientHello.Extensions;
- byte[] clientRenegExtData = TlsUtilities.GetExtensionData(m_clientExtensions, ExtensionType.renegotiation_info);
- // NOT renegotiating
- {
- /*
- * RFC 5746 3.6. Server Behavior: Initial Handshake (both full and session-resumption)
- */
- /*
- * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
- * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
- * ClientHello. Including both is NOT RECOMMENDED.
- */
- /*
- * When a ClientHello is received, the server MUST check if it includes the
- * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
- * to TRUE.
- */
- if (Arrays.Contains(m_offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
- {
- securityParameters.m_secureRenegotiation = true;
- }
- /*
- * The server MUST check if the "renegotiation_info" extension is included in the
- * ClientHello.
- */
- if (clientRenegExtData != null)
- {
- /*
- * If the extension is present, set secure_renegotiation flag to TRUE. The
- * server MUST then verify that the length of the "renegotiated_connection"
- * field is zero, and if it is not, MUST abort the handshake.
- */
- securityParameters.m_secureRenegotiation = true;
- if (!Arrays.ConstantTimeAreEqual(clientRenegExtData,
- CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
- }
- m_tlsServer.NotifySecureRenegotiation(securityParameters.IsSecureRenegotiation);
- bool offeredExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(
- m_clientExtensions);
- if (m_clientExtensions != null)
- {
- // NOTE: Validates the padding extension data, if present
- TlsExtensionsUtilities.GetPaddingExtension(m_clientExtensions);
- securityParameters.m_clientServerNames = TlsExtensionsUtilities.GetServerNameExtensionClient(
- m_clientExtensions);
- /*
- * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior
- * to 1.2. Clients MUST NOT offer it if they are offering prior versions.
- */
- if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(clientVersion))
- {
- TlsUtilities.EstablishClientSigAlgs(securityParameters, m_clientExtensions);
- }
- securityParameters.m_clientSupportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(
- m_clientExtensions);
- m_tlsServer.ProcessClientExtensions(m_clientExtensions);
- }
- this.m_resumedSession = EstablishSession(m_tlsServer.GetSessionToResume(clientHello.SessionID));
- if (!m_resumedSession)
- {
- byte[] newSessionID = m_tlsServer.GetNewSessionID();
- if (null == newSessionID)
- {
- newSessionID = TlsUtilities.EmptyBytes;
- }
- this.m_tlsSession = TlsUtilities.ImportSession(newSessionID, null);
- this.m_sessionParameters = null;
- this.m_sessionMasterSecret = null;
- }
- securityParameters.m_sessionID = m_tlsSession.SessionID;
- m_tlsServer.NotifySession(m_tlsSession);
- TlsUtilities.NegotiatedVersionTlsServer(m_tlsServerContext);
- {
- bool useGmtUnixTime = m_tlsServer.ShouldUseGmtUnixTime();
- securityParameters.m_serverRandom = CreateRandomBlock(useGmtUnixTime, m_tlsServerContext);
- if (!serverVersion.Equals(ProtocolVersion.GetLatestTls(m_tlsServer.GetProtocolVersions())))
- {
- TlsUtilities.WriteDowngradeMarker(serverVersion, securityParameters.ServerRandom);
- }
- }
- {
- int cipherSuite = m_resumedSession
- ? m_sessionParameters.CipherSuite
- : m_tlsServer.GetSelectedCipherSuite();
- if (!TlsUtilities.IsValidCipherSuiteSelection(m_offeredCipherSuites, cipherSuite) ||
- !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, serverVersion))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite);
- }
- m_tlsServerContext.SetRsaPreMasterSecretVersion(clientLegacyVersion);
- {
- IDictionary sessionServerExtensions = m_resumedSession
- ? m_sessionParameters.ReadServerExtensions()
- : m_tlsServer.GetServerExtensions();
- this.m_serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(sessionServerExtensions);
- }
- m_tlsServer.GetServerExtensionsForConnection(m_serverExtensions);
- // NOT renegotiating
- {
- /*
- * RFC 5746 3.6. Server Behavior: Initial Handshake (both full and session-resumption)
- */
- if (securityParameters.IsSecureRenegotiation)
- {
- byte[] serverRenegExtData = TlsUtilities.GetExtensionData(m_serverExtensions,
- ExtensionType.renegotiation_info);
- bool noRenegExt = (null == serverRenegExtData);
- if (noRenegExt)
- {
- /*
- * Note that sending a "renegotiation_info" extension in response to a ClientHello
- * containing only the SCSV is an explicit exception to the prohibition in RFC 5246,
- * Section 7.4.1.4, on the server sending unsolicited extensions and is only allowed
- * because the client is signaling its willingness to receive the extension via the
- * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
- */
- /*
- * If the secure_renegotiation flag is set to TRUE, the server MUST include an empty
- * "renegotiation_info" extension in the ServerHello message.
- */
- this.m_serverExtensions[ExtensionType.renegotiation_info] = CreateRenegotiationInfo(
- TlsUtilities.EmptyBytes);
- }
- }
- }
- /*
- * RFC 7627 4. Clients and servers SHOULD NOT accept handshakes that do not use the extended
- * master secret [..]. (and see 5.2, 5.3)
- */
- if (m_resumedSession)
- {
- if (!m_sessionParameters.IsExtendedMasterSecret)
- {
- /*
- * TODO[resumption] ProvTlsServer currently only resumes EMS sessions. Revisit this
- * in relation to 'tlsServer.allowLegacyResumption()'.
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- if (!offeredExtendedMasterSecret)
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- securityParameters.m_extendedMasterSecret = true;
- TlsExtensionsUtilities.AddExtendedMasterSecretExtension(m_serverExtensions);
- }
- else
- {
- securityParameters.m_extendedMasterSecret = offeredExtendedMasterSecret && !serverVersion.IsSsl
- && m_tlsServer.ShouldUseExtendedMasterSecret();
- if (securityParameters.IsExtendedMasterSecret)
- {
- TlsExtensionsUtilities.AddExtendedMasterSecretExtension(m_serverExtensions);
- }
- else if (m_tlsServer.RequiresExtendedMasterSecret())
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
- 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 = ProcessMaxFragmentLengthExtension(m_clientExtensions,
- m_serverExtensions, AlertDescription.internal_error);
- securityParameters.m_truncatedHmac = TlsExtensionsUtilities.HasTruncatedHmacExtension(
- m_serverExtensions);
- if (!m_resumedSession)
- {
- if (TlsUtilities.HasExpectedEmptyExtensionData(m_serverExtensions, ExtensionType.status_request_v2,
- AlertDescription.internal_error))
- {
- securityParameters.m_statusRequestVersion = 2;
- }
- else if (TlsUtilities.HasExpectedEmptyExtensionData(m_serverExtensions, ExtensionType.status_request,
- AlertDescription.internal_error))
- {
- securityParameters.m_statusRequestVersion = 1;
- }
- this.m_expectSessionTicket = TlsUtilities.HasExpectedEmptyExtensionData(m_serverExtensions,
- ExtensionType.session_ticket, AlertDescription.internal_error);
- }
- }
- ApplyMaxFragmentLengthExtension(securityParameters.MaxFragmentLength);
- return new ServerHello(serverVersion, securityParameters.ServerRandom, m_tlsSession.SessionID,
- securityParameters.CipherSuite, m_serverExtensions);
- }
- protected override TlsContext Context
- {
- get { return m_tlsServerContext; }
- }
- internal override AbstractTlsContext ContextAdmin
- {
- get { return m_tlsServerContext; }
- }
- protected override TlsPeer Peer
- {
- get { return m_tlsServer; }
- }
- /// <exception cref="IOException"/>
- protected virtual void Handle13HandshakeMessage(short type, HandshakeMessageInput buf)
- {
- if (!IsTlsV13ConnectionState())
- throw new TlsFatalAlert(AlertDescription.internal_error);
- if (m_resumedSession)
- {
- /*
- * TODO[tls13] Abbreviated handshakes (PSK resumption)
- *
- * NOTE: No CertificateRequest, Certificate, CertificateVerify messages, but client
- * might now send EndOfEarlyData after receiving server Finished message.
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- switch (type)
- {
- case HandshakeType.certificate:
- {
- switch (m_connectionState)
- {
- case CS_SERVER_FINISHED:
- {
- Receive13ClientCertificate(buf);
- this.m_connectionState = CS_CLIENT_CERTIFICATE;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.certificate_verify:
- {
- switch (m_connectionState)
- {
- case CS_CLIENT_CERTIFICATE:
- {
- Receive13ClientCertificateVerify(buf);
- buf.UpdateHash(m_handshakeHash);
- this.m_connectionState = CS_CLIENT_CERTIFICATE_VERIFY;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.client_hello:
- {
- switch (m_connectionState)
- {
- case CS_START:
- {
- // NOTE: Legacy handler should be dispatching initial ClientHello.
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- case CS_SERVER_HELLO_RETRY_REQUEST:
- {
- ClientHello clientHelloRetry = ReceiveClientHelloMessage(buf);
- this.m_connectionState = CS_CLIENT_HELLO_RETRY;
- ServerHello serverHello = Generate13ServerHello(clientHelloRetry, buf, true);
- SendServerHelloMessage(serverHello);
- this.m_connectionState = CS_SERVER_HELLO;
- Send13ServerHelloCoda(serverHello, true);
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.finished:
- {
- switch (m_connectionState)
- {
- case CS_SERVER_FINISHED:
- case CS_CLIENT_CERTIFICATE:
- case CS_CLIENT_CERTIFICATE_VERIFY:
- {
- if (m_connectionState == CS_SERVER_FINISHED)
- {
- Skip13ClientCertificate();
- }
- if (m_connectionState != CS_CLIENT_CERTIFICATE_VERIFY)
- {
- Skip13ClientCertificateVerify();
- }
- Receive13ClientFinished(buf);
- this.m_connectionState = CS_CLIENT_FINISHED;
- // See RFC 8446 D.4.
- m_recordStream.SetIgnoreChangeCipherSpec(false);
- // NOTE: Completes the switch to application-data phase (server entered after CS_SERVER_FINISHED).
- m_recordStream.EnablePendingCipherRead(false);
- CompleteHandshake();
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.key_update:
- {
- Receive13KeyUpdate(buf);
- break;
- }
- case HandshakeType.certificate_request:
- case HandshakeType.certificate_status:
- case HandshakeType.certificate_url:
- case HandshakeType.client_key_exchange:
- case HandshakeType.encrypted_extensions:
- case HandshakeType.end_of_early_data:
- case HandshakeType.hello_request:
- case HandshakeType.hello_verify_request:
- case HandshakeType.message_hash:
- case HandshakeType.new_session_ticket:
- case HandshakeType.server_hello:
- case HandshakeType.server_hello_done:
- case HandshakeType.server_key_exchange:
- case HandshakeType.supplemental_data:
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
- protected override void HandleHandshakeMessage(short type, HandshakeMessageInput buf)
- {
- SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters;
- if (m_connectionState > CS_CLIENT_HELLO
- && TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion))
- {
- Handle13HandshakeMessage(type, buf);
- return;
- }
- if (!IsLegacyConnectionState())
- throw new TlsFatalAlert(AlertDescription.internal_error);
- if (m_resumedSession)
- {
- if (type != HandshakeType.finished || m_connectionState != CS_SERVER_FINISHED)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- ProcessFinishedMessage(buf);
- this.m_connectionState = CS_CLIENT_FINISHED;
- CompleteHandshake();
- return;
- }
- switch (type)
- {
- case HandshakeType.client_hello:
- {
- if (IsApplicationDataReady)
- {
- RefuseRenegotiation();
- break;
- }
- switch (m_connectionState)
- {
- case CS_END:
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- case CS_START:
- {
- ClientHello clientHello = ReceiveClientHelloMessage(buf);
- this.m_connectionState = CS_CLIENT_HELLO;
- 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);
- this.m_connectionState = CS_SERVER_HELLO_RETRY_REQUEST;
- // See RFC 8446 D.4.
- SendChangeCipherSpecMessage();
- }
- else
- {
- SendServerHelloMessage(serverHello);
- this.m_connectionState = CS_SERVER_HELLO;
- // See RFC 8446 D.4.
- SendChangeCipherSpecMessage();
- Send13ServerHelloCoda(serverHello, false);
- }
- break;
- }
- // For TLS 1.3+, this was already done by GenerateServerHello
- buf.UpdateHash(m_handshakeHash);
- SendServerHelloMessage(serverHello);
- this.m_connectionState = CS_SERVER_HELLO;
- if (m_resumedSession)
- {
- securityParameters.m_masterSecret = m_sessionMasterSecret;
- m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsServerContext));
- SendChangeCipherSpec();
- SendFinishedMessage();
- this.m_connectionState = CS_SERVER_FINISHED;
- break;
- }
- IList serverSupplementalData = m_tlsServer.GetServerSupplementalData();
- if (serverSupplementalData != null)
- {
- SendSupplementalDataMessage(serverSupplementalData);
- this.m_connectionState = CS_SERVER_SUPPLEMENTAL_DATA;
- }
- this.m_keyExchange = TlsUtilities.InitKeyExchangeServer(m_tlsServerContext, m_tlsServer);
- TlsCredentials serverCredentials = TlsUtilities.EstablishServerCredentials(m_tlsServer);
- // Server certificate
- {
- Certificate serverCertificate = null;
- MemoryStream endPointHash = new MemoryStream();
- if (null == serverCredentials)
- {
- m_keyExchange.SkipServerCredentials();
- }
- else
- {
- m_keyExchange.ProcessServerCredentials(serverCredentials);
- serverCertificate = serverCredentials.Certificate;
- SendCertificateMessage(serverCertificate, endPointHash);
- this.m_connectionState = CS_SERVER_CERTIFICATE;
- }
- securityParameters.m_tlsServerEndPoint = endPointHash.ToArray();
- // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes
- // CertificateStatus
- if (null == serverCertificate || serverCertificate.IsEmpty)
- {
- securityParameters.m_statusRequestVersion = 0;
- }
- }
- if (securityParameters.StatusRequestVersion > 0)
- {
- CertificateStatus certificateStatus = m_tlsServer.GetCertificateStatus();
- if (certificateStatus != null)
- {
- SendCertificateStatusMessage(certificateStatus);
- this.m_connectionState = CS_SERVER_CERTIFICATE_STATUS;
- }
- }
- byte[] serverKeyExchange = m_keyExchange.GenerateServerKeyExchange();
- if (serverKeyExchange != null)
- {
- SendServerKeyExchangeMessage(serverKeyExchange);
- this.m_connectionState = CS_SERVER_KEY_EXCHANGE;
- }
- if (null != serverCredentials)
- {
- this.m_certificateRequest = m_tlsServer.GetCertificateRequest();
- if (null == m_certificateRequest)
- {
- /*
- * For static agreement key exchanges, CertificateRequest is required since
- * the client Certificate message is mandatory but can only be sent if the
- * server requests it.
- */
- if (!m_keyExchange.RequiresCertificateVerify)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- else
- {
- if (TlsUtilities.IsTlsV12(m_tlsServerContext)
- != (m_certificateRequest.SupportedSignatureAlgorithms != null))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- this.m_certificateRequest = TlsUtilities.ValidateCertificateRequest(m_certificateRequest,
- m_keyExchange);
- TlsUtilities.EstablishServerSigAlgs(securityParameters, m_certificateRequest);
- TlsUtilities.TrackHashAlgorithms(m_handshakeHash, securityParameters.ServerSigAlgs);
- SendCertificateRequestMessage(m_certificateRequest);
- this.m_connectionState = CS_SERVER_CERTIFICATE_REQUEST;
- }
- }
- SendServerHelloDoneMessage();
- this.m_connectionState = CS_SERVER_HELLO_DONE;
- bool forceBuffering = false;
- TlsUtilities.SealHandshakeHash(m_tlsServerContext, m_handshakeHash, forceBuffering);
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.supplemental_data:
- {
- switch (m_connectionState)
- {
- case CS_SERVER_HELLO_DONE:
- {
- m_tlsServer.ProcessClientSupplementalData(ReadSupplementalDataMessage(buf));
- this.m_connectionState = CS_CLIENT_SUPPLEMENTAL_DATA;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.certificate:
- {
- switch (m_connectionState)
- {
- case CS_SERVER_HELLO_DONE:
- case CS_CLIENT_SUPPLEMENTAL_DATA:
- {
- if (m_connectionState != CS_CLIENT_SUPPLEMENTAL_DATA)
- {
- m_tlsServer.ProcessClientSupplementalData(null);
- }
- ReceiveCertificateMessage(buf);
- this.m_connectionState = CS_CLIENT_CERTIFICATE;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.client_key_exchange:
- {
- switch (m_connectionState)
- {
- case CS_SERVER_HELLO_DONE:
- case CS_CLIENT_SUPPLEMENTAL_DATA:
- case CS_CLIENT_CERTIFICATE:
- {
- if (m_connectionState == CS_SERVER_HELLO_DONE)
- {
- m_tlsServer.ProcessClientSupplementalData(null);
- }
- if (m_connectionState != CS_CLIENT_CERTIFICATE)
- {
- if (null == m_certificateRequest)
- {
- m_keyExchange.SkipClientCredentials();
- }
- else if (TlsUtilities.IsTlsV12(m_tlsServerContext))
- {
- /*
- * RFC 5246 If no suitable certificate is available, the client MUST send a
- * certificate message containing no certificates.
- *
- * NOTE: In previous RFCs, this was SHOULD instead of MUST.
- */
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- else if (TlsUtilities.IsSsl(m_tlsServerContext))
- {
- /*
- * SSL 3.0 If the server has sent a certificate request Message, the client must
- * send either the certificate message or a no_certificate alert.
- */
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- else
- {
- NotifyClientCertificate(Certificate.EmptyChain);
- }
- }
- ReceiveClientKeyExchangeMessage(buf);
- this.m_connectionState = CS_CLIENT_KEY_EXCHANGE;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.certificate_verify:
- {
- switch (m_connectionState)
- {
- case CS_CLIENT_KEY_EXCHANGE:
- {
- /*
- * RFC 5246 7.4.8 This message is only sent following a client certificate that has
- * signing capability (i.e., all certificates except those containing fixed
- * Diffie-Hellman parameters).
- */
- if (!ExpectCertificateVerifyMessage())
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- ReceiveCertificateVerifyMessage(buf);
- buf.UpdateHash(m_handshakeHash);
- this.m_connectionState = CS_CLIENT_CERTIFICATE_VERIFY;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.finished:
- {
- switch (m_connectionState)
- {
- case CS_CLIENT_KEY_EXCHANGE:
- case CS_CLIENT_CERTIFICATE_VERIFY:
- {
- if (m_connectionState != CS_CLIENT_CERTIFICATE_VERIFY)
- {
- if (ExpectCertificateVerifyMessage())
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- ProcessFinishedMessage(buf);
- buf.UpdateHash(m_handshakeHash);
- this.m_connectionState = CS_CLIENT_FINISHED;
- if (m_expectSessionTicket)
- {
- /*
- * TODO[new_session_ticket] Check the server-side rules regarding the session ID, since
- * the client is going to ignore any session ID it received once it sees the
- * new_session_ticket message.
- */
- SendNewSessionTicketMessage(m_tlsServer.GetNewSessionTicket());
- this.m_connectionState = CS_SERVER_SESSION_TICKET;
- }
- SendChangeCipherSpec();
- SendFinishedMessage();
- this.m_connectionState = CS_SERVER_FINISHED;
- CompleteHandshake();
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.certificate_request:
- case HandshakeType.certificate_status:
- case HandshakeType.certificate_url:
- case HandshakeType.encrypted_extensions:
- case HandshakeType.end_of_early_data:
- case HandshakeType.hello_request:
- case HandshakeType.hello_verify_request:
- case HandshakeType.key_update:
- case HandshakeType.message_hash:
- case HandshakeType.new_session_ticket:
- case HandshakeType.server_hello:
- case HandshakeType.server_hello_done:
- case HandshakeType.server_key_exchange:
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
- protected override void HandleAlertWarningMessage(short alertDescription)
- {
- /*
- * SSL 3.0 If the server has sent a certificate request Message, the client must send
- * either the certificate message or a no_certificate alert.
- */
- if (AlertDescription.no_certificate == alertDescription && null != m_certificateRequest
- && TlsUtilities.IsSsl(m_tlsServerContext))
- {
- switch (m_connectionState)
- {
- case CS_SERVER_HELLO_DONE:
- case CS_CLIENT_SUPPLEMENTAL_DATA:
- {
- if (m_connectionState != CS_CLIENT_SUPPLEMENTAL_DATA)
- {
- m_tlsServer.ProcessClientSupplementalData(null);
- }
- NotifyClientCertificate(Certificate.EmptyChain);
- this.m_connectionState = CS_CLIENT_CERTIFICATE;
- return;
- }
- }
- }
- base.HandleAlertWarningMessage(alertDescription);
- }
- /// <exception cref="IOException"/>
- protected virtual void NotifyClientCertificate(Certificate clientCertificate)
- {
- if (null == m_certificateRequest)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- TlsUtilities.ProcessClientCertificate(m_tlsServerContext, clientCertificate, m_keyExchange, m_tlsServer);
- }
- /// <exception cref="IOException"/>
- protected virtual void Receive13ClientCertificate(MemoryStream buf)
- {
- // TODO[tls13] This currently just duplicates 'receiveCertificateMessage'
- if (null == m_certificateRequest)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- Certificate.ParseOptions options = new Certificate.ParseOptions()
- .SetMaxChainLength(m_tlsServer.GetMaxCertificateChainLength());
- Certificate clientCertificate = Certificate.Parse(options, m_tlsServerContext, buf, null);
- AssertEmpty(buf);
- NotifyClientCertificate(clientCertificate);
- }
- /// <exception cref="IOException"/>
- protected void Receive13ClientCertificateVerify(MemoryStream buf)
- {
- Certificate clientCertificate = m_tlsServerContext.SecurityParameters.PeerCertificate;
- if (null == clientCertificate || clientCertificate.IsEmpty)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- // TODO[tls13] Actual structure is 'CertificateVerify' in RFC 8446, consider adding for clarity
- DigitallySigned certificateVerify = DigitallySigned.Parse(m_tlsServerContext, buf);
- AssertEmpty(buf);
- TlsUtilities.Verify13CertificateVerifyClient(m_tlsServerContext, m_certificateRequest, certificateVerify,
- m_handshakeHash);
- }
- /// <exception cref="IOException"/>
- protected virtual void Receive13ClientFinished(MemoryStream buf)
- {
- Process13FinishedMessage(buf);
- }
- /// <exception cref="IOException"/>
- protected virtual void ReceiveCertificateMessage(MemoryStream buf)
- {
- if (null == m_certificateRequest)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- Certificate.ParseOptions options = new Certificate.ParseOptions()
- .SetMaxChainLength(m_tlsServer.GetMaxCertificateChainLength());
- Certificate clientCertificate = Certificate.Parse(options, m_tlsServerContext, buf, null);
- AssertEmpty(buf);
- NotifyClientCertificate(clientCertificate);
- }
- /// <exception cref="IOException"/>
- protected virtual void ReceiveCertificateVerifyMessage(MemoryStream buf)
- {
- DigitallySigned certificateVerify = DigitallySigned.Parse(m_tlsServerContext, buf);
- AssertEmpty(buf);
- TlsUtilities.VerifyCertificateVerifyClient(m_tlsServerContext, m_certificateRequest, certificateVerify,
- m_handshakeHash);
- this.m_handshakeHash = m_handshakeHash.StopTracking();
- }
- /// <exception cref="IOException"/>
- protected virtual ClientHello ReceiveClientHelloMessage(MemoryStream buf)
- {
- return ClientHello.Parse(buf, null);
- }
- /// <exception cref="IOException"/>
- protected virtual void ReceiveClientKeyExchangeMessage(MemoryStream buf)
- {
- m_keyExchange.ProcessClientKeyExchange(buf);
- AssertEmpty(buf);
- bool isSsl = TlsUtilities.IsSsl(m_tlsServerContext);
- if (isSsl)
- {
- // NOTE: For SSLv3 (only), master_secret needed to calculate session hash
- EstablishMasterSecret(m_tlsServerContext, m_keyExchange);
- }
- m_tlsServerContext.SecurityParameters.m_sessionHash = TlsUtilities.GetCurrentPrfHash(m_handshakeHash);
- if (!isSsl)
- {
- // NOTE: For (D)TLS, session hash potentially needed for extended_master_secret
- EstablishMasterSecret(m_tlsServerContext, m_keyExchange);
- }
- m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsServerContext));
- if (!ExpectCertificateVerifyMessage())
- {
- this.m_handshakeHash = m_handshakeHash.StopTracking();
- }
- }
- /// <exception cref="IOException"/>
- protected virtual void Send13EncryptedExtensionsMessage(IDictionary serverExtensions)
- {
- // TODO[tls13] Avoid extra copy; use placeholder to write opaque-16 data directly to message buffer
- byte[] extBytes = WriteExtensionsData(serverExtensions);
- HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.encrypted_extensions);
- TlsUtilities.WriteOpaque16(extBytes, message);
- message.Send(this);
- }
- /// <exception cref="IOException"/>
- protected virtual void Send13ServerHelloCoda(ServerHello serverHello, bool afterHelloRetryRequest)
- {
- SecurityParameters securityParameters = m_tlsServerContext.SecurityParameters;
- byte[] serverHelloTranscriptHash = TlsUtilities.GetCurrentPrfHash(m_handshakeHash);
- TlsUtilities.Establish13PhaseHandshake(m_tlsServerContext, serverHelloTranscriptHash, m_recordStream);
- m_recordStream.EnablePendingCipherWrite();
- m_recordStream.EnablePendingCipherRead(true);
- Send13EncryptedExtensionsMessage(m_serverExtensions);
- this.m_connectionState = CS_SERVER_ENCRYPTED_EXTENSIONS;
- if (m_selectedPsk13)
- {
- /*
- * For PSK-only key exchange, there's no CertificateRequest, Certificate, CertificateVerify.
- */
- }
- else
- {
- // CertificateRequest
- {
- this.m_certificateRequest = m_tlsServer.GetCertificateRequest();
- if (null != m_certificateRequest)
- {
- if (!m_certificateRequest.HasCertificateRequestContext(TlsUtilities.EmptyBytes))
- throw new TlsFatalAlert(AlertDescription.internal_error);
- TlsUtilities.EstablishServerSigAlgs(securityParameters, m_certificateRequest);
- SendCertificateRequestMessage(m_certificateRequest);
- this.m_connectionState = CS_SERVER_CERTIFICATE_REQUEST;
- }
- }
- TlsCredentialedSigner serverCredentials = TlsUtilities.Establish13ServerCredentials(m_tlsServer);
- if (null == serverCredentials)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- // Certificate
- {
- /*
- * TODO[tls13] Note that we are expecting the TlsServer implementation to take care of
- * e.g. adding optional "status_request" extension to each CertificateEntry.
- */
- /*
- * No CertificateStatus message is sent; TLS 1.3 uses per-CertificateEntry
- * "status_request" extension instead.
- */
- Certificate serverCertificate = serverCredentials.Certificate;
- Send13CertificateMessage(serverCertificate);
- securityParameters.m_tlsServerEndPoint = null;
- this.m_connectionState = CS_SERVER_CERTIFICATE;
- }
- // CertificateVerify
- {
- DigitallySigned certificateVerify = TlsUtilities.Generate13CertificateVerify(m_tlsServerContext,
- serverCredentials, m_handshakeHash);
- Send13CertificateVerifyMessage(certificateVerify);
- this.m_connectionState = CS_CLIENT_CERTIFICATE_VERIFY;
- }
- }
- // Finished
- {
- Send13FinishedMessage();
- this.m_connectionState = CS_SERVER_FINISHED;
- }
- byte[] serverFinishedTranscriptHash = TlsUtilities.GetCurrentPrfHash(m_handshakeHash);
- TlsUtilities.Establish13PhaseApplication(m_tlsServerContext, serverFinishedTranscriptHash, m_recordStream);
- m_recordStream.EnablePendingCipherWrite();
- }
- /// <exception cref="IOException"/>
- protected virtual void SendCertificateRequestMessage(CertificateRequest certificateRequest)
- {
- HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.certificate_request);
- certificateRequest.Encode(m_tlsServerContext, message);
- message.Send(this);
- }
- /// <exception cref="IOException"/>
- protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus)
- {
- HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.certificate_status);
- // TODO[tls13] Ensure this cannot happen for (D)TLS1.3+
- certificateStatus.Encode(message);
- message.Send(this);
- }
- /// <exception cref="IOException"/>
- protected virtual void SendHelloRequestMessage()
- {
- HandshakeMessageOutput.Send(this, HandshakeType.hello_request, TlsUtilities.EmptyBytes);
- }
- /// <exception cref="IOException"/>
- protected virtual void SendNewSessionTicketMessage(NewSessionTicket newSessionTicket)
- {
- if (newSessionTicket == null)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.new_session_ticket);
- newSessionTicket.Encode(message);
- message.Send(this);
- }
- /// <exception cref="IOException"/>
- protected virtual void SendServerHelloDoneMessage()
- {
- HandshakeMessageOutput.Send(this, HandshakeType.server_hello_done, TlsUtilities.EmptyBytes);
- }
- /// <exception cref="IOException"/>
- protected virtual void SendServerHelloMessage(ServerHello serverHello)
- {
- HandshakeMessageOutput message = new HandshakeMessageOutput(HandshakeType.server_hello);
- serverHello.Encode(m_tlsServerContext, message);
- message.Send(this);
- }
- /// <exception cref="IOException"/>
- protected virtual void SendServerKeyExchangeMessage(byte[] serverKeyExchange)
- {
- HandshakeMessageOutput.Send(this, HandshakeType.server_key_exchange, serverKeyExchange);
- }
- /// <exception cref="IOException"/>
- protected virtual void Skip13ClientCertificate()
- {
- if (null != m_certificateRequest)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- /// <exception cref="IOException"/>
- protected virtual void Skip13ClientCertificateVerify()
- {
- if (ExpectCertificateVerifyMessage())
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
- }
- #pragma warning restore
- #endif
|