Implement OCSP stapling and SCT in Go TLS 1.3.

While the random connection property extensions like ALPN and SRTP
remain largely unchanged in TLS 1.3 (but for interaction with 0-RTT),
authentication-related extensions change significantly and need
dedicated logic.

Change-Id: I2588935c2563a22e9879fb81478b8df5168b43de
Reviewed-on: https://boringssl-review.googlesource.com/8602
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 1ec5aab..5496fa2 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -497,9 +497,18 @@
 	var chainToSend *Certificate
 	var certRequested bool
 	var certRequestContext []byte
-	if hs.suite.flags&suitePSK == 0 {
-		// TODO(davidben): Save OCSP response and SCT list. Forbid them
-		// if not negotiating a certificate-based extension.
+	if hs.suite.flags&suitePSK != 0 {
+		if encryptedExtensions.extensions.ocspResponse != nil {
+			c.sendAlert(alertUnsupportedExtension)
+			return errors.New("tls: server sent OCSP response without a certificate")
+		}
+		if encryptedExtensions.extensions.sctList != nil {
+			c.sendAlert(alertUnsupportedExtension)
+			return errors.New("tls: server sent SCT list without a certificate")
+		}
+	} else {
+		c.ocspResponse = encryptedExtensions.extensions.ocspResponse
+		c.sctList = encryptedExtensions.extensions.sctList
 
 		msg, err := c.readHandshake()
 		if err != nil {
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index d349ae7..baa07bd 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -738,7 +738,7 @@
 			extensions.addU16(0) // Length
 		}
 	} else {
-		m.extensions.marshal(extensions)
+		m.extensions.marshal(extensions, m.vers)
 		if extensions.len() == 0 {
 			hello.discardChild()
 		}
@@ -837,7 +837,7 @@
 				return false
 			}
 		}
-	} else if !m.extensions.unmarshal(data) {
+	} else if !m.extensions.unmarshal(data, m.vers) {
 		return false
 	}
 
@@ -858,7 +858,7 @@
 	encryptedExtensionsMsg.addU8(typeEncryptedExtensions)
 	encryptedExtensions := encryptedExtensionsMsg.addU24LengthPrefixed()
 	extensions := encryptedExtensions.addU16LengthPrefixed()
-	m.extensions.marshal(extensions)
+	m.extensions.marshal(extensions, VersionTLS13)
 
 	m.raw = encryptedExtensionsMsg.finish()
 	return m.raw
@@ -881,13 +881,14 @@
 	if extLen != len(data) {
 		return false
 	}
-	return m.extensions.unmarshal(data)
+	return m.extensions.unmarshal(data, VersionTLS13)
 }
 
 type serverExtensions struct {
 	nextProtoNeg            bool
 	nextProtos              []string
 	ocspStapling            bool
+	ocspResponse            []byte
 	ticketSupported         bool
 	secureRenegotiation     []byte
 	alpnProtocol            string
@@ -902,7 +903,7 @@
 	npnLast                 bool
 }
 
-func (m *serverExtensions) marshal(extensions *byteBuilder) {
+func (m *serverExtensions) marshal(extensions *byteBuilder, version uint16) {
 	if m.duplicateExtension {
 		// Add a duplicate bogus extension at the beginning and end.
 		extensions.addU16(0xffff)
@@ -920,9 +921,19 @@
 			npn.addBytes([]byte(v))
 		}
 	}
-	if m.ocspStapling {
-		extensions.addU16(extensionStatusRequest)
-		extensions.addU16(0)
+	if version >= VersionTLS13 && enableTLS13Handshake {
+		if m.ocspResponse != nil {
+			extensions.addU16(extensionStatusRequest)
+			body := extensions.addU16LengthPrefixed()
+			body.addU8(statusTypeOCSP)
+			response := body.addU24LengthPrefixed()
+			response.addBytes(m.ocspResponse)
+		}
+	} else {
+		if m.ocspStapling {
+			extensions.addU16(extensionStatusRequest)
+			extensions.addU16(0)
+		}
 	}
 	if m.ticketSupported {
 		extensions.addU16(extensionSessionTicket)
@@ -989,7 +1000,7 @@
 	}
 }
 
-func (m *serverExtensions) unmarshal(data []byte) bool {
+func (m *serverExtensions) unmarshal(data []byte, version uint16) bool {
 	// Reset all fields.
 	*m = serverExtensions{}
 
@@ -1018,10 +1029,25 @@
 				d = d[l:]
 			}
 		case extensionStatusRequest:
-			if length > 0 {
-				return false
+			if version >= VersionTLS13 && enableTLS13Handshake {
+				if length < 4 {
+					return false
+				}
+				d := data[:length]
+				if d[0] != statusTypeOCSP {
+					return false
+				}
+				respLen := int(d[1])<<16 | int(d[2])<<8 | int(d[3])
+				if respLen+4 != len(d) || respLen == 0 {
+					return false
+				}
+				m.ocspResponse = d[4:]
+			} else {
+				if length > 0 {
+					return false
+				}
+				m.ocspStapling = true
 			}
-			m.ocspStapling = true
 		case extensionSessionTicket:
 			if length > 0 {
 				return false