Add tests for OCSP stapling and SCT lists.

We forgot to add those when we implemented the features. (Also relevant because
they will provide test coverage later for configuring features when using the
generic method tables rather than *_client_method.)

Change-Id: Ie08b27de893095e01a05a7084775676616459807
Reviewed-on: https://boringssl-review.googlesource.com/2410
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 476a2a4..02ee7e2 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -72,18 +72,19 @@
 
 // TLS extension numbers
 const (
-	extensionServerName           uint16 = 0
-	extensionStatusRequest        uint16 = 5
-	extensionSupportedCurves      uint16 = 10
-	extensionSupportedPoints      uint16 = 11
-	extensionSignatureAlgorithms  uint16 = 13
-	extensionUseSRTP              uint16 = 14
-	extensionALPN                 uint16 = 16
-	extensionExtendedMasterSecret uint16 = 23
-	extensionSessionTicket        uint16 = 35
-	extensionNextProtoNeg         uint16 = 13172 // not IANA assigned
-	extensionRenegotiationInfo    uint16 = 0xff01
-	extensionChannelID            uint16 = 30032 // not IANA assigned
+	extensionServerName                 uint16 = 0
+	extensionStatusRequest              uint16 = 5
+	extensionSupportedCurves            uint16 = 10
+	extensionSupportedPoints            uint16 = 11
+	extensionSignatureAlgorithms        uint16 = 13
+	extensionUseSRTP                    uint16 = 14
+	extensionALPN                       uint16 = 16
+	extensionSignedCertificateTimestamp uint16 = 18
+	extensionExtendedMasterSecret       uint16 = 23
+	extensionSessionTicket              uint16 = 35
+	extensionNextProtoNeg               uint16 = 13172 // not IANA assigned
+	extensionRenegotiationInfo          uint16 = 0xff01
+	extensionChannelID                  uint16 = 30032 // not IANA assigned
 )
 
 // TLS signaling cipher suite values
@@ -731,6 +732,10 @@
 	// OCSPStaple contains an optional OCSP response which will be served
 	// to clients that request it.
 	OCSPStaple []byte
+	// SignedCertificateTimestampList contains an optional encoded
+	// SignedCertificateTimestampList structure which will be
+	// served to clients that request it.
+	SignedCertificateTimestampList []byte
 	// Leaf is the parsed form of the leaf certificate, which may be
 	// initialized using x509.ParseCertificate to reduce per-handshake
 	// processing for TLS clients doing client authentication. If nil, the
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index cb3b5c4..ce214fd 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -31,6 +31,7 @@
 	extendedMasterSecret    bool
 	srtpProtectionProfiles  []uint16
 	srtpMasterKeyIdentifier string
+	sctListSupported        bool
 }
 
 func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -63,7 +64,8 @@
 		m.npnLast == m1.npnLast &&
 		m.extendedMasterSecret == m1.extendedMasterSecret &&
 		eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
-		m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier
+		m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
+		m.sctListSupported == m1.sctListSupported
 }
 
 func (m *clientHelloMsg) marshal() []byte {
@@ -133,6 +135,9 @@
 		extensionsLength += 1 + len(m.srtpMasterKeyIdentifier)
 		numExtensions++
 	}
+	if m.sctListSupported {
+		numExtensions++
+	}
 	if numExtensions > 0 {
 		extensionsLength += 4 * numExtensions
 		length += 2 + extensionsLength
@@ -366,6 +371,11 @@
 		copy(z[1:], []byte(m.srtpMasterKeyIdentifier))
 		z = z[1+mkiLen:]
 	}
+	if m.sctListSupported {
+		z[0] = byte(extensionSignedCertificateTimestamp >> 8)
+		z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
+		z = z[4:]
+	}
 
 	m.raw = x
 
@@ -589,6 +599,11 @@
 				return false
 			}
 			m.srtpMasterKeyIdentifier = string(d[1:])
+		case extensionSignedCertificateTimestamp:
+			if length != 0 {
+				return false
+			}
+			m.sctListSupported = true
 		}
 		data = data[length:]
 	}
@@ -615,6 +630,7 @@
 	extendedMasterSecret    bool
 	srtpProtectionProfile   uint16
 	srtpMasterKeyIdentifier string
+	sctList                 []byte
 }
 
 func (m *serverHelloMsg) equal(i interface{}) bool {
@@ -641,7 +657,8 @@
 		m.channelIDRequested == m1.channelIDRequested &&
 		m.extendedMasterSecret == m1.extendedMasterSecret &&
 		m.srtpProtectionProfile == m1.srtpProtectionProfile &&
-		m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier
+		m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
+		bytes.Equal(m.sctList, m1.sctList)
 }
 
 func (m *serverHelloMsg) marshal() []byte {
@@ -692,6 +709,10 @@
 		extensionsLength += 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
 		numExtensions++
 	}
+	if m.sctList != nil {
+		extensionsLength += len(m.sctList)
+		numExtensions++
+	}
 
 	if numExtensions > 0 {
 		extensionsLength += 4 * numExtensions
@@ -808,6 +829,15 @@
 		copy(z[9:], []byte(m.srtpMasterKeyIdentifier))
 		z = z[9+l:]
 	}
+	if m.sctList != nil {
+		z[0] = byte(extensionSignedCertificateTimestamp >> 8)
+		z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
+		l := len(m.sctList)
+		z[2] = byte(l >> 8)
+		z[3] = byte(l & 0xff)
+		copy(z[4:], m.sctList)
+		z = z[4+l:]
+	}
 
 	m.raw = x
 
@@ -934,6 +964,15 @@
 				return false
 			}
 			m.srtpMasterKeyIdentifier = string(d[1:])
+		case extensionSignedCertificateTimestamp:
+			if length < 2 {
+				return false
+			}
+			l := int(data[0])<<8 | int(data[1])
+			if l != len(data)-2 {
+				return false
+			}
+			m.sctList = data[2:length]
 		}
 		data = data[length:]
 	}
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index b087b46..ec79b79 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -428,6 +428,10 @@
 		hs.hello.ocspStapling = true
 	}
 
+	if hs.clientHello.sctListSupported && len(hs.cert.SignedCertificateTimestampList) > 0 {
+		hs.hello.sctList = hs.cert.SignedCertificateTimestampList
+	}
+
 	hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled && c.vers > VersionSSL30
 	hs.hello.cipherSuite = hs.suite.id
 	c.extendedMasterSecret = hs.hello.extendedMasterSecret
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 1ee6362..697437b 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -45,17 +45,24 @@
 var channelIDKey *ecdsa.PrivateKey
 var channelIDBytes []byte
 
+var testOCSPResponse = []byte{1, 2, 3, 4}
+var testSCTList = []byte{5, 6, 7, 8}
+
 func initCertificates() {
 	var err error
 	rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
 	if err != nil {
 		panic(err)
 	}
+	rsaCertificate.OCSPStaple = testOCSPResponse
+	rsaCertificate.SignedCertificateTimestampList = testSCTList
 
 	ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
 	if err != nil {
 		panic(err)
 	}
+	ecdsaCertificate.OCSPStaple = testOCSPResponse
+	ecdsaCertificate.SignedCertificateTimestampList = testSCTList
 
 	channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
 	if err != nil {
@@ -1878,6 +1885,23 @@
 		shouldFail:    true,
 		expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
 	})
+	// Test OCSP stapling and SCT list.
+	testCases = append(testCases, testCase{
+		name: "OCSPStapling",
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-expect-ocsp-response",
+			base64.StdEncoding.EncodeToString(testOCSPResponse),
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "SignedCertificateTimestampList",
+		flags: []string{
+			"-enable-signed-cert-timestamps",
+			"-expect-signed-cert-timestamps",
+			base64.StdEncoding.EncodeToString(testSCTList),
+		},
+	})
 }
 
 func addResumptionVersionTests() {