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

net/handshake: Add API for sending TLS Closure alerts

This helper sends an alert only if a TLS session was established.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Link: https://lore.kernel.org/r/169047936730.5241.618595693821012638.stgit@oracle-102.nfsv4bat.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Chuck Lever and committed by
Jakub Kicinski
35b1b538 02574271

+92 -1
+1
include/net/handshake.h
··· 40 40 int tls_server_hello_psk(const struct tls_handshake_args *args, gfp_t flags); 41 41 42 42 bool tls_handshake_cancel(struct sock *sk); 43 + void tls_handshake_close(struct socket *sock); 43 44 44 45 #endif /* _NET_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 tlshd.o trace.o 11 + handshake-y := alert.o genl.o netlink.o request.o tlshd.o trace.o 12 12 13 13 obj-$(CONFIG_NET_HANDSHAKE_KUNIT_TEST) += handshake-test.o
+61
net/handshake/alert.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Handle the TLS Alert protocol 4 + * 5 + * Author: Chuck Lever <chuck.lever@oracle.com> 6 + * 7 + * Copyright (c) 2023, Oracle and/or its affiliates. 8 + */ 9 + 10 + #include <linux/types.h> 11 + #include <linux/socket.h> 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/skbuff.h> 15 + #include <linux/inet.h> 16 + 17 + #include <net/sock.h> 18 + #include <net/handshake.h> 19 + #include <net/tls.h> 20 + #include <net/tls_prot.h> 21 + 22 + #include "handshake.h" 23 + 24 + /** 25 + * tls_alert_send - send a TLS Alert on a kTLS socket 26 + * @sock: open kTLS socket to send on 27 + * @level: TLS Alert level 28 + * @description: TLS Alert description 29 + * 30 + * Returns zero on success or a negative errno. 31 + */ 32 + int tls_alert_send(struct socket *sock, u8 level, u8 description) 33 + { 34 + u8 record_type = TLS_RECORD_TYPE_ALERT; 35 + u8 buf[CMSG_SPACE(sizeof(record_type))]; 36 + struct msghdr msg = { 0 }; 37 + struct cmsghdr *cmsg; 38 + struct kvec iov; 39 + u8 alert[2]; 40 + int ret; 41 + 42 + alert[0] = level; 43 + alert[1] = description; 44 + iov.iov_base = alert; 45 + iov.iov_len = sizeof(alert); 46 + 47 + memset(buf, 0, sizeof(buf)); 48 + msg.msg_control = buf; 49 + msg.msg_controllen = sizeof(buf); 50 + msg.msg_flags = MSG_DONTWAIT; 51 + 52 + cmsg = CMSG_FIRSTHDR(&msg); 53 + cmsg->cmsg_level = SOL_TLS; 54 + cmsg->cmsg_type = TLS_SET_RECORD_TYPE; 55 + cmsg->cmsg_len = CMSG_LEN(sizeof(record_type)); 56 + memcpy(CMSG_DATA(cmsg), &record_type, sizeof(record_type)); 57 + 58 + iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, iov.iov_len); 59 + ret = sock_sendmsg(sock, &msg); 60 + return ret < 0 ? ret : 0; 61 + }
+6
net/handshake/handshake.h
··· 41 41 42 42 enum hr_flags_bits { 43 43 HANDSHAKE_F_REQ_COMPLETED, 44 + HANDSHAKE_F_REQ_SESSION, 44 45 }; 46 + 47 + struct genl_info; 45 48 46 49 /* Invariants for all handshake requests for one transport layer 47 50 * security protocol ··· 65 62 enum hp_flags_bits { 66 63 HANDSHAKE_F_PROTO_NOTIFY, 67 64 }; 65 + 66 + /* alert.c */ 67 + int tls_alert_send(struct socket *sock, u8 level, u8 description); 68 68 69 69 /* netlink.c */ 70 70 int handshake_genl_notify(struct net *net, const struct handshake_proto *proto,
+23
net/handshake/tlshd.c
··· 18 18 #include <net/sock.h> 19 19 #include <net/handshake.h> 20 20 #include <net/genetlink.h> 21 + #include <net/tls_prot.h> 21 22 22 23 #include <uapi/linux/keyctl.h> 23 24 #include <uapi/linux/handshake.h> ··· 100 99 treq->th_peerid[0] = TLS_NO_PEERID; 101 100 if (info) 102 101 tls_handshake_remote_peerids(treq, info); 102 + 103 + if (!status) 104 + set_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags); 103 105 104 106 treq->th_consumer_done(treq->th_consumer_data, -status, 105 107 treq->th_peerid[0]); ··· 428 424 return handshake_req_cancel(sk); 429 425 } 430 426 EXPORT_SYMBOL(tls_handshake_cancel); 427 + 428 + /** 429 + * tls_handshake_close - send a Closure alert 430 + * @sock: an open socket 431 + * 432 + */ 433 + void tls_handshake_close(struct socket *sock) 434 + { 435 + struct handshake_req *req; 436 + 437 + req = handshake_req_hash_lookup(sock->sk); 438 + if (!req) 439 + return; 440 + if (!test_and_clear_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags)) 441 + return; 442 + tls_alert_send(sock, TLS_ALERT_LEVEL_WARNING, 443 + TLS_ALERT_DESC_CLOSE_NOTIFY); 444 + } 445 + EXPORT_SYMBOL(tls_handshake_close);