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

net/handshake: Add a kernel API for requesting a TLSv1.3 handshake

To enable kernel consumers of TLS to request a TLS handshake, add
support to net/handshake/ to request a handshake upcall.

This patch also acts as a template for adding handshake upcall
support for other kernel transport layer security providers.

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
2fd55320 3b3009ea

+689 -3
+3 -1
Documentation/netlink/specs/handshake.yaml
··· 16 16 type: enum 17 17 name: handler-class 18 18 value-start: 0 19 - entries: [ none, max ] 19 + entries: [ none, tlshd, max ] 20 20 - 21 21 type: enum 22 22 name: msg-type ··· 120 120 list: 121 121 - 122 122 name: none 123 + - 124 + name: tlshd
+1
Documentation/networking/index.rst
··· 36 36 scaling 37 37 tls 38 38 tls-offload 39 + tls-handshake 39 40 nfc 40 41 6lowpan 41 42 6pack
+217
Documentation/networking/tls-handshake.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ======================= 4 + In-Kernel TLS Handshake 5 + ======================= 6 + 7 + Overview 8 + ======== 9 + 10 + Transport Layer Security (TLS) is a Upper Layer Protocol (ULP) that runs 11 + over TCP. TLS provides end-to-end data integrity and confidentiality in 12 + addition to peer authentication. 13 + 14 + The kernel's kTLS implementation handles the TLS record subprotocol, but 15 + does not handle the TLS handshake subprotocol which is used to establish 16 + a TLS session. Kernel consumers can use the API described here to 17 + request TLS session establishment. 18 + 19 + There are several possible ways to provide a handshake service in the 20 + kernel. The API described here is designed to hide the details of those 21 + implementations so that in-kernel TLS consumers do not need to be 22 + aware of how the handshake gets done. 23 + 24 + 25 + User handshake agent 26 + ==================== 27 + 28 + As of this writing, there is no TLS handshake implementation in the 29 + Linux kernel. To provide a handshake service, a handshake agent 30 + (typically in user space) is started in each network namespace where a 31 + kernel consumer might require a TLS handshake. Handshake agents listen 32 + for events sent from the kernel that indicate a handshake request is 33 + waiting. 34 + 35 + An open socket is passed to a handshake agent via a netlink operation, 36 + which creates a socket descriptor in the agent's file descriptor table. 37 + If the handshake completes successfully, the handshake agent promotes 38 + the socket to use the TLS ULP and sets the session information using the 39 + SOL_TLS socket options. The handshake agent returns the socket to the 40 + kernel via a second netlink operation. 41 + 42 + 43 + Kernel Handshake API 44 + ==================== 45 + 46 + A kernel TLS consumer initiates a client-side TLS handshake on an open 47 + socket by invoking one of the tls_client_hello() functions. First, it 48 + fills in a structure that contains the parameters of the request: 49 + 50 + .. code-block:: c 51 + 52 + struct tls_handshake_args { 53 + struct socket *ta_sock; 54 + tls_done_func_t ta_done; 55 + void *ta_data; 56 + unsigned int ta_timeout_ms; 57 + key_serial_t ta_keyring; 58 + key_serial_t ta_my_cert; 59 + key_serial_t ta_my_privkey; 60 + unsigned int ta_num_peerids; 61 + key_serial_t ta_my_peerids[5]; 62 + }; 63 + 64 + The @ta_sock field references an open and connected socket. The consumer 65 + must hold a reference on the socket to prevent it from being destroyed 66 + while the handshake is in progress. The consumer must also have 67 + instantiated a struct file in sock->file. 68 + 69 + 70 + @ta_done contains a callback function that is invoked when the handshake 71 + has completed. Further explanation of this function is in the "Handshake 72 + Completion" sesction below. 73 + 74 + The consumer can fill in the @ta_timeout_ms field to force the servicing 75 + handshake agent to exit after a number of milliseconds. This enables the 76 + socket to be fully closed once both the kernel and the handshake agent 77 + have closed their endpoints. 78 + 79 + Authentication material such as x.509 certificates, private certificate 80 + keys, and pre-shared keys are provided to the handshake agent in keys 81 + that are instantiated by the consumer before making the handshake 82 + request. The consumer can provide a private keyring that is linked into 83 + the handshake agent's process keyring in the @ta_keyring field to prevent 84 + access of those keys by other subsystems. 85 + 86 + To request an x.509-authenticated TLS session, the consumer fills in 87 + the @ta_my_cert and @ta_my_privkey fields with the serial numbers of 88 + keys containing an x.509 certificate and the private key for that 89 + certificate. Then, it invokes this function: 90 + 91 + .. code-block:: c 92 + 93 + ret = tls_client_hello_x509(args, gfp_flags); 94 + 95 + The function returns zero when the handshake request is under way. A 96 + zero return guarantees the callback function @ta_done will be invoked 97 + for this socket. The function returns a negative errno if the handshake 98 + could not be started. A negative errno guarantees the callback function 99 + @ta_done will not be invoked on this socket. 100 + 101 + 102 + To initiate a client-side TLS handshake with a pre-shared key, use: 103 + 104 + .. code-block:: c 105 + 106 + ret = tls_client_hello_psk(args, gfp_flags); 107 + 108 + However, in this case, the consumer fills in the @ta_my_peerids array 109 + with serial numbers of keys containing the peer identities it wishes 110 + to offer, and the @ta_num_peerids field with the number of array 111 + entries it has filled in. The other fields are filled in as above. 112 + 113 + 114 + To initiate an anonymous client-side TLS handshake use: 115 + 116 + .. code-block:: c 117 + 118 + ret = tls_client_hello_anon(args, gfp_flags); 119 + 120 + The handshake agent presents no peer identity information to the remote 121 + during this type of handshake. Only server authentication (ie the client 122 + verifies the server's identity) is performed during the handshake. Thus 123 + the established session uses encryption only. 124 + 125 + 126 + Consumers that are in-kernel servers use: 127 + 128 + .. code-block:: c 129 + 130 + ret = tls_server_hello_x509(args, gfp_flags); 131 + 132 + or 133 + 134 + .. code-block:: c 135 + 136 + ret = tls_server_hello_psk(args, gfp_flags); 137 + 138 + The argument structure is filled in as above. 139 + 140 + 141 + If the consumer needs to cancel the handshake request, say, due to a ^C 142 + or other exigent event, the consumer can invoke: 143 + 144 + .. code-block:: c 145 + 146 + bool tls_handshake_cancel(sock); 147 + 148 + This function returns true if the handshake request associated with 149 + @sock has been canceled. The consumer's handshake completion callback 150 + will not be invoked. If this function returns false, then the consumer's 151 + completion callback has already been invoked. 152 + 153 + 154 + Handshake Completion 155 + ==================== 156 + 157 + When the handshake agent has completed processing, it notifies the 158 + kernel that the socket may be used by the consumer again. At this point, 159 + the consumer's handshake completion callback, provided in the @ta_done 160 + field in the tls_handshake_args structure, is invoked. 161 + 162 + The synopsis of this function is: 163 + 164 + .. code-block:: c 165 + 166 + typedef void (*tls_done_func_t)(void *data, int status, 167 + key_serial_t peerid); 168 + 169 + The consumer provides a cookie in the @ta_data field of the 170 + tls_handshake_args structure that is returned in the @data parameter of 171 + this callback. The consumer uses the cookie to match the callback to the 172 + thread waiting for the handshake to complete. 173 + 174 + The success status of the handshake is returned via the @status 175 + parameter: 176 + 177 + +------------+----------------------------------------------+ 178 + | status | meaning | 179 + +============+==============================================+ 180 + | 0 | TLS session established successfully | 181 + +------------+----------------------------------------------+ 182 + | -EACCESS | Remote peer rejected the handshake or | 183 + | | authentication failed | 184 + +------------+----------------------------------------------+ 185 + | -ENOMEM | Temporary resource allocation failure | 186 + +------------+----------------------------------------------+ 187 + | -EINVAL | Consumer provided an invalid argument | 188 + +------------+----------------------------------------------+ 189 + | -ENOKEY | Missing authentication material | 190 + +------------+----------------------------------------------+ 191 + | -EIO | An unexpected fault occurred | 192 + +------------+----------------------------------------------+ 193 + 194 + The @peerid parameter contains the serial number of a key containing the 195 + remote peer's identity or the value TLS_NO_PEERID if the session is not 196 + authenticated. 197 + 198 + A best practice is to close and destroy the socket immediately if the 199 + handshake failed. 200 + 201 + 202 + Other considerations 203 + -------------------- 204 + 205 + While a handshake is under way, the kernel consumer must alter the 206 + socket's sk_data_ready callback function to ignore all incoming data. 207 + Once the handshake completion callback function has been invoked, normal 208 + receive operation can be resumed. 209 + 210 + Once a TLS session is established, the consumer must provide a buffer 211 + for and then examine the control message (CMSG) that is part of every 212 + subsequent sock_recvmsg(). Each control message indicates whether the 213 + received message data is TLS record data or session metadata. 214 + 215 + See tls.rst for details on how a kTLS consumer recognizes incoming 216 + (decrypted) application data, alerts, and handshake packets once the 217 + socket has been promoted to use the TLS ULP.
+2
MAINTAINERS
··· 8953 8953 L: netdev@vger.kernel.org 8954 8954 S: Maintained 8955 8955 F: Documentation/netlink/specs/handshake.yaml 8956 + F: Documentation/networking/tls-handshake.rst 8957 + F: include/net/handshake.h 8956 8958 F: include/trace/events/handshake.h 8957 8959 F: net/handshake/ 8958 8960
+43
include/net/handshake.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Generic netlink HANDSHAKE service. 4 + * 5 + * Author: Chuck Lever <chuck.lever@oracle.com> 6 + * 7 + * Copyright (c) 2023, Oracle and/or its affiliates. 8 + */ 9 + 10 + #ifndef _NET_HANDSHAKE_H 11 + #define _NET_HANDSHAKE_H 12 + 13 + enum { 14 + TLS_NO_KEYRING = 0, 15 + TLS_NO_PEERID = 0, 16 + TLS_NO_CERT = 0, 17 + TLS_NO_PRIVKEY = 0, 18 + }; 19 + 20 + typedef void (*tls_done_func_t)(void *data, int status, 21 + key_serial_t peerid); 22 + 23 + struct tls_handshake_args { 24 + struct socket *ta_sock; 25 + tls_done_func_t ta_done; 26 + void *ta_data; 27 + unsigned int ta_timeout_ms; 28 + key_serial_t ta_keyring; 29 + key_serial_t ta_my_cert; 30 + key_serial_t ta_my_privkey; 31 + unsigned int ta_num_peerids; 32 + key_serial_t ta_my_peerids[5]; 33 + }; 34 + 35 + int tls_client_hello_anon(const struct tls_handshake_args *args, gfp_t flags); 36 + int tls_client_hello_x509(const struct tls_handshake_args *args, gfp_t flags); 37 + int tls_client_hello_psk(const struct tls_handshake_args *args, gfp_t flags); 38 + int tls_server_hello_x509(const struct tls_handshake_args *args, gfp_t flags); 39 + int tls_server_hello_psk(const struct tls_handshake_args *args, gfp_t flags); 40 + 41 + bool tls_handshake_cancel(struct sock *sk); 42 + 43 + #endif /* _NET_HANDSHAKE_H */
+2
include/uapi/linux/handshake.h
··· 11 11 12 12 enum handshake_handler_class { 13 13 HANDSHAKE_HANDLER_CLASS_NONE, 14 + HANDSHAKE_HANDLER_CLASS_TLSHD, 14 15 HANDSHAKE_HANDLER_CLASS_MAX, 15 16 }; 16 17 ··· 68 67 }; 69 68 70 69 #define HANDSHAKE_MCGRP_NONE "none" 70 + #define HANDSHAKE_MCGRP_TLSHD "tlshd" 71 71 72 72 #endif /* _UAPI_LINUX_HANDSHAKE_H */
+1 -1
net/handshake/Makefile
··· 8 8 # 9 9 10 10 obj-y += handshake.o 11 - handshake-y := genl.o netlink.o request.o trace.o 11 + handshake-y := genl.o netlink.o request.o tlshd.o trace.o
+2 -1
net/handshake/genl.c
··· 12 12 13 13 /* HANDSHAKE_CMD_ACCEPT - do */ 14 14 static const struct nla_policy handshake_accept_nl_policy[HANDSHAKE_A_ACCEPT_HANDLER_CLASS + 1] = { 15 - [HANDSHAKE_A_ACCEPT_HANDLER_CLASS] = NLA_POLICY_MAX(NLA_U32, 1), 15 + [HANDSHAKE_A_ACCEPT_HANDLER_CLASS] = NLA_POLICY_MAX(NLA_U32, 2), 16 16 }; 17 17 18 18 /* HANDSHAKE_CMD_DONE - do */ ··· 42 42 43 43 static const struct genl_multicast_group handshake_nl_mcgrps[] = { 44 44 [HANDSHAKE_NLGRP_NONE] = { "none", }, 45 + [HANDSHAKE_NLGRP_TLSHD] = { "tlshd", }, 45 46 }; 46 47 47 48 struct genl_family handshake_nl_family __ro_after_init = {
+1
net/handshake/genl.h
··· 16 16 17 17 enum { 18 18 HANDSHAKE_NLGRP_NONE, 19 + HANDSHAKE_NLGRP_TLSHD, 19 20 }; 20 21 21 22 extern struct genl_family handshake_nl_family;
+417
net/handshake/tlshd.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Establish a TLS session for a kernel socket consumer 4 + * using the tlshd user space handler. 5 + * 6 + * Author: Chuck Lever <chuck.lever@oracle.com> 7 + * 8 + * Copyright (c) 2021-2023, Oracle and/or its affiliates. 9 + */ 10 + 11 + #include <linux/types.h> 12 + #include <linux/socket.h> 13 + #include <linux/kernel.h> 14 + #include <linux/module.h> 15 + #include <linux/slab.h> 16 + #include <linux/key.h> 17 + 18 + #include <net/sock.h> 19 + #include <net/handshake.h> 20 + #include <net/genetlink.h> 21 + 22 + #include <uapi/linux/keyctl.h> 23 + #include <uapi/linux/handshake.h> 24 + #include "handshake.h" 25 + 26 + struct tls_handshake_req { 27 + void (*th_consumer_done)(void *data, int status, 28 + key_serial_t peerid); 29 + void *th_consumer_data; 30 + 31 + int th_type; 32 + unsigned int th_timeout_ms; 33 + int th_auth_mode; 34 + key_serial_t th_keyring; 35 + key_serial_t th_certificate; 36 + key_serial_t th_privkey; 37 + 38 + unsigned int th_num_peerids; 39 + key_serial_t th_peerid[5]; 40 + }; 41 + 42 + static struct tls_handshake_req * 43 + tls_handshake_req_init(struct handshake_req *req, 44 + const struct tls_handshake_args *args) 45 + { 46 + struct tls_handshake_req *treq = handshake_req_private(req); 47 + 48 + treq->th_timeout_ms = args->ta_timeout_ms; 49 + treq->th_consumer_done = args->ta_done; 50 + treq->th_consumer_data = args->ta_data; 51 + treq->th_keyring = args->ta_keyring; 52 + treq->th_num_peerids = 0; 53 + treq->th_certificate = TLS_NO_CERT; 54 + treq->th_privkey = TLS_NO_PRIVKEY; 55 + return treq; 56 + } 57 + 58 + static void tls_handshake_remote_peerids(struct tls_handshake_req *treq, 59 + struct genl_info *info) 60 + { 61 + struct nlattr *head = nlmsg_attrdata(info->nlhdr, GENL_HDRLEN); 62 + int rem, len = nlmsg_attrlen(info->nlhdr, GENL_HDRLEN); 63 + struct nlattr *nla; 64 + unsigned int i; 65 + 66 + i = 0; 67 + nla_for_each_attr(nla, head, len, rem) { 68 + if (nla_type(nla) == HANDSHAKE_A_DONE_REMOTE_AUTH) 69 + i++; 70 + } 71 + if (!i) 72 + return; 73 + treq->th_num_peerids = min_t(unsigned int, i, 74 + ARRAY_SIZE(treq->th_peerid)); 75 + 76 + i = 0; 77 + nla_for_each_attr(nla, head, len, rem) { 78 + if (nla_type(nla) == HANDSHAKE_A_DONE_REMOTE_AUTH) 79 + treq->th_peerid[i++] = nla_get_u32(nla); 80 + if (i >= treq->th_num_peerids) 81 + break; 82 + } 83 + } 84 + 85 + /** 86 + * tls_handshake_done - callback to handle a CMD_DONE request 87 + * @req: socket on which the handshake was performed 88 + * @status: session status code 89 + * @info: full results of session establishment 90 + * 91 + */ 92 + static void tls_handshake_done(struct handshake_req *req, 93 + unsigned int status, struct genl_info *info) 94 + { 95 + struct tls_handshake_req *treq = handshake_req_private(req); 96 + 97 + treq->th_peerid[0] = TLS_NO_PEERID; 98 + if (info) 99 + tls_handshake_remote_peerids(treq, info); 100 + 101 + treq->th_consumer_done(treq->th_consumer_data, -status, 102 + treq->th_peerid[0]); 103 + } 104 + 105 + #if IS_ENABLED(CONFIG_KEYS) 106 + static int tls_handshake_private_keyring(struct tls_handshake_req *treq) 107 + { 108 + key_ref_t process_keyring_ref, keyring_ref; 109 + int ret; 110 + 111 + if (treq->th_keyring == TLS_NO_KEYRING) 112 + return 0; 113 + 114 + process_keyring_ref = lookup_user_key(KEY_SPEC_PROCESS_KEYRING, 115 + KEY_LOOKUP_CREATE, 116 + KEY_NEED_WRITE); 117 + if (IS_ERR(process_keyring_ref)) { 118 + ret = PTR_ERR(process_keyring_ref); 119 + goto out; 120 + } 121 + 122 + keyring_ref = lookup_user_key(treq->th_keyring, KEY_LOOKUP_CREATE, 123 + KEY_NEED_LINK); 124 + if (IS_ERR(keyring_ref)) { 125 + ret = PTR_ERR(keyring_ref); 126 + goto out_put_key; 127 + } 128 + 129 + ret = key_link(key_ref_to_ptr(process_keyring_ref), 130 + key_ref_to_ptr(keyring_ref)); 131 + 132 + key_ref_put(keyring_ref); 133 + out_put_key: 134 + key_ref_put(process_keyring_ref); 135 + out: 136 + return ret; 137 + } 138 + #else 139 + static int tls_handshake_private_keyring(struct tls_handshake_req *treq) 140 + { 141 + return 0; 142 + } 143 + #endif 144 + 145 + static int tls_handshake_put_peer_identity(struct sk_buff *msg, 146 + struct tls_handshake_req *treq) 147 + { 148 + unsigned int i; 149 + 150 + for (i = 0; i < treq->th_num_peerids; i++) 151 + if (nla_put_u32(msg, HANDSHAKE_A_ACCEPT_PEER_IDENTITY, 152 + treq->th_peerid[i]) < 0) 153 + return -EMSGSIZE; 154 + return 0; 155 + } 156 + 157 + static int tls_handshake_put_certificate(struct sk_buff *msg, 158 + struct tls_handshake_req *treq) 159 + { 160 + struct nlattr *entry_attr; 161 + 162 + if (treq->th_certificate == TLS_NO_CERT && 163 + treq->th_privkey == TLS_NO_PRIVKEY) 164 + return 0; 165 + 166 + entry_attr = nla_nest_start(msg, HANDSHAKE_A_ACCEPT_CERTIFICATE); 167 + if (!entry_attr) 168 + return -EMSGSIZE; 169 + 170 + if (nla_put_u32(msg, HANDSHAKE_A_X509_CERT, 171 + treq->th_certificate) || 172 + nla_put_u32(msg, HANDSHAKE_A_X509_PRIVKEY, 173 + treq->th_privkey)) { 174 + nla_nest_cancel(msg, entry_attr); 175 + return -EMSGSIZE; 176 + } 177 + 178 + nla_nest_end(msg, entry_attr); 179 + return 0; 180 + } 181 + 182 + /** 183 + * tls_handshake_accept - callback to construct a CMD_ACCEPT response 184 + * @req: handshake parameters to return 185 + * @info: generic netlink message context 186 + * @fd: file descriptor to be returned 187 + * 188 + * Returns zero on success, or a negative errno on failure. 189 + */ 190 + static int tls_handshake_accept(struct handshake_req *req, 191 + struct genl_info *info, int fd) 192 + { 193 + struct tls_handshake_req *treq = handshake_req_private(req); 194 + struct nlmsghdr *hdr; 195 + struct sk_buff *msg; 196 + int ret; 197 + 198 + ret = tls_handshake_private_keyring(treq); 199 + if (ret < 0) 200 + goto out; 201 + 202 + ret = -ENOMEM; 203 + msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 204 + if (!msg) 205 + goto out; 206 + hdr = handshake_genl_put(msg, info); 207 + if (!hdr) 208 + goto out_cancel; 209 + 210 + ret = -EMSGSIZE; 211 + ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_SOCKFD, fd); 212 + if (ret < 0) 213 + goto out_cancel; 214 + ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MESSAGE_TYPE, treq->th_type); 215 + if (ret < 0) 216 + goto out_cancel; 217 + if (treq->th_timeout_ms) { 218 + ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_TIMEOUT, treq->th_timeout_ms); 219 + if (ret < 0) 220 + goto out_cancel; 221 + } 222 + 223 + ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_AUTH_MODE, 224 + treq->th_auth_mode); 225 + if (ret < 0) 226 + goto out_cancel; 227 + switch (treq->th_auth_mode) { 228 + case HANDSHAKE_AUTH_PSK: 229 + ret = tls_handshake_put_peer_identity(msg, treq); 230 + if (ret < 0) 231 + goto out_cancel; 232 + break; 233 + case HANDSHAKE_AUTH_X509: 234 + ret = tls_handshake_put_certificate(msg, treq); 235 + if (ret < 0) 236 + goto out_cancel; 237 + break; 238 + } 239 + 240 + genlmsg_end(msg, hdr); 241 + return genlmsg_reply(msg, info); 242 + 243 + out_cancel: 244 + genlmsg_cancel(msg, hdr); 245 + out: 246 + return ret; 247 + } 248 + 249 + static const struct handshake_proto tls_handshake_proto = { 250 + .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 251 + .hp_privsize = sizeof(struct tls_handshake_req), 252 + 253 + .hp_accept = tls_handshake_accept, 254 + .hp_done = tls_handshake_done, 255 + }; 256 + 257 + /** 258 + * tls_client_hello_anon - request an anonymous TLS handshake on a socket 259 + * @args: socket and handshake parameters for this request 260 + * @flags: memory allocation control flags 261 + * 262 + * Return values: 263 + * %0: Handshake request enqueue; ->done will be called when complete 264 + * %-ESRCH: No user agent is available 265 + * %-ENOMEM: Memory allocation failed 266 + */ 267 + int tls_client_hello_anon(const struct tls_handshake_args *args, gfp_t flags) 268 + { 269 + struct tls_handshake_req *treq; 270 + struct handshake_req *req; 271 + 272 + req = handshake_req_alloc(&tls_handshake_proto, flags); 273 + if (!req) 274 + return -ENOMEM; 275 + treq = tls_handshake_req_init(req, args); 276 + treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO; 277 + treq->th_auth_mode = HANDSHAKE_AUTH_UNAUTH; 278 + 279 + return handshake_req_submit(args->ta_sock, req, flags); 280 + } 281 + EXPORT_SYMBOL(tls_client_hello_anon); 282 + 283 + /** 284 + * tls_client_hello_x509 - request an x.509-based TLS handshake on a socket 285 + * @args: socket and handshake parameters for this request 286 + * @flags: memory allocation control flags 287 + * 288 + * Return values: 289 + * %0: Handshake request enqueue; ->done will be called when complete 290 + * %-ESRCH: No user agent is available 291 + * %-ENOMEM: Memory allocation failed 292 + */ 293 + int tls_client_hello_x509(const struct tls_handshake_args *args, gfp_t flags) 294 + { 295 + struct tls_handshake_req *treq; 296 + struct handshake_req *req; 297 + 298 + req = handshake_req_alloc(&tls_handshake_proto, flags); 299 + if (!req) 300 + return -ENOMEM; 301 + treq = tls_handshake_req_init(req, args); 302 + treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO; 303 + treq->th_auth_mode = HANDSHAKE_AUTH_X509; 304 + treq->th_certificate = args->ta_my_cert; 305 + treq->th_privkey = args->ta_my_privkey; 306 + 307 + return handshake_req_submit(args->ta_sock, req, flags); 308 + } 309 + EXPORT_SYMBOL(tls_client_hello_x509); 310 + 311 + /** 312 + * tls_client_hello_psk - request a PSK-based TLS handshake on a socket 313 + * @args: socket and handshake parameters for this request 314 + * @flags: memory allocation control flags 315 + * 316 + * Return values: 317 + * %0: Handshake request enqueue; ->done will be called when complete 318 + * %-EINVAL: Wrong number of local peer IDs 319 + * %-ESRCH: No user agent is available 320 + * %-ENOMEM: Memory allocation failed 321 + */ 322 + int tls_client_hello_psk(const struct tls_handshake_args *args, gfp_t flags) 323 + { 324 + struct tls_handshake_req *treq; 325 + struct handshake_req *req; 326 + unsigned int i; 327 + 328 + if (!args->ta_num_peerids || 329 + args->ta_num_peerids > ARRAY_SIZE(treq->th_peerid)) 330 + return -EINVAL; 331 + 332 + req = handshake_req_alloc(&tls_handshake_proto, flags); 333 + if (!req) 334 + return -ENOMEM; 335 + treq = tls_handshake_req_init(req, args); 336 + treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO; 337 + treq->th_auth_mode = HANDSHAKE_AUTH_PSK; 338 + treq->th_num_peerids = args->ta_num_peerids; 339 + for (i = 0; i < args->ta_num_peerids; i++) 340 + treq->th_peerid[i] = args->ta_my_peerids[i]; 341 + 342 + return handshake_req_submit(args->ta_sock, req, flags); 343 + } 344 + EXPORT_SYMBOL(tls_client_hello_psk); 345 + 346 + /** 347 + * tls_server_hello_x509 - request a server TLS handshake on a socket 348 + * @args: socket and handshake parameters for this request 349 + * @flags: memory allocation control flags 350 + * 351 + * Return values: 352 + * %0: Handshake request enqueue; ->done will be called when complete 353 + * %-ESRCH: No user agent is available 354 + * %-ENOMEM: Memory allocation failed 355 + */ 356 + int tls_server_hello_x509(const struct tls_handshake_args *args, gfp_t flags) 357 + { 358 + struct tls_handshake_req *treq; 359 + struct handshake_req *req; 360 + 361 + req = handshake_req_alloc(&tls_handshake_proto, flags); 362 + if (!req) 363 + return -ENOMEM; 364 + treq = tls_handshake_req_init(req, args); 365 + treq->th_type = HANDSHAKE_MSG_TYPE_SERVERHELLO; 366 + treq->th_auth_mode = HANDSHAKE_AUTH_X509; 367 + treq->th_certificate = args->ta_my_cert; 368 + treq->th_privkey = args->ta_my_privkey; 369 + 370 + return handshake_req_submit(args->ta_sock, req, flags); 371 + } 372 + EXPORT_SYMBOL(tls_server_hello_x509); 373 + 374 + /** 375 + * tls_server_hello_psk - request a server TLS handshake on a socket 376 + * @args: socket and handshake parameters for this request 377 + * @flags: memory allocation control flags 378 + * 379 + * Return values: 380 + * %0: Handshake request enqueue; ->done will be called when complete 381 + * %-ESRCH: No user agent is available 382 + * %-ENOMEM: Memory allocation failed 383 + */ 384 + int tls_server_hello_psk(const struct tls_handshake_args *args, gfp_t flags) 385 + { 386 + struct tls_handshake_req *treq; 387 + struct handshake_req *req; 388 + 389 + req = handshake_req_alloc(&tls_handshake_proto, flags); 390 + if (!req) 391 + return -ENOMEM; 392 + treq = tls_handshake_req_init(req, args); 393 + treq->th_type = HANDSHAKE_MSG_TYPE_SERVERHELLO; 394 + treq->th_auth_mode = HANDSHAKE_AUTH_PSK; 395 + treq->th_num_peerids = 1; 396 + treq->th_peerid[0] = args->ta_my_peerids[0]; 397 + 398 + return handshake_req_submit(args->ta_sock, req, flags); 399 + } 400 + EXPORT_SYMBOL(tls_server_hello_psk); 401 + 402 + /** 403 + * tls_handshake_cancel - cancel a pending handshake 404 + * @sk: socket on which there is an ongoing handshake 405 + * 406 + * Request cancellation races with request completion. To determine 407 + * who won, callers examine the return value from this function. 408 + * 409 + * Return values: 410 + * %true - Uncompleted handshake request was canceled 411 + * %false - Handshake request already completed or not found 412 + */ 413 + bool tls_handshake_cancel(struct sock *sk) 414 + { 415 + return handshake_req_cancel(sk); 416 + } 417 + EXPORT_SYMBOL(tls_handshake_cancel);