summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2019-04-07 07:46:14 +0000
committerDaiki Ueno <ueno@gnu.org>2019-04-07 07:46:14 +0000
commitd5f5b6a200c815245853e7a47a1ea666217473b7 (patch)
tree916d05cbad26b0d5dfc1dc57d7f0254ee4857a38 /lib
parentdc573c8409dabc5cf7f7588368445383f3d861d5 (diff)
parent456170176a95d9c0855c872748c1295e805961a2 (diff)
downloadgnutls-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.h1
-rw-r--r--lib/tls13/certificate_request.c46
-rw-r--r--lib/tls13/certificate_verify.c27
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);