summary refs log tree commit diff
path: root/crypto/src/tls/DtlsVerifier.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/tls/DtlsVerifier.cs')
-rw-r--r--crypto/src/tls/DtlsVerifier.cs89
1 files changed, 89 insertions, 0 deletions
diff --git a/crypto/src/tls/DtlsVerifier.cs b/crypto/src/tls/DtlsVerifier.cs
new file mode 100644
index 000000000..edadeae70
--- /dev/null
+++ b/crypto/src/tls/DtlsVerifier.cs
@@ -0,0 +1,89 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Tls.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Tls
+{
+    public class DtlsVerifier
+    {
+        private static TlsMac CreateCookieMac(TlsCrypto crypto)
+        {
+            TlsMac mac = crypto.CreateHmac(MacAlgorithm.hmac_sha256);
+
+            byte[] secret = new byte[mac.MacLength];
+            crypto.SecureRandom.NextBytes(secret);
+
+            mac.SetKey(secret, 0, secret.Length);
+
+            return mac;
+        }
+
+        private readonly TlsMac m_cookieMac;
+        private readonly TlsMacSink m_cookieMacSink;
+
+        public DtlsVerifier(TlsCrypto crypto)
+        {
+            this.m_cookieMac = CreateCookieMac(crypto);
+            this.m_cookieMacSink = new TlsMacSink(m_cookieMac);
+        }
+
+        public virtual DtlsRequest VerifyRequest(byte[] clientID, byte[] data, int dataOff, int dataLen,
+            DatagramSender sender)
+        {
+            lock (this)
+            {
+                bool resetCookieMac = true;
+
+                try
+                {
+                    m_cookieMac.Update(clientID, 0, clientID.Length);
+
+                    DtlsRequest request = DtlsReliableHandshake.ReadClientRequest(data, dataOff, dataLen,
+                        m_cookieMacSink);
+                    if (null != request)
+                    {
+                        byte[] expectedCookie = m_cookieMac.CalculateMac();
+                        resetCookieMac = false;
+
+                        // TODO Consider stricter HelloVerifyRequest protocol
+                        //switch (request.MessageSeq)
+                        //{
+                        //case 0:
+                        //{
+                        //    DtlsReliableHandshake.SendHelloVerifyRequest(sender, request.RecordSeq, expectedCookie);
+                        //    break;
+                        //}
+                        //case 1:
+                        //{
+                        //    if (Arrays.ConstantTimeAreEqual(expectedCookie, request.ClientHello.Cookie))
+                        //        return request;
+
+                        //    break;
+                        //}
+                        //}
+
+                        if (Arrays.ConstantTimeAreEqual(expectedCookie, request.ClientHello.Cookie))
+                            return request;
+
+                        DtlsReliableHandshake.SendHelloVerifyRequest(sender, request.RecordSeq, expectedCookie);
+                    }
+                }
+                catch (IOException)
+                {
+                    // Ignore
+                }
+                finally
+                {
+                    if (resetCookieMac)
+                    {
+                        m_cookieMac.Reset();
+                    }
+                }
+
+                return null;
+            }
+        }
+    }
+}