summary refs log tree commit diff
path: root/crypto/test/src/tls/test/ServerHandshakeDropper.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/test/src/tls/test/ServerHandshakeDropper.cs')
-rw-r--r--crypto/test/src/tls/test/ServerHandshakeDropper.cs63
1 files changed, 63 insertions, 0 deletions
diff --git a/crypto/test/src/tls/test/ServerHandshakeDropper.cs b/crypto/test/src/tls/test/ServerHandshakeDropper.cs
new file mode 100644
index 000000000..89c752333
--- /dev/null
+++ b/crypto/test/src/tls/test/ServerHandshakeDropper.cs
@@ -0,0 +1,63 @@
+using System;
+
+namespace Org.BouncyCastle.Tls.Tests
+{
+    /** This is a [Transport] wrapper which causes the first retransmission of the second flight of a server
+     * handshake to be dropped. */
+    public class ServerHandshakeDropper
+        : FilteredDatagramTransport
+    {
+        private static FilterPredicate Choose(bool condition, FilterPredicate left, FilterPredicate right)
+        {
+            if (condition) { return left; } else { return right; }
+        }
+
+        public ServerHandshakeDropper(DatagramTransport transport, bool dropOnReceive)
+            : base(transport,
+                Choose(dropOnReceive, new DropFirstServerFinalFlight().AllowPacket, AlwaysAllow),
+                Choose(dropOnReceive, AlwaysAllow, new DropFirstServerFinalFlight().AllowPacket))
+        {
+        }
+
+        /** This drops the first instance of DTLS packets that either begin with a ChangeCipherSpec, or handshake in
+         * epoch 1.  This is the server's final flight of the handshake.  It will test whether the client properly
+         * retransmits its second flight, and the server properly retransmits the dropped flight.
+         */
+        private class DropFirstServerFinalFlight
+        {
+            private bool m_sawChangeCipherSpec = false;
+            private bool m_sawEpoch1Handshake = false;
+
+            private bool IsChangeCipherSpec(byte[] buf, int off, int len)
+            {
+                short contentType = TlsUtilities.ReadUint8(buf, off);
+                return ContentType.change_cipher_spec == contentType;
+            }
+
+            private bool IsEpoch1Handshake(byte[] buf, int off, int len)
+            {
+                short contentType = TlsUtilities.ReadUint8(buf, off);
+                if (ContentType.handshake != contentType)
+                    return false;
+
+                int epoch = TlsUtilities.ReadUint16(buf, off + 3);
+                return 1 == epoch;
+            }
+
+            public bool AllowPacket(byte[] buf, int off, int len)
+            {
+                if (!m_sawChangeCipherSpec && IsChangeCipherSpec(buf, off, len))
+                {
+                    m_sawChangeCipherSpec = true;
+                    return false;
+                }
+                if (!m_sawEpoch1Handshake && IsEpoch1Handshake(buf, off, len))
+                {
+                    m_sawEpoch1Handshake = true;
+                    return false;
+                }
+                return true;
+            }
+        }
+    }
+}