protected override void ProcessFinished(HandshakeMessage finished) { if (_state != HandshakeState.ReceivedChangeCipherSpec) { throw new AlertException(AlertDescription.UnexpectedMessage, "Finished received at the wrong time"); } byte[] allMessages = _handshakeStream.ToArray(); byte[] handshakeMessages = new byte[allMessages.Length - finished.Encode().Length]; Buffer.BlockCopy(allMessages, 0, handshakeMessages, 0, handshakeMessages.Length); PseudoRandomFunction prf = _cipherSuite.PseudoRandomFunction; HashAlgorithm verifyHash = prf.CreateVerifyHashAlgorithm(_connectionState.MasterSecret); verifyHash.TransformBlock(handshakeMessages, 0, handshakeMessages.Length, handshakeMessages, 0); byte[] ourVerifyData; if (_version == ProtocolVersion.SSL3_0) { byte[] senderBytes = Encoding.ASCII.GetBytes("CLNT"); verifyHash.TransformFinalBlock(senderBytes, 0, senderBytes.Length); ourVerifyData = verifyHash.Hash; } else { verifyHash.TransformFinalBlock(new byte[0], 0, 0); byte[] hash = verifyHash.Hash; int length = _cipherSuite.PseudoRandomFunction.VerifyDataLength; ourVerifyData = _cipherSuite.PseudoRandomFunction.GetBytes(_connectionState.MasterSecret, "client finished", hash, length); } // Verify that the received data matches ours bool verifyOk = false; if (ourVerifyData.Length == finished.Data.Length) { verifyOk = true; for (int i = 0; i < ourVerifyData.Length; i++) { if (ourVerifyData[i] != finished.Data[i]) { verifyOk = false; } } } if (!verifyOk) { throw new AlertException(AlertDescription.DecryptError, "Finished packet contents incorrect"); } _connectionState.ClientVerifyData = ourVerifyData; // Send our own change cipher spec _state = HandshakeState.SendChangeCipherSpec; }
public void SendFinished(Stream stream) { Record record; /* change cipher spec */ record = new Record(20, VERSION); record.Fragment = new byte[] { 0x01 }; _recordHandler.ProcessOutputRecord(record); SendRecord(stream, record); /* change our own cipher spec */ _recordHandler.ChangeLocalState(); ProtocolVersion version = VERSION; byte[] handshakeMessages = _handshakeStream.ToArray(); Console.WriteLine("handshake messages length " + handshakeMessages.Length); PseudoRandomFunction prf = _cipherSuite.PseudoRandomFunction; HashAlgorithm verifyHash = prf.CreateVerifyHashAlgorithm(_masterSecret); verifyHash.TransformBlock(handshakeMessages, 0, handshakeMessages.Length, handshakeMessages, 0); byte[] verifyData; if (version == ProtocolVersion.SSL3_0) { byte[] senderBytes = Encoding.ASCII.GetBytes("CLNT"); verifyHash.TransformFinalBlock(senderBytes, 0, senderBytes.Length); verifyData = verifyHash.Hash; } else { verifyHash.TransformFinalBlock(new byte[0], 0, 0); byte[] hash = verifyHash.Hash; int length = _cipherSuite.PseudoRandomFunction.VerifyDataLength; verifyData = _cipherSuite.PseudoRandomFunction.GetBytes(_masterSecret, "client finished", hash, length); } HandshakeMessage finished = new HandshakeMessage(HandshakeMessageType.Finished, VERSION, verifyData); PrintBytes("verify data", finished.Data); record = new Record(22, VERSION); record.Fragment = finished.Encode(); _recordHandler.ProcessOutputRecord(record); SendRecord(stream, record); Console.WriteLine("encrypted finished sent"); }
protected override void ProcessLocalChangeCipherSpec() { if (_state != HandshakeState.SendChangeCipherSpec) { throw new AlertException(AlertDescription.UnexpectedMessage, "Change cipher spec not after server hello done"); } byte[] handshakeMessages = _handshakeStream.ToArray(); PseudoRandomFunction prf = _cipherSuite.PseudoRandomFunction; HashAlgorithm verifyHash = prf.CreateVerifyHashAlgorithm(_connectionState.MasterSecret); verifyHash.TransformBlock(handshakeMessages, 0, handshakeMessages.Length, handshakeMessages, 0); byte[] verifyData; if (_version == ProtocolVersion.SSL3_0) { byte[] senderBytes = Encoding.ASCII.GetBytes("SRVR"); verifyHash.TransformFinalBlock(senderBytes, 0, senderBytes.Length); verifyData = verifyHash.Hash; } else { verifyHash.TransformFinalBlock(new byte[0], 0, 0); byte[] hash = verifyHash.Hash; int length = _cipherSuite.PseudoRandomFunction.VerifyDataLength; verifyData = _cipherSuite.PseudoRandomFunction.GetBytes(_connectionState.MasterSecret, "server finished", hash, length); } _connectionState.ServerVerifyData = verifyData; HandshakeMessage finished = new HandshakeMessage(HandshakeMessageType.Finished, _version, verifyData); OutputMessage(finished); // Cleanup the handshake stream used for verify hashes _handshakeStream = new MemoryStream(); // Everything done and handshake finished _state = HandshakeState.Finished; }