示例#1
0
        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);
        }
示例#2
0
        public void HandshakeSuccessful()
        {
            if (readEpoch == currentEpoch || writeEpoch == currentEpoch)
            {
                throw new InvalidOperationException();
            }

            this.inHandshake  = false;
            this.currentEpoch = pendingEpoch;
            this.pendingEpoch = null;
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }