Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/handshake: Enable the SNI extension to work properly

Enable the upper layer protocol to specify the SNI peername. This
avoids the need for tlshd to use a DNS lookup, which can return a
hostname that doesn't match the incoming certificate's SubjectName.

Fixes: 2fd5532044a8 ("net/handshake: Add a kernel API for requesting a TLSv1.3 handshake")
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Chuck Lever and committed by
Jakub Kicinski
26fb5480 1ce77c99

+19
+4
Documentation/netlink/specs/handshake.yaml
··· 68 68 type: nest 69 69 nested-attributes: x509 70 70 multi-attr: true 71 + - 72 + name: peername 73 + type: string 71 74 - 72 75 name: done 73 76 attributes: ··· 108 105 - auth-mode 109 106 - peer-identity 110 107 - certificate 108 + - peername 111 109 - 112 110 name: done 113 111 doc: Handler reports handshake completion
+5
Documentation/networking/tls-handshake.rst
··· 53 53 struct socket *ta_sock; 54 54 tls_done_func_t ta_done; 55 55 void *ta_data; 56 + const char *ta_peername; 56 57 unsigned int ta_timeout_ms; 57 58 key_serial_t ta_keyring; 58 59 key_serial_t ta_my_cert; ··· 71 70 @ta_done contains a callback function that is invoked when the handshake 72 71 has completed. Further explanation of this function is in the "Handshake 73 72 Completion" sesction below. 73 + 74 + The consumer can provide a NUL-terminated hostname in the @ta_peername 75 + field that is sent as part of ClientHello. If no peername is provided, 76 + the DNS hostname associated with the server's IP address is used instead. 74 77 75 78 The consumer can fill in the @ta_timeout_ms field to force the servicing 76 79 handshake agent to exit after a number of milliseconds. This enables the
+1
include/net/handshake.h
··· 24 24 struct socket *ta_sock; 25 25 tls_done_func_t ta_done; 26 26 void *ta_data; 27 + const char *ta_peername; 27 28 unsigned int ta_timeout_ms; 28 29 key_serial_t ta_keyring; 29 30 key_serial_t ta_my_cert;
+1
include/uapi/linux/handshake.h
··· 44 44 HANDSHAKE_A_ACCEPT_AUTH_MODE, 45 45 HANDSHAKE_A_ACCEPT_PEER_IDENTITY, 46 46 HANDSHAKE_A_ACCEPT_CERTIFICATE, 47 + HANDSHAKE_A_ACCEPT_PEERNAME, 47 48 48 49 __HANDSHAKE_A_ACCEPT_MAX, 49 50 HANDSHAKE_A_ACCEPT_MAX = (__HANDSHAKE_A_ACCEPT_MAX - 1)
+8
net/handshake/tlshd.c
··· 31 31 int th_type; 32 32 unsigned int th_timeout_ms; 33 33 int th_auth_mode; 34 + const char *th_peername; 34 35 key_serial_t th_keyring; 35 36 key_serial_t th_certificate; 36 37 key_serial_t th_privkey; ··· 49 48 treq->th_timeout_ms = args->ta_timeout_ms; 50 49 treq->th_consumer_done = args->ta_done; 51 50 treq->th_consumer_data = args->ta_data; 51 + treq->th_peername = args->ta_peername; 52 52 treq->th_keyring = args->ta_keyring; 53 53 treq->th_num_peerids = 0; 54 54 treq->th_certificate = TLS_NO_CERT; ··· 216 214 ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MESSAGE_TYPE, treq->th_type); 217 215 if (ret < 0) 218 216 goto out_cancel; 217 + if (treq->th_peername) { 218 + ret = nla_put_string(msg, HANDSHAKE_A_ACCEPT_PEERNAME, 219 + treq->th_peername); 220 + if (ret < 0) 221 + goto out_cancel; 222 + } 219 223 if (treq->th_timeout_ms) { 220 224 ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_TIMEOUT, treq->th_timeout_ms); 221 225 if (ret < 0)