Exemplo n.º 1
0
        public async Task HandleHandshakeMessage(HandshakeType handshakeMessageType, ReadableBuffer buffer, IPipelineWriter pipe)
        {
            switch (State)
            {
            case StateType.WaitServerHello:
                if (handshakeMessageType == HandshakeType.server_hello)
                {
                    Hello.ReadServerHello(buffer, this);
                    GenerateHandshakeKeys();
                    State = StateType.WaitEncryptedExtensions;
                    return;
                }
                break;

            case StateType.WaitEncryptedExtensions:
                if (handshakeMessageType == HandshakeType.encrypted_extensions)
                {
                    HandshakeContext(buffer);
                    State = StateType.WaitServerVerification;
                    return;
                }
                break;

            case StateType.WaitServerVerification:
                if (handshakeMessageType == HandshakeType.certificate)
                {
                    Handshake.Certificates.ReadCertificates(buffer, Listener);
                    HandshakeContext(buffer);
                    return;
                }
                if (handshakeMessageType == HandshakeType.certificate_verify)
                {
                    HandshakeContext(buffer);
                    State = StateType.WaitServerFinished;
                    return;
                }
                break;

            case StateType.WaitServerFinished:
                if (handshakeMessageType == HandshakeType.finished)
                {
                    HandshakeContext(buffer);
                    var hash = new byte[HandshakeHash.HashSize];
                    HandshakeHash.InterimHash(hash);
                    var writer = pipe.Alloc();
                    ServerHandshakeTls13.ServerFinished(ref writer, this, KeySchedule.GenerateClientFinishedKey());
                    _dataForCurrentScheduleSent.Reset();
                    await writer.FlushAsync();

                    await _dataForCurrentScheduleSent;
                    GenerateApplicationKeys(hash);
                    KeySchedule.GenerateResumptionSecret();
                    HandshakeHash.Dispose();
                    HandshakeHash = null;
                    State         = StateType.HandshakeComplete;
                    return;
                }
                break;

            case StateType.HandshakeComplete:
                if (handshakeMessageType == HandshakeType.new_session_ticket)
                {
                    Listener.ResumptionProvider.RegisterSessionTicket(buffer);
                    return;
                }
                break;
            }
            Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, "");
        }
Exemplo n.º 2
0
        public override async Task HandleHandshakeMessage(HandshakeType handshakeMessageType, ReadableBuffer buffer, IPipelineWriter pipe)
        {
            WritableBuffer writer;

            switch (State)
            {
            case StateType.None:
            case StateType.WaitHelloRetry:
                if (handshakeMessageType != HandshakeType.client_hello)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"State is wait hello retry but got {handshakeMessageType}");
                }
                Hello.ReadClientHelloTls13(buffer, this);
                if (CipherSuite == null)
                {
                    //Couldn't agree a set of ciphers
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Could not agree on a cipher suite during reading client hello");
                }
                this.StartHandshakeHash(buffer);
                //If we can't agree on a schedule we will have to send a hello retry and try again
                if (!NegotiationComplete())
                {
                    writer = pipe.Alloc();
                    this.WriteHandshake(ref writer, HandshakeType.hello_retry_request, Hello.SendHelloRetry);
                    _state = StateType.WaitHelloRetry;
                    await writer.FlushAsync();

                    return;
                }
                if (PskIdentity != -1 && EarlyDataSupported)
                {
                    KeySchedule.GenerateEarlyTrafficKey(ref _readKey);
                    Console.WriteLine("Generated Early Traffic Key");
                }
                //Write the server hello, the last of the unencrypted messages
                _state = StateType.SendServerHello;
                writer = pipe.Alloc();
                this.WriteHandshake(ref writer, HandshakeType.server_hello, Hello.SendServerHello13);
                //block our next actions because we need to have sent the message before changing keys
                DataForCurrentScheduleSent.Reset();
                await writer.FlushAsync();

                await DataForCurrentScheduleSent;
                _state = StateType.ServerAuthentication;
                //Generate the encryption keys and send the next set of messages
                GenerateHandshakeKeys();
                writer = pipe.Alloc();
                ServerHandshakeTls13.SendFlightOne(ref writer, this);
                ServerHandshakeTls13.SendFlightOne2(ref writer, this);
                DataForCurrentScheduleSent.Reset();
                await writer.FlushAsync();

                await DataForCurrentScheduleSent;
                writer = pipe.Alloc();
                ServerHandshakeTls13.SendFlightOne3(ref writer, this);
                ServerHandshakeTls13.ServerFinished(ref writer, this, KeySchedule.GenerateServerFinishKey());
                DataForCurrentScheduleSent.Reset();
                await writer.FlushAsync();

                await DataForCurrentScheduleSent;
                GenerateServerApplicationKey();
                if (EarlyDataSupported && PskIdentity != -1)
                {
                    _state = StateType.WaitEarlyDataFinished;
                }
                else
                {
                    _state = StateType.WaitClientFinished;
                }
                return;

            case StateType.WaitClientFinished:
                if (handshakeMessageType != HandshakeType.finished)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"Waiting for client finished but received {handshakeMessageType}");
                }
                Finished.ReadClientFinished(buffer, this);
                _readKey?.Dispose();
                _readKey = KeySchedule.GenerateClientApplicationKey();
                //Hash the finish message now we have made the traffic keys
                //Then we can make the resumption secret
                HandshakeHash.HashData(buffer);
                KeySchedule.GenerateResumptionSecret();
                HandshakeHash.Dispose();
                HandshakeHash = null;
                //Send a new session ticket
                writer = pipe.Alloc();
                this.WriteHandshake(ref writer, HandshakeType.new_session_ticket, SessionKeys.CreateNewSessionKey);
                await writer.FlushAsync();

                _state = StateType.HandshakeComplete;
                break;

            default:
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"Not in any known state {State} that we expected a handshake messge from {handshakeMessageType}");
                break;
            }
        }