Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Jan 2020 23:28:24 +0000
From:      Rick Macklem <rmacklem@uoguelph.ca>
To:        John Baldwin <jhb@FreeBSD.org>, "freebsd-current@FreeBSD.org" <freebsd-current@FreeBSD.org>
Subject:   Re: how to use the ktls
Message-ID:  <YQBPR0101MB1427789FF1B79EC532737D20DD0B0@YQBPR0101MB1427.CANPRD01.PROD.OUTLOOK.COM>
In-Reply-To: <d29b4343-b8e0-88e7-9076-d2a94eb45386@FreeBSD.org>
References:  <YQBPR0101MB142760894682CA3663CB53BDDD3F0@YQBPR0101MB1427.CANPRD01.PROD.OUTLOOK.COM> <5be57c87-90fe-fcbe-ea37-bdb1bcff2da8@FreeBSD.org> <YQBPR0101MB1427F6950084C3CA30713A75DD080@YQBPR0101MB1427.CANPRD01.PROD.OUTLOOK.COM>, <d29b4343-b8e0-88e7-9076-d2a94eb45386@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
John Baldwin wrote:=0A=
>On 1/26/20 8:08 PM, Rick Macklem wrote:=0A=
>> John Baldwin wrote:=0A=
>> [stuff snipped]=0A=
>>> Hmmm, this might be a fair bit of work indeed.=0A=
>>>=0A=
>>> Right now KTLS only works for transmit (though I have some WIP for rece=
ive).=0A=
>>>=0A=
>>> KTLS does assumes that the initial handshake and key negotiation is han=
dled by=0A=
>>> OpenSSL.  OpenSSL uses custom setockopt() calls to tell the kernel whic=
h=0A=
>>> session keys to use.=0A=
>>>=0A=
>>> I think what you would want to do is use something like OpenSSL_connect=
() in=0A=
>>> userspace, and then check to see if KTLS "worked".  If it did, you can =
tell=0A=
>>> the kernel it can write to the socket directly, otherwise you will have=
 to=0A=
>>> bounce data back out to userspace to run it through SSL_write() and hav=
e=0A=
>>> userspace do SSL_read() and then feed data into the kernel.=0A=
>>>=0A=
>>> The pseudo-code might look something like:=0A=
>>>=0A=
>>> SSL *s;=0A=
>>>=0A=
>>> s =3D SSL_new(...);=0A=
>>>=0A=
>>> /* fd is the existing TCP socket */=0A=
>>> SSL_set_fd(s, fd);=0A=
>>> OpenSSL_connect(s);=0A=
>>> if (BIO_get_ktls_send(SSL_get_wbio(s)) {=0A=
>>>    /* Can use KTLS for transmit. */=0A=
>>> }=0A=
>>> if (BIO_get_ktls_recv(SSL_get_rbio(s)) {=0A=
>>>    /* Can use KTLS for receive. */=0A=
>>> }=0A=
>>=0A=
>> So, I've been making some progress. The first stab at the daemons that d=
o the=0A=
>> handshake are now on svn in base/projects/nfs-over-tls/usr.sbin/rpctlscd=
 and=0A=
>> rpctlssd.=0A=
>>=0A=
>> A couple of questions...=0A=
>> 1 - I haven't found BIO_get_ktls_send() or BIO_get_ktls_recv(). Are they=
 in some=0A=
>>        different library?=0A=
>=0A=
>They only existing currently in OpenSSL master (which will be OpenSSL 3.0.=
0 when it=0A=
>is released).  I have some not-yet-tested WIP changes to backport those ch=
anges into=0A=
>the base OpenSSL, but it will also add overhead to future OpenSSL imports =
perhaps,=0A=
>so it is something I need to work with secteam@ on to decide if it's viabl=
e once I=0A=
>have a tested PoC.=0A=
>=0A=
>I will try to at least provide a patch to the security/openssl port to add=
 a KTLS=0A=
>option "soon" that you could use for testing.=0A=
John, I wouldn't worry much about this.=0A=
The calls are currently #ifdef notnow in the daemon and I'm fine with that.=
=0A=
SSL_connect() has returned 1, so the daemon knows that the handshake is com=
plete and=0A=
the kernel code that did the upcall to the daemon can check for KERN_TLS su=
pport.=0A=
=0A=
>> 2 - After a successful SSL_connect(), the receive queue for the socket h=
as 478bytes=0A=
>>       of stuff in it. SSL_read() seems to know how to skip over it, but =
I haven't=0A=
>>       figured out a good way to do this. (I currently just do a recv(..4=
78,0) on the=0A=
>>       socket.)=0A=
>>       Any idea what to do with this? (Or will the receive side of the kt=
ls figure out=0A=
>>       how to skip over it?)=0A=
>=0A=
>I don't know yet. :-/  With the TOE-based TLS I had been testing with, thi=
s doesn't=0A=
>happen because the NIC blocks the data until it gets the key and then it's=
 always=0A=
>available via KTLS.  With software-based KTLS for RX (which I'm going to s=
tart=0A=
>working on soon), this won't be the case and you will potentially have som=
e data=0A=
>already ready by OpenSSL that needs to be drained from OpenSSL before you =
can=0A=
>depend on KTLS.  It's probably only the first few messsages, but I will ne=
ed to figure=0A=
>out a way that you can tell how much pending data in userland you need to =
read via=0A=
>SSL_read() and then pass back into the kernel before relying on KTLS (it w=
ould just=0A=
>be a single chunk of data after SSL_connect you would have to do this for)=
.=0A=
Well, SSL_read() doesn't return these bytes. I think it just throws them aw=
ay.=0A=
=0A=
I have a simple test client/server where the client sends "HELLO THERE" to =
the=0A=
server and the server replies "GOODBYE" after the SSL_connect()/SSL_accept(=
)=0A=
has been done.=0A=
--> If the "HELLO THERE"/"GOODBYE" is done with SSL_write()/SSL_read() it w=
orks.=0A=
however=0A=
--> If the above is done with send()/recv(), the server gets the "HELLO THE=
RE", but=0A=
      the client gets 485bytes of data, where the last 7 are "GOODBYE".=0A=
      --> If I do a recv( ..475..) in the client right after SSL_connect() =
it works ok.=0A=
=0A=
I do this for testing, since it can then do the NFS mount (unencrypted).=0A=
=0A=
Looking inside SSL_read() I found:=0A=
*=0A=
1742	     * If we are a client and haven't received the ServerHello etc the=
n we=0A=
1743	     * better do that=0A=
1744	     */=0A=
1745	    ossl_statem_check_finish_init(s, 0);=0A=
=0A=
but all ossl_statem_check_finish_init(s, 0); seems to do is set a variable =
"in_init =3D 1".=0A=
Then it calls the method->read() function, which I'd guess is in the crypto=
 code=0A=
and it seems to get rid of these bytes. (I hate trying to figure out what c=
alls what=0A=
for object oriented code;-).=0A=
=0A=
Btw. SSL_is_finished_init() returns 1 right after the SSL_connect(), so it =
seems to=0A=
think the hadnshake is done, although it hasn't read these 478 bytes from t=
he server.=0A=
=0A=
Anyhow, I'd guess the TOE engine knows how to do get rid of this stuff like=
 SSL_read()=0A=
does?=0A=
=0A=
>> I'm currently testing with a kernel that doesn't have options KERN_TLS a=
nd=0A=
>> (so long as I get rid of the 478 bytes), it then just does unencrypted R=
PCs.=0A=
>>=0A=
>> So, I guess the big question is.... can I get access to your WIP code fo=
r KTLS=0A=
>> receive? (I have no idea if I can make progress on it, but I can't do a =
lot more=0A=
>> before I have that.)=0A=
>=0A=
>The WIP only works right now if you have a Chelsio T6 NIC as it uses the T=
6's TCP=0A=
>offload engine to do TLS.  If you don't have that gear, ping me off-list. =
 It=0A=
>would also let you not worry about the SSL_read case for now for initial t=
esting.=0A=
I may contact you in April about this.=0A=
Since you've noted above that you haven't started the software version, I m=
ight try=0A=
coming up with something and will let you know if I do.=0A=
=0A=
Thanks, rick=0A=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?YQBPR0101MB1427789FF1B79EC532737D20DD0B0>