// SPDX-License-Identifier: GPL-2.0-only /* * Establish a TLS session for a kernel socket consumer * using the tlshd user space handler. * * Author: Chuck Lever <chuck.lever@oracle.com> * * Copyright (c) 2021-2023, Oracle and/or its affiliates.
*/
i = 0;
nla_for_each_attr(nla, head, len, rem) { if (nla_type(nla) == HANDSHAKE_A_DONE_REMOTE_AUTH)
i++;
} if (!i) return;
treq->th_num_peerids = min_t(unsignedint, i,
ARRAY_SIZE(treq->th_peerid));
i = 0;
nla_for_each_attr(nla, head, len, rem) { if (nla_type(nla) == HANDSHAKE_A_DONE_REMOTE_AUTH)
treq->th_peerid[i++] = nla_get_u32(nla); if (i >= treq->th_num_peerids) break;
}
}
/** * tls_handshake_done - callback to handle a CMD_DONE request * @req: socket on which the handshake was performed * @status: session status code * @info: full results of session establishment *
*/ staticvoid tls_handshake_done(struct handshake_req *req, unsignedint status, struct genl_info *info)
{ struct tls_handshake_req *treq = handshake_req_private(req);
treq->th_peerid[0] = TLS_NO_PEERID; if (info)
tls_handshake_remote_peerids(treq, info);
if (!status)
set_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags);
for (i = 0; i < treq->th_num_peerids; i++) if (nla_put_u32(msg, HANDSHAKE_A_ACCEPT_PEER_IDENTITY,
treq->th_peerid[i]) < 0) return -EMSGSIZE; return 0;
}
/** * tls_handshake_accept - callback to construct a CMD_ACCEPT response * @req: handshake parameters to return * @info: generic netlink message context * @fd: file descriptor to be returned * * Returns zero on success, or a negative errno on failure.
*/ staticint tls_handshake_accept(struct handshake_req *req, struct genl_info *info, int fd)
{ struct tls_handshake_req *treq = handshake_req_private(req); struct nlmsghdr *hdr; struct sk_buff *msg; int ret;
ret = tls_handshake_private_keyring(treq); if (ret < 0) goto out;
ret = -ENOMEM;
msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) goto out;
hdr = handshake_genl_put(msg, info); if (!hdr) goto out_cancel;
ret = nla_put_s32(msg, HANDSHAKE_A_ACCEPT_SOCKFD, fd); if (ret < 0) goto out_cancel;
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MESSAGE_TYPE, treq->th_type); if (ret < 0) goto out_cancel; if (treq->th_peername) {
ret = nla_put_string(msg, HANDSHAKE_A_ACCEPT_PEERNAME,
treq->th_peername); if (ret < 0) goto out_cancel;
} if (treq->th_timeout_ms) {
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_TIMEOUT, treq->th_timeout_ms); if (ret < 0) goto out_cancel;
} if (treq->th_keyring) {
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_KEYRING,
treq->th_keyring); if (ret < 0) goto out_cancel;
}
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_AUTH_MODE,
treq->th_auth_mode); if (ret < 0) goto out_cancel; switch (treq->th_auth_mode) { case HANDSHAKE_AUTH_PSK:
ret = tls_handshake_put_peer_identity(msg, treq); if (ret < 0) goto out_cancel; break; case HANDSHAKE_AUTH_X509:
ret = tls_handshake_put_certificate(msg, treq); if (ret < 0) goto out_cancel; break;
}
/** * tls_client_hello_anon - request an anonymous TLS handshake on a socket * @args: socket and handshake parameters for this request * @flags: memory allocation control flags * * Return values: * %0: Handshake request enqueue; ->done will be called when complete * %-ESRCH: No user agent is available * %-ENOMEM: Memory allocation failed
*/ int tls_client_hello_anon(conststruct tls_handshake_args *args, gfp_t flags)
{ struct tls_handshake_req *treq; struct handshake_req *req;
/** * tls_client_hello_x509 - request an x.509-based TLS handshake on a socket * @args: socket and handshake parameters for this request * @flags: memory allocation control flags * * Return values: * %0: Handshake request enqueue; ->done will be called when complete * %-ESRCH: No user agent is available * %-ENOMEM: Memory allocation failed
*/ int tls_client_hello_x509(conststruct tls_handshake_args *args, gfp_t flags)
{ struct tls_handshake_req *treq; struct handshake_req *req;
/** * tls_client_hello_psk - request a PSK-based TLS handshake on a socket * @args: socket and handshake parameters for this request * @flags: memory allocation control flags * * Return values: * %0: Handshake request enqueue; ->done will be called when complete * %-EINVAL: Wrong number of local peer IDs * %-ESRCH: No user agent is available * %-ENOMEM: Memory allocation failed
*/ int tls_client_hello_psk(conststruct tls_handshake_args *args, gfp_t flags)
{ struct tls_handshake_req *treq; struct handshake_req *req; unsignedint i;
if (!args->ta_num_peerids ||
args->ta_num_peerids > ARRAY_SIZE(treq->th_peerid)) return -EINVAL;
req = handshake_req_alloc(&tls_handshake_proto, flags); if (!req) return -ENOMEM;
treq = tls_handshake_req_init(req, args);
treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO;
treq->th_auth_mode = HANDSHAKE_AUTH_PSK;
treq->th_num_peerids = args->ta_num_peerids; for (i = 0; i < args->ta_num_peerids; i++)
treq->th_peerid[i] = args->ta_my_peerids[i];
/** * tls_server_hello_x509 - request a server TLS handshake on a socket * @args: socket and handshake parameters for this request * @flags: memory allocation control flags * * Return values: * %0: Handshake request enqueue; ->done will be called when complete * %-ESRCH: No user agent is available * %-ENOMEM: Memory allocation failed
*/ int tls_server_hello_x509(conststruct tls_handshake_args *args, gfp_t flags)
{ struct tls_handshake_req *treq; struct handshake_req *req;
/** * tls_server_hello_psk - request a server TLS handshake on a socket * @args: socket and handshake parameters for this request * @flags: memory allocation control flags * * Return values: * %0: Handshake request enqueue; ->done will be called when complete * %-ESRCH: No user agent is available * %-ENOMEM: Memory allocation failed
*/ int tls_server_hello_psk(conststruct tls_handshake_args *args, gfp_t flags)
{ struct tls_handshake_req *treq; struct handshake_req *req;
/** * tls_handshake_cancel - cancel a pending handshake * @sk: socket on which there is an ongoing handshake * * Request cancellation races with request completion. To determine * who won, callers examine the return value from this function. * * Return values: * %true - Uncompleted handshake request was canceled * %false - Handshake request already completed or not found
*/ bool tls_handshake_cancel(struct sock *sk)
{ return handshake_req_cancel(sk);
}
EXPORT_SYMBOL(tls_handshake_cancel);
/** * tls_handshake_close - send a Closure alert * @sock: an open socket *
*/ void tls_handshake_close(struct socket *sock)
{ struct handshake_req *req;
req = handshake_req_hash_lookup(sock->sk); if (!req) return; if (!test_and_clear_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags)) return;
tls_alert_send(sock, TLS_ALERT_LEVEL_WARNING,
TLS_ALERT_DESC_CLOSE_NOTIFY);
}
EXPORT_SYMBOL(tls_handshake_close);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.