Try to be more consistent about the alerts we send
We are quite inconsistent about which alerts get sent. Specifically, these
alerts should be used (normally) in the following circumstances:
SSL_AD_DECODE_ERROR = The peer sent a syntactically incorrect message
SSL_AD_ILLEGAL_PARAMETER = The peer sent a message which was syntactically
correct, but a parameter given is invalid for the context
SSL_AD_HANDSHAKE_FAILURE = The peer's messages were syntactically and
semantically correct, but the parameters provided were unacceptable to us
(e.g. because we do not support the requested parameters)
SSL_AD_INTERNAL_ERROR = We messed up (e.g. malloc failure)
The standards themselves aren't always consistent but I think the above
represents the best interpretation.
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3480)
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index 68d8cea..d77d493 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -1116,7 +1116,7 @@
&& (!s->hit
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
/* Nothing left we can do - just fail */
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_MISSING_EXTENSION;
SSLerr(SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
return 0;
}
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index bbe94d0..c5f8d3d 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -930,7 +930,7 @@
if (!PACKET_get_1_len(pkt, &ilen)) {
SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_ENCODING_ERR);
- *al = SSL_AD_ILLEGAL_PARAMETER;
+ *al = SSL_AD_DECODE_ERROR;
return 0;
}
@@ -938,7 +938,7 @@
if (PACKET_remaining(pkt) != ilen) {
SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_ENCODING_ERR);
- *al = SSL_AD_ILLEGAL_PARAMETER;
+ *al = SSL_AD_DECODE_ERROR;
return 0;
}
@@ -946,7 +946,7 @@
if (ilen != expected_len) {
SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
@@ -955,7 +955,7 @@
s->s3->previous_client_finished_len) != 0) {
SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
@@ -975,8 +975,13 @@
int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al)
{
- if (s->ext.hostname == NULL || PACKET_remaining(pkt) > 0) {
- *al = SSL_AD_UNRECOGNIZED_NAME;
+ if (s->ext.hostname == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ if (PACKET_remaining(pkt) > 0) {
+ *al = SSL_AD_DECODE_ERROR;
return 0;
}
@@ -1042,10 +1047,14 @@
return 0;
}
- if (!tls_use_ticket(s) || PACKET_remaining(pkt) > 0) {
+ if (!tls_use_ticket(s)) {
*al = SSL_AD_UNSUPPORTED_EXTENSION;
return 0;
}
+ if (PACKET_remaining(pkt) > 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
s->ext.ticket_expected = 1;
@@ -1060,11 +1069,14 @@
* MUST only be sent if we've requested a status
* request message. In TLS <= 1.2 it must also be empty.
*/
- if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp
- || (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0)) {
+ if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
*al = SSL_AD_UNSUPPORTED_EXTENSION;
return 0;
}
+ if (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
if (SSL_IS_TLS13(s)) {
/* We only know how to handle this if it's for the first Certificate in
@@ -1407,7 +1419,7 @@
}
if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_ECPOINT);
EVP_PKEY_free(skey);
return 0;
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 9cde695..95bacdf 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -25,7 +25,7 @@
|| !PACKET_get_bytes(pkt, &data, ilen)) {
SSLerr(SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
SSL_R_RENEGOTIATION_ENCODING_ERR);
- *al = SSL_AD_ILLEGAL_PARAMETER;
+ *al = SSL_AD_DECODE_ERROR;
return 0;
}
@@ -154,7 +154,7 @@
* upon resumption. Instead, we MUST ignore the login.
*/
if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) {
- *al = TLS1_AD_INTERNAL_ERROR;
+ *al = SSL_AD_INTERNAL_ERROR;
return 0;
}
@@ -178,7 +178,7 @@
if (!PACKET_memdup(&ec_point_format_list,
&s->session->ext.ecpointformats,
&s->session->ext.ecpointformats_len)) {
- *al = TLS1_AD_INTERNAL_ERROR;
+ *al = SSL_AD_INTERNAL_ERROR;
return 0;
}
}
@@ -194,7 +194,7 @@
!s->ext.session_ticket_cb(s, PACKET_data(pkt),
PACKET_remaining(pkt),
s->ext.session_ticket_cb_arg)) {
- *al = TLS1_AD_INTERNAL_ERROR;
+ *al = SSL_AD_INTERNAL_ERROR;
return 0;
}
@@ -213,7 +213,7 @@
}
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs)) {
- *al = TLS1_AD_DECODE_ERROR;
+ *al = SSL_AD_DECODE_ERROR;
return 0;
}
@@ -368,7 +368,7 @@
s->s3->alpn_proposed_len = 0;
if (!PACKET_memdup(&save_protocol_list,
&s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
- *al = TLS1_AD_INTERNAL_ERROR;
+ *al = SSL_AD_INTERNAL_ERROR;
return 0;
}
@@ -614,7 +614,7 @@
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT);
return 0;
}
@@ -646,7 +646,7 @@
if (!PACKET_memdup(&supported_groups_list,
&s->session->ext.supportedgroups,
&s->session->ext.supportedgroups_len)) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = SSL_AD_INTERNAL_ERROR;
return 0;
}
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index e6a0b35..d4382e8 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1183,7 +1183,6 @@
/* TLS extensions */
if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0, &al)) {
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1928,7 +1927,6 @@
}
if (!srp_verify_server_param(s, al)) {
- *al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, SSL_R_BAD_SRP_PARAMETERS);
return 0;
}
@@ -1987,7 +1985,7 @@
/* test non-zero pubkey */
if (BN_is_zero(bnpub_key)) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE);
goto err;
}
@@ -2000,7 +1998,7 @@
p = g = NULL;
if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE);
goto err;
}
@@ -2075,7 +2073,7 @@
* invalid curve. ECParameters is 3 bytes.
*/
if (!tls1_check_curve(s, ecparams, 3)) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_WRONG_CURVE);
return 0;
}
@@ -2124,7 +2122,7 @@
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_BAD_ECPOINT);
return 0;
}
@@ -2201,7 +2199,7 @@
if (!PACKET_get_sub_packet(&save_param_start, ¶ms,
PACKET_remaining(&save_param_start) -
PACKET_remaining(pkt))) {
- al = SSL_AD_INTERNAL_ERROR;
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -2750,7 +2748,7 @@
identitylen = strlen(identity);
if (identitylen > PSK_MAX_IDENTITY_LEN) {
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_INTERNAL_ERROR;
goto err;
}
@@ -3137,7 +3135,7 @@
if (!tls_construct_cke_srp(s, pkt, &al))
goto err;
} else if (!(alg_k & SSL_kPSK)) {
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
diff --git a/ssl/statem/statem_dtls.c b/ssl/statem/statem_dtls.c
index b2ba357..5cab355 100644
--- a/ssl/statem/statem_dtls.c
+++ b/ssl/statem/statem_dtls.c
@@ -770,7 +770,7 @@
* Fragments must not span records.
*/
if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
- al = SSL3_AD_ILLEGAL_PARAMETER;
+ al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
goto f_err;
}
@@ -845,8 +845,8 @@
* to fail
*/
if (readbytes != frag_len) {
- al = SSL3_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL3_AD_ILLEGAL_PARAMETER);
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
goto f_err;
}
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 4a399ca..e6f6293 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -333,10 +333,8 @@
peer = s->session->peer;
pkey = X509_get0_pubkey(peer);
- if (pkey == NULL) {
- al = SSL_AD_INTERNAL_ERROR;
+ if (pkey == NULL)
goto f_err;
- }
type = X509_certificate_type(peer, pkey);
@@ -670,14 +668,14 @@
&& remain != DTLS1_CCS_HEADER_LENGTH + 1)
|| (s->version != DTLS1_BAD_VER
&& remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
- al = SSL_AD_ILLEGAL_PARAMETER;
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
SSL_R_BAD_CHANGE_CIPHER_SPEC);
goto f_err;
}
} else {
if (remain != 0) {
- al = SSL_AD_ILLEGAL_PARAMETER;
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
SSL_R_BAD_CHANGE_CIPHER_SPEC);
goto f_err;
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 5c22ba7..02c6e56 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1260,7 +1260,7 @@
unsigned int mt;
if (!SSL_IS_FIRST_HANDSHAKE(s) || s->hello_retry_request) {
- al = SSL_AD_HANDSHAKE_FAILURE;
+ al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
}
@@ -1318,7 +1318,7 @@
}
if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
- al = SSL_AD_DECODE_ERROR;
+ al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
@@ -1376,8 +1376,8 @@
if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
DTLS1_COOKIE_LENGTH,
&clienthello->dtls_cookie_len)) {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto f_err;
}
/*
@@ -1419,8 +1419,8 @@
if (!PACKET_copy_all(&compression, clienthello->compressions,
MAX_COMPRESSIONS_SIZE,
&clienthello->compressions_len)) {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto f_err;
}
@@ -2221,7 +2221,7 @@
pkdhp = pkdh;
}
if (pkdhp == NULL) {
- al = SSL_AD_HANDSHAKE_FAILURE;
+ al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
SSL_R_MISSING_TMP_DH_KEY);
goto f_err;
@@ -2314,7 +2314,7 @@
} else
#endif
{
- al = SSL_AD_HANDSHAKE_FAILURE;
+ al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
goto f_err;
@@ -2631,7 +2631,7 @@
rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey);
if (rsa == NULL) {
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_MISSING_RSA_CERTIFICATE);
return 0;
}
@@ -2794,20 +2794,20 @@
int ret = 0;
if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) {
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE,
SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
goto err;
}
skey = s->s3->tmp.pkey;
if (skey == NULL) {
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (PACKET_remaining(pkt) == 0L) {
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
@@ -2886,7 +2886,7 @@
goto err;
}
if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EC_LIB);
goto err;
}
@@ -2926,6 +2926,7 @@
return 0;
}
if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_BN_LIB);
return 0;
}
@@ -3070,7 +3071,7 @@
if (alg_k & SSL_kPSK) {
/* Identity extracted earlier: should be nothing left */
if (PACKET_remaining(pkt) != 0) {
- al = SSL_AD_HANDSHAKE_FAILURE;
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
SSL_R_LENGTH_MISMATCH);
goto err;
@@ -3097,7 +3098,7 @@
if (!tls_process_cke_gost(s, pkt, &al))
goto err;
} else {
- al = SSL_AD_HANDSHAKE_FAILURE;
+ al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
SSL_R_UNKNOWN_CIPHER_TYPE);
goto err;
@@ -3584,6 +3585,7 @@
{
PACKET next_proto, padding;
size_t next_proto_len;
+ int al = SSL_AD_INTERNAL_ERROR;
/*-
* The payload looks like:
@@ -3595,6 +3597,7 @@
if (!PACKET_get_length_prefixed_1(pkt, &next_proto)
|| !PACKET_get_length_prefixed_1(pkt, &padding)
|| PACKET_remaining(pkt) > 0) {
+ al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_PROCESS_NEXT_PROTO, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -3608,6 +3611,7 @@
return MSG_PROCESS_CONTINUE_READING;
err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
ossl_statem_set_error(s);
return MSG_PROCESS_ERROR;
}
@@ -3621,7 +3625,6 @@
NULL, 0, &al)) {
ssl3_send_alert(s, SSL3_AL_FATAL, al);
SSLerr(SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS, ERR_R_INTERNAL_ERROR);
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;
}