diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index e4469e8f..f6ad654e 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2736,6 +2736,7 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void); #define SSL_R_SESSION_MAY_NOT_BE_CREATED 442 #define SSL_R_INVALID_SSL_SESSION 443 #define SSL_R_BAD_ALERT 444 +#define SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO 445 #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/s3_clnt.c b/ssl/s3_clnt.c index 1a458056..fdcaf764 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -748,6 +748,18 @@ int ssl3_get_server_hello(SSL *s) { SSL_GET_MESSAGE_HASH_MESSAGE, &ok); if (!ok) { + uint32_t err = ERR_peek_error(); + if (ERR_GET_LIB(err) == ERR_LIB_SSL && + ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE) { + /* Add a dedicated error code to the queue for a handshake_failure alert + * in response to ClientHello. This matches NSS's client behavior and + * gives a better error on a (probable) failure to negotiate initial + * parameters. Note: this error code comes after the original one. + * + * See https://crbug.com/446505. */ + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO); + } return n; } diff --git a/ssl/ssl_error.c b/ssl/ssl_error.c index f9be633b..2f06460f 100644 --- a/ssl/ssl_error.c +++ b/ssl/ssl_error.c @@ -314,6 +314,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = { {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_CHANNEL_ID_BEFORE_A_CCS), "GOT_CHANNEL_ID_BEFORE_A_CCS"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS), "GOT_NEXT_PROTO_BEFORE_A_CCS"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION), "GOT_NEXT_PROTO_WITHOUT_EXTENSION"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO), "HANDSHAKE_FAILURE_ON_CLIENT_HELLO"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HANDSHAKE_RECORD_BEFORE_CCS), "HANDSHAKE_RECORD_BEFORE_CCS"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HTTPS_PROXY_REQUEST), "HTTPS_PROXY_REQUEST"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HTTP_REQUEST), "HTTP_REQUEST"}, diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 8d6dabc5..6faccb5b 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -556,6 +556,14 @@ var testCases = []testCase{ shouldFail: true, expectedError: ":WRONG_SSL_VERSION:", }, + { + name: "NoSharedCipher", + config: Config{ + CipherSuites: []uint16{}, + }, + shouldFail: true, + expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:", + }, } func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {