diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-10-03 11:43:45 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-02-19 15:29:35 +0100 |
commit | 72674eebe537f08b6b229902a22407aa283fa8e2 (patch) | |
tree | f717ec4f42caa73f62ae37dde3b95bf684aa7d5f | |
parent | ce97793cd7532e9d4752313fe96f22de90cd5484 (diff) | |
download | gnutls-72674eebe537f08b6b229902a22407aa283fa8e2.tar.gz |
handshake: send certificate request when requested
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r-- | lib/extv.h | 4 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/tls13/certificate_request.c | 61 |
3 files changed, 64 insertions, 2 deletions
diff --git a/lib/extv.h b/lib/extv.h index b16ad3cc65..b5089efed5 100644 --- a/lib/extv.h +++ b/lib/extv.h @@ -63,10 +63,12 @@ int _gnutls_extv_append_final(gnutls_buffer_st *buf, unsigned init) return 0; } +typedef int (*extv_append_func)(void *ctx, gnutls_buffer_st *buf); + int _gnutls_extv_append(gnutls_buffer_st *buf, uint16_t tls_id, void *ctx, - int (*cb)(void *ctx, gnutls_buffer_st *buf)); + extv_append_func cb); #endif diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index b19eb987ed..b5eac7d5ef 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1114,6 +1114,7 @@ typedef struct { #define HSK_CRT_ASKED (1<<2) #define HSK_HRR_SENT (1<<3) #define HSK_HRR_RECEIVED (1<<4) +#define HSK_CRT_REQ_SENT (1<<5) unsigned hsk_flags; /* TLS1.3 only */ unsigned crt_requested; /* 1 if client auth was requested (i.e., client cert). diff --git a/lib/tls13/certificate_request.c b/lib/tls13/certificate_request.c index a8f2c03b3c..290b2d5f47 100644 --- a/lib/tls13/certificate_request.c +++ b/lib/tls13/certificate_request.c @@ -25,6 +25,8 @@ #include "extv.h" #include "handshake.h" #include "tls13/certificate_request.h" +#include "ext/signature.h" +#include "mbuffers.h" static int parse_cert_extension(void *ctx, uint16_t tls_id, const uint8_t *data, int data_size) @@ -71,7 +73,64 @@ int _gnutls13_recv_certificate_request(gnutls_session_t session) return 0; } + int _gnutls13_send_certificate_request(gnutls_session_t session, unsigned again) { - return 0; + gnutls_certificate_credentials_t cred; + int ret; + mbuffer_st *bufel = NULL; + gnutls_buffer_st buf; + unsigned init_pos; + + if (again == 0) { + if (session->internals.send_cert_req == 0) + return 0; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + + ret = _gnutls_buffer_init_handshake_mbuffer(&buf); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_buffer_append_prefix(&buf, 8, 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_extv_append_init(&buf); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + init_pos = ret; + + ret = _gnutls_extv_append(&buf, ext_mod_sig.tls_id, session, + (extv_append_func)_gnutls_sign_algorithm_write_params); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_extv_append_final(&buf, init_pos); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + bufel = _gnutls_buffer_to_mbuffer(&buf); + + session->internals.hsk_flags |= HSK_CRT_REQ_SENT; + } + + return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST); + + cleanup: + _gnutls_buffer_clear(&buf); + return ret; + } + |