summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-07-27 23:13:49 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-07-27 23:13:49 +0700
commit739bef8b6390a8b75f9a6f9909ee325da5e878cc (patch)
tree1c4b691cb53f97ad9f2d0b5b590eae9cf85d843b
parentSeal handshake hash externally (diff)
downloadBouncyCastle.NET-ed25519-739bef8b6390a8b75f9a6f9909ee325da5e878cc.tar.xz
Filter PSK set for ClientHello retry
-rw-r--r--crypto/src/tls/AbstractTlsClient.cs4
-rw-r--r--crypto/src/tls/TlsClient.cs2
-rw-r--r--crypto/src/tls/TlsClientProtocol.cs35
-rw-r--r--crypto/src/tls/TlsUtilities.cs77
4 files changed, 91 insertions, 27 deletions
diff --git a/crypto/src/tls/AbstractTlsClient.cs b/crypto/src/tls/AbstractTlsClient.cs
index 8d9d9de3d..fc62765c8 100644
--- a/crypto/src/tls/AbstractTlsClient.cs
+++ b/crypto/src/tls/AbstractTlsClient.cs
@@ -373,6 +373,10 @@ namespace Org.BouncyCastle.Tls
         {
         }
 
+        public virtual void NotifySelectedPsk(TlsPsk selectedPsk)
+        {
+        }
+
         /// <exception cref="IOException"/>
         public virtual void ProcessServerExtensions(IDictionary serverExtensions)
         {
diff --git a/crypto/src/tls/TlsClient.cs b/crypto/src/tls/TlsClient.cs
index a9356aa4b..ef4586574 100644
--- a/crypto/src/tls/TlsClient.cs
+++ b/crypto/src/tls/TlsClient.cs
@@ -61,6 +61,8 @@ namespace Org.BouncyCastle.Tls
 
         void NotifySelectedCipherSuite(int selectedCipherSuite);
 
+        void NotifySelectedPsk(TlsPsk selectedPsk);
+
         /// <summary>The protocol implementation validates that any server extensions received correspond to client
         /// extensions sent.</summary>
         /// <remarks>
diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs
index daa5664b0..870a898f8 100644
--- a/crypto/src/tls/TlsClientProtocol.cs
+++ b/crypto/src/tls/TlsClientProtocol.cs
@@ -840,8 +840,9 @@ namespace Org.BouncyCastle.Tls
             {
                 if (!Arrays.Contains(m_clientBinders.m_pskKeyExchangeModes, PskKeyExchangeMode.psk_dhe_ke))
                 {
-                    // TODO[tls13-psk] Notify client that no PSK was selected.
                     this.m_clientBinders = null;
+
+                    m_tlsClient.NotifySelectedPsk(null);
                 }
             }
 
@@ -1511,8 +1512,7 @@ namespace Org.BouncyCastle.Tls
             clientHelloExtensions.Remove(ExtensionType.cookie);
             clientHelloExtensions.Remove(ExtensionType.early_data);
             clientHelloExtensions.Remove(ExtensionType.key_share);
-            // TODO[tls13-psk]
-            //clientHelloExtensions.Remove(ExtensionType.pre_shared_key);
+            clientHelloExtensions.Remove(ExtensionType.pre_shared_key);
 
             /*
              * RFC 4.2.2. When sending the new ClientHello, the client MUST copy the contents of the
@@ -1529,6 +1529,21 @@ namespace Org.BouncyCastle.Tls
             }
 
             /*
+             * - Updating the "pre_shared_key" extension if present by recomputing the "obfuscated_ticket_age"
+             * and binder values and (optionally) removing any PSKs which are incompatible with the server's
+             * indicated cipher suite.
+             */
+            if (null != m_clientBinders)
+            {
+                this.m_clientBinders = TlsUtilities.AddPreSharedKeyToClientHelloRetry(m_tlsClientContext,
+                    m_clientBinders, clientHelloExtensions);
+                if (null == m_clientBinders)
+                {
+                    m_tlsClient.NotifySelectedPsk(null);
+                }
+            }
+
+            /*
              * RFC 8446 4.2.8. [..] when sending the new ClientHello, the client MUST replace the
              * original "key_share" extension with one containing only a new KeyShareEntry for the group
              * indicated in the selected_group field of the triggering HelloRetryRequest.
@@ -1544,18 +1559,6 @@ namespace Org.BouncyCastle.Tls
                 clientHelloExtensions, m_retryGroup);
 
             /*
-             * - Updating the "pre_shared_key" extension if present by recomputing the "obfuscated_ticket_age"
-             * and binder values and (optionally) removing any PSKs which are incompatible with the server's
-             * indicated cipher suite.
-             */
-            if (null != m_clientBinders)
-            {
-                // TODO[tls13-psk]
-                //this.m_clientBinders = TlsUtilities.AddPreSharedKeyToClientHelloRetry(m_tlsClientContext,
-                //    m_clientBinders, clientHelloExtensions);
-            }
-
-            /*
              * TODO[tls13] Optionally adding, removing, or changing the length of the "padding"
              * extension [RFC7685].
              */
@@ -1748,7 +1751,7 @@ namespace Org.BouncyCastle.Tls
 
             if (null != m_clientBinders)
             {
-                OfferedPsks.EncodeBinders(message, Context.Crypto, m_handshakeHash, m_clientBinders);
+                OfferedPsks.EncodeBinders(message, m_tlsClientContext.Crypto, m_handshakeHash, m_clientBinders);
             }
 
             message.SendClientHello(this, m_handshakeHash, m_clientHello.BindersSize);
diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs
index 7f529d8c5..9dea576f5 100644
--- a/crypto/src/tls/TlsUtilities.cs
+++ b/crypto/src/tls/TlsUtilities.cs
@@ -5434,6 +5434,21 @@ namespace Org.BouncyCastle.Tls
 #endif
 
         /// <exception cref="IOException"/>
+        internal static void AddPreSharedKeyToClientExtensions(TlsPsk[] psks, IDictionary clientExtensions)
+        {
+            IList identities = Platform.CreateArrayList(psks.Length);
+            for (int i = 0; i < psks.Length; ++i)
+            {
+                TlsPsk psk = psks[i];
+
+                // TODO[tls13-psk] Handle obfuscated_ticket_age for resumption PSKs
+                identities.Add(new PskIdentity(psk.Identity, 0L));
+            }
+
+            TlsExtensionsUtilities.AddPreSharedKeyClientHello(clientExtensions, new OfferedPsks(identities));
+        }
+
+        /// <exception cref="IOException"/>
         internal static OfferedPsks.BindersConfig AddPreSharedKeyToClientHello(TlsClientContext clientContext,
             TlsClient client, IDictionary clientExtensions, int[] offeredCipherSuites)
         {
@@ -5449,25 +5464,52 @@ namespace Org.BouncyCastle.Tls
                 throw new TlsFatalAlert(AlertDescription.internal_error,
                     "External PSKs configured but no PskKeyExchangeMode available");
 
-            // Add the pre_shared_key extension
+            TlsSecret[] pskEarlySecrets = GetPskEarlySecrets(clientContext.Crypto, pskExternals);
+
+            int bindersSize = OfferedPsks.GetBindersSize(pskExternals);
+
+            AddPreSharedKeyToClientExtensions(pskExternals, clientExtensions);
+
+            return new OfferedPsks.BindersConfig(pskExternals, pskKeyExchangeModes, pskEarlySecrets, bindersSize);
+        }
+
+        /// <exception cref="IOException"/>
+        internal static OfferedPsks.BindersConfig AddPreSharedKeyToClientHelloRetry(TlsClientContext clientContext,
+            OfferedPsks.BindersConfig clientBinders, IDictionary clientExtensions)
+        {
+            SecurityParameters securityParameters = clientContext.SecurityParameters;
+
+            int prfAlgorithm = GetPrfAlgorithm13(securityParameters.CipherSuite);
+
+            IList pskIndices = GetPskIndices(clientBinders.m_psks, prfAlgorithm);
+            if (pskIndices.Count < 1)
+                return null;
+
+            OfferedPsks.BindersConfig result = clientBinders;
+
+            int count = pskIndices.Count;
+            if (count < clientBinders.m_psks.Length)
             {
-                IList identities = Platform.CreateArrayList(pskExternals.Length);
-                for (int i = 0; i < pskExternals.Length; ++i)
+                TlsPsk[] psks = new TlsPsk[count];
+                TlsSecret[] earlySecrets = new TlsSecret[count];
+
+                for (int i = 0; i < count; ++i)
                 {
-                    TlsPskExternal pskExternal = pskExternals[i];
+                    int j = (int)pskIndices[i];
 
-                    // TODO[tls13-psk] Handle obfuscated_ticket_age for resumption PSKs
-                    identities.Add(new PskIdentity(pskExternal.Identity, 0L));
+                    psks[i] = clientBinders.m_psks[j];
+                    earlySecrets[i] = clientBinders.m_earlySecrets[j];
                 }
 
-                TlsExtensionsUtilities.AddPreSharedKeyClientHello(clientExtensions, new OfferedPsks(identities));
+                int bindersSize = OfferedPsks.GetBindersSize(psks);
+
+                result = new OfferedPsks.BindersConfig(psks, clientBinders.m_pskKeyExchangeModes, earlySecrets,
+                    bindersSize);
             }
 
-            TlsSecret[] pskEarlySecrets = GetPskEarlySecrets(clientContext.Crypto, pskExternals);
+            AddPreSharedKeyToClientExtensions(result.m_psks, clientExtensions);
 
-            int bindersSize = OfferedPsks.GetBindersSize(pskExternals);
-
-            return new OfferedPsks.BindersConfig(pskExternals, pskKeyExchangeModes, pskEarlySecrets, bindersSize);
+            return result;
         }
 
         internal static TlsSecret GetPskEarlySecret(TlsCrypto crypto, TlsPsk psk)
@@ -5518,5 +5560,18 @@ namespace Org.BouncyCastle.Tls
 
             return result;
         }
+
+        internal static IList GetPskIndices(TlsPsk[] psks, int prfAlgorithm)
+        {
+            IList v = Platform.CreateArrayList(psks.Length);
+            for (int i = 0; i < psks.Length; ++i)
+            {
+                if (psks[i].PrfAlgorithm == prfAlgorithm)
+                {
+                    v.Add(i);
+                }
+            }
+            return v;
+        }
     }
 }