private void AwaitEncryptedMessage(Byte[] l7Data, PmFrameBase pdu) { if (l7Data[0] == Record) { // record protocol this._state = this.Decrypter.DoDecryption(l7Data, pdu, ref this._decryptedBytes)? SslSessionState.DataExchange : SslSessionState.Intermezzo; } else if (l7Data[0] == Handshake) { // tls handshaking protocol // renegotiation // TODO could be Finished? this._msgUnderReview--; // TODO isn't renegotiation encrypted?? this._state = SslSessionState.NegotiationInit; } else if (l7Data[0] == ChangeCipherSpec && l7Data.Length > 6) // ChangeCipherSpec message has 6 bytes { // 'Finished' is in this pdu - TODO can be in next pdu? var finished = new Byte[l7Data.Length - 6]; Array.Copy(l7Data, 6, finished, 0, finished.Length); this.Decrypter.DoDecryption(finished, pdu, ref this._decryptedBytes); this._decryptedBytes = null; this._state = SslSessionState.Intermezzo; } else if (l7Data[0] == Alert) { // alert protocol // ignore this._state = SslSessionState.Intermezzo; } // else something wrong }
private void AwaitFinishedMessage(Byte[] l7Data, PmFrameBase pdu) { if (l7Data[0] == Handshake && l7Data[1] == Ssl3VerMajor) { this.Decrypter.DoDecryption(l7Data, pdu, ref this._decryptedBytes); this._decryptedBytes = null; this._state = SslSessionState.Intermezzo; } }
private void AwaitClientKeyExchange(Byte[] l7Data, PmFrameBase pdu) { if (l7Data[0] == Handshake && l7Data[1] == Ssl3VerMajor && l7Data[5] == ClientKeyExchange) { this.Decrypter.ClientDirection = pdu.SrcAddress.GetAddressBytes(); this.Decrypter.KeyDecrypter.ParseClientKeyExchange(l7Data); var preMaster = this.Decrypter.KeyDecrypter.DecryptKey(); // use premaster to get ciphering key var master = this.Decrypter.Prf(preMaster, "master secret", this.Decrypter.ClientRnd, this.Decrypter.ServerRnd, 48, l7Data[2]); // Save Master key for current session SessionsMasterKeys.Add(this._currentSessionID, master); var keyBlock = this.Decrypter.Prf(master, "key expansion", this.Decrypter.ServerRnd, this.Decrypter.ClientRnd, this.Decrypter.DataDecrypter.MacKeyLength * 2 + this.Decrypter.DataDecrypter.KeyLength * 2 + this.Decrypter.DataDecrypter.IvLength * 2, l7Data[2]); this.Decrypter.ClientHMacKey = new Byte[this.Decrypter.DataDecrypter.MacKeyLength]; this.Decrypter.ServerHMacKey = new Byte[this.Decrypter.DataDecrypter.MacKeyLength]; Array.Copy(keyBlock, 0, this.Decrypter.ClientHMacKey, 0, this.Decrypter.DataDecrypter.MacKeyLength); Array.Copy(keyBlock, this.Decrypter.DataDecrypter.MacKeyLength, this.Decrypter.ServerHMacKey, 0, this.Decrypter.DataDecrypter.MacKeyLength); // Only part of key_block is used to encrypt data this.Decrypter.DataDecrypter.Init(keyBlock); // Look for finished - sent immediately after change cipher spec var totalLen = 0; do { var t = new Byte[2]; Array.Copy(l7Data, 3, t, 0, 2); Array.Reverse(t); totalLen += 5; totalLen += BitConverter.ToInt16(t, 0); } while(totalLen < l7Data.Length && l7Data[totalLen] != ChangeCipherSpec); if (totalLen < l7Data.Length) { // 'Finished' is in this pdu totalLen += 6; // ChangeCipherSpec message has 6 bytes var finished = new Byte[l7Data.Length - totalLen]; Array.Copy(l7Data, totalLen, finished, 0, finished.Length); this.Decrypter.DoDecryption(finished, pdu, ref this._decryptedBytes); this._decryptedBytes = null; this._state = SslSessionState.Intermezzo; } else { this._state = SslSessionState.NegotiationChangeCipherSpec; } } }
public override Boolean Reset() { this._state = SslSessionState.NegotiationInit; this._msgUnderReview = 0; this._decryptedDataCnt = 0; this._decryptedDataOffset = 0; this.DataList.Clear(); this._decryptedBytes = null; this._processedPdus.Clear(); this._dataDecrypted = false; this._lastPDU = false; this.Pdus = this._conversation.L7PDUs.ToArray(); this.Decrypter = new PDUDecrypter(); SessionsMasterKeys.Clear(); return(this.ResetSoft()); }
private void AwaitChangeCipherSpecMessage(Byte[] l7Data, PmFrameBase pdu) { if (l7Data[0] == ChangeCipherSpec && l7Data[1] == Ssl3VerMajor && l7Data[5] == ChangeCipherSpecMessage) { //1 byte for content type //2 bytes for protocol version //2 bytes for message length //1 byte for change cypher spec message if (l7Data.Length > 6) //If finished message follows directly after Change Cipher Spec { var l7FinishedMsg = new byte[l7Data.Length - 6]; Array.Copy(l7Data, 6, l7FinishedMsg, 0, l7Data.Length - 6); this.AwaitFinishedMessage(l7FinishedMsg, pdu); } else { this._state = SslSessionState.NegotiationFinished; } } }
extern static /* OSStatus */ SslStatus SSLGetSessionState(/* SSLContextRef */ IntPtr context, ref SslSessionState state);
private void AwaitHelloMessages(Byte[] l7Data, PmFrameBase pdu) { // Get server hello message if (l7Data[0] == Handshake && l7Data[1] == Ssl3VerMajor && l7Data[5] == ServerHello) { this.Decrypter.ServerRnd = new Byte[32]; Array.Copy(l7Data, 11, this.Decrypter.ServerRnd, 0, this.Decrypter.ServerRnd.Length); ConversationCipherSuite conversationCipherSuite; KeyDecrypter keyDecrypter; DataDecrypter dataDecrypter; this.Decrypter.ChangeCipherSuite(l7Data, out conversationCipherSuite); this._conversation.CipherSuite = conversationCipherSuite; CipherSuiteInitializer.PrepareDecryptingAlgorithms(this._conversation.Key.ServerPrivateKey, this._conversation.CipherSuite, out keyDecrypter, out dataDecrypter); this.Decrypter.KeyDecrypter = keyDecrypter; this.Decrypter.DataDecrypter = dataDecrypter; // Get SSL Session ID and save it var sessionID = new Byte[32]; Array.Copy(l7Data, 44, sessionID, 0, 32); Array.Copy(sessionID, this._currentSessionID, this._currentSessionID.Length); // Get ServerHello content length var serverHelloContentLengthBytes = new Byte[2]; Array.Copy(l7Data, 3, serverHelloContentLengthBytes, 0, 2); Array.Reverse(serverHelloContentLengthBytes); var serverHelloContentLength = BitConverter.ToUInt16(serverHelloContentLengthBytes, 0); // Get total ServerHello length // ContentType(1B) Version(2B) Length(2B) Content var serverHelloLength = 1 + 2 + 2 + serverHelloContentLength; // Check whether there is something else after ServerHello message and whether it is ChangeCipherSpec message // If yes, session resumption is used if (serverHelloLength < l7Data.Length && l7Data[serverHelloLength + 0] == ChangeCipherSpec && SessionsMasterKeys.ContainsKey(sessionID)) { this.Decrypter.ClientDirection = pdu.DstAddress.GetAddressBytes(); // Load saved Master key for given Session ID var master = SessionsMasterKeys[sessionID]; var keyBlock = this.Decrypter.Prf(master, "key expansion", this.Decrypter.ServerRnd, this.Decrypter.ClientRnd, this.Decrypter.DataDecrypter.MacKeyLength * 2 + this.Decrypter.DataDecrypter.KeyLength * 2 + this.Decrypter.DataDecrypter.IvLength * 2, l7Data[2]); this.Decrypter.ClientHMacKey = new Byte[this.Decrypter.DataDecrypter.MacKeyLength]; this.Decrypter.ServerHMacKey = new Byte[this.Decrypter.DataDecrypter.MacKeyLength]; Array.Copy(keyBlock, 0, this.Decrypter.ClientHMacKey, 0, this.Decrypter.DataDecrypter.MacKeyLength); Array.Copy(keyBlock, this.Decrypter.DataDecrypter.MacKeyLength, this.Decrypter.ServerHMacKey, 0, this.Decrypter.DataDecrypter.MacKeyLength); // Only part of key_block is used to encrypt data this.Decrypter.DataDecrypter.Init(keyBlock); var changeCipherSpecLength = 6; if (serverHelloLength + changeCipherSpecLength < l7Data.Length) { var finishedOffset = serverHelloLength + changeCipherSpecLength; var finished = new Byte[l7Data.Length - finishedOffset]; Array.Copy(l7Data, finishedOffset, finished, 0, finished.Length); this.Decrypter.DoDecryption(finished, pdu, ref this._decryptedBytes); this._decryptedBytes = null; } this._state = SslSessionState.NegotiationChangeCipherSpec; } // Otherwise, new session is made else { this._state = SslSessionState.Negotiation; } } else if (l7Data[0] == Handshake && l7Data[1] == Ssl3VerMajor && l7Data[5] == ClientHello) { // client hello - should be found before server hello message this.Decrypter.ClientRnd = new Byte[32]; Array.Copy(l7Data, 11, this.Decrypter.ClientRnd, 0, this.Decrypter.ClientRnd.Length); } }
static extern SslStatus SSLGetSessionState(/* SSLContextRef */ IntPtr context, ref SslSessionState state);