Esempio n. 1
0
        public override void HandleHandshakeMessage(HandshakeType handshakeMessageType, ReadableBuffer buffer, ref WritableBuffer outBuffer)
        {
            switch (State)
            {
            case StateType.None:
                if (handshakeMessageType != HandshakeType.client_hello)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, "Tls 12 didnt get a client hello");
                }
                Hello.ReadClientHelloTls12(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);
                //Write server hello
                ChangeState(StateType.SendServerHello);
                _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                this.WriteHandshake(ref outBuffer, HandshakeType.server_hello, Hello.SendServerHello12);
                _frameWriter.FinishFrame(ref outBuffer);
                _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                this.WriteHandshake(ref outBuffer, HandshakeType.certificate, ServerHandshakeTls12.SendCertificates);
                _frameWriter.FinishFrame(ref outBuffer);

                if (CipherSuite.ExchangeType == KeyExchangeType.Ecdhe || CipherSuite.ExchangeType == KeyExchangeType.Dhe)
                {
                    if (KeyShare == null)
                    {
                        KeyShare = CryptoProvider.GetDefaultKeyShare(CipherSuite.ExchangeType);
                    }
                    _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                    this.WriteHandshake(ref outBuffer, HandshakeType.server_key_exchange, ServerHandshakeTls12.SendKeyExchange);
                    _frameWriter.FinishFrame(ref outBuffer);
                }
                _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                this.WriteHandshake(ref outBuffer, HandshakeType.server_hello_done, (w, state) => w);
                _frameWriter.FinishFrame(ref outBuffer);
                ChangeState(StateType.WaitClientKeyExchange);
                break;

            case StateType.WaitClientKeyExchange:
                if (handshakeMessageType != HandshakeType.client_key_exchange)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"Received a {handshakeMessageType} when we expected a {HandshakeType.client_key_exchange}");
                }
                HandshakeHash.HashData(buffer);
                KeyShare.SetPeerKey(buffer.Slice(5));
                _schedule.GenerateMasterSecret();
                _schedule.CalculateClientFinished();
                //We can send the server finished because we have the expected client finished
                _schedule.GenerateKeyMaterial();
                ChangeState(StateType.ChangeCipherSpec);
                break;

            case StateType.WaitClientFinished:
                if (handshakeMessageType != HandshakeType.finished)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"unexpected message");
                }
                _schedule.CompareClientFinishedGenerateServerFinished(buffer);
                _frameWriter.StartFrame(RecordType.ChangeCipherSpec, ref outBuffer);
                outBuffer.WriteBigEndian <byte>(1);
                _frameWriter.FinishFrame(ref outBuffer);

                _writeKey = _schedule.GetServerKey();

                _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                this.WriteHandshake(ref outBuffer, HandshakeType.finished, _schedule.WriteServerFinished);
                _frameWriter.FinishFrame(ref outBuffer);
                KeyShare?.Dispose();
                KeyShare = null;
                ChangeState(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;
            }
        }