private void ProcessHandshakeRecord(Record record, AsyncHandshakeResult asyncHandshakeResult) { // Process each handshake message included in this record fragment separately HandshakeMessage[] msgs = _handshakePacketizer.ProcessHandshakeRecord(_handshakeSession.NegotiatedVersion, record); for (int i = 0; i < msgs.Length; i++) { _handshakeSession.ProcessMessage(msgs[i]); } // Continue processing handshake by attempting to send packets ProcessSendHandshakePacket(asyncHandshakeResult); }
private async Task ReceiveChangeCipherSpecAndFinished(CancellationToken token) { var recordList = new List <Record>(); var changeCipherSpecReceived = false; var finishedReceived = false; while (!token.IsCancellationRequested) { var records = await _recordStream.ReceiveAsync(token); if (records == null || records.Count == 0) { continue; } // Check for alerts foreach (var record in records) { if (record.Type == RecordType.Alert) { logger?.Error($"Alert received: { (AlertDescription)record.Fragment[1]}"); if (record.Fragment.Length == 2) { var alert = (AlertDescription)record.Fragment[1]; throw new AlertException((AlertDescription)record.Fragment[1], $"Received TLS alert record: {alert}"); } } } recordList.AddRange(records); if (recordList.Count < 2) { continue; } foreach (var record in recordList) { _recordHandler.ProcessInputRecord(record); if (record.Type == RecordType.ChangeCipherSpec) { changeCipherSpecReceived = true; if (record.Fragment.Length != 1 || record.Fragment[0] != 0x01) { throw new AlertException(AlertDescription.IllegalParameter, "Received an invalid ChangeCipherSpec record"); } // NOTE: keep this before recordHandler.ChangeLocalState since it may generate masterSecret _handshakeSession.RemoteChangeCipherSpec(); // Change cipher suite in record handler and handle it in handshake session _recordHandler.SetCipherSuite(_handshakeSession.CipherSuite, _handshakeSession.ConnectionState); _recordHandler.ChangeRemoteState(); continue; } if (record.Type == RecordType.Handshake) { finishedReceived = true; HandshakeMessage[] handshakeMessages = _handshakePacketizer.ProcessHandshakeRecord(_handshakeSession.NegotiatedVersion, record); foreach (HandshakeMessage hsm in handshakeMessages) { if (hsm.Type != HandshakeMessageType.Finished) { throw new AlertException(AlertDescription.UnexpectedMessage, "Finished handshake message was expected"); } logger?.Debug("Received Handshake message {0}", hsm.Type); _handshakeSession.ProcessMessage(hsm); } } if (changeCipherSpecReceived && finishedReceived) { return; } } } throw new TimeoutException("ReceiveAsync change cipher spec timed out"); }