public void Send(short sequence, MessageType messageType, IByteBuffer buffer) { if (closed) { return; } if (messageType == MessageType.FINISHED) { AsyncDtlsEpoch nextEpoch = null; if (this.inHandshake) { nextEpoch = pendingEpoch; } if (nextEpoch == null) { throw new InvalidOperationException(); } IByteBuffer cipherSpecBuf = Unpooled.Buffer(1); cipherSpecBuf.WriteByte(1); SendRecord(ContentType.change_cipher_spec, cipherSpecBuf); writeEpoch = nextEpoch; } IByteBuffer copy = buffer.Copy(); byte[] realArray = new byte[copy.ReadableBytes]; copy.ReadBytes(realArray); if (buffer.ReadableBytes <= GetSendLimit()) { SendRecord(ContentType.handshake, buffer); } else { int fragmentOffset = 0; int totalLength = buffer.ReadableBytes - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH; IByteBuffer header = buffer.ReadBytes(DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH); header.Release(); do { int fragmentLength = Math.Min(buffer.ReadableBytes + DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH, GetSendLimit()); IByteBuffer current = Unpooled.Buffer(fragmentLength); DtlsHelper.WriteHandshakeHeader(fragmentOffset, fragmentLength - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH, sequence, messageType, current, totalLength); buffer.ReadBytes(current, fragmentLength - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH); SendRecord(ContentType.handshake, current); fragmentOffset += fragmentLength - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH; }while (buffer.ReadableBytes > 0); } handshakeHash.BlockUpdate(realArray, 0, DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH); handshakeHash.BlockUpdate(realArray, DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH, realArray.Length - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH); }
public void HandshakeSuccessful() { if (readEpoch == currentEpoch || writeEpoch == currentEpoch) { throw new InvalidOperationException(); } this.inHandshake = false; this.currentEpoch = pendingEpoch; this.pendingEpoch = null; }
public AsyncDtlsRecordLayer(TlsHandshakeHash handshakeHash, HandshakeHandler handshakeHandler, IChannel channel, TlsContext context, TlsPeer peer) { this.handshakeHash = handshakeHash; this.channel = channel; this.handshakeHandler = handshakeHandler; this.peer = peer; this.inHandshake = true; this.currentEpoch = new AsyncDtlsEpoch(0, new TlsNullCipher(context)); this.pendingEpoch = null; this.readEpoch = currentEpoch; this.writeEpoch = currentEpoch; SetPlaintextLimit(MAX_FRAGMENT_LENGTH); }
public List <IByteBuffer> Receive(IByteBuffer record) { List <IByteBuffer> outputList = new List <IByteBuffer>(); while (record.ReadableBytes > RECORD_HEADER_LENGTH) { byte type = (byte)(record.ReadByte() & 0x00FF); ProtocolVersion version = ProtocolVersion.Get(record.ReadByte() & 0xFF, record.ReadByte() & 0xFF); int epoch = record.ReadUnsignedShort(); long seq = DtlsHelper.ReadUint48(record); //just reading length,not using it short packetLength = record.ReadShort(); byte[] realData = new byte[packetLength]; record.ReadBytes(realData); AsyncDtlsEpoch recordEpoch = null; if (epoch == readEpoch.Epoch) { recordEpoch = readEpoch; } if (recordEpoch == null) { continue; } if (recordEpoch.ReplayWindow.ShouldDiscard(seq)) { continue; } if (!version.IsDtls) { continue; } if (readVersion != null && !readVersion.Equals(version)) { continue; } byte[] plaintext = recordEpoch.getCipher().DecodeCiphertext(GetMacSequenceNumber(recordEpoch.Epoch, seq), type, realData, 0, realData.Length); IByteBuffer output = Unpooled.WrappedBuffer(plaintext); recordEpoch.ReplayWindow.ReportAuthenticated(seq); if (plaintext.Length > this.plaintextLimit) { continue; } if (readVersion == null) { readVersion = version; } switch (type) { case ContentType.alert: if (output.ReadableBytes == 2) { byte alertLevel = (byte)(output.ReadByte() & 0x0FF); byte alertDescription = (byte)(output.ReadByte() & 0x0FF); peer.NotifyAlertReceived(alertLevel, alertDescription); if (alertLevel == AlertLevel.fatal) { Failed(); throw new TlsFatalAlert(alertDescription); } if (alertDescription == AlertDescription.close_notify) { CloseTransport(); } } continue; case ContentType.application_data: if (inHandshake) { continue; } break; case ContentType.change_cipher_spec: while (output.ReadableBytes > 0) { short message = (short)(output.ReadByte() & 0x0FF); if (message != ChangeCipherSpec.change_cipher_spec) { continue; } if (pendingEpoch != null) { readEpoch = pendingEpoch; } } continue; case ContentType.handshake: if (!inHandshake) { continue; } HandshakeHeader handshakeHeader = DtlsHelper.ReadHandshakeHeader(output); if (handshakeHeader != null) { if (!handshakeHeader.FragmentLength.Equals(handshakeHeader.TotalLength)) { PendingMessageData data = null; if (pendingBuffers.ContainsKey(handshakeHeader.MessageSequence)) { data = pendingBuffers[handshakeHeader.MessageSequence]; } if (data == null) { data = new PendingMessageData(Unpooled.Buffer(handshakeHeader.TotalLength)); pendingBuffers[handshakeHeader.MessageSequence] = data; } data.WriteBytes(output, handshakeHeader.FragmentOffset); if (data.WrottenBytes.Equals(handshakeHeader.TotalLength)) { data.Buffer.SetWriterIndex(handshakeHeader.TotalLength); byte[] packetData = null; IByteBuffer copy = data.Buffer.Copy(); packetData = new byte[copy.ReadableBytes]; copy.ReadBytes(packetData); if (handshakeHeader.MessageType.HasValue && handshakeHandler != null) { handshakeHandler.HandleHandshake(handshakeHeader.MessageType.Value, data.Buffer); } byte[] pseudoHeader = new byte[DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH]; IByteBuffer headerBuffer = Unpooled.WrappedBuffer(pseudoHeader); headerBuffer.SetWriterIndex(0); DtlsHelper.WriteHandshakeHeader(handshakeHeader.MessageSequence, handshakeHeader.MessageType.Value, headerBuffer, handshakeHeader.TotalLength); headerBuffer.SetReaderIndex(0); handshakeHash.BlockUpdate(pseudoHeader, 0, pseudoHeader.Length); handshakeHash.BlockUpdate(packetData, 0, packetData.Length); if (handshakeHeader.MessageType.HasValue && handshakeHandler != null) { handshakeHandler.PostProcessHandshake(handshakeHeader.MessageType.Value, data.Buffer); } pendingBuffers.Remove(handshakeHeader.MessageSequence); } } else { byte[] packetData = null; IByteBuffer copy = output.Copy(); packetData = new byte[copy.ReadableBytes]; copy.ReadBytes(packetData); if (handshakeHeader.MessageType.HasValue && handshakeHandler != null) { handshakeHandler.HandleHandshake(handshakeHeader.MessageType.Value, output); } byte[] pseudoHeader = new byte[DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH]; IByteBuffer headerBuffer = Unpooled.WrappedBuffer(pseudoHeader); headerBuffer.SetWriterIndex(0); DtlsHelper.WriteHandshakeHeader(handshakeHeader.MessageSequence, handshakeHeader.MessageType.Value, headerBuffer, handshakeHeader.TotalLength); headerBuffer.SetReaderIndex(0); handshakeHash.BlockUpdate(pseudoHeader, 0, pseudoHeader.Length); handshakeHash.BlockUpdate(packetData, 0, packetData.Length); if (handshakeHeader.MessageType.HasValue && handshakeHandler != null) { handshakeHandler.PostProcessHandshake(handshakeHeader.MessageType.Value, output); } } } continue; case ContentType.heartbeat: continue; } outputList.Add(output); } return(outputList); }