Consolidate CCS_OK paths in s3_clnt.c.

Introduce a CR_CHANGE state just before entering CR_FINISHED_A. This replaces
the CCS_OK in the CR_FINISHED_A/CR_FINISHED_B case which otherwise would get
applied after partial reads of Finished. The other CCS_OK settings are
redundant with this one.

The copy in tls_secret_session_cb codepath is made unnecessary with
9eaeef81fa2d4fd6246dc02b6203fa936a5eaf67.

The copy in the normal session resumption case is unnecessary with
6444287806d801b9a45baf1f6f02a0e3a16e144c. Before that commit, OpenSSL would
potentially read Finished a state early. Now that we are strict (and get the
book-keeping correct) for expecting the NewSessionTicket message it too is
redundant.

Of particular note is the one after ssl3_send_finished. That was added in
response to upstream's PR#3400. I've reproduced the bug and concluded it was
actually a bug around expecting a NewSessionTicket message. That has been fixed
properly in 6444287806d801b9a45baf1f6f02a0e3a16e144c by resetting
tlsext_expect_ticket on renegotiations.

Change-Id: I6a928386994fcd5efff26a5f0efb12b65bf7f299
Reviewed-on: https://boringssl-review.googlesource.com/1298
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index dda2ef7..52d88c6 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -279,7 +279,7 @@
 
 			if (s->hit)
 				{
-				s->state=SSL3_ST_CR_FINISHED_A;
+				s->state=SSL3_ST_CR_CHANGE;
 				if (s->tlsext_ticket_expected)
 					{
 					/* receive renewed session ticket */
@@ -457,7 +457,6 @@
 				s->method->ssl3_enc->client_finished_label,
 				s->method->ssl3_enc->client_finished_label_len);
 			if (ret <= 0) goto end;
-			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			s->state=SSL3_ST_CW_FLUSH;
 
 			/* clear flags */
@@ -493,7 +492,7 @@
 					if (s->tlsext_ticket_expected)
 						s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
 					else
-						s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
+						s->s3->tmp.next_state=SSL3_ST_CR_CHANGE;
 					}
 				}
 			s->init_num=0;
@@ -503,7 +502,7 @@
 		case SSL3_ST_CR_SESSION_TICKET_B:
 			ret=ssl3_get_new_session_ticket(s);
 			if (ret <= 0) goto end;
-			s->state=SSL3_ST_CR_FINISHED_A;
+			s->state=SSL3_ST_CR_CHANGE;
 			s->init_num=0;
 		break;
 
@@ -515,10 +514,15 @@
 			s->init_num=0;
 		break;
 
+		case SSL3_ST_CR_CHANGE:
+			/* At this point, the next message must be entirely
+			 * behind a ChangeCipherSpec. */
+			s->s3->flags |= SSL3_FLAGS_CCS_OK;
+			s->state = SSL3_ST_CR_FINISHED_A;
+			break;
+
 		case SSL3_ST_CR_FINISHED_A:
 		case SSL3_ST_CR_FINISHED_B:
-
-			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
 				SSL3_ST_CR_FINISHED_B);
 			if (ret <= 0) goto end;
@@ -943,7 +947,6 @@
 			s->session->cipher = pref_cipher ?
 				pref_cipher :
 				ssl3_get_cipher_by_value(cipher_suite);
-	    		s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			s->hit = 1;
 			}
 		}
@@ -960,7 +963,6 @@
 			OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
 			goto f_err;
 			}
-		s->s3->flags |= SSL3_FLAGS_CCS_OK;
 		s->hit = 1;
 		}