Don't allow invalid SCT lists to be set.

This change causes SSL_CTX_set_signed_cert_timestamp_list to check the
SCT list for shallow validity before allowing it to be set.

Change-Id: Ib8a1fe185224ff02ed4ce53a0109e60d934e96b3
Reviewed-on: https://boringssl-review.googlesource.com/12401
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
index e034001..b50f9ab 100644
--- a/crypto/err/ssl.errordata
+++ b/crypto/err/ssl.errordata
@@ -66,6 +66,7 @@
 SSL,256,INVALID_COMPRESSION_LIST
 SSL,159,INVALID_MESSAGE
 SSL,251,INVALID_OUTER_RECORD_TYPE
+SSL,269,INVALID_SCT_LIST
 SSL,160,INVALID_SSL_SESSION
 SSL,161,INVALID_TICKET_KEYS_LENGTH
 SSL,162,LENGTH_MISMATCH
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index e39fa89..f5b9f9d 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -4551,6 +4551,7 @@
 #define SSL_R_NO_SHARED_GROUP 266
 #define SSL_R_PRE_SHARED_KEY_MUST_BE_LAST 267
 #define SSL_R_OLD_SESSION_PRF_HASH_MISMATCH 268
+#define SSL_R_INVALID_SCT_LIST 269
 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 001928f..70a39ea 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1779,16 +1779,15 @@
 
 int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx, const uint8_t *list,
                                            size_t list_len) {
-  OPENSSL_free(ctx->signed_cert_timestamp_list);
-  ctx->signed_cert_timestamp_list_length = 0;
-
-  ctx->signed_cert_timestamp_list = BUF_memdup(list, list_len);
-  if (ctx->signed_cert_timestamp_list == NULL) {
+  CBS sct_list;
+  CBS_init(&sct_list, list, list_len);
+  if (!ssl_is_sct_list_valid(&sct_list)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SCT_LIST);
     return 0;
   }
-  ctx->signed_cert_timestamp_list_length = list_len;
 
-  return 1;
+  return CBS_stow(&sct_list, &ctx->signed_cert_timestamp_list,
+                  &ctx->signed_cert_timestamp_list_length);
 }
 
 int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response,
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 6c0cd57..683f07c 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -5560,6 +5560,17 @@
 		shouldFail:    true,
 		expectedError: ":DUPLICATE_EXTENSION:",
 	})
+
+	testCases = append(testCases, testCase{
+		name:     "SignedCertificateTimestampListInvalid-Server",
+		testType: serverTest,
+		flags: []string{
+			"-signed-cert-timestamps",
+			base64.StdEncoding.EncodeToString([]byte{0, 0}),
+		},
+		shouldFail: true,
+		expectedError: ":INVALID_SCT_LIST:",
+	})
 }
 
 func addResumptionVersionTests() {