summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-10-03 11:43:45 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-02-19 15:29:35 +0100
commit72674eebe537f08b6b229902a22407aa283fa8e2 (patch)
treef717ec4f42caa73f62ae37dde3b95bf684aa7d5f
parentce97793cd7532e9d4752313fe96f22de90cd5484 (diff)
downloadgnutls-72674eebe537f08b6b229902a22407aa283fa8e2.tar.gz
handshake: send certificate request when requested
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/extv.h4
-rw-r--r--lib/gnutls_int.h1
-rw-r--r--lib/tls13/certificate_request.c61
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;
+
}
+