예제 #1
0
        /// <summary>
        /// Sends the Client Key Exchange message flight.
        /// </summary>
        /// <param name="Endpoint">Endpoint.</param>
        /// <param name="State">Endpoint state.</param>
        public override void SendClientKeyExchange(DtlsEndpoint Endpoint, EndpointState State)
        {
            this.CalcMasterSecret(State);

            // Sends the Client Key Exchange message for Pre-shared key ciphers,
            // as defined in §2 of RFC 4279: https://tools.ietf.org/html/rfc4279

            if (State.credentials is PresharedKey Psk)
            {
                ushort N = (ushort)Psk.Identity.Length;
                byte[] ClientKeyExchange = new byte[2 + N];

                ClientKeyExchange[0] = (byte)(N >> 8);
                ClientKeyExchange[1] = (byte)N;

                Array.Copy(Psk.Identity, 0, ClientKeyExchange, 2, N);

                Endpoint.SendHandshake(HandshakeType.client_key_exchange, ClientKeyExchange, true, true, State);

                // RFC 5246, §7.1, Change Cipher Spec Protocol:

                Endpoint.SendRecord(ContentType.change_cipher_spec, new byte[] { 1 }, true, true, State);
                Endpoint.ChangeCipherSpec(State, true);

                this.SendFinished(Endpoint, State, true);
            }
        }
예제 #2
0
        /// <summary>
        /// Verifies the claims in a finished message.
        /// </summary>
        /// <param name="VerifyData">Verify data in finished message.</param>
        /// <param name="State">Endpoint state.</param>
        /// <returns>If the <paramref name="VerifyData"/> is valid or not.</returns>
        public virtual bool VerifyFinished(byte[] VerifyData, EndpointState State)
        {
            if (State.masterSecret == null)
            {
                return(false);
            }

            string Label;

            byte[] HandshakeHash;
            byte[] VerifyData0;

            if (State.isClient)
            {
                Label = "server finished";
                State.CalcServerHandshakeHash();
                HandshakeHash = State.serverHandshakeHash;
            }
            else
            {
                Label = "client finished";
                State.CalcClientHandshakeHash();
                HandshakeHash = State.clientHandshakeHash;
            }

            VerifyData0 = this.PRF(State.masterSecret, Label, HandshakeHash, 12);

            return(DtlsEndpoint.AreEqual(VerifyData0, VerifyData));
        }
예제 #3
0
        /// <summary>
        /// <see cref="IDisposable.Dispose"/>
        /// </summary>
        public void Dispose()
        {
            if (this.dtls != null)
            {
                this.dtls.Dispose();
                this.dtls = null;
            }

            if (this.udp != null)
            {
                this.udp.Dispose();
                this.udp = null;
            }
        }
예제 #4
0
        /// <summary>
        /// <see cref="IDisposable.Dispose"/>
        /// </summary>
        public void Dispose()
        {
            if (!(this.dtls is null))
            {
                this.dtls.Dispose();
                this.dtls = null;
            }

            if (!(this.udp is null))
            {
                this.udp.Dispose();
                this.udp = null;
            }
        }
예제 #5
0
        public void TestInitialize()
        {
            this.sniffer = new TextWriterSniffer(Console.Out, BinaryPresentationMethod.Hexadecimal);
            this.users   = new Users(new User("testid", "01020304", "HEX"));

            this.toServer = new DtlsBridge(null);
            this.toClient = new DtlsBridge(null);

            this.toServer.RemoteBridge = toClient;
            this.toClient.RemoteBridge = toServer;

            this.client = new DtlsEndpoint(DtlsMode.Client, toServer, this.sniffer);
            this.server = new DtlsEndpoint(DtlsMode.Server, toClient, this.users);
        }
예제 #6
0
        /// <summary>
        /// Class managing DTLS over UDP.
        /// </summary>
        /// <param name="UdpClient">UDP connection.</param>
        /// <param name="Mode">DTLS mode.</param>
        /// <param name="Users">User data source, if pre-shared keys should be allowed by a DTLS server endpoint.</param>
        /// <param name="RequiredPrivilege">Required privilege, for the user to be acceptable
        /// in PSK handshakes.</param>
        /// <param name="Sniffers">Sniffers.</param>
        public DtlsOverUdp(UdpClient UdpClient, DtlsMode Mode, IUserSource Users,
                           string RequiredPrivilege, params ISniffer[] Sniffers)
        {
            this.udp  = new UdpCommunicationLayer(UdpClient);
            this.dtls = new DtlsEndpoint(Mode, this.udp, Users, RequiredPrivilege, Sniffers);

            this.dtlsStates                       = new Cache <IPEndPoint, DtlsOverUdpState>(int.MaxValue, TimeSpan.MaxValue, new TimeSpan(1, 0, 0));
            this.dtlsStates.Removed              += DtlsStates_Removed;
            this.dtls.OnApplicationDataReceived  += Dtls_OnApplicationDataReceived;
            this.dtls.OnHandshakeFailed          += Dtls_OnHandshakeFailed;
            this.dtls.OnHandshakeSuccessful      += Dtls_OnHandshakeSuccessful;
            this.dtls.OnSessionFailed            += Dtls_OnSessionFailed;
            this.dtls.OnIncomingHandshakeStarted += Dtls_OnIncomingHandshakeStarted;
            this.dtls.OnStateChanged             += Dtls_OnStateChanged;
        }
예제 #7
0
        public void TestCleanup()
        {
            if (this.client != null)
            {
                this.client.Dispose();
                this.client = null;
            }

            if (this.server != null)
            {
                this.server.Dispose();
                this.server = null;
            }

            this.toServer = null;
            this.toClient = null;
            this.users    = null;
            this.sniffer  = null;
        }
예제 #8
0
        public void Test_03_GracefulShutdown()
        {
            ManualResetEvent Done1  = new ManualResetEvent(false);
            ManualResetEvent Error1 = new ManualResetEvent(false);
            ManualResetEvent Done2  = new ManualResetEvent(false);
            ManualResetEvent Error2 = new ManualResetEvent(false);

            this.Test_02_ApplicationData();

            this.client.OnStateChanged += (sender, e) =>
            {
                if (e.State == DtlsState.Closed)
                {
                    Done1.Set();
                }
                else
                {
                    Error1.Set();
                }
            };

            this.server.OnStateChanged += (sender, e) =>
            {
                if (e.State == DtlsState.Closed)
                {
                    Done2.Set();
                }
                else
                {
                    Error2.Set();
                }
            };

            this.client.Dispose();
            this.client = null;

            Assert.AreEqual(0, WaitHandle.WaitAny(new WaitHandle[] { Done1, Error1 }, 60000));
            Assert.AreEqual(0, WaitHandle.WaitAny(new WaitHandle[] { Done2, Error2 }, 60000));
        }
예제 #9
0
        /// <summary>
        /// Finishes the handshake.
        /// </summary>
        /// <param name="Endpoint">Endpoint.</param>
        /// <param name="State">Endpoint state.</param>
        /// <param name="Resendable">If flight of records is resendable.</param>
        public virtual void SendFinished(DtlsEndpoint Endpoint, EndpointState State, bool Resendable)
        {
            if (State.masterSecret == null)
            {
                Endpoint.SendAlert(AlertLevel.fatal, AlertDescription.handshake_failure, State);
            }
            else
            {
                string Label;
                byte[] HandshakeHash;
                byte[] VerifyData;

                if (State.isClient)
                {
                    State.clientFinished = true;
                    Label = "client finished";
                    State.CalcClientHandshakeHash();
                    HandshakeHash = State.clientHandshakeHash;
                }
                else
                {
                    State.serverFinished = true;
                    Label = "server finished";
                    State.CalcServerHandshakeHash();
                    HandshakeHash = State.serverHandshakeHash;
                }

                VerifyData = this.PRF(State.masterSecret, Label, HandshakeHash, 12);

                Endpoint.SendHandshake(HandshakeType.finished, VerifyData, false, Resendable, State);

                if (State.clientFinished && State.serverFinished)
                {
                    Endpoint.HandshakeSuccess(State);
                }
            }
        }
예제 #10
0
 /// <summary>
 /// Sends the Server Key Exchange message flight.
 /// </summary>
 /// <param name="Endpoint">Endpoint.</param>
 /// <param name="State">Endpoint state.</param>
 public abstract void SendServerKeyExchange(DtlsEndpoint Endpoint, EndpointState State);
예제 #11
0
 /// <summary>
 /// Sends the Client Key Exchange message flight.
 /// </summary>
 /// <param name="Endpoint">Endpoint.</param>
 /// <param name="State">Endpoint state.</param>
 public abstract void SendClientKeyExchange(DtlsEndpoint Endpoint, EndpointState State);
예제 #12
0
 /// <summary>
 /// Maintains the communication state for a remote endpoint.
 /// </summary>
 /// <param name="LocalEndpoint">Local endpoint.</param>
 /// <param name="RemoteEndpoint">Remote endpoint.</param>
 public EndpointState(DtlsEndpoint LocalEndpoint, object RemoteEndpoint)
 {
     this.localEndpoint  = LocalEndpoint;
     this.remoteEndpoint = RemoteEndpoint;
 }
예제 #13
0
 /// <summary>
 /// Sends the Server Key Exchange message flight.
 /// </summary>
 /// <param name="Endpoint">Endpoint.</param>
 /// <param name="State">Endpoint state.</param>
 public override void SendServerKeyExchange(DtlsEndpoint Endpoint, EndpointState State)
 {
     Endpoint.SendHandshake(HandshakeType.server_hello_done, new byte[0], false, true, State);
 }