summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-07-07 17:51:23 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-07-07 17:51:23 +0700
commit3e43ee2765dd0e059e616bc8d5fbf403645fa3a9 (patch)
tree54c4df3e32d6937d7fca3e9746731e581bb6aa76
parentRefactoring in DTLS (diff)
downloadBouncyCastle.NET-ed25519-3e43ee2765dd0e059e616bc8d5fbf403645fa3a9.tar.xz
Refactoring in DTLS
-rw-r--r--crypto/src/tls/DtlsClientProtocol.cs161
-rw-r--r--crypto/src/tls/TlsClientProtocol.cs4
-rw-r--r--crypto/src/tls/TlsProtocol.cs4
3 files changed, 122 insertions, 47 deletions
diff --git a/crypto/src/tls/DtlsClientProtocol.cs b/crypto/src/tls/DtlsClientProtocol.cs
index 3f52d3c6b..eec920c4a 100644
--- a/crypto/src/tls/DtlsClientProtocol.cs
+++ b/crypto/src/tls/DtlsClientProtocol.cs
@@ -40,23 +40,18 @@ namespace Org.BouncyCastle.Tls
             {
                 SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
 
-                /*
-                 * NOTE: If we ever enable session resumption without extended_master_secret, then
-                 * renegotiation MUST be disabled (see RFC 7627 5.4).
-                 */
                 if (sessionParameters != null
                     && (sessionParameters.IsExtendedMasterSecret
                         || (!client.RequiresExtendedMasterSecret() && client.AllowLegacyResumption())))
                 {
-                    TlsSecret masterSecret = sessionParameters.MasterSecret;
-                    lock (masterSecret)
+                    TlsCrypto crypto = clientContext.Crypto;
+                    TlsSecret sessionMasterSecret = TlsUtilities.GetSessionMasterSecret(crypto,
+                        sessionParameters.MasterSecret);
+                    if (sessionMasterSecret != null)
                     {
-                        if (masterSecret.IsAlive())
-                        {
-                            state.tlsSession = sessionToResume;
-                            state.sessionParameters = sessionParameters;
-                            state.sessionMasterSecret = clientContext.Crypto.AdoptSecret(masterSecret);
-                        }
+                        state.tlsSession = sessionToResume;
+                        state.sessionParameters = sessionParameters;
+                        state.sessionMasterSecret = sessionMasterSecret;
                     }
                 }
             }
@@ -415,44 +410,65 @@ namespace Org.BouncyCastle.Tls
             TlsClientContextImpl clientContext = state.clientContext;
             SecurityParameters securityParameters = clientContext.SecurityParameters;
 
-            clientContext.SetClientSupportedVersions(client.GetProtocolVersions());
+            ProtocolVersion[] supportedVersions = client.GetProtocolVersions();
 
-            ProtocolVersion client_version = ProtocolVersion.GetLatestDtls(clientContext.ClientSupportedVersions);
-            if (!ProtocolVersion.IsSupportedDtlsVersionClient(client_version))
+            //ProtocolVersion earliestVersion = ProtocolVersion.GetEarliestDtls(supportedVersions);
+            ProtocolVersion latestVersion = ProtocolVersion.GetLatestDtls(supportedVersions);
+
+            if (!ProtocolVersion.IsSupportedDtlsVersionClient(latestVersion))
                 throw new TlsFatalAlert(AlertDescription.internal_error);
 
-            clientContext.SetClientVersion(client_version);
+            clientContext.SetClientVersion(latestVersion);
+            clientContext.SetClientSupportedVersions(supportedVersions);
+
+            //bool offeringDtlsV12Minus = ProtocolVersion.DTLSv12.IsEqualOrLaterVersionOf(earliestVersion);
+            bool offeringDtlsV13Plus = ProtocolVersion.DTLSv13.IsEqualOrEarlierVersionOf(latestVersion);
 
             {
-                bool useGmtUnixTime = ProtocolVersion.DTLSv12.IsEqualOrLaterVersionOf(client_version)
-                    && client.ShouldUseGmtUnixTime();
+                bool useGmtUnixTime = !offeringDtlsV13Plus && client.ShouldUseGmtUnixTime();
 
                 securityParameters.m_clientRandom = TlsProtocol.CreateRandomBlock(useGmtUnixTime, clientContext);
             }
 
-            byte[] session_id = TlsUtilities.GetSessionID(state.tlsSession);
-
             bool fallback = client.IsFallback();
 
             state.offeredCipherSuites = client.GetCipherSuites();
 
-            if (session_id.Length > 0 && state.sessionParameters != null)
+            state.clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(client.GetClientExtensions());
+
+            byte[] legacy_session_id = TlsUtilities.GetSessionID(state.tlsSession);
+
+            if (legacy_session_id.Length > 0)
             {
                 if (!Arrays.Contains(state.offeredCipherSuites, state.sessionParameters.CipherSuite))
                 {
-                    session_id = TlsUtilities.EmptyBytes;
+                    legacy_session_id = TlsUtilities.EmptyBytes;
                 }
             }
 
-            state.clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(client.GetClientExtensions());
+            ProtocolVersion sessionVersion = null;
+            if (legacy_session_id.Length > 0)
+            {
+                sessionVersion = state.sessionParameters.NegotiatedVersion;
+
+                if (!ProtocolVersion.Contains(supportedVersions, sessionVersion))
+                {
+                    legacy_session_id = TlsUtilities.EmptyBytes;
+                }
+            }
+
+            client.NotifySessionToResume(legacy_session_id.Length < 1 ? null : state.tlsSession);
 
-            ProtocolVersion legacy_version = client_version;
-            if (client_version.IsLaterVersionOf(ProtocolVersion.DTLSv12))
+            ProtocolVersion legacy_version = latestVersion;
+            if (offeringDtlsV13Plus)
             {
                 legacy_version = ProtocolVersion.DTLSv12;
 
-                TlsExtensionsUtilities.AddSupportedVersionsExtensionClient(state.clientExtensions,
-                    clientContext.ClientSupportedVersions);
+                TlsExtensionsUtilities.AddSupportedVersionsExtensionClient(state.clientExtensions, supportedVersions);
+
+                /*
+                 * RFC 9147 5. DTLS implementations do not use the TLS 1.3 "compatibility mode" [..].
+                 */
             }
 
             clientContext.SetRsaPreMasterSecretVersion(legacy_version);
@@ -460,7 +476,7 @@ namespace Org.BouncyCastle.Tls
             securityParameters.m_clientServerNames = TlsExtensionsUtilities.GetServerNameExtensionClient(
                 state.clientExtensions);
 
-            if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(client_version))
+            if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(latestVersion))
             {
                 TlsUtilities.EstablishClientSigAlgs(securityParameters, state.clientExtensions);
             }
@@ -468,15 +484,21 @@ namespace Org.BouncyCastle.Tls
             securityParameters.m_clientSupportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(
                 state.clientExtensions);
 
+            // TODO[dtls13]
+            //state.clientBinders = TlsUtilities.AddPreSharedKeyToClientHello(clientContext, client,
+            //    state.clientExtensions, state.offeredCipherSuites);
+            state.clientBinders = null;
+
+            // TODO[tls13-psk] Perhaps don't add key_share if external PSK(s) offered and 'psk_dhe_ke' not offered
             state.clientAgreements = TlsUtilities.AddKeyShareToClientHello(clientContext, client,
                 state.clientExtensions);
 
-            if (TlsUtilities.IsExtendedMasterSecretOptional(clientContext.ClientSupportedVersions)
+            if (TlsUtilities.IsExtendedMasterSecretOptional(supportedVersions)
                 && client.ShouldUseExtendedMasterSecret())
             {
                 TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.clientExtensions);
             }
-            else if (!TlsUtilities.IsTlsV13(client_version)
+            else if (!offeringDtlsV13Plus
                 && client.RequiresExtendedMasterSecret())
             {
                 throw new TlsFatalAlert(AlertDescription.internal_error);
@@ -527,9 +549,16 @@ namespace Org.BouncyCastle.Tls
 
 
 
-            ClientHello clientHello = new ClientHello(legacy_version, securityParameters.ClientRandom, session_id,
-                cookie: TlsUtilities.EmptyBytes, state.offeredCipherSuites, state.clientExtensions, 0);
+            int bindersSize = null == state.clientBinders ? 0 : state.clientBinders.m_bindersSize;
+
+            ClientHello clientHello = new ClientHello(legacy_version, securityParameters.ClientRandom,
+                legacy_session_id, cookie: TlsUtilities.EmptyBytes, state.offeredCipherSuites, state.clientExtensions,
+                bindersSize);
 
+            /*
+             * TODO[dtls13] See TlsClientProtocol.SendClientHelloMessage for how to prepare/encode binders and also
+             * consider the impact of binders on cookie patching after HelloVerifyRequest.
+             */
             MemoryStream buf = new MemoryStream();
             clientHello.Encode(clientContext, buf);
             return buf.ToArray();
@@ -653,18 +682,52 @@ namespace Org.BouncyCastle.Tls
             TlsClientContextImpl clientContext = state.clientContext;
             SecurityParameters securityParameters = clientContext.SecurityParameters;
 
-
             MemoryStream buf = new MemoryStream(body, false);
-
             ServerHello serverHello = ServerHello.Parse(buf);
-            ProtocolVersion server_version = serverHello.Version;
 
             state.serverExtensions = serverHello.Extensions;
 
+            ProtocolVersion legacy_version = serverHello.Version;
+            ProtocolVersion supported_version = TlsExtensionsUtilities.GetSupportedVersionsExtensionServer(
+                state.serverExtensions);
 
-            // TODO[dtls13] Check supported_version extension for negotiated version
+            ProtocolVersion server_version;
+            if (null == supported_version)
+            {
+                server_version = legacy_version;
+            }
+            else
+            {
+                if (!ProtocolVersion.DTLSv12.Equals(legacy_version) ||
+                    !ProtocolVersion.DTLSv13.IsEqualOrEarlierVersionOf(supported_version))
+                {
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+
+                server_version = supported_version;
+            }
+
+            // NOT renegotiating
+            {
+                ReportServerVersion(state, server_version);
+            }
 
-            ReportServerVersion(state, server_version);
+            // NOTE: This is integrated into ReportServerVersion call above
+            //TlsUtilities.NegotiatedVersionDtlsClient(clientContext, state.client);
+
+            // TODO[dtls13]
+            //if (ProtocolVersion.DTLSv13.IsEqualOrEarlierVersionOf(server_version))
+            //{
+            //    Process13ServerHello(serverHello, false);
+            //    return;
+            //}
+
+            int[] offeredCipherSuites = state.offeredCipherSuites;
+
+            // TODO[dtls13]
+            //state.clientHello = null;
+            //state.retryCookie = null;
+            //state.retryGroup = -1;
 
             securityParameters.m_serverRandom = serverHello.Random;
 
@@ -679,6 +742,16 @@ namespace Org.BouncyCastle.Tls
                 client.NotifySessionID(selectedSessionID);
                 securityParameters.m_resumedSession = selectedSessionID.Length > 0 && state.tlsSession != null
                     && Arrays.AreEqual(selectedSessionID, state.tlsSession.SessionID);
+
+                if (securityParameters.IsResumedSession)
+                {
+                    if (serverHello.CipherSuite != state.sessionParameters.CipherSuite ||
+                        !securityParameters.NegotiatedVersion.Equals(state.sessionParameters.NegotiatedVersion))
+                    {
+                        throw new TlsFatalAlert(AlertDescription.illegal_parameter,
+                            "ServerHello parameters do not match resumed session");
+                    }
+                }
             }
 
             /*
@@ -689,10 +762,11 @@ namespace Org.BouncyCastle.Tls
                 int cipherSuite = ValidateSelectedCipherSuite(serverHello.CipherSuite,
                     AlertDescription.illegal_parameter);
 
-                if (!TlsUtilities.IsValidCipherSuiteSelection(state.offeredCipherSuites, cipherSuite) ||
+                if (!TlsUtilities.IsValidCipherSuiteSelection(offeredCipherSuites, cipherSuite) ||
                     !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, securityParameters.NegotiatedVersion))
                 {
-                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter,
+                        "ServerHello selected invalid cipher suite");
                 }
 
                 TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite);
@@ -866,8 +940,6 @@ namespace Org.BouncyCastle.Tls
                 }
             }
 
-
-
             var sessionClientExtensions = state.clientExtensions;
             var sessionServerExtensions = state.serverExtensions;
 
@@ -965,6 +1037,12 @@ namespace Org.BouncyCastle.Tls
             if (!ProtocolVersion.Contains(clientContext.ClientSupportedVersions, server_version))
                 throw new TlsFatalAlert(AlertDescription.protocol_version);
 
+            // TODO[dtls13] Read draft/RFC for guidance on the legacy_record_version field
+            //ProtocolVersion legacy_record_version = server_version.IsLaterVersionOf(ProtocolVersion.DTLSv12)
+            //    ?   ProtocolVersion.DTLSv12
+            //    :   server_version;
+
+            //recordLayer.SetWriteVersion(legacy_record_version);
             securityParameters.m_negotiatedVersion = server_version;
 
             TlsUtilities.NegotiatedVersionDtlsClient(clientContext, state.client);
@@ -1003,6 +1081,7 @@ namespace Org.BouncyCastle.Tls
             internal IDictionary<int, byte[]> serverExtensions = null;
             internal bool expectSessionTicket = false;
             internal IDictionary<int, TlsAgreement> clientAgreements = null;
+            internal OfferedPsks.BindersConfig clientBinders = null;
             internal TlsKeyExchange keyExchange = null;
             internal TlsAuthentication authentication = null;
             internal CertificateStatus certificateStatus = null;
diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs
index 731638467..b117a4025 100644
--- a/crypto/src/tls/TlsClientProtocol.cs
+++ b/crypto/src/tls/TlsClientProtocol.cs
@@ -1686,10 +1686,6 @@ namespace Org.BouncyCastle.Tls
 
             EstablishSession(sessionToResume);
 
-            /*
-             * TODO RFC 5077 3.4. When presenting a ticket, the client MAY generate and include a
-             * Session ID in the TLS ClientHello.
-             */
             byte[] legacy_session_id = TlsUtilities.GetSessionID(m_tlsSession);
 
             if (legacy_session_id.Length > 0)
diff --git a/crypto/src/tls/TlsProtocol.cs b/crypto/src/tls/TlsProtocol.cs
index 9b8039a5e..773412973 100644
--- a/crypto/src/tls/TlsProtocol.cs
+++ b/crypto/src/tls/TlsProtocol.cs
@@ -1470,8 +1470,8 @@ namespace Org.BouncyCastle.Tls
                     return false;
             }
 
-            TlsSecret sessionMasterSecret = TlsUtilities.GetSessionMasterSecret(Context.Crypto,
-                sessionParameters.MasterSecret);
+            TlsCrypto crypto = Context.Crypto;
+            TlsSecret sessionMasterSecret = TlsUtilities.GetSessionMasterSecret(crypto, sessionParameters.MasterSecret);
             if (null == sessionMasterSecret)
                 return false;