[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <D3C72D0A-7542-49CA-BB68-B42A26F9D636@oracle.com>
Date: Mon, 30 Jan 2023 15:00:51 +0000
From: Chuck Lever III <chuck.lever@...cle.com>
To: Marcel Holtmann <marcel@...tmann.org>
CC: Hannes Reinecke <hare@...e.de>, Jakub Kicinski <kuba@...nel.org>,
"open list:NETWORKING [GENERAL]" <netdev@...r.kernel.org>,
"hare@...e.com" <hare@...e.com>,
David Howells <dhowells@...hat.com>,
Olga Kornievskaia <kolga@...app.com>,
"jmeneghi@...hat.com" <jmeneghi@...hat.com>,
Benjamin Coddington <bcodding@...hat.com>,
Jeff Layton <jlayton@...hat.com>
Subject: Re: [PATCH v2 2/3] net/handshake: Add support for PF_HANDSHAKE
Hello Marcel-
> On Jan 30, 2023, at 8:44 AM, Marcel Holtmann <marcel@...tmann.org> wrote:
>
> Hi Hannes,
>
>>>> I've designed a way to pass a connected kernel socket endpoint to
>>>> user space using the traditional listen/accept mechanism. accept(2)
>>>> gives us a well-worn building block that can materialize a connected
>>>> socket endpoint as a file descriptor in a specific user space
>>>> process. Like any open socket descriptor, the accepted FD can then
>>>> be passed to a library such as GnuTLS to perform a TLS handshake.
>>> I can't bring myself to like the new socket family layer.
>>> I'd like a second opinion on that, if anyone within netdev
>>> is willing to share..
>>
>> I am not particularly fond of that, either, but the alternative of using netlink doesn't make it any better
>> You can't pass the fd/socket directly via netlink messages, you can only pass the (open!) fd number with the message.
>> The fd itself _needs_ be be part of the process context of the application by the time the application processes that message.
>> Consequently:
>> - I can't see how an application can _reject_ the message; the fd needs to be present in the fd table even before the message is processed, rendering any decision by the application pointless (and I would _so_ love to be proven wrong on this point)
>> - It's slightly tricky to handle processes which go away prior to handling the message; I _think_ the process cleanup code will close the fd, but I guess it also depends on how and when the fd is stored in the process context.
>>
>> If someone can point me to a solution for these points I would vastly prefer to move to netlink. But with these issues in place I'm not sure if netlink doesn't cause more issues than it solves.
>
> I think we first need to figure out the security model behind this.
>
> For kTLS you have the TLS Handshake messages inline with the TCP
> socket and thus credentials are given by the owner of that socket.
> This is simple and makes a lot of sense since whoever opened that
> connection has to decide to give a client certificate or accept
> the server certificate (in case of session resumption also provide
> the PSK).
>
> I like to have a generic TLS Handshake interface as well since more
> and more protocols will take TLS 1.3 as reference and use its
> handshake protocol. What I would not do is insist on using an fd,
> because that is what OpenSSL and others are just used to. The TLS
> libraries need to go away from the fd as IO model and provide
> appropriate APIs into the TLS Handshake (and also TLS Alert
> protocol) for a “codec style” operation.
Note that we are not attempting to replace handshakes for user
applications -- the purpose of AF_HANDSHAKE is for dealing with
the needs of /kernel/ consumers of transport layer security.
> Fundamentally nothing speaks against TLS Handshake in the kernel. All
> the core functionality is already present. All KPP, HKDF and even the
> certifiacate handling is present. In a simplified view, you just need
> To give the kernel a keyctl keyring that has the CA certs to verify
> and provide the keyring with either client or server certificate to
> use.
I agree strongly that the handshake logic can and should reside
in the kernel. The kernel security community and many file
system developers have told us repeatedly that an in-kernel
design is a non-starter, thus we are going with an upcall for
now.
> On a TCP socket for example you could do this:
>
> setsockopt(fd, SOL_TCP, TCP_ULP, “tls+hs", ..);
>
> tls_client.cert_id = key_id_cert;
> tls_client.ca_id = key_id_ca;
>
> setsockopt(fd, SOL_TLS, TLS_CLIENT, &tls_client, ..);
>
> Failures or errors would be reported out via socket errors or SCM.
> And you need some extra options to select cipher ranges or limit to
> TLS 1.3 only etc.
>
> But overall it would make using TCP+TLS really simple. The complicated
> part is providing the key ring. Then again, the CA key ring could be
> inherited from systemd or some basic component setting it up and
> sealing it.
>
> For other protocols or usages the input would be similar. It should
> be rather straight forward to provide key ring identifiers as mount
> option or via an ioctl.
That is essentially what I'm attempting to do here: provide a
stable API that kernel TLS consumers can use that hides the
mechanism of the handshake. It can be an upcall, it can be done
in the kernel, it can use a struct socket * endpoint or a file
descriptor. But the API that kernel consumers see does not
change, and we can build something very much like what you
described behind that API, or replace it all with chewing gum,
bailing wire, and band-aids. The consumers should not care, as
long as it works.
> This however needs to overcome the fear of putting the TLS Handshake
> into the kernel. I can understand anybody thinking that it is not a
> good idea and with TLS 1.2 and before it is a bit convoluted and
> error prone. However starting with TLS 1.3 things are a lot simpler
> and streamlined. There are few oddities where TLS 1.3 has to look
> like TLS 1.2 on the wire, but that mainly only affects the TLS
> record protocol and kTLS does that today already anyway.
We've been looking at the mbed-based in-kernel handshake that
Tempesta did, so it's not a stretch to imagine what such a
thing would look like.
Tempesta, however, is indeed looking at a handshake facility
that can be used by user applications, it should be noted.
The point of having a fixed in-kernel handshake API is that,
if something like Tempesta is ever adopted, in-kernel TLS
consumers can be switched over to that with little fuss.
Also note: the current cohort of kernel consumers do not need
or want anything older than TLSv1.3. Anything that has to
deal with user space applications likely needs compatibility
with TLSv1.2 at least.
The kernel consumers we want to support include:
- RPC-with-TLS (RFC 9289)
- NVMe over TCP with TLS (part of NVMe/TCP rev 1.0a)
- SMB on QUIC (no public specification found)
All of these mandate at least TLSv1.3.
> For reference ELL (git.kernel.org/pub/scm/libs/ell/ell.git) has a
> TLS implementation that utilizes AF_ALG and keyctl for all the
> basic crypto needs. Certificates and certificate operations are
> purely done via keyctl and that works nicely. If KPP would finally
> get an usersapce interface, even shared secret derivation would go
> via kernel crypto.
>
> The code is currently TLS 1.2 and earlier, but I have code for
> TLS 1.3 and also code for utilizing kTLS. It needs a bit more
> cleanup, but then I am happy to publish it. The modified code
> for TLS 1.3 support has TLS Handshake+Alert separated from TLS
> Record protocol and doesn’t even rely on an fd to operate. This
> comes from the requirement that TLS for WiFi Enterprise (or in
> the future QUIC) doesn’t have a fd either.
We have our eye on QUIC as well, for exactly those reasons.
But as I said, our use case is for kernel consumers of
transport layer security, such as SMB on QUIC support in
the kernel's cifs client.
> Long story short, who is suppose to run the TLS Handshake if
> we push it to userspace. There will be never a generic daemon
> that handles all handshakes since they are all application
> specific. No daemon can run the TLS Handshake on behalf of
> Chrome browser for example. This leads me to AF_HANDSHAKE
> is not a good idea.
In our narrow use case, user space applications will continue
to use existing libraries directly for doing the handshaking
that they need. I'm not advocating for using AF_HANDSHAKE to
replace existing user space TLS library users, because I
agree that user space is going to have a much broader set of
use cases that handshake implementations have to deal with.
For kernel consumers, we have provided an example user space
daemon that handles handshake requests via a direct call to
the GnuTLS library. We can add as much decoration on that
mechanism as kernel consumers require...
https://github.com/oracle/ktls-utils
We expect there to be one of these daemons running in each
network namespace. The daemon reads authentication material
from local files or gets it from kernel keyrings.
> One nice thing we found with using keyctl for WiFi Enterprise
> is that we can have certificates that are backed by the TPM.
TPM support is one reason we use kernel keyrings in our design,
though for us this is currently untested.
> Doing that via keyctl was a lot simpler than dealing with the
> different oddities of SSL engines or different variations of
> crypto libraries. The unification by the kernel is really
> nice. I have to re-read how much EFI can provide securely
> hardware backed keys, but for everybody working in early
> userspace or initramfs it is nice to be able to utilize
> this without having to drag in megabytes of TLS library.
Performing handshakes during early boot is one very important
use case that doing an upcall does not handle without a lot
of additional complexity. This is one reason we'd like to see
an in-kernel handshake implementation.
--
Chuck Lever
Powered by blists - more mailing lists