Remove method swap in DTLS_ANY_VERSION.

DTLS_method() can now negotiate versions without switching methods.

Change-Id: I0655b3221b6e7e4b3ed4acc45f1f41c594447021
Reviewed-on: https://boringssl-review.googlesource.com/2582
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 4f98ac9..0021657 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -1317,15 +1317,15 @@
 	 * we haven't decided which version to use yet send back using 
 	 * version 1.0 header: otherwise some clients will ignore it.
 	 */
-	if (s->method->version == DTLS_ANY_VERSION)
+	if (!s->s3->have_version)
 		{
-		*(p++)=DTLS1_VERSION>>8;
-		*(p++)=DTLS1_VERSION&0xff;
+		*(p++) = DTLS1_VERSION >> 8;
+		*(p++) = DTLS1_VERSION & 0xff;
 		}
 	else
 		{
-		*(p++)=s->version>>8;
-		*(p++)=s->version&0xff;
+		*(p++) = s->version >> 8;
+		*(p++) = s->version & 0xff;
 		}
 
 	/* field where we are to write out packet epoch, seq num and len */
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 5570a82..2f2c451 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -590,7 +590,7 @@
 	buf=(unsigned char *)s->init_buf->data;
 	if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
 		{
-		if (s->method->version == DTLS_ANY_VERSION)
+		if (!s->s3->have_version && s->method->version == DTLS_ANY_VERSION)
 			{
 			uint16_t max_version = ssl3_get_max_client_version(s);
 			/* Disabling all versions is silly: return an error. */
@@ -771,7 +771,7 @@
 		goto f_err;
 		}
 
-	if (s->method->version == DTLS_ANY_VERSION)
+	if (!s->s3->have_version && s->method->version == DTLS_ANY_VERSION)
 		{
 		if (!ssl3_is_version_enabled(s, server_version))
 			{
@@ -781,13 +781,10 @@
 			goto f_err;
 			}
 		s->version = server_version;
-		s->method = ssl3_get_method(server_version);
-		assert(s->method != NULL);
 		s->enc_method = ssl3_get_enc_method(server_version);
 		assert(s->enc_method != NULL);
 		}
-
-	if (server_version != s->version)
+	else if (server_version != s->version)
 		{
 		OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_SSL_VERSION);
 		s->version = (s->version & 0xff00) | (server_version & 0xff);
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index f9012cc..71f7fef 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -794,21 +794,6 @@
 	 * (may differ: see RFC 2246, Appendix E, second paragraph) */
 	s->client_version = client_version;
 
-	if (SSL_IS_DTLS(s)  ?	(s->client_version > s->version &&
-				 s->method->version != DTLS_ANY_VERSION)
-			    :	(s->client_version < s->version))
-		{
-		OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER);
-		if ((s->client_version>>8) == SSL3_VERSION_MAJOR &&
-			!s->s3->have_version)
-			{
-			/* similar to ssl3_get_record, send alert using remote version number */
-			s->version = s->client_version;
-			}
-		al = SSL_AD_PROTOCOL_VERSION;
-		goto f_err;
-		}
-
 	/* Load the client random. */
 	memcpy(s->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
 
@@ -850,24 +835,35 @@
 			 * don't send HelloVerifyRequest. */
 			ret = -2;
 			}
+		}
 
-		if (s->method->version == DTLS_ANY_VERSION)
+	if (!s->s3->have_version && s->method->version == DTLS_ANY_VERSION)
+		{
+		/* Select version to use */
+		uint16_t version = ssl3_get_mutual_version(s, client_version);
+		if (version == 0)
 			{
-			/* Select version to use */
-			uint16_t version = ssl3_get_mutual_version(s, client_version);
-			if (version == 0)
-				{
-				OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER);
-				s->version = s->client_version;
-				al = SSL_AD_PROTOCOL_VERSION;
-				goto f_err;
-				}
-			s->version = version;
-			s->method = ssl3_get_method(version);
-			assert(s->method != NULL);
-			s->enc_method = ssl3_get_enc_method(version);
-			assert(s->enc_method != NULL);
+			OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER);
+			s->version = s->client_version;
+			al = SSL_AD_PROTOCOL_VERSION;
+			goto f_err;
 			}
+		s->version = version;
+		s->enc_method = ssl3_get_enc_method(version);
+		assert(s->enc_method != NULL);
+		}
+	else if (SSL_IS_DTLS(s)  ?	(s->client_version > s->version)
+		                 :	(s->client_version < s->version))
+		{
+		OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER);
+		if ((s->client_version>>8) == SSL3_VERSION_MAJOR &&
+			!s->s3->have_version)
+			{
+			/* similar to ssl3_get_record, send alert using remote version number */
+			s->version = s->client_version;
+			}
+		al = SSL_AD_PROTOCOL_VERSION;
+		goto f_err;
 		}
 
 	/* At this point, the connection's version is known and s->version is