summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2016-03-25 15:10:12 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2016-03-25 15:10:12 +0700
commit22467cd66eea50f418f6398910def1f3b84db404 (patch)
treefee9fc4c1f9231a83ce4cf9a3a65282813d4cfb2
parentPrefer high bits for powers-of-two (diff)
downloadBouncyCastle.NET-ed25519-22467cd66eea50f418f6398910def1f3b84db404.tar.xz
Put zero-length extensions first in the ClientHello
-rw-r--r--crypto/src/crypto/tls/TlsProtocol.cs28
1 files changed, 20 insertions, 8 deletions
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index df1c50f02..6e3bbbbdf 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -1086,20 +1086,32 @@ namespace Org.BouncyCastle.Crypto.Tls
         {
             MemoryStream buf = new MemoryStream();
 
-            foreach (int extension_type in extensions.Keys)
-            {
-                byte[] extension_data = (byte[])extensions[extension_type];
-
-                TlsUtilities.CheckUint16(extension_type);
-                TlsUtilities.WriteUint16(extension_type, buf);
-                TlsUtilities.WriteOpaque16(extension_data, buf);
-            }
+            /*
+             * NOTE: There are reports of servers that don't accept a zero-length extension as the last
+             * one, so we write out any zero-length ones first as a best-effort workaround.
+             */
+            WriteSelectedExtensions(buf, extensions, true);
+            WriteSelectedExtensions(buf, extensions, false);
 
             byte[] extBytes = buf.ToArray();
 
             TlsUtilities.WriteOpaque16(extBytes, output);
         }
 
+        protected internal static void WriteSelectedExtensions(Stream output, IDictionary extensions, bool selectEmpty)
+        {
+            foreach (int extension_type in extensions.Keys)
+            {
+                byte[] extension_data = (byte[])extensions[extension_type];
+                if (selectEmpty == (extension_data.Length == 0))
+                {
+                    TlsUtilities.CheckUint16(extension_type);
+                    TlsUtilities.WriteUint16(extension_type, output);
+                    TlsUtilities.WriteOpaque16(extension_data, output);
+                }
+            }
+        }
+
         protected internal static void WriteSupplementalData(Stream output, IList supplementalData)
         {
             MemoryStream buf = new MemoryStream();