private DTLSRecord CreateRecord(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence) { int size = handshakeMessage.CalculateSize(session.Version); DTLSRecord record = new DTLSRecord(); record.RecordType = TRecordType.Handshake; record.Epoch = session.Epoch; record.SequenceNumber = session.NextSequenceNumber(); record.Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size]; if (session.Version != null) { record.Version = session.Version; } HandshakeRecord handshakeRecord = new HandshakeRecord(); handshakeRecord.MessageType = handshakeMessage.MessageType; handshakeRecord.MessageSeq = messageSequence; handshakeRecord.Length = (uint)size; handshakeRecord.FragmentLength = (uint)size; using (MemoryStream stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, session.Version); } if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest) { session.Handshake.UpdateHandshakeHash(record.Fragment); } if (session.Cipher != null) { long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); } return(record); }
private void SendHandshakeMessage(IHandshakeMessage handshakeMessage, bool encrypt) { int size = handshakeMessage.CalculateSize(_Version); int maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD; if (size > maxPayloadSize) { } else { DTLSRecord record = new DTLSRecord { RecordType = TRecordType.Handshake, Epoch = _Epoch, SequenceNumber = NextSequenceNumber(), Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size] }; if (_Version != null) { record.Version = _Version; } HandshakeRecord handshakeRecord = new HandshakeRecord { MessageType = handshakeMessage.MessageType, MessageSeq = _MessageSequence }; _MessageSequence++; handshakeRecord.Length = (uint)size; handshakeRecord.FragmentLength = (uint)size; using (MemoryStream stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, _Version); } if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest) { _HandshakeInfo.UpdateHandshakeHash(record.Fragment); } int responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size; if ((_Cipher != null) && encrypt) { long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = _Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length; } byte[] response = new byte[responseSize]; using (MemoryStream stream = new MemoryStream(response)) { record.Serialise(stream); } SocketAsyncEventArgs parameters = new SocketAsyncEventArgs() { RemoteEndPoint = _ServerEndPoint }; parameters.SetBuffer(response, 0, responseSize); _Socket.SendToAsync(parameters); } }
private void SendResponse(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence) { int size = handshakeMessage.CalculateSize(session.Version); int maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD; if (size > maxPayloadSize) { } else { DTLSRecord record = new DTLSRecord(); record.RecordType = TRecordType.Handshake; record.Epoch = session.Epoch; record.SequenceNumber = session.NextSequenceNumber(); record.Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size]; if (session.Version != null) { record.Version = session.Version; } HandshakeRecord handshakeRecord = new HandshakeRecord(); handshakeRecord.MessageType = handshakeMessage.MessageType; handshakeRecord.MessageSeq = messageSequence; handshakeRecord.Length = (uint)size; handshakeRecord.FragmentLength = (uint)size; using (MemoryStream stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, session.Version); } if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest) { session.Handshake.UpdateHandshakeHash(record.Fragment); } int responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size; if (session.Cipher != null) { long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length; } byte[] response = new byte[responseSize]; using (MemoryStream stream = new MemoryStream(response)) { record.Serialise(stream); } SocketAsyncEventArgs parameters = new SocketAsyncEventArgs() { RemoteEndPoint = session.RemoteEndPoint }; parameters.SetBuffer(response, 0, responseSize); _Socket.SendToAsync(parameters); } }
private DTLSRecord CreateRecord(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence) { if (session == null) { throw new ArgumentNullException(nameof(session)); } if (handshakeMessage == null) { throw new ArgumentNullException(nameof(handshakeMessage)); } var size = handshakeMessage.CalculateSize(session.Version); var record = new DTLSRecord { RecordType = TRecordType.Handshake, Epoch = session.Epoch, SequenceNumber = session.NextSequenceNumber(), Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size] }; if (session.Version != null) { record.Version = session.Version; } var handshakeRecord = new HandshakeRecord { MessageType = handshakeMessage.MessageType, MessageSeq = messageSequence, Length = (uint)size, FragmentLength = (uint)size }; using (var stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, session.Version); } if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest) { session.Handshake.UpdateHandshakeHash(record.Fragment); } if (session.Cipher != null) { var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); } return(record); }
private IEnumerable <byte[]> _GetBytes(IHandshakeMessage handshakeMessage, bool encrypt) { if (handshakeMessage == null) { throw new ArgumentNullException(nameof(handshakeMessage)); } var size = handshakeMessage.CalculateSize(this._Version); var maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD; if (size > maxPayloadSize) { var wholeMessage = new List <byte[]>(); var record = new DTLSRecord { RecordType = TRecordType.Handshake, Epoch = _Epoch, Version = this._Version }; var handshakeRecord = new HandshakeRecord { MessageType = handshakeMessage.MessageType, MessageSeq = _MessageSequence }; if (!(handshakeMessage.MessageType == THandshakeType.HelloVerifyRequest || (handshakeMessage.MessageType == THandshakeType.ClientHello && (handshakeMessage as ClientHello).Cookie == null))) { record.Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size]; handshakeRecord.Length = (uint)size; handshakeRecord.FragmentLength = (uint)size; handshakeRecord.FragmentOffset = 0u; using (var stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, this._Version); } this._HandshakeInfo.UpdateHandshakeHash(record.Fragment); } var dataMessage = new byte[size]; using (var stream = new MemoryStream(dataMessage)) { handshakeMessage.Serialise(stream, this._Version); } var dataMessageFragments = dataMessage.ChunkBySize(maxPayloadSize); handshakeRecord.FragmentOffset = 0U; dataMessageFragments.ForEach(x => { handshakeRecord.Length = (uint)size; handshakeRecord.FragmentLength = (uint)x.Count(); record.SequenceNumber = this._NextSequenceNumber(); var baseMessage = new byte[HandshakeRecord.RECORD_OVERHEAD]; using (var stream = new MemoryStream(baseMessage)) { handshakeRecord.Serialise(stream); } record.Fragment = baseMessage.Concat(x).ToArray(); var responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + x.Count(); if ((this._Cipher != null) && encrypt) { var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = this._Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length; } var response = new byte[responseSize]; using (var stream = new MemoryStream(response)) { record.Serialise(stream); } wholeMessage.Add(response); handshakeRecord.FragmentOffset += (uint)x.Count(); }); this._MessageSequence++; return(wholeMessage); } else { var record = new DTLSRecord { RecordType = TRecordType.Handshake, Epoch = _Epoch, SequenceNumber = this._NextSequenceNumber(), Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size], Version = this._Version }; var handshakeRecord = new HandshakeRecord { MessageType = handshakeMessage.MessageType, MessageSeq = _MessageSequence }; this._MessageSequence++; handshakeRecord.Length = (uint)size; handshakeRecord.FragmentLength = (uint)size; using (var stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, this._Version); } if (!(handshakeMessage.MessageType == THandshakeType.HelloVerifyRequest || (handshakeMessage.MessageType == THandshakeType.ClientHello && (handshakeMessage as ClientHello).Cookie == null))) { this._HandshakeInfo.UpdateHandshakeHash(record.Fragment); } var responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size; if ((this._Cipher != null) && encrypt) { var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = this._Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length; } var response = new byte[responseSize]; using (var stream = new MemoryStream(response)) { record.Serialise(stream); } return(new List <byte[]>() { response }); } }
private async Task _ProcessHandshakeAsync(DTLSRecord record) { if (record == null) { throw new ArgumentNullException(nameof(record)); } var data = record.Fragment; if (this._EncyptedServerEpoch == record.Epoch) { var count = 0; while ((this._Cipher == null) && (count < 500)) { await Task.Delay(10).ConfigureAwait(false); count++; } if (this._Cipher == null) { throw new Exception("Need Cipher for Encrypted Session"); } var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; data = this._Cipher.DecodeCiphertext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); } using (var tempStream = new MemoryStream(data)) { var handshakeRec = HandshakeRecord.Deserialise(tempStream); if (handshakeRec.Length > (handshakeRec.FragmentLength + handshakeRec.FragmentOffset)) { this._IsFragment = true; this._FragmentedRecordList.Add(data); return; } else if (this._IsFragment) { this._FragmentedRecordList.Add(data); data = new byte[0]; foreach (var rec in this._FragmentedRecordList) { data = data.Concat(rec.Skip(HandshakeRecord.RECORD_OVERHEAD)).ToArray(); } var tempHandshakeRec = new HandshakeRecord() { Length = handshakeRec.Length, MessageSeq = handshakeRec.MessageSeq, MessageType = handshakeRec.MessageType, FragmentLength = handshakeRec.Length, FragmentOffset = 0 }; var tempHandshakeBytes = new byte[HandshakeRecord.RECORD_OVERHEAD]; using (var updateStream = new MemoryStream(tempHandshakeBytes)) { tempHandshakeRec.Serialise(updateStream); } data = tempHandshakeBytes.Concat(data).ToArray(); } } using (var stream = new MemoryStream(data)) { var handshakeRecord = HandshakeRecord.Deserialise(stream); switch (handshakeRecord.MessageType) { case THandshakeType.HelloRequest: { break; } case THandshakeType.ClientHello: { break; } case THandshakeType.ServerHello: { var serverHello = ServerHello.Deserialise(stream); this._HandshakeInfo.UpdateHandshakeHash(data); this._ServerEpoch = record.Epoch; this._HandshakeInfo.CipherSuite = (TCipherSuite)serverHello.CipherSuite; this._HandshakeInfo.ServerRandom = serverHello.Random; this._Version = serverHello.ServerVersion <= this._Version ? serverHello.ServerVersion : _SupportedVersion; break; } case THandshakeType.HelloVerifyRequest: { var helloVerifyRequest = HelloVerifyRequest.Deserialise(stream); this._Version = helloVerifyRequest.ServerVersion; await this._SendHelloAsync(helloVerifyRequest.Cookie).ConfigureAwait(false); break; } case THandshakeType.Certificate: { var cert = Certificate.Deserialise(stream, TCertificateType.X509); this._HandshakeInfo.UpdateHandshakeHash(data); this.ServerCertificate = cert.Cert; break; } case THandshakeType.ServerKeyExchange: { this._HandshakeInfo.UpdateHandshakeHash(data); var keyExchangeAlgorithm = CipherSuites.GetKeyExchangeAlgorithm(this._HandshakeInfo.CipherSuite); byte[] preMasterSecret = null; IKeyExchange keyExchange = null; if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.ECDHE_ECDSA) { var serverKeyExchange = ECDHEServerKeyExchange.Deserialise(stream, this._Version); var keyExchangeECDHE = new ECDHEKeyExchange { CipherSuite = this._HandshakeInfo.CipherSuite, Curve = serverKeyExchange.EllipticCurve, KeyExchangeAlgorithm = keyExchangeAlgorithm, ClientRandom = this._HandshakeInfo.ClientRandom, ServerRandom = this._HandshakeInfo.ServerRandom }; keyExchangeECDHE.GenerateEphemeralKey(); var clientKeyExchange = new ECDHEClientKeyExchange(keyExchangeECDHE.PublicKey); this._ClientKeyExchange = clientKeyExchange; preMasterSecret = keyExchangeECDHE.GetPreMasterSecret(serverKeyExchange.PublicKeyBytes); keyExchange = keyExchangeECDHE; } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.ECDHE_PSK) { var serverKeyExchange = ECDHEPSKServerKeyExchange.Deserialise(stream); var keyExchangeECDHE = new ECDHEKeyExchange { CipherSuite = this._HandshakeInfo.CipherSuite, Curve = serverKeyExchange.EllipticCurve, KeyExchangeAlgorithm = keyExchangeAlgorithm, ClientRandom = this._HandshakeInfo.ClientRandom, ServerRandom = this._HandshakeInfo.ServerRandom }; keyExchangeECDHE.GenerateEphemeralKey(); var clientKeyExchange = new ECDHEPSKClientKeyExchange(keyExchangeECDHE.PublicKey); if (serverKeyExchange.PSKIdentityHint != null) { var key = this.PSKIdentities.GetKey(serverKeyExchange.PSKIdentityHint); if (key != null) { this._PSKIdentity = new PSKIdentity() { Identity = serverKeyExchange.PSKIdentityHint, Key = key }; } } if (this._PSKIdentity == null) { this._PSKIdentity = this.PSKIdentities.GetRandom(); } clientKeyExchange.PSKIdentity = this._PSKIdentity.Identity; this._ClientKeyExchange = clientKeyExchange; var otherSecret = keyExchangeECDHE.GetPreMasterSecret(serverKeyExchange.PublicKeyBytes); preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, this._PSKIdentity.Key); keyExchange = keyExchangeECDHE; } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.PSK) { var serverKeyExchange = PSKServerKeyExchange.Deserialise(stream); var clientKeyExchange = new PSKClientKeyExchange(); if (serverKeyExchange.PSKIdentityHint != null) { var key = this.PSKIdentities.GetKey(serverKeyExchange.PSKIdentityHint); if (key != null) { this._PSKIdentity = new PSKIdentity() { Identity = serverKeyExchange.PSKIdentityHint, Key = key }; } } if (this._PSKIdentity == null) { this._PSKIdentity = this.PSKIdentities.GetRandom(); } var otherSecret = new byte[this._PSKIdentity.Key.Length]; clientKeyExchange.PSKIdentity = this._PSKIdentity.Identity; this._ClientKeyExchange = clientKeyExchange; preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, this._PSKIdentity.Key); } this._Cipher = TLSUtils.AssignCipher(preMasterSecret, true, this._Version, this._HandshakeInfo); break; } case THandshakeType.CertificateRequest: { this._HandshakeInfo.UpdateHandshakeHash(data); this._SendCertificate = true; break; } case THandshakeType.ServerHelloDone: { this._HandshakeInfo.UpdateHandshakeHash(data); var keyExchangeAlgorithm = CipherSuites.GetKeyExchangeAlgorithm(this._HandshakeInfo.CipherSuite); if (this._Cipher == null) { if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.PSK) { var clientKeyExchange = new PSKClientKeyExchange(); this._PSKIdentity = this.PSKIdentities.GetRandom(); var otherSecret = new byte[this._PSKIdentity.Key.Length]; clientKeyExchange.PSKIdentity = this._PSKIdentity.Identity; this._ClientKeyExchange = clientKeyExchange; var preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, this._PSKIdentity.Key); this._Cipher = TLSUtils.AssignCipher(preMasterSecret, true, this._Version, this._HandshakeInfo); } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.RSA) { var clientKeyExchange = new RSAClientKeyExchange(); this._ClientKeyExchange = clientKeyExchange; var PreMasterSecret = TLSUtils.GetRsaPreMasterSecret(this._Version); clientKeyExchange.PremasterSecret = TLSUtils.GetEncryptedRsaPreMasterSecret(this.ServerCertificate, PreMasterSecret); this._Cipher = TLSUtils.AssignCipher(PreMasterSecret, true, this._Version, this._HandshakeInfo); } else { throw new NotImplementedException($"Key Exchange Algorithm {keyExchangeAlgorithm} Not Implemented"); } } if (this._SendCertificate) { await this._SendHandshakeMessageAsync(this._Certificate, false).ConfigureAwait(false); } await this._SendHandshakeMessageAsync(this._ClientKeyExchange, false).ConfigureAwait(false); if (this._SendCertificate) { var signatureHashAlgorithm = new SignatureHashAlgorithm() { Signature = TSignatureAlgorithm.ECDSA, Hash = THashAlgorithm.SHA256 }; if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.RSA) { signatureHashAlgorithm = new SignatureHashAlgorithm() { Signature = TSignatureAlgorithm.RSA, Hash = THashAlgorithm.SHA1 }; } var certVerify = new CertificateVerify { SignatureHashAlgorithm = signatureHashAlgorithm, Signature = TLSUtils.Sign(this._PrivateKey, this._PrivateKeyRsa, true, this._Version, this._HandshakeInfo, signatureHashAlgorithm, this._HandshakeInfo.GetHash(this._Version)) }; await this._SendHandshakeMessageAsync(certVerify, false).ConfigureAwait(false); } await this._SendChangeCipherSpecAsync().ConfigureAwait(false); var handshakeHash = this._HandshakeInfo.GetHash(this._Version); var finished = new Finished { VerifyData = TLSUtils.GetVerifyData(this._Version, this._HandshakeInfo, true, true, handshakeHash) }; await this._SendHandshakeMessageAsync(finished, true).ConfigureAwait(false); break; } case THandshakeType.NewSessionTicket: { this._HandshakeInfo.UpdateHandshakeHash(data); break; } case THandshakeType.CertificateVerify: { break; } case THandshakeType.ClientKeyExchange: { break; } case THandshakeType.Finished: { var serverFinished = Finished.Deserialise(stream); var handshakeHash = this._HandshakeInfo.GetHash(this._Version); var calculatedVerifyData = TLSUtils.GetVerifyData(this._Version, this._HandshakeInfo, true, false, handshakeHash); if (serverFinished.VerifyData.SequenceEqual(calculatedVerifyData)) { this._ConnectionComplete = true; } break; } default: { break; } } } this._IsFragment = false; this._FragmentedRecordList.RemoveAll(x => true); }
private DTLSRecord CreateRecord(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence) { int size = handshakeMessage.CalculateSize(session.Version); DTLSRecord record = new DTLSRecord(); record.RecordType = TRecordType.Handshake; record.Epoch = session.Epoch; record.SequenceNumber = session.NextSequenceNumber(); record.Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size]; if (session.Version != null) record.Version = session.Version; HandshakeRecord handshakeRecord = new HandshakeRecord(); handshakeRecord.MessageType = handshakeMessage.MessageType; handshakeRecord.MessageSeq = messageSequence; handshakeRecord.Length = (uint)size; handshakeRecord.FragmentLength = (uint)size; using (MemoryStream stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, session.Version); } if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest) { session.Handshake.UpdateHandshakeHash(record.Fragment); } if (session.Cipher != null) { long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); } return record; }
private void SendResponse(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence) { int size = handshakeMessage.CalculateSize(session.Version); int maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD; if (size > maxPayloadSize) { } else { DTLSRecord record = new DTLSRecord(); record.RecordType = TRecordType.Handshake; record.Epoch = session.Epoch; record.SequenceNumber = session.NextSequenceNumber(); record.Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size]; if (session.Version != null) record.Version = session.Version; HandshakeRecord handshakeRecord = new HandshakeRecord(); handshakeRecord.MessageType = handshakeMessage.MessageType; handshakeRecord.MessageSeq = messageSequence; handshakeRecord.Length = (uint)size; handshakeRecord.FragmentLength = (uint)size; using (MemoryStream stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, session.Version); } if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest) { session.Handshake.UpdateHandshakeHash(record.Fragment); } int responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size; if (session.Cipher != null) { long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length; } byte[] response = new byte[responseSize]; using (MemoryStream stream = new MemoryStream(response)) { record.Serialise(stream); } SocketAsyncEventArgs parameters = new SocketAsyncEventArgs() { RemoteEndPoint = session.RemoteEndPoint }; parameters.SetBuffer(response, 0, responseSize); _Socket.SendToAsync(parameters); } }
private void SendResponse(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence) { if (session == null) { throw new ArgumentNullException(nameof(session)); } if (handshakeMessage == null) { throw new ArgumentNullException(nameof(handshakeMessage)); } var size = handshakeMessage.CalculateSize(session.Version); var maxPayloadSize = this._MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD; if (size > maxPayloadSize) { //fragments return; } var record = new DTLSRecord { RecordType = TRecordType.Handshake, Epoch = session.Epoch, SequenceNumber = session.NextSequenceNumber(), Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size] }; if (session.Version != null) { record.Version = session.Version; } var handshakeRecord = new HandshakeRecord { MessageType = handshakeMessage.MessageType, MessageSeq = messageSequence, Length = (uint)size, FragmentLength = (uint)size }; using (var stream = new MemoryStream(record.Fragment)) { handshakeRecord.Serialise(stream); handshakeMessage.Serialise(stream, session.Version); } if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest) { session.Handshake.UpdateHandshakeHash(record.Fragment); } var responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size; if (session.Cipher != null) { var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length; } var response = new byte[responseSize]; using (var stream = new MemoryStream(response)) { record.Serialise(stream); } var parameters = new SocketAsyncEventArgs() { RemoteEndPoint = session.RemoteEndPoint }; parameters.SetBuffer(response, 0, responseSize); this._Socket.SendToAsync(parameters); }