If you do Finished
after change_cipher_spec
, and since Finished
has to be the first message after setting the cipher spec, you get the added benefit of requiring a successful decryption of a message before any (potentially sensitive) user data is transmitted. This step serves as an extra "checksum".
From Section 7.4.9 of RFC 5246: (emphasis mine)
The Finished message is the first one protected with the just
negotiated algorithms, keys, and secrets. Recipients of Finished
messages MUST verify that the contents are correct. Once a side
has sent its Finished message and received and validated the
Finished message from its peer, it may begin to send and receive
application data over the connection.
Edit:
You wonder if encrypting Finished
is unnecessary given that verify_data
provides sufficient authentication against tampering. I claim that an sending an unencrypted Finished
message would be quite disastrous for TLS.
The end of a normal TLS handshake looks as follows:
$\text{client} \rightarrow \text{server}:$ change_cipher_spec
$\text{client} \rightarrow \text{server}:$ Finished
$a_k$
$\text{server} \rightarrow \text{client}:$ change_cipher_spec
$\text{server} \rightarrow \text{client}:$ Finished
$a_k$
$\text{client} \rightarrow \text{server}:$ encrypted application data transmits...
$m_k$
Here, $a_k$ and $m_k$ are the authenticaton code for Finished
and session data keyed by $k$. It's important to reiterate that before a change_cipher_spec
message is received, the current cipher suite offers no encryption or authentication; it's still pending the negotiated parameters upon receipt of change_cipher_spec
.
Now imagine Andy Adversary on the network observing this handshake. In the special case where the negotiated cipher suite only handles authentication and not encryption, Andy removes the change_cipher_spec
messages, so that the client and server never update their cipher suites and thus never enable authentication or encryption with the negotiated parameters. Welcome to catastrophe. Now Andy sits in the middle, stripping off authentication fields from Finished
messages and later sensitive session data. So now you have no authentication either.
Here's the modified, defeated handshake:
$\text{client} \rightarrow \text{adversary}:$ change_cipher_spec
$\text{client} \rightarrow \text{adversary}:$ Finished
$a_k$
$\text{adversary} \rightarrow \text{client}:$ Finished
$a$
$\text{server} \rightarrow \text{adversary}:$ change_cipher_spec
$\text{server} \rightarrow \text{adversary}:$ Finished
$a_k$
$\text{adversary} \rightarrow \text{client}:$ Finished
$a$
$\text{client} \rightarrow \text{adversary}:$ unencrypted application data transmits...
$m_k$
$\text{adversary} \rightarrow \text{server}:$ unencrypted application data transmits...
$m$
It's easy for Andy Adversary to strip off the MAC field since there's no encryption. So now he has not only access to unencrypted, unauthenticated messages, but he can also forge whatever messages he likes.
If encryption were part of the cipher suite as is normal, the attack is much harder, but the point is that by passing in Finished
after change_cipher_spec
, you eliminate even the possibility of the attack.
What I have described here comes directly from Wagner and Schneier, who knew of this attack by 1997. As a matter of fact, they note that Netscape's SSL 3 implementation was vulnerable to it. Read Section 4.3 of that paper for more details.
Their recommendation to prevent such attacks?
The simplest fix is to require that a SSL implementation
receive a change cipher spec message before
accepting a finished message.
They recognize this as a basic flaw in the specification of SSL, which of course was corrected in TLS:
Some readers might complain
that this requirement ought to be obvious with a moment’s
reflection, even if it is not explicitly stated in
the SSL specification. We cannot fault such clarity of vision.
In general, this is not the only attack that can be prevented by the "checksum" argument, or what Bellare and Rogaway call matching conversations, where both client and server verify encryption and authentication before transmitting sensitive data. See Section II-1 for another.
Conclusion: sending an encrypted Finished
after change_cipher_spec
is the simplest solution to protect the change_cipher_spec
message.