コード例 #1
0
        private void HandleServerKeyExchange(ReadableBuffer messageBuffer)
        {
            HandshakeHash.HashData(messageBuffer);
            var parser = new ServerKeyExchangeParser(messageBuffer);

            _signatureScheme = parser.SignatureScheme;
            _certificate.CheckSignature(_cryptoProvider.HashProvider, _signatureScheme, parser.Signature, parser.Data);
            KeyExchange.SetPeerKey(parser.Key, _certificate, _signatureScheme);
        }
コード例 #2
0
 public override void Dispose()
 {
     HandshakeHash?.Dispose();
     KeySchedule?.Dispose();
     KeyShare?.Dispose();
     ReadKey?.Dispose();
     WriteKey?.Dispose();
     GC.SuppressFinalize(this);
 }
コード例 #3
0
 private Span<byte> HandleClientKeyExchange(ReadableBuffer messageBuffer)
 {
     var span = messageBuffer.ToSpan();
     HandshakeHash.HashData(span);
     span = span.Slice(HandshakeFraming.HeaderSize);
     KeyExchange.SetPeerKey(new BigEndianAdvancingSpan(span), _certificate, _signatureScheme);
     _secretSchedule.GenerateMasterSecret(dispose: true);
     _state = HandshakeState.WaitingForChangeCipherSpec;
     return span;
 }
コード例 #4
0
        private unsafe void GenerateServerApplicationKey()
        {
            var hash = stackalloc byte[HandshakeHash.HashSize];
            var span = new Span <byte>(hash, HandshakeHash.HashSize);

            HandshakeHash.InterimHash(hash, HandshakeHash.HashSize);
            KeySchedule.GenerateMasterSecret(span);
            Console.WriteLine("Application Write Key");
            _writeKey?.Dispose();
            _writeKey = KeySchedule.GenerateServerApplicationKey();
        }
コード例 #5
0
 private void HandleServerCertificate(ReadableBuffer messageBuffer)
 {
     HandshakeHash.HashData(messageBuffer);
     _certificate = Connection.Listener.CertificateList.CheckCertificate(messageBuffer);
     KeyExchange.SetCertificate(_certificate);
     if (KeyExchange.RequiresServerKeyExchange)
     {
         _state = HandshakeState.WaitingForServerKeyExchange;
     }
     else
     {
         _state = HandshakeState.WaitingForServerHelloDone;
     }
 }
コード例 #6
0
        private void HandleServerHello(ReadableBuffer messageBuffer)
        {
            var helloParser = new ServerHelloParser(messageBuffer, Connection);
            var version     = GetVersion(ref helloParser);

            if (version != TlsVersion.Tls12)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.protocol_version, "Invalid protocol version");
            }
            _secretSchedule.SetServerRandom(helloParser.ServerRandom);
            CipherSuite = _cryptoProvider.CipherSuites.GetCipherSuite(TlsVersion.Tls12, helloParser.CipherSuite);
            KeyExchange = _cryptoProvider.KeyExchangeProvider.GetKeyExchange(CipherSuite.KeyExchange, new BigEndianAdvancingSpan(helloParser.SupportedGroups));
            var oldHash = HandshakeHash;

            HandshakeHash = _cryptoProvider.HashProvider.GetHash(CipherSuite.HashType);
            HandshakeHash.HashData(((HashBuffer)oldHash).GetBufferedData());
            HandshakeHash.HashData(helloParser.OriginalMessage);
            _state = HandshakeState.WaitingForServerCertificate;
        }
コード例 #7
0
        private unsafe void GenerateHandshakeKeys()
        {
            if (KeySchedule == null)
            {
                KeySchedule = Listener.KeyScheduleProvider.GetKeySchedule(this);
            }
            KeySchedule.SetDheDerivedValue(KeyShare);
            var hash = stackalloc byte[HandshakeHash.HashSize];
            var span = new Span <byte>(hash, HandshakeHash.HashSize);

            HandshakeHash.InterimHash(hash, HandshakeHash.HashSize);
            KeySchedule.GenerateHandshakeTrafficSecrets(span);
            _writeKey = KeySchedule.GenerateServerHandshakeKey();
            if (PskIdentity == -1 || !EarlyDataSupported)
            {
                _readKey?.Dispose();
                _readKey = KeySchedule.GenerateClientHandshakeKey();
            }
        }
コード例 #8
0
        private void SecondFlight(ReadableBuffer messageBuffer)
        {
            HandshakeHash.HashData(messageBuffer);
            if (messageBuffer.Length < 4)
            {
                throw new NotImplementedException();
            }
            // send second flight
            var sendSize = KeyExchange.ClientSendSize;

            _secretSchedule.GenerateMasterSecret(false);
            this.WriteHandshakeFrame(sendSize, KeyExchange.ClientSendKey, HandshakeType.client_key_exchange);
            RecordHandler.WriteRecords(Connection.HandshakeOutput.Reader, RecordType.Handshake);
            WriteChangeCipherSpec();
            (_writeKey, _storedKey) = _secretSchedule.GenerateKeys();
            _state = HandshakeState.WaitingForClientFinished;
            this.WriteHandshakeFrame(_secretSchedule.ClientVerifySize, WriteClientVerify, HandshakeType.finished);
            RecordHandler.WriteRecords(Connection.HandshakeOutput.Reader, RecordType.Handshake);
            _state = HandshakeState.WaitingForChangeCipherSpec;
        }
コード例 #9
0
        public bool HandleClientHello(ref ClientHelloParser clientHello)
        {
            CipherSuite = _cryptoProvider.CipherSuites.GetCipherSuite(TlsVersion.Tls12, clientHello.CipherSuites);
            HandshakeHash = _cryptoProvider.HashProvider.GetHash(CipherSuite.HashType);
            HandshakeHash.HashData(clientHello.OriginalMessage);

            _certificate = Connection.Listener.CertificateList.GetCertificate(null, CipherSuite.CertificateType.Value);
            _secretSchedule.SetClientRandom(clientHello.ClientRandom);
            _negotiatedAlpn = clientHello.NegotiatedAlpn;
            _hostName = clientHello.HostName;

            KeyExchange = _cryptoProvider.KeyExchangeProvider.GetKeyExchange(CipherSuite.KeyExchange, clientHello.SupportedGroups);

            if (_certificate == null)
            {
                (_certificate, _signatureScheme) = Connection.Listener.CertificateList.GetCertificate(clientHello.SignatureAlgos);
            }
            else
            {
                _signatureScheme = _certificate.SelectAlgorithm(clientHello.SignatureAlgos);
            }
            if (clientHello.SessionTicket.Length > 0)
            {
                ProcessSessionTicket(clientHello.SessionTicket);
            }

            if (_abbreviatedHandshake)
            {
                SendFirstFlightAbbreviated(clientHello);
            }
            else
            {
                SendFirstFlightFull();
            }
            return true;
        }
コード例 #10
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, "");
        }
コード例 #11
0
 public void HandshakeContext(ReadableBuffer readable)
 {
     HandshakeHash?.HashData(readable);
 }
コード例 #12
0
ファイル: ServerStateTls12.cs プロジェクト: benaadams/Leto
        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;
            }
        }
コード例 #13
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;
            }
        }