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