Beispiel #1
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);
        }
Beispiel #2
0
        public void HandleHandshake(MessageType messageType, IByteBuffer data)
        {
            if (parentHandler != null)
            {
                parentHandler.HandleHandshake(messageType, data);
            }

            switch (messageType)
            {
            case MessageType.HELLO_VERIFY_REQUEST:
                if (handshakeState != State.CLIENT_HELLO_SENT)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessHelloVerifyRequest(data);
                break;

            case MessageType.SERVER_HELLO:
                if (handshakeState != State.CLIENT_HELLO_SENT)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessServerHello(data);
                clientState.HandshakeHash = clientState.HandshakeHash.NotifyPrfDetermined();

                short maxFragmentLength = ((AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters).GetMaxFragmentLength();
                if (maxFragmentLength >= 0)
                {
                    if (!MaxFragmentLength.IsValid((byte)maxFragmentLength))
                    {
                        throw new TlsFatalAlert(AlertDescription.internal_error);
                    }

                    int plainTextLimit = 1 << (8 + maxFragmentLength);
                    recordLayer.SetPlaintextLimit(plainTextLimit);
                }

                if (clientState.ResumedSession)
                {
                    byte[] masterSecret = new byte[clientState.SessionParameters.MasterSecret.Length];
                    Array.Copy(clientState.SessionParameters.MasterSecret, 0, masterSecret, 0, masterSecret.Length);
                    ((AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters).SetMasterSecret(masterSecret);
                    recordLayer.InitPendingEpoch(clientState.Client.GetCipher());
                }
                else
                {
                    if (clientState.SessionParameters != null)
                    {
                        clientState.SessionParameters.Clear();
                        clientState.SessionParameters = null;
                    }

                    if (clientState.TlsSession != null)
                    {
                        clientState.TlsSession.Invalidate();
                        clientState.TlsSession = null;
                    }

                    if (clientState.SelectedSessionID.Length > 0)
                    {
                        clientState.TlsSession = new AsyncDtlsSessionImpl(clientState.SelectedSessionID, null);
                    }
                }
                handshakeState = State.SERVER_HELLO_RECEIVED;
                break;

            case MessageType.SUPPLEMENTAL_DATA:
                if (handshakeState != State.SERVER_HELLO_RECEIVED)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessServerSupplementalData(data);
                handshakeState = State.SUPP_DATA_RECEIVED;
                break;

            case MessageType.CERTIFICATE:
                if (handshakeState == State.SERVER_HELLO_RECEIVED)
                {
                    clientState.Client.ProcessServerSupplementalData(null);
                    handshakeState = State.SUPP_DATA_RECEIVED;
                }

                if (handshakeState != State.SUPP_DATA_RECEIVED)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                clientState.KeyExchange = clientState.Client.GetKeyExchange();
                clientState.KeyExchange.Init(clientState.ClientContext);

                ProcessServerCertificate(data);
                handshakeState = State.CERTIFICATE_RECEIVED;
                break;

            case MessageType.CERTIFICATE_STATUS:
                if (handshakeState == State.SERVER_HELLO_RECEIVED)
                {
                    clientState.Client.ProcessServerSupplementalData(null);
                    handshakeState = State.SUPP_DATA_RECEIVED;
                }

                if (handshakeState == State.SUPP_DATA_RECEIVED)
                {
                    clientState.KeyExchange = clientState.Client.GetKeyExchange();
                    clientState.KeyExchange.Init(clientState.ClientContext);
                    clientState.KeyExchange.SkipServerCredentials();
                    handshakeState = State.CERTIFICATE_RECEIVED;
                }

                if (handshakeState != State.CERTIFICATE_RECEIVED)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessCertificateStatus(data);
                handshakeState = State.CERTIFICATE_STATUS_RECEIVED;
                break;

            case MessageType.SERVER_KEY_EXCHANGE:
                if (handshakeState == State.SERVER_HELLO_RECEIVED)
                {
                    clientState.Client.ProcessServerSupplementalData(null);
                    handshakeState = State.SUPP_DATA_RECEIVED;
                }

                if (handshakeState == State.SUPP_DATA_RECEIVED)
                {
                    clientState.KeyExchange = clientState.Client.GetKeyExchange();
                    clientState.KeyExchange.Init(clientState.ClientContext);
                    clientState.KeyExchange.SkipServerCredentials();
                    handshakeState = State.CERTIFICATE_RECEIVED;
                }

                if (handshakeState == State.CERTIFICATE_RECEIVED)
                {
                    handshakeState = State.CERTIFICATE_STATUS_RECEIVED;
                }

                if (handshakeState != State.CERTIFICATE_STATUS_RECEIVED)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessServerKeyExchange(data);
                handshakeState = State.SERVER_KEY_EXCHANGE_RECEIVED;
                break;

            case MessageType.CERTIFICATE_REQUEST:
                if (handshakeState == State.SERVER_HELLO_RECEIVED)
                {
                    clientState.Client.ProcessServerSupplementalData(null);
                    handshakeState = State.SUPP_DATA_RECEIVED;
                }

                if (handshakeState == State.SUPP_DATA_RECEIVED)
                {
                    clientState.KeyExchange = clientState.Client.GetKeyExchange();
                    clientState.KeyExchange.Init(clientState.ClientContext);
                    clientState.KeyExchange.SkipServerCredentials();
                    handshakeState = State.CERTIFICATE_RECEIVED;
                }

                if (handshakeState == State.CERTIFICATE_RECEIVED)
                {
                    handshakeState = State.CERTIFICATE_STATUS_RECEIVED;
                }

                if (handshakeState == State.CERTIFICATE_STATUS_RECEIVED)
                {
                    clientState.KeyExchange.SkipServerKeyExchange();
                    handshakeState = State.SERVER_KEY_EXCHANGE_RECEIVED;
                }

                if (handshakeState != State.SERVER_KEY_EXCHANGE_RECEIVED)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessCertificateRequest(data);
                handshakeState = State.CERTIFICATE_REQUEST_RECEIVED;
                break;

            case MessageType.SERVER_HELLO_DONE:
                if (handshakeState == State.SERVER_HELLO_RECEIVED)
                {
                    clientState.Client.ProcessServerSupplementalData(null);
                    handshakeState = State.SUPP_DATA_RECEIVED;
                }

                if (handshakeState == State.SUPP_DATA_RECEIVED)
                {
                    clientState.KeyExchange = clientState.Client.GetKeyExchange();
                    clientState.KeyExchange.Init(clientState.ClientContext);
                    clientState.KeyExchange.SkipServerCredentials();
                    handshakeState = State.CERTIFICATE_RECEIVED;
                }

                if (handshakeState == State.CERTIFICATE_RECEIVED)
                {
                    handshakeState = State.CERTIFICATE_STATUS_RECEIVED;
                }

                if (handshakeState == State.CERTIFICATE_STATUS_RECEIVED)
                {
                    clientState.KeyExchange.SkipServerKeyExchange();
                    handshakeState = State.SERVER_KEY_EXCHANGE_RECEIVED;
                }

                if (handshakeState == State.SERVER_KEY_EXCHANGE_RECEIVED)
                {
                    handshakeState = State.CERTIFICATE_REQUEST_RECEIVED;
                }

                if (handshakeState != State.CERTIFICATE_REQUEST_RECEIVED)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessServerHelloDone(data);
                handshakeState = State.SERVER_HELLO_DONE;
                break;

            case MessageType.SESSION_TICKET:
                if (handshakeState != State.FINISH_SENT || !clientState.ExpectSessionTicket)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessNewSessionTicket(data);
                handshakeState = State.SESSION_TICKET_RECEIVED;
                break;

            case MessageType.FINISHED:
                if (handshakeState != State.FINISH_SENT && handshakeState != State.SESSION_TICKET_RECEIVED && handshakeState != State.SERVER_HELLO_RECEIVED)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                if (handshakeState == State.FINISH_SENT && clientState.ExpectSessionTicket)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                if (handshakeState == State.SERVER_HELLO_RECEIVED && clientState.ResumedSession)
                {
                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
                }

                ProcessFinished(data);
                break;

            default:
                throw new TlsFatalAlert(AlertDescription.unexpected_message);
            }
        }