/// <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); } }
/// <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)); }
/// <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; } }
/// <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; } }
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); }
/// <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; }
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; }
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)); }
/// <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); } } }
/// <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);
/// <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);
/// <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; }
/// <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); }