]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
handshake: send certificate request when requested
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Tue, 3 Oct 2017 09:43:45 +0000 (11:43 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 19 Feb 2018 14:29:35 +0000 (15:29 +0100)
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/extv.h
lib/gnutls_int.h
lib/tls13/certificate_request.c

index b16ad3cc654661d6c4dd6b63a60bd78b5effb28a..b5089efed5b0fe8f0647fa41ce3fb1c26f11a6cd 100644 (file)
@@ -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
index b19eb987ed1bd4d7bb7ce967446d11f1bd7bc8e5..b5eac7d5ef3da6e5e743b4ed0ebca1a36b3385d7 100644 (file)
@@ -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).
index a8f2c03b3cfec3ef5f4385f3d690a6d3b7679211..290b2d5f475180cd9d1716ef23f6c73b0d96d903 100644 (file)
@@ -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;
+
 }
+