diff options
author | Daiki Ueno <ueno@gnu.org> | 2019-04-07 07:46:14 +0000 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2019-04-07 07:46:14 +0000 |
commit | d5f5b6a200c815245853e7a47a1ea666217473b7 (patch) | |
tree | 916d05cbad26b0d5dfc1dc57d7f0254ee4857a38 /lib | |
parent | dc573c8409dabc5cf7f7588368445383f3d861d5 (diff) | |
parent | 456170176a95d9c0855c872748c1295e805961a2 (diff) | |
download | gnutls-d5f5b6a200c815245853e7a47a1ea666217473b7.tar.gz |
Merge branch 'tmp-client-auth-decline' into 'master'
cert auth: reject auth if no signature algorithm is usable in TLS 1.3
Closes #730
See merge request gnutls/gnutls!967
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/tls13/certificate_request.c | 46 | ||||
-rw-r--r-- | lib/tls13/certificate_verify.c | 27 |
3 files changed, 46 insertions, 28 deletions
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index f5c89c18cf..72d6c066b6 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1320,7 +1320,6 @@ typedef struct { #define HSK_PSK_KE_MODES_RECEIVED (HSK_PSK_KE_MODE_PSK|HSK_PSK_KE_MODE_DHE_PSK|HSK_PSK_KE_MODE_INVALID) #define HSK_CRT_VRFY_EXPECTED 1 -#define HSK_CRT_SENT (1<<1) #define HSK_CRT_ASKED (1<<2) #define HSK_HRR_SENT (1<<3) #define HSK_HRR_RECEIVED (1<<4) diff --git a/lib/tls13/certificate_request.c b/lib/tls13/certificate_request.c index 002646ed6b..d56ce42738 100644 --- a/lib/tls13/certificate_request.c +++ b/lib/tls13/certificate_request.c @@ -128,17 +128,20 @@ int _gnutls13_recv_certificate_request_int(gnutls_session_t session, gnutls_buff { int ret; crt_req_ctx_st ctx; + gnutls_pcert_st *apr_cert_list; + gnutls_privkey_t apr_pkey; + int apr_cert_list_length; _gnutls_handshake_log("HSK[%p]: parsing certificate request\n", session); + if (unlikely(session->security_parameters.entity == GNUTLS_SERVER)) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + /* if initial negotiation is complete, this is a post-handshake auth */ - if (!session->internals.initial_negotiation_completed || - session->security_parameters.entity == GNUTLS_SERVER) { + if (!session->internals.initial_negotiation_completed) { if (buf->data[0] != 0) { /* The context field must be empty during handshake */ - ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; - gnutls_assert(); - goto cleanup; + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); } /* buf->length is positive */ @@ -162,10 +165,8 @@ int _gnutls13_recv_certificate_request_int(gnutls_session_t session, gnutls_buff ctx.session = session; ret = _gnutls_extv_parse(&ctx, parse_cert_extension, buf->data, buf->length); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + if (ret < 0) + return gnutls_assert_val(ret); /* The "signature_algorithms" extension MUST be specified */ if (!ctx.got_sig_algo) @@ -175,15 +176,28 @@ int _gnutls13_recv_certificate_request_int(gnutls_session_t session, gnutls_buff ret = _gnutls_select_client_cert(session, ctx.rdn, ctx.rdn_size, ctx.pk_algos, ctx.pk_algos_length); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + if (ret < 0) + return gnutls_assert_val(ret); - ret = 0; + ret = _gnutls_get_selected_cert(session, &apr_cert_list, + &apr_cert_list_length, &apr_pkey); + if (ret < 0) + return gnutls_assert_val(ret); - cleanup: - return ret; + if (apr_cert_list_length > 0) { + gnutls_sign_algorithm_t algo; + + algo = _gnutls_session_get_sign_algo(session, &apr_cert_list[0], apr_pkey, 0); + if (algo == GNUTLS_SIGN_UNKNOWN) { + _gnutls_handshake_log("HSK[%p]: rejecting client auth because of no suitable signature algorithm\n", session); + _gnutls_selected_certs_deinit(session); + return gnutls_assert_val(0); + } + + gnutls_sign_algorithm_set_client(session, algo); + } + + return 0; } int _gnutls13_recv_certificate_request(gnutls_session_t session) diff --git a/lib/tls13/certificate_verify.c b/lib/tls13/certificate_verify.c index 72b4488115..7300f88f5d 100644 --- a/lib/tls13/certificate_verify.c +++ b/lib/tls13/certificate_verify.c @@ -179,22 +179,27 @@ int _gnutls13_send_certificate_verify(gnutls_session_t session, unsigned again) if (server) { return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); } else { - /* if we didn't get a cert request there will not be any */ - if (!(session->internals.hsk_flags & HSK_CRT_SENT)) - return 0; - else - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + /* for client, this means either we + * didn't get a cert request or we are + * declining authentication; in either + * case we don't send a cert verify */ + return 0; } } - algo = _gnutls_session_get_sign_algo(session, &apr_cert_list[0], apr_pkey, 0); - if (algo == GNUTLS_SIGN_UNKNOWN) - return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY); + if (server) { + algo = _gnutls_session_get_sign_algo(session, &apr_cert_list[0], apr_pkey, 0); + if (algo == GNUTLS_SIGN_UNKNOWN) + return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY); - if (server) gnutls_sign_algorithm_set_server(session, algo); - else - gnutls_sign_algorithm_set_client(session, algo); + } else { + /* for client, signature algorithm is already + * determined from Certificate Request */ + algo = gnutls_sign_algorithm_get_client(session); + if (unlikely(algo == GNUTLS_SIGN_UNKNOWN)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } se = _gnutls_sign_to_entry(algo); |