Fix SSL_version on 0-RTT.

Like other handshake properties, when in 0-RTT on the client,
SSL_version should report the predicted version. This used to work on
accident because of how ssl->version got set in handshake_client.c early
(and that TLS 1.4 does not exist), but we no longer do that.

Change-Id: Ifb63a22b795fe8964ac553844a46040acd5d7323
Reviewed-on: https://boringssl-review.googlesource.com/17664
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/ssl_versions.c b/ssl/ssl_versions.c
index 80b62cc..5d92771 100644
--- a/ssl/ssl_versions.c
+++ b/ssl/ssl_versions.c
@@ -224,13 +224,21 @@
   return 1;
 }
 
+static uint16_t ssl_version(const SSL *ssl) {
+  /* In early data, we report the predicted version. */
+  if (SSL_in_early_data(ssl) && !ssl->server) {
+    return ssl->s3->hs->early_session->ssl_version;
+  }
+  return ssl->version;
+}
+
 int SSL_version(const SSL *ssl) {
+  uint16_t ret = ssl_version(ssl);
   /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
-  if (ssl->version == TLS1_3_DRAFT_VERSION) {
+  if (ret == TLS1_3_DRAFT_VERSION) {
     return TLS1_3_VERSION;
   }
-
-  return ssl->version;
+  return ret;
 }
 
 static const char *ssl_get_version(int version) {
@@ -263,7 +271,7 @@
 }
 
 const char *SSL_get_version(const SSL *ssl) {
-  return ssl_get_version(ssl->version);
+  return ssl_get_version(ssl_version(ssl));
 }
 
 const char *SSL_SESSION_get_version(const SSL_SESSION *session) {
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index f3cbec1..6d3e6d1 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -1372,6 +1372,13 @@
     return false;
   }
 
+  if (config->expect_version != 0 &&
+      SSL_version(ssl) != config->expect_version) {
+    fprintf(stderr, "want version %04x, got %04x\n", config->expect_version,
+            SSL_version(ssl));
+    return false;
+  }
+
   bool expect_resume =
       is_resume && (!config->expect_session_miss || SSL_in_early_data(ssl));
   if (!!SSL_session_reused(ssl) != expect_resume) {
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 04c94b2..03ba755 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -11155,6 +11155,24 @@
 			"-enable-early-data",
 		},
 	})
+
+	// Test that the client reports TLS 1.3 as the version while sending
+	// early data.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-EarlyData-Client-VersionAPI",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-expect-accept-early-data",
+			"-expect-version", strconv.Itoa(VersionTLS13),
+		},
+	})
 }
 
 func addTLS13CipherPreferenceTests() {
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 2004565..195371f 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -174,6 +174,7 @@
   { "-resume-count", &TestConfig::resume_count },
   { "-min-version", &TestConfig::min_version },
   { "-max-version", &TestConfig::max_version },
+  { "-expect-version", &TestConfig::expect_version },
   { "-mtu", &TestConfig::mtu },
   { "-export-keying-material", &TestConfig::export_keying_material },
   { "-expect-total-renegotiations", &TestConfig::expect_total_renegotiations },
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 8ad53d5..7b4b342 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -69,6 +69,7 @@
   std::string expected_signed_cert_timestamps;
   int min_version = 0;
   int max_version = 0;
+  int expect_version = 0;
   int mtu = 0;
   bool implicit_handshake = false;
   bool use_early_callback = false;