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