Add the certificate_required alert.

This is part of TLS 1.3 draft 16 but isn't much of a wire format change,
so go ahead and add it now. When rolling into Chromium, we'll want to
add an entry to the error mapping.

Change-Id: I8fd7f461dca83b725a31ae19ef96c890d603ce53
Reviewed-on: https://boringssl-review.googlesource.com/11563
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
index 9045e9a..c25683e 100644
--- a/crypto/err/ssl.errordata
+++ b/crypto/err/ssl.errordata
@@ -157,7 +157,9 @@
 SSL,1090,TLSV1_ALERT_USER_CANCELLED
 SSL,1114,TLSV1_BAD_CERTIFICATE_HASH_VALUE
 SSL,1113,TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE
+SSL,1116,TLSV1_CERTIFICATE_REQUIRED
 SSL,1111,TLSV1_CERTIFICATE_UNOBTAINABLE
+SSL,1115,TLSV1_UNKNOWN_PSK_IDENTITY
 SSL,1112,TLSV1_UNRECOGNIZED_NAME
 SSL,1110,TLSV1_UNSUPPORTED_EXTENSION
 SSL,217,TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 8d105aa..52ed52c 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2708,6 +2708,7 @@
 #define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION
 #define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY
 #define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR
+#define SSL_AD_INAPPROPRIATE_FALLBACK SSL3_AD_INAPPROPRIATE_FALLBACK
 #define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
 #define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
 #define SSL_AD_MISSING_EXTENSION TLS1_AD_MISSING_EXTENSION
@@ -2718,7 +2719,7 @@
   TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
 #define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY
-#define SSL_AD_INAPPROPRIATE_FALLBACK SSL3_AD_INAPPROPRIATE_FALLBACK
+#define SSL_AD_CERTIFICATE_REQUIRED TLS1_AD_CERTIFICATE_REQUIRED
 
 /* SSL_alert_type_string_long returns a string description of |value| as an
  * alert type (warning or fatal). */
@@ -4764,5 +4765,7 @@
 #define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
 #define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113
 #define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114
+#define SSL_R_TLSV1_UNKNOWN_PSK_IDENTITY 1115
+#define SSL_R_TLSV1_CERTIFICATE_REQUIRED 1116
 
 #endif /* OPENSSL_HEADER_SSL_H */
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index c1db7ab..1c55ab3 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -160,14 +160,14 @@
 #define TLS1_AD_END_OF_EARLY_DATA 1
 #define TLS1_AD_DECRYPTION_FAILED 21
 #define TLS1_AD_RECORD_OVERFLOW 22
-#define TLS1_AD_UNKNOWN_CA 48    /* fatal */
-#define TLS1_AD_ACCESS_DENIED 49 /* fatal */
-#define TLS1_AD_DECODE_ERROR 50  /* fatal */
+#define TLS1_AD_UNKNOWN_CA 48
+#define TLS1_AD_ACCESS_DENIED 49
+#define TLS1_AD_DECODE_ERROR 50
 #define TLS1_AD_DECRYPT_ERROR 51
-#define TLS1_AD_EXPORT_RESTRICTION 60    /* fatal */
-#define TLS1_AD_PROTOCOL_VERSION 70      /* fatal */
-#define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */
-#define TLS1_AD_INTERNAL_ERROR 80        /* fatal */
+#define TLS1_AD_EXPORT_RESTRICTION 60
+#define TLS1_AD_PROTOCOL_VERSION 70
+#define TLS1_AD_INSUFFICIENT_SECURITY 71
+#define TLS1_AD_INTERNAL_ERROR 80
 #define TLS1_AD_USER_CANCELLED 90
 #define TLS1_AD_NO_RENEGOTIATION 100
 #define TLS1_AD_MISSING_EXTENSION 109
@@ -177,7 +177,8 @@
 #define TLS1_AD_UNRECOGNIZED_NAME 112
 #define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
 #define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
-#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115
+#define TLS1_AD_CERTIFICATE_REQUIRED 116
 
 /* ExtensionType values from RFC6066 */
 #define TLSEXT_TYPE_server_name 0
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index 3fdc6e5..1ed0bdf 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -476,6 +476,9 @@
     case TLS1_AD_INTERNAL_ERROR:
       return "internal error";
 
+    case SSL3_AD_INAPPROPRIATE_FALLBACK:
+      return "inappropriate fallback";
+
     case TLS1_AD_USER_CANCELLED:
       return "user canceled";
 
@@ -500,8 +503,8 @@
     case TLS1_AD_UNKNOWN_PSK_IDENTITY:
       return "unknown PSK identity";
 
-    case SSL3_AD_INAPPROPRIATE_FALLBACK:
-      return "inappropriate fallback";
+    case TLS1_AD_CERTIFICATE_REQUIRED:
+      return "certificate required";
 
     default:
       return "unknown";
diff --git a/ssl/test/runner/alert.go b/ssl/test/runner/alert.go
index b690c6f..8320b7e 100644
--- a/ssl/test/runner/alert.go
+++ b/ssl/test/runner/alert.go
@@ -43,6 +43,7 @@
 	alertUnsupportedExtension   alert = 110
 	alertUnrecognizedName       alert = 112
 	alertUnknownPSKIdentity     alert = 115
+	alertCertificateRequired    alert = 116
 )
 
 var alertText = map[alert]string{
@@ -73,6 +74,7 @@
 	alertUnsupportedExtension:   "unsupported extension",
 	alertUnrecognizedName:       "unrecognized name",
 	alertUnknownPSKIdentity:     "unknown PSK identity",
+	alertCertificateRequired:    "certificate required",
 }
 
 func (e alert) String() string {
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 7c2fd17..abadf3a 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -830,7 +830,7 @@
 			// The client didn't actually send a certificate
 			switch config.ClientAuth {
 			case RequireAnyClientCert, RequireAndVerifyClientCert:
-				c.sendAlert(alertBadCertificate)
+				c.sendAlert(alertCertificateRequired)
 				return errors.New("tls: client didn't provide a certificate")
 			}
 		}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 2a7f141..8ca3917 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -2950,6 +2950,12 @@
 			resumeSession: true,
 		})
 
+		certificateRequired := "remote error: certificate required"
+		if ver.version < VersionTLS13 {
+			// Prior to TLS 1.3, the generic handshake_failure alert
+			// was used.
+			certificateRequired = "remote error: handshake failure"
+		}
 		testCases = append(testCases, testCase{
 			testType: serverTest,
 			name:     "RequireAnyClientCertificate-" + ver.name,
@@ -2957,9 +2963,10 @@
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
 			},
-			flags:         []string{"-require-any-client-certificate"},
-			shouldFail:    true,
-			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+			flags:              []string{"-require-any-client-certificate"},
+			shouldFail:         true,
+			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+			expectedLocalError: certificateRequired,
 		})
 
 		if ver.version != VersionSSL30 {
diff --git a/ssl/tls13_both.c b/ssl/tls13_both.c
index e634790..3928ab7 100644
--- a/ssl/tls13_both.c
+++ b/ssl/tls13_both.c
@@ -178,7 +178,7 @@
   if (sk_X509_num(chain) == 0) {
     if (!allow_anonymous) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
       goto err;
     }