2017-06-14 18:37:39 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016-2017, Mellanox Technologies. All rights reserved.
|
|
|
|
* Copyright (c) 2016-2017, Dave Watson <davejwatson@fb.com>. All rights reserved.
|
|
|
|
* Copyright (c) 2016-2017, Lance Chao <lancerchao@fb.com>. All rights reserved.
|
|
|
|
* Copyright (c) 2016, Fridolin Pokorny <fridolin.pokorny@gmail.com>. All rights reserved.
|
|
|
|
* Copyright (c) 2016, Nikos Mavrogiannopoulos <nmav@gnutls.org>. All rights reserved.
|
|
|
|
*
|
|
|
|
* This software is available to you under a choice of one of two
|
|
|
|
* licenses. You may choose to be licensed under the terms of the GNU
|
|
|
|
* General Public License (GPL) Version 2, available from the file
|
|
|
|
* COPYING in the main directory of this source tree, or the
|
|
|
|
* OpenIB.org BSD license below:
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or
|
|
|
|
* without modification, are permitted provided that the following
|
|
|
|
* conditions are met:
|
|
|
|
*
|
|
|
|
* - Redistributions of source code must retain the above
|
|
|
|
* copyright notice, this list of conditions and the following
|
|
|
|
* disclaimer.
|
|
|
|
*
|
|
|
|
* - Redistributions in binary form must reproduce the above
|
|
|
|
* copyright notice, this list of conditions and the following
|
|
|
|
* disclaimer in the documentation and/or other materials
|
|
|
|
* provided with the distribution.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
#include <linux/sched/signal.h>
|
2017-06-14 18:37:39 +00:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <crypto/aead.h>
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
#include <net/strparser.h>
|
2017-06-14 18:37:39 +00:00
|
|
|
#include <net/tls.h>
|
|
|
|
|
2018-04-11 00:52:34 +00:00
|
|
|
#define MAX_IV_SIZE TLS_CIPHER_AES_GCM_128_IV_SIZE
|
|
|
|
|
2018-08-28 23:33:57 +00:00
|
|
|
static int __skb_nsg(struct sk_buff *skb, int offset, int len,
|
|
|
|
unsigned int recursion_level)
|
|
|
|
{
|
|
|
|
int start = skb_headlen(skb);
|
|
|
|
int i, chunk = start - offset;
|
|
|
|
struct sk_buff *frag_iter;
|
|
|
|
int elt = 0;
|
|
|
|
|
|
|
|
if (unlikely(recursion_level >= 24))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
if (chunk > 0) {
|
|
|
|
if (chunk > len)
|
|
|
|
chunk = len;
|
|
|
|
elt++;
|
|
|
|
len -= chunk;
|
|
|
|
if (len == 0)
|
|
|
|
return elt;
|
|
|
|
offset += chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
|
|
|
int end;
|
|
|
|
|
|
|
|
WARN_ON(start > offset + len);
|
|
|
|
|
|
|
|
end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]);
|
|
|
|
chunk = end - offset;
|
|
|
|
if (chunk > 0) {
|
|
|
|
if (chunk > len)
|
|
|
|
chunk = len;
|
|
|
|
elt++;
|
|
|
|
len -= chunk;
|
|
|
|
if (len == 0)
|
|
|
|
return elt;
|
|
|
|
offset += chunk;
|
|
|
|
}
|
|
|
|
start = end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unlikely(skb_has_frag_list(skb))) {
|
|
|
|
skb_walk_frags(skb, frag_iter) {
|
|
|
|
int end, ret;
|
|
|
|
|
|
|
|
WARN_ON(start > offset + len);
|
|
|
|
|
|
|
|
end = start + frag_iter->len;
|
|
|
|
chunk = end - offset;
|
|
|
|
if (chunk > 0) {
|
|
|
|
if (chunk > len)
|
|
|
|
chunk = len;
|
|
|
|
ret = __skb_nsg(frag_iter, offset - start, chunk,
|
|
|
|
recursion_level + 1);
|
|
|
|
if (unlikely(ret < 0))
|
|
|
|
return ret;
|
|
|
|
elt += ret;
|
|
|
|
len -= chunk;
|
|
|
|
if (len == 0)
|
|
|
|
return elt;
|
|
|
|
offset += chunk;
|
|
|
|
}
|
|
|
|
start = end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BUG_ON(len);
|
|
|
|
return elt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the number of scatterlist elements required to completely map the
|
|
|
|
* skb, or -EMSGSIZE if the recursion depth is exceeded.
|
|
|
|
*/
|
|
|
|
static int skb_nsg(struct sk_buff *skb, int offset, int len)
|
|
|
|
{
|
|
|
|
return __skb_nsg(skb, offset, len, 0);
|
|
|
|
}
|
|
|
|
|
2018-08-29 09:56:55 +00:00
|
|
|
static void tls_decrypt_done(struct crypto_async_request *req, int err)
|
|
|
|
{
|
|
|
|
struct aead_request *aead_req = (struct aead_request *)req;
|
|
|
|
struct scatterlist *sgout = aead_req->dst;
|
2018-09-14 20:01:46 +00:00
|
|
|
struct tls_sw_context_rx *ctx;
|
|
|
|
struct tls_context *tls_ctx;
|
2018-08-29 09:56:55 +00:00
|
|
|
struct scatterlist *sg;
|
2018-09-14 20:01:46 +00:00
|
|
|
struct sk_buff *skb;
|
2018-08-29 09:56:55 +00:00
|
|
|
unsigned int pages;
|
2018-09-14 20:01:46 +00:00
|
|
|
int pending;
|
|
|
|
|
|
|
|
skb = (struct sk_buff *)req->data;
|
|
|
|
tls_ctx = tls_get_ctx(skb->sk);
|
|
|
|
ctx = tls_sw_ctx_rx(tls_ctx);
|
|
|
|
pending = atomic_dec_return(&ctx->decrypt_pending);
|
2018-08-29 09:56:55 +00:00
|
|
|
|
|
|
|
/* Propagate if there was an err */
|
|
|
|
if (err) {
|
|
|
|
ctx->async_wait.err = err;
|
2018-09-14 20:01:46 +00:00
|
|
|
tls_err_abort(skb->sk, err);
|
2018-08-29 09:56:55 +00:00
|
|
|
}
|
|
|
|
|
2018-09-14 20:01:46 +00:00
|
|
|
/* After using skb->sk to propagate sk through crypto async callback
|
|
|
|
* we need to NULL it again.
|
|
|
|
*/
|
|
|
|
skb->sk = NULL;
|
|
|
|
|
2018-08-29 09:56:55 +00:00
|
|
|
/* Release the skb, pages and memory allocated for crypto req */
|
2018-09-14 20:01:46 +00:00
|
|
|
kfree_skb(skb);
|
2018-08-29 09:56:55 +00:00
|
|
|
|
|
|
|
/* Skip the first S/G entry as it points to AAD */
|
|
|
|
for_each_sg(sg_next(sgout), sg, UINT_MAX, pages) {
|
|
|
|
if (!sg)
|
|
|
|
break;
|
|
|
|
put_page(sg_page(sg));
|
|
|
|
}
|
|
|
|
|
|
|
|
kfree(aead_req);
|
|
|
|
|
|
|
|
if (!pending && READ_ONCE(ctx->async_notify))
|
|
|
|
complete(&ctx->async_wait.completion);
|
|
|
|
}
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
static int tls_do_decryption(struct sock *sk,
|
2018-08-29 09:56:55 +00:00
|
|
|
struct sk_buff *skb,
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
struct scatterlist *sgin,
|
|
|
|
struct scatterlist *sgout,
|
|
|
|
char *iv_recv,
|
|
|
|
size_t data_len,
|
2018-08-29 09:56:55 +00:00
|
|
|
struct aead_request *aead_req,
|
|
|
|
bool async)
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
int ret;
|
|
|
|
|
2018-08-10 15:16:41 +00:00
|
|
|
aead_request_set_tfm(aead_req, ctx->aead_recv);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
|
|
|
|
aead_request_set_crypt(aead_req, sgin, sgout,
|
|
|
|
data_len + tls_ctx->rx.tag_size,
|
|
|
|
(u8 *)iv_recv);
|
|
|
|
|
2018-08-29 09:56:55 +00:00
|
|
|
if (async) {
|
2018-09-14 20:01:46 +00:00
|
|
|
/* Using skb->sk to push sk through to crypto async callback
|
|
|
|
* handler. This allows propagating errors up to the socket
|
|
|
|
* if needed. It _must_ be cleared in the async handler
|
|
|
|
* before kfree_skb is called. We _know_ skb->sk is NULL
|
|
|
|
* because it is a clone from strparser.
|
|
|
|
*/
|
|
|
|
skb->sk = sk;
|
2018-08-29 09:56:55 +00:00
|
|
|
aead_request_set_callback(aead_req,
|
|
|
|
CRYPTO_TFM_REQ_MAY_BACKLOG,
|
|
|
|
tls_decrypt_done, skb);
|
|
|
|
atomic_inc(&ctx->decrypt_pending);
|
|
|
|
} else {
|
|
|
|
aead_request_set_callback(aead_req,
|
|
|
|
CRYPTO_TFM_REQ_MAY_BACKLOG,
|
|
|
|
crypto_req_done, &ctx->async_wait);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = crypto_aead_decrypt(aead_req);
|
|
|
|
if (ret == -EINPROGRESS) {
|
|
|
|
if (async)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
ret = crypto_wait_req(ret, &ctx->async_wait);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (async)
|
|
|
|
atomic_dec(&ctx->decrypt_pending);
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-06-14 18:37:39 +00:00
|
|
|
static void trim_sg(struct sock *sk, struct scatterlist *sg,
|
|
|
|
int *sg_num_elem, unsigned int *sg_size, int target_size)
|
|
|
|
{
|
|
|
|
int i = *sg_num_elem - 1;
|
|
|
|
int trim = *sg_size - target_size;
|
|
|
|
|
|
|
|
if (trim <= 0) {
|
|
|
|
WARN_ON(trim < 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*sg_size = target_size;
|
|
|
|
while (trim >= sg[i].length) {
|
|
|
|
trim -= sg[i].length;
|
|
|
|
sk_mem_uncharge(sk, sg[i].length);
|
|
|
|
put_page(sg_page(&sg[i]));
|
|
|
|
i--;
|
|
|
|
|
|
|
|
if (i < 0)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
sg[i].length -= trim;
|
|
|
|
sk_mem_uncharge(sk, trim);
|
|
|
|
|
|
|
|
out:
|
|
|
|
*sg_num_elem = i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void trim_both_sgl(struct sock *sk, int target_size)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec = ctx->open_rec;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
trim_sg(sk, rec->sg_plaintext_data,
|
|
|
|
&rec->sg_plaintext_num_elem,
|
|
|
|
&rec->sg_plaintext_size,
|
2017-06-14 18:37:39 +00:00
|
|
|
target_size);
|
|
|
|
|
|
|
|
if (target_size > 0)
|
2018-03-22 17:10:06 +00:00
|
|
|
target_size += tls_ctx->tx.overhead_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
trim_sg(sk, rec->sg_encrypted_data,
|
|
|
|
&rec->sg_encrypted_num_elem,
|
|
|
|
&rec->sg_encrypted_size,
|
2017-06-14 18:37:39 +00:00
|
|
|
target_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int alloc_encrypted_sg(struct sock *sk, int len)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec = ctx->open_rec;
|
2017-06-14 18:37:39 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2018-03-18 19:56:49 +00:00
|
|
|
rc = sk_alloc_sg(sk, len,
|
2018-09-21 04:16:13 +00:00
|
|
|
rec->sg_encrypted_data, 0,
|
|
|
|
&rec->sg_encrypted_num_elem,
|
|
|
|
&rec->sg_encrypted_size, 0);
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-06 16:11:40 +00:00
|
|
|
if (rc == -ENOSPC)
|
2018-09-21 04:16:13 +00:00
|
|
|
rec->sg_encrypted_num_elem = ARRAY_SIZE(rec->sg_encrypted_data);
|
2018-09-06 16:11:40 +00:00
|
|
|
|
2017-06-14 18:37:39 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int alloc_plaintext_sg(struct sock *sk, int len)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec = ctx->open_rec;
|
2017-06-14 18:37:39 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
rc = sk_alloc_sg(sk, len, rec->sg_plaintext_data, 0,
|
|
|
|
&rec->sg_plaintext_num_elem, &rec->sg_plaintext_size,
|
2018-03-18 19:56:49 +00:00
|
|
|
tls_ctx->pending_open_record_frags);
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-06 16:11:40 +00:00
|
|
|
if (rc == -ENOSPC)
|
2018-09-21 04:16:13 +00:00
|
|
|
rec->sg_plaintext_num_elem = ARRAY_SIZE(rec->sg_plaintext_data);
|
2018-09-06 16:11:40 +00:00
|
|
|
|
2017-06-14 18:37:39 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_sg(struct sock *sk, struct scatterlist *sg,
|
|
|
|
int *sg_num_elem, unsigned int *sg_size)
|
|
|
|
{
|
|
|
|
int i, n = *sg_num_elem;
|
|
|
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
|
|
sk_mem_uncharge(sk, sg[i].length);
|
|
|
|
put_page(sg_page(&sg[i]));
|
|
|
|
}
|
|
|
|
*sg_num_elem = 0;
|
|
|
|
*sg_size = 0;
|
|
|
|
}
|
|
|
|
|
2018-09-25 14:51:51 +00:00
|
|
|
static void tls_free_open_rec(struct sock *sk)
|
2017-06-14 18:37:39 +00:00
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec = ctx->open_rec;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
/* Return if there is no open record */
|
|
|
|
if (!rec)
|
|
|
|
return;
|
|
|
|
|
|
|
|
free_sg(sk, rec->sg_encrypted_data,
|
|
|
|
&rec->sg_encrypted_num_elem,
|
|
|
|
&rec->sg_encrypted_size);
|
|
|
|
|
|
|
|
free_sg(sk, rec->sg_plaintext_data,
|
|
|
|
&rec->sg_plaintext_num_elem,
|
|
|
|
&rec->sg_plaintext_size);
|
2018-09-25 14:51:51 +00:00
|
|
|
|
|
|
|
kfree(rec);
|
2018-09-21 04:16:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int tls_tx_records(struct sock *sk, int flags)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
|
|
|
struct tls_rec *rec, *tmp;
|
|
|
|
int tx_flags, rc = 0;
|
|
|
|
|
|
|
|
if (tls_is_partially_sent_record(tls_ctx)) {
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
rec = list_first_entry(&ctx->tx_list,
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec, list);
|
|
|
|
|
|
|
|
if (flags == -1)
|
|
|
|
tx_flags = rec->tx_flags;
|
|
|
|
else
|
|
|
|
tx_flags = flags;
|
|
|
|
|
|
|
|
rc = tls_push_partial_record(sk, tls_ctx, tx_flags);
|
|
|
|
if (rc)
|
|
|
|
goto tx_err;
|
|
|
|
|
|
|
|
/* Full record has been transmitted.
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
* Remove the head of tx_list
|
2018-09-21 04:16:13 +00:00
|
|
|
*/
|
|
|
|
list_del(&rec->list);
|
2018-09-25 10:56:17 +00:00
|
|
|
free_sg(sk, rec->sg_plaintext_data,
|
|
|
|
&rec->sg_plaintext_num_elem, &rec->sg_plaintext_size);
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
kfree(rec);
|
|
|
|
}
|
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
/* Tx all ready records */
|
|
|
|
list_for_each_entry_safe(rec, tmp, &ctx->tx_list, list) {
|
|
|
|
if (READ_ONCE(rec->tx_ready)) {
|
2018-09-21 04:16:13 +00:00
|
|
|
if (flags == -1)
|
|
|
|
tx_flags = rec->tx_flags;
|
|
|
|
else
|
|
|
|
tx_flags = flags;
|
|
|
|
|
|
|
|
rc = tls_push_sg(sk, tls_ctx,
|
|
|
|
&rec->sg_encrypted_data[0],
|
|
|
|
0, tx_flags);
|
|
|
|
if (rc)
|
|
|
|
goto tx_err;
|
|
|
|
|
|
|
|
list_del(&rec->list);
|
2018-09-25 10:56:17 +00:00
|
|
|
free_sg(sk, rec->sg_plaintext_data,
|
|
|
|
&rec->sg_plaintext_num_elem,
|
|
|
|
&rec->sg_plaintext_size);
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
kfree(rec);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tx_err:
|
|
|
|
if (rc < 0 && rc != -EAGAIN)
|
|
|
|
tls_err_abort(sk, EBADMSG);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tls_encrypt_done(struct crypto_async_request *req, int err)
|
|
|
|
{
|
|
|
|
struct aead_request *aead_req = (struct aead_request *)req;
|
|
|
|
struct sock *sk = req->data;
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
|
|
|
struct tls_rec *rec;
|
|
|
|
bool ready = false;
|
|
|
|
int pending;
|
|
|
|
|
|
|
|
rec = container_of(aead_req, struct tls_rec, aead_req);
|
|
|
|
|
|
|
|
rec->sg_encrypted_data[0].offset -= tls_ctx->tx.prepend_size;
|
|
|
|
rec->sg_encrypted_data[0].length += tls_ctx->tx.prepend_size;
|
|
|
|
|
|
|
|
|
|
|
|
/* Free the record if error is previously set on socket */
|
|
|
|
if (err || sk->sk_err) {
|
|
|
|
free_sg(sk, rec->sg_encrypted_data,
|
|
|
|
&rec->sg_encrypted_num_elem, &rec->sg_encrypted_size);
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
kfree(rec);
|
|
|
|
rec = NULL;
|
|
|
|
|
|
|
|
/* If err is already set on socket, return the same code */
|
|
|
|
if (sk->sk_err) {
|
|
|
|
ctx->async_wait.err = sk->sk_err;
|
|
|
|
} else {
|
|
|
|
ctx->async_wait.err = err;
|
|
|
|
tls_err_abort(sk, err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
if (rec) {
|
|
|
|
struct tls_rec *first_rec;
|
|
|
|
|
|
|
|
/* Mark the record as ready for transmission */
|
|
|
|
smp_store_mb(rec->tx_ready, true);
|
|
|
|
|
|
|
|
/* If received record is at head of tx_list, schedule tx */
|
|
|
|
first_rec = list_first_entry(&ctx->tx_list,
|
|
|
|
struct tls_rec, list);
|
|
|
|
if (rec == first_rec)
|
|
|
|
ready = true;
|
|
|
|
}
|
2018-09-21 04:16:13 +00:00
|
|
|
|
|
|
|
pending = atomic_dec_return(&ctx->encrypt_pending);
|
|
|
|
|
|
|
|
if (!pending && READ_ONCE(ctx->async_notify))
|
|
|
|
complete(&ctx->async_wait.completion);
|
|
|
|
|
|
|
|
if (!ready)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Schedule the transmission */
|
|
|
|
if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
|
|
|
|
schedule_delayed_work(&ctx->tx_work.work, 1);
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
static int tls_do_encryption(struct sock *sk,
|
|
|
|
struct tls_context *tls_ctx,
|
2018-06-15 01:07:45 +00:00
|
|
|
struct tls_sw_context_tx *ctx,
|
|
|
|
struct aead_request *aead_req,
|
|
|
|
size_t data_len)
|
2017-06-14 18:37:39 +00:00
|
|
|
{
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec = ctx->open_rec;
|
2017-06-14 18:37:39 +00:00
|
|
|
int rc;
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
rec->sg_encrypted_data[0].offset += tls_ctx->tx.prepend_size;
|
|
|
|
rec->sg_encrypted_data[0].length -= tls_ctx->tx.prepend_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
aead_request_set_tfm(aead_req, ctx->aead_send);
|
|
|
|
aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
|
2018-09-21 04:16:13 +00:00
|
|
|
aead_request_set_crypt(aead_req, rec->sg_aead_in,
|
|
|
|
rec->sg_aead_out,
|
2018-03-22 17:10:06 +00:00
|
|
|
data_len, tls_ctx->tx.iv);
|
2018-01-31 16:04:37 +00:00
|
|
|
|
|
|
|
aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
2018-09-21 04:16:13 +00:00
|
|
|
tls_encrypt_done, sk);
|
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
/* Add the record in tx_list */
|
|
|
|
list_add_tail((struct list_head *)&rec->list, &ctx->tx_list);
|
2018-09-21 04:16:13 +00:00
|
|
|
atomic_inc(&ctx->encrypt_pending);
|
2018-01-31 16:04:37 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
rc = crypto_aead_encrypt(aead_req);
|
|
|
|
if (!rc || rc != -EINPROGRESS) {
|
|
|
|
atomic_dec(&ctx->encrypt_pending);
|
|
|
|
rec->sg_encrypted_data[0].offset -= tls_ctx->tx.prepend_size;
|
|
|
|
rec->sg_encrypted_data[0].length += tls_ctx->tx.prepend_size;
|
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
if (!rc) {
|
|
|
|
WRITE_ONCE(rec->tx_ready, true);
|
|
|
|
} else if (rc != -EINPROGRESS) {
|
|
|
|
list_del(&rec->list);
|
2018-09-21 04:16:13 +00:00
|
|
|
return rc;
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
/* Unhook the record from context if encryption is not failure */
|
|
|
|
ctx->open_rec = NULL;
|
|
|
|
tls_advance_record_sn(sk, &tls_ctx->tx);
|
2017-06-14 18:37:39 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int tls_push_record(struct sock *sk, int flags,
|
|
|
|
unsigned char record_type)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec = ctx->open_rec;
|
2018-06-15 01:07:45 +00:00
|
|
|
struct aead_request *req;
|
2017-06-14 18:37:39 +00:00
|
|
|
int rc;
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
if (!rec)
|
|
|
|
return 0;
|
2018-06-15 01:07:45 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
rec->tx_flags = flags;
|
|
|
|
req = &rec->aead_req;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
sg_mark_end(rec->sg_plaintext_data + rec->sg_plaintext_num_elem - 1);
|
|
|
|
sg_mark_end(rec->sg_encrypted_data + rec->sg_encrypted_num_elem - 1);
|
|
|
|
|
|
|
|
tls_make_aad(rec->aad_space, rec->sg_plaintext_size,
|
2018-03-22 17:10:06 +00:00
|
|
|
tls_ctx->tx.rec_seq, tls_ctx->tx.rec_seq_size,
|
2017-06-14 18:37:39 +00:00
|
|
|
record_type);
|
|
|
|
|
|
|
|
tls_fill_prepend(tls_ctx,
|
2018-09-21 04:16:13 +00:00
|
|
|
page_address(sg_page(&rec->sg_encrypted_data[0])) +
|
|
|
|
rec->sg_encrypted_data[0].offset,
|
|
|
|
rec->sg_plaintext_size, record_type);
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
tls_ctx->pending_open_record_frags = 0;
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
rc = tls_do_encryption(sk, tls_ctx, ctx, req, rec->sg_plaintext_size);
|
|
|
|
if (rc == -EINPROGRESS)
|
|
|
|
return -EINPROGRESS;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
if (rc < 0) {
|
2018-03-22 17:10:15 +00:00
|
|
|
tls_err_abort(sk, EBADMSG);
|
2018-09-21 04:16:13 +00:00
|
|
|
return rc;
|
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
return tls_tx_records(sk, flags);
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int tls_sw_push_pending_record(struct sock *sk, int flags)
|
|
|
|
{
|
|
|
|
return tls_push_record(sk, flags, TLS_RECORD_TYPE_DATA);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int zerocopy_from_iter(struct sock *sk, struct iov_iter *from,
|
2018-03-22 17:09:53 +00:00
|
|
|
int length, int *pages_used,
|
|
|
|
unsigned int *size_used,
|
|
|
|
struct scatterlist *to, int to_max_pages,
|
2018-07-26 14:59:36 +00:00
|
|
|
bool charge)
|
2017-06-14 18:37:39 +00:00
|
|
|
{
|
|
|
|
struct page *pages[MAX_SKB_FRAGS];
|
|
|
|
|
|
|
|
size_t offset;
|
|
|
|
ssize_t copied, use;
|
|
|
|
int i = 0;
|
2018-03-22 17:09:53 +00:00
|
|
|
unsigned int size = *size_used;
|
|
|
|
int num_elem = *pages_used;
|
2017-06-14 18:37:39 +00:00
|
|
|
int rc = 0;
|
|
|
|
int maxpages;
|
|
|
|
|
|
|
|
while (length > 0) {
|
|
|
|
i = 0;
|
2018-03-22 17:09:53 +00:00
|
|
|
maxpages = to_max_pages - num_elem;
|
2017-06-14 18:37:39 +00:00
|
|
|
if (maxpages == 0) {
|
|
|
|
rc = -EFAULT;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
copied = iov_iter_get_pages(from, pages,
|
|
|
|
length,
|
|
|
|
maxpages, &offset);
|
|
|
|
if (copied <= 0) {
|
|
|
|
rc = -EFAULT;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
iov_iter_advance(from, copied);
|
|
|
|
|
|
|
|
length -= copied;
|
|
|
|
size += copied;
|
|
|
|
while (copied) {
|
|
|
|
use = min_t(int, copied, PAGE_SIZE - offset);
|
|
|
|
|
2018-03-22 17:09:53 +00:00
|
|
|
sg_set_page(&to[num_elem],
|
2017-06-14 18:37:39 +00:00
|
|
|
pages[i], use, offset);
|
2018-03-22 17:09:53 +00:00
|
|
|
sg_unmark_end(&to[num_elem]);
|
|
|
|
if (charge)
|
|
|
|
sk_mem_charge(sk, use);
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
copied -= use;
|
|
|
|
|
|
|
|
++i;
|
|
|
|
++num_elem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-02 15:13:10 +00:00
|
|
|
/* Mark the end in the last sg entry if newly added */
|
|
|
|
if (num_elem > *pages_used)
|
|
|
|
sg_mark_end(&to[num_elem - 1]);
|
2017-06-14 18:37:39 +00:00
|
|
|
out:
|
2018-07-26 14:59:36 +00:00
|
|
|
if (rc)
|
|
|
|
iov_iter_revert(from, size - *size_used);
|
2018-03-22 17:09:53 +00:00
|
|
|
*size_used = size;
|
|
|
|
*pages_used = num_elem;
|
|
|
|
|
2017-06-14 18:37:39 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int memcopy_from_iter(struct sock *sk, struct iov_iter *from,
|
|
|
|
int bytes)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec = ctx->open_rec;
|
|
|
|
struct scatterlist *sg = rec->sg_plaintext_data;
|
2017-06-14 18:37:39 +00:00
|
|
|
int copy, i, rc = 0;
|
|
|
|
|
|
|
|
for (i = tls_ctx->pending_open_record_frags;
|
2018-09-21 04:16:13 +00:00
|
|
|
i < rec->sg_plaintext_num_elem; ++i) {
|
2017-06-14 18:37:39 +00:00
|
|
|
copy = sg[i].length;
|
|
|
|
if (copy_from_iter(
|
|
|
|
page_address(sg_page(&sg[i])) + sg[i].offset,
|
|
|
|
copy, from) != copy) {
|
|
|
|
rc = -EFAULT;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
bytes -= copy;
|
|
|
|
|
|
|
|
++tls_ctx->pending_open_record_frags;
|
|
|
|
|
|
|
|
if (!bytes)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2018-09-26 12:10:48 +00:00
|
|
|
static struct tls_rec *get_rec(struct sock *sk)
|
2017-06-14 18:37:39 +00:00
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec;
|
|
|
|
int mem_size;
|
|
|
|
|
|
|
|
/* Return if we already have an open record */
|
|
|
|
if (ctx->open_rec)
|
|
|
|
return ctx->open_rec;
|
|
|
|
|
|
|
|
mem_size = sizeof(struct tls_rec) + crypto_aead_reqsize(ctx->aead_send);
|
|
|
|
|
|
|
|
rec = kzalloc(mem_size, sk->sk_allocation);
|
|
|
|
if (!rec)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
sg_init_table(&rec->sg_plaintext_data[0],
|
|
|
|
ARRAY_SIZE(rec->sg_plaintext_data));
|
|
|
|
sg_init_table(&rec->sg_encrypted_data[0],
|
|
|
|
ARRAY_SIZE(rec->sg_encrypted_data));
|
|
|
|
|
|
|
|
sg_init_table(rec->sg_aead_in, 2);
|
|
|
|
sg_set_buf(&rec->sg_aead_in[0], rec->aad_space,
|
|
|
|
sizeof(rec->aad_space));
|
|
|
|
sg_unmark_end(&rec->sg_aead_in[1]);
|
|
|
|
sg_chain(rec->sg_aead_in, 2, rec->sg_plaintext_data);
|
|
|
|
|
|
|
|
sg_init_table(rec->sg_aead_out, 2);
|
|
|
|
sg_set_buf(&rec->sg_aead_out[0], rec->aad_space,
|
|
|
|
sizeof(rec->aad_space));
|
|
|
|
sg_unmark_end(&rec->sg_aead_out[1]);
|
|
|
|
sg_chain(rec->sg_aead_out, 2, rec->sg_encrypted_data);
|
|
|
|
|
|
|
|
ctx->open_rec = rec;
|
|
|
|
|
|
|
|
return rec;
|
|
|
|
}
|
|
|
|
|
|
|
|
int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
|
|
|
|
{
|
2017-06-14 18:37:39 +00:00
|
|
|
long timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
|
|
|
struct crypto_tfm *tfm = crypto_aead_tfm(ctx->aead_send);
|
|
|
|
bool async_capable = tfm->__crt_alg->cra_flags & CRYPTO_ALG_ASYNC;
|
|
|
|
unsigned char record_type = TLS_RECORD_TYPE_DATA;
|
|
|
|
bool is_kvec = msg->msg_iter.type & ITER_KVEC;
|
2017-06-14 18:37:39 +00:00
|
|
|
bool eor = !(msg->msg_flags & MSG_MORE);
|
|
|
|
size_t try_to_copy, copied = 0;
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec;
|
|
|
|
int required_size;
|
|
|
|
int num_async = 0;
|
2017-06-14 18:37:39 +00:00
|
|
|
bool full_record;
|
2018-09-21 04:16:13 +00:00
|
|
|
int record_room;
|
|
|
|
int num_zc = 0;
|
2017-06-14 18:37:39 +00:00
|
|
|
int orig_size;
|
2018-09-24 10:39:49 +00:00
|
|
|
int ret = 0;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL))
|
|
|
|
return -ENOTSUPP;
|
|
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
/* Wait till there is any pending write on socket */
|
|
|
|
if (unlikely(sk->sk_write_pending)) {
|
|
|
|
ret = wait_on_pending_writer(sk, &timeo);
|
|
|
|
if (unlikely(ret))
|
|
|
|
goto send_end;
|
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
if (unlikely(msg->msg_controllen)) {
|
|
|
|
ret = tls_proccess_cmsg(sk, msg, &record_type);
|
2018-09-21 04:16:13 +00:00
|
|
|
if (ret) {
|
|
|
|
if (ret == -EINPROGRESS)
|
|
|
|
num_async++;
|
|
|
|
else if (ret != -EAGAIN)
|
|
|
|
goto send_end;
|
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (msg_data_left(msg)) {
|
|
|
|
if (sk->sk_err) {
|
2018-01-12 14:42:06 +00:00
|
|
|
ret = -sk->sk_err;
|
2017-06-14 18:37:39 +00:00
|
|
|
goto send_end;
|
|
|
|
}
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
rec = get_rec(sk);
|
|
|
|
if (!rec) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto send_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
orig_size = rec->sg_plaintext_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
full_record = false;
|
|
|
|
try_to_copy = msg_data_left(msg);
|
2018-09-21 04:16:13 +00:00
|
|
|
record_room = TLS_MAX_PAYLOAD_SIZE - rec->sg_plaintext_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
if (try_to_copy >= record_room) {
|
|
|
|
try_to_copy = record_room;
|
|
|
|
full_record = true;
|
|
|
|
}
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
required_size = rec->sg_plaintext_size + try_to_copy +
|
2018-03-22 17:10:06 +00:00
|
|
|
tls_ctx->tx.overhead_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
if (!sk_stream_memory_free(sk))
|
|
|
|
goto wait_for_sndbuf;
|
2018-09-21 04:16:13 +00:00
|
|
|
|
2017-06-14 18:37:39 +00:00
|
|
|
alloc_encrypted:
|
|
|
|
ret = alloc_encrypted_sg(sk, required_size);
|
|
|
|
if (ret) {
|
|
|
|
if (ret != -ENOSPC)
|
|
|
|
goto wait_for_memory;
|
|
|
|
|
|
|
|
/* Adjust try_to_copy according to the amount that was
|
|
|
|
* actually allocated. The difference is due
|
|
|
|
* to max sg elements limit
|
|
|
|
*/
|
2018-09-21 04:16:13 +00:00
|
|
|
try_to_copy -= required_size - rec->sg_encrypted_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
full_record = true;
|
|
|
|
}
|
2018-09-21 04:16:13 +00:00
|
|
|
|
|
|
|
if (!is_kvec && (full_record || eor) && !async_capable) {
|
2017-06-14 18:37:39 +00:00
|
|
|
ret = zerocopy_from_iter(sk, &msg->msg_iter,
|
2018-09-21 04:16:13 +00:00
|
|
|
try_to_copy, &rec->sg_plaintext_num_elem,
|
|
|
|
&rec->sg_plaintext_size,
|
|
|
|
rec->sg_plaintext_data,
|
|
|
|
ARRAY_SIZE(rec->sg_plaintext_data),
|
2018-07-26 14:59:36 +00:00
|
|
|
true);
|
2017-06-14 18:37:39 +00:00
|
|
|
if (ret)
|
|
|
|
goto fallback_to_reg_send;
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
num_zc++;
|
2017-06-14 18:37:39 +00:00
|
|
|
copied += try_to_copy;
|
|
|
|
ret = tls_push_record(sk, msg->msg_flags, record_type);
|
2018-09-21 04:16:13 +00:00
|
|
|
if (ret) {
|
|
|
|
if (ret == -EINPROGRESS)
|
|
|
|
num_async++;
|
|
|
|
else if (ret != -EAGAIN)
|
|
|
|
goto send_end;
|
|
|
|
}
|
2018-07-26 14:59:35 +00:00
|
|
|
continue;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
fallback_to_reg_send:
|
2018-09-21 04:16:13 +00:00
|
|
|
trim_sg(sk, rec->sg_plaintext_data,
|
|
|
|
&rec->sg_plaintext_num_elem,
|
|
|
|
&rec->sg_plaintext_size,
|
2017-06-14 18:37:39 +00:00
|
|
|
orig_size);
|
|
|
|
}
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
required_size = rec->sg_plaintext_size + try_to_copy;
|
2017-06-14 18:37:39 +00:00
|
|
|
alloc_plaintext:
|
|
|
|
ret = alloc_plaintext_sg(sk, required_size);
|
|
|
|
if (ret) {
|
|
|
|
if (ret != -ENOSPC)
|
|
|
|
goto wait_for_memory;
|
|
|
|
|
|
|
|
/* Adjust try_to_copy according to the amount that was
|
|
|
|
* actually allocated. The difference is due
|
|
|
|
* to max sg elements limit
|
|
|
|
*/
|
2018-09-21 04:16:13 +00:00
|
|
|
try_to_copy -= required_size - rec->sg_plaintext_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
full_record = true;
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
trim_sg(sk, rec->sg_encrypted_data,
|
|
|
|
&rec->sg_encrypted_num_elem,
|
|
|
|
&rec->sg_encrypted_size,
|
|
|
|
rec->sg_plaintext_size +
|
2018-03-22 17:10:06 +00:00
|
|
|
tls_ctx->tx.overhead_size);
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = memcopy_from_iter(sk, &msg->msg_iter, try_to_copy);
|
|
|
|
if (ret)
|
|
|
|
goto trim_sgl;
|
|
|
|
|
|
|
|
copied += try_to_copy;
|
|
|
|
if (full_record || eor) {
|
|
|
|
ret = tls_push_record(sk, msg->msg_flags, record_type);
|
|
|
|
if (ret) {
|
2018-09-21 04:16:13 +00:00
|
|
|
if (ret == -EINPROGRESS)
|
|
|
|
num_async++;
|
|
|
|
else if (ret != -EAGAIN)
|
|
|
|
goto send_end;
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
wait_for_sndbuf:
|
|
|
|
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
|
|
|
|
wait_for_memory:
|
|
|
|
ret = sk_stream_wait_memory(sk, &timeo);
|
|
|
|
if (ret) {
|
|
|
|
trim_sgl:
|
|
|
|
trim_both_sgl(sk, orig_size);
|
|
|
|
goto send_end;
|
|
|
|
}
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
if (rec->sg_encrypted_size < required_size)
|
2017-06-14 18:37:39 +00:00
|
|
|
goto alloc_encrypted;
|
|
|
|
|
|
|
|
goto alloc_plaintext;
|
|
|
|
}
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
if (!num_async) {
|
|
|
|
goto send_end;
|
|
|
|
} else if (num_zc) {
|
|
|
|
/* Wait for pending encryptions to get completed */
|
|
|
|
smp_store_mb(ctx->async_notify, true);
|
|
|
|
|
|
|
|
if (atomic_read(&ctx->encrypt_pending))
|
|
|
|
crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
|
|
|
|
else
|
|
|
|
reinit_completion(&ctx->async_wait.completion);
|
|
|
|
|
|
|
|
WRITE_ONCE(ctx->async_notify, false);
|
|
|
|
|
|
|
|
if (ctx->async_wait.err) {
|
|
|
|
ret = ctx->async_wait.err;
|
|
|
|
copied = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Transmit if any encryptions have completed */
|
|
|
|
if (test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) {
|
|
|
|
cancel_delayed_work(&ctx->tx_work.work);
|
|
|
|
tls_tx_records(sk, msg->msg_flags);
|
|
|
|
}
|
|
|
|
|
2017-06-14 18:37:39 +00:00
|
|
|
send_end:
|
|
|
|
ret = sk_stream_error(sk, msg->msg_flags, ret);
|
|
|
|
|
|
|
|
release_sock(sk);
|
|
|
|
return copied ? copied : ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int tls_sw_sendpage(struct sock *sk, struct page *page,
|
|
|
|
int offset, size_t size, int flags)
|
|
|
|
{
|
2018-09-21 04:16:13 +00:00
|
|
|
long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
|
2017-06-14 18:37:39 +00:00
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2017-06-14 18:37:39 +00:00
|
|
|
unsigned char record_type = TLS_RECORD_TYPE_DATA;
|
2018-09-21 04:16:13 +00:00
|
|
|
size_t orig_size = size;
|
2017-06-14 18:37:39 +00:00
|
|
|
struct scatterlist *sg;
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec;
|
|
|
|
int num_async = 0;
|
2017-06-14 18:37:39 +00:00
|
|
|
bool full_record;
|
|
|
|
int record_room;
|
2018-09-24 10:39:49 +00:00
|
|
|
int ret = 0;
|
2018-09-21 04:16:13 +00:00
|
|
|
bool eor;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
if (flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL |
|
|
|
|
MSG_SENDPAGE_NOTLAST))
|
|
|
|
return -ENOTSUPP;
|
|
|
|
|
|
|
|
/* No MSG_EOR from splice, only look at MSG_MORE */
|
|
|
|
eor = !(flags & (MSG_MORE | MSG_SENDPAGE_NOTLAST));
|
|
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
|
|
|
|
sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
/* Wait till there is any pending write on socket */
|
|
|
|
if (unlikely(sk->sk_write_pending)) {
|
|
|
|
ret = wait_on_pending_writer(sk, &timeo);
|
|
|
|
if (unlikely(ret))
|
|
|
|
goto sendpage_end;
|
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
/* Call the sk_stream functions to manage the sndbuf mem. */
|
|
|
|
while (size > 0) {
|
|
|
|
size_t copy, required_size;
|
|
|
|
|
|
|
|
if (sk->sk_err) {
|
2018-01-12 14:42:06 +00:00
|
|
|
ret = -sk->sk_err;
|
2017-06-14 18:37:39 +00:00
|
|
|
goto sendpage_end;
|
|
|
|
}
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
rec = get_rec(sk);
|
|
|
|
if (!rec) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto sendpage_end;
|
|
|
|
}
|
|
|
|
|
2017-06-14 18:37:39 +00:00
|
|
|
full_record = false;
|
2018-09-21 04:16:13 +00:00
|
|
|
record_room = TLS_MAX_PAYLOAD_SIZE - rec->sg_plaintext_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
copy = size;
|
|
|
|
if (copy >= record_room) {
|
|
|
|
copy = record_room;
|
|
|
|
full_record = true;
|
|
|
|
}
|
2018-09-21 04:16:13 +00:00
|
|
|
required_size = rec->sg_plaintext_size + copy +
|
2018-03-22 17:10:06 +00:00
|
|
|
tls_ctx->tx.overhead_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
if (!sk_stream_memory_free(sk))
|
|
|
|
goto wait_for_sndbuf;
|
|
|
|
alloc_payload:
|
|
|
|
ret = alloc_encrypted_sg(sk, required_size);
|
|
|
|
if (ret) {
|
|
|
|
if (ret != -ENOSPC)
|
|
|
|
goto wait_for_memory;
|
|
|
|
|
|
|
|
/* Adjust copy according to the amount that was
|
|
|
|
* actually allocated. The difference is due
|
|
|
|
* to max sg elements limit
|
|
|
|
*/
|
2018-09-21 04:16:13 +00:00
|
|
|
copy -= required_size - rec->sg_plaintext_size;
|
2017-06-14 18:37:39 +00:00
|
|
|
full_record = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
get_page(page);
|
2018-09-21 04:16:13 +00:00
|
|
|
sg = rec->sg_plaintext_data + rec->sg_plaintext_num_elem;
|
2017-06-14 18:37:39 +00:00
|
|
|
sg_set_page(sg, page, copy, offset);
|
2018-01-19 20:30:13 +00:00
|
|
|
sg_unmark_end(sg);
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
rec->sg_plaintext_num_elem++;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
sk_mem_charge(sk, copy);
|
|
|
|
offset += copy;
|
|
|
|
size -= copy;
|
2018-09-21 04:16:13 +00:00
|
|
|
rec->sg_plaintext_size += copy;
|
|
|
|
tls_ctx->pending_open_record_frags = rec->sg_plaintext_num_elem;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
if (full_record || eor ||
|
2018-09-21 04:16:13 +00:00
|
|
|
rec->sg_plaintext_num_elem ==
|
|
|
|
ARRAY_SIZE(rec->sg_plaintext_data)) {
|
2017-06-14 18:37:39 +00:00
|
|
|
ret = tls_push_record(sk, flags, record_type);
|
|
|
|
if (ret) {
|
2018-09-21 04:16:13 +00:00
|
|
|
if (ret == -EINPROGRESS)
|
|
|
|
num_async++;
|
|
|
|
else if (ret != -EAGAIN)
|
|
|
|
goto sendpage_end;
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
wait_for_sndbuf:
|
|
|
|
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
|
|
|
|
wait_for_memory:
|
|
|
|
ret = sk_stream_wait_memory(sk, &timeo);
|
|
|
|
if (ret) {
|
2018-09-21 04:16:13 +00:00
|
|
|
trim_both_sgl(sk, rec->sg_plaintext_size);
|
2017-06-14 18:37:39 +00:00
|
|
|
goto sendpage_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
goto alloc_payload;
|
|
|
|
}
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
if (num_async) {
|
|
|
|
/* Transmit if any encryptions have completed */
|
|
|
|
if (test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) {
|
|
|
|
cancel_delayed_work(&ctx->tx_work.work);
|
|
|
|
tls_tx_records(sk, flags);
|
|
|
|
}
|
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
sendpage_end:
|
|
|
|
if (orig_size > size)
|
|
|
|
ret = orig_size - size;
|
|
|
|
else
|
|
|
|
ret = sk_stream_error(sk, flags, ret);
|
|
|
|
|
|
|
|
release_sock(sk);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
static struct sk_buff *tls_wait_data(struct sock *sk, int flags,
|
|
|
|
long timeo, int *err)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
struct sk_buff *skb;
|
|
|
|
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
|
|
|
|
|
|
|
while (!(skb = ctx->recv_pkt)) {
|
|
|
|
if (sk->sk_err) {
|
|
|
|
*err = sock_error(sk);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-07-18 23:22:27 +00:00
|
|
|
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
|
|
|
return NULL;
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
if (sock_flag(sk, SOCK_DONE))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if ((flags & MSG_DONTWAIT) || !timeo) {
|
|
|
|
*err = -EAGAIN;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
add_wait_queue(sk_sleep(sk), &wait);
|
|
|
|
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
|
|
|
sk_wait_event(sk, &timeo, ctx->recv_pkt != skb, &wait);
|
|
|
|
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
|
|
|
remove_wait_queue(sk_sleep(sk), &wait);
|
|
|
|
|
|
|
|
/* Handle signals */
|
|
|
|
if (signal_pending(current)) {
|
|
|
|
*err = sock_intr_errno(timeo);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
2018-08-10 15:16:41 +00:00
|
|
|
/* This function decrypts the input skb into either out_iov or in out_sg
|
|
|
|
* or in skb buffers itself. The input parameter 'zc' indicates if
|
|
|
|
* zero-copy mode needs to be tried or not. With zero-copy mode, either
|
|
|
|
* out_iov or out_sg must be non-NULL. In case both out_iov and out_sg are
|
|
|
|
* NULL, then the decryption happens inside skb buffers itself, i.e.
|
|
|
|
* zero-copy gets disabled and 'zc' is updated.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
|
|
|
|
struct iov_iter *out_iov,
|
|
|
|
struct scatterlist *out_sg,
|
|
|
|
int *chunk, bool *zc)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
|
|
|
struct strp_msg *rxm = strp_msg(skb);
|
|
|
|
int n_sgin, n_sgout, nsg, mem_size, aead_size, err, pages = 0;
|
|
|
|
struct aead_request *aead_req;
|
|
|
|
struct sk_buff *unused;
|
|
|
|
u8 *aad, *iv, *mem = NULL;
|
|
|
|
struct scatterlist *sgin = NULL;
|
|
|
|
struct scatterlist *sgout = NULL;
|
|
|
|
const int data_len = rxm->full_len - tls_ctx->rx.overhead_size;
|
|
|
|
|
|
|
|
if (*zc && (out_iov || out_sg)) {
|
|
|
|
if (out_iov)
|
|
|
|
n_sgout = iov_iter_npages(out_iov, INT_MAX) + 1;
|
|
|
|
else
|
|
|
|
n_sgout = sg_nents(out_sg);
|
2018-08-28 23:33:57 +00:00
|
|
|
n_sgin = skb_nsg(skb, rxm->offset + tls_ctx->rx.prepend_size,
|
|
|
|
rxm->full_len - tls_ctx->rx.prepend_size);
|
2018-08-10 15:16:41 +00:00
|
|
|
} else {
|
|
|
|
n_sgout = 0;
|
|
|
|
*zc = false;
|
2018-08-28 23:33:57 +00:00
|
|
|
n_sgin = skb_cow_data(skb, 0, &unused);
|
2018-08-10 15:16:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (n_sgin < 1)
|
|
|
|
return -EBADMSG;
|
|
|
|
|
|
|
|
/* Increment to accommodate AAD */
|
|
|
|
n_sgin = n_sgin + 1;
|
|
|
|
|
|
|
|
nsg = n_sgin + n_sgout;
|
|
|
|
|
|
|
|
aead_size = sizeof(*aead_req) + crypto_aead_reqsize(ctx->aead_recv);
|
|
|
|
mem_size = aead_size + (nsg * sizeof(struct scatterlist));
|
|
|
|
mem_size = mem_size + TLS_AAD_SPACE_SIZE;
|
|
|
|
mem_size = mem_size + crypto_aead_ivsize(ctx->aead_recv);
|
|
|
|
|
|
|
|
/* Allocate a single block of memory which contains
|
|
|
|
* aead_req || sgin[] || sgout[] || aad || iv.
|
|
|
|
* This order achieves correct alignment for aead_req, sgin, sgout.
|
|
|
|
*/
|
|
|
|
mem = kmalloc(mem_size, sk->sk_allocation);
|
|
|
|
if (!mem)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
/* Segment the allocated memory */
|
|
|
|
aead_req = (struct aead_request *)mem;
|
|
|
|
sgin = (struct scatterlist *)(mem + aead_size);
|
|
|
|
sgout = sgin + n_sgin;
|
|
|
|
aad = (u8 *)(sgout + n_sgout);
|
|
|
|
iv = aad + TLS_AAD_SPACE_SIZE;
|
|
|
|
|
|
|
|
/* Prepare IV */
|
|
|
|
err = skb_copy_bits(skb, rxm->offset + TLS_HEADER_SIZE,
|
|
|
|
iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
|
|
|
|
tls_ctx->rx.iv_size);
|
|
|
|
if (err < 0) {
|
|
|
|
kfree(mem);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
|
|
|
|
|
|
|
|
/* Prepare AAD */
|
|
|
|
tls_make_aad(aad, rxm->full_len - tls_ctx->rx.overhead_size,
|
|
|
|
tls_ctx->rx.rec_seq, tls_ctx->rx.rec_seq_size,
|
|
|
|
ctx->control);
|
|
|
|
|
|
|
|
/* Prepare sgin */
|
|
|
|
sg_init_table(sgin, n_sgin);
|
|
|
|
sg_set_buf(&sgin[0], aad, TLS_AAD_SPACE_SIZE);
|
|
|
|
err = skb_to_sgvec(skb, &sgin[1],
|
|
|
|
rxm->offset + tls_ctx->rx.prepend_size,
|
|
|
|
rxm->full_len - tls_ctx->rx.prepend_size);
|
|
|
|
if (err < 0) {
|
|
|
|
kfree(mem);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n_sgout) {
|
|
|
|
if (out_iov) {
|
|
|
|
sg_init_table(sgout, n_sgout);
|
|
|
|
sg_set_buf(&sgout[0], aad, TLS_AAD_SPACE_SIZE);
|
|
|
|
|
|
|
|
*chunk = 0;
|
|
|
|
err = zerocopy_from_iter(sk, out_iov, data_len, &pages,
|
|
|
|
chunk, &sgout[1],
|
|
|
|
(n_sgout - 1), false);
|
|
|
|
if (err < 0)
|
|
|
|
goto fallback_to_reg_recv;
|
|
|
|
} else if (out_sg) {
|
|
|
|
memcpy(sgout, out_sg, n_sgout * sizeof(*sgout));
|
|
|
|
} else {
|
|
|
|
goto fallback_to_reg_recv;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fallback_to_reg_recv:
|
|
|
|
sgout = sgin;
|
|
|
|
pages = 0;
|
|
|
|
*chunk = 0;
|
|
|
|
*zc = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Prepare and submit AEAD request */
|
2018-08-29 09:56:55 +00:00
|
|
|
err = tls_do_decryption(sk, skb, sgin, sgout, iv,
|
|
|
|
data_len, aead_req, *zc);
|
|
|
|
if (err == -EINPROGRESS)
|
|
|
|
return err;
|
2018-08-10 15:16:41 +00:00
|
|
|
|
|
|
|
/* Release the pages in case iov was mapped to pages */
|
|
|
|
for (; pages > 0; pages--)
|
|
|
|
put_page(sg_page(&sgout[pages]));
|
|
|
|
|
|
|
|
kfree(mem);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2018-07-13 11:33:40 +00:00
|
|
|
static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
|
2018-08-10 15:16:41 +00:00
|
|
|
struct iov_iter *dest, int *chunk, bool *zc)
|
2018-07-13 11:33:40 +00:00
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
|
|
|
struct strp_msg *rxm = strp_msg(skb);
|
|
|
|
int err = 0;
|
|
|
|
|
2018-07-13 11:33:43 +00:00
|
|
|
#ifdef CONFIG_TLS_DEVICE
|
|
|
|
err = tls_device_decrypted(sk, skb);
|
2018-07-13 11:33:40 +00:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
2018-07-13 11:33:43 +00:00
|
|
|
#endif
|
|
|
|
if (!ctx->decrypted) {
|
2018-08-10 15:16:41 +00:00
|
|
|
err = decrypt_internal(sk, skb, dest, NULL, chunk, zc);
|
2018-08-29 09:56:55 +00:00
|
|
|
if (err < 0) {
|
|
|
|
if (err == -EINPROGRESS)
|
|
|
|
tls_advance_record_sn(sk, &tls_ctx->rx);
|
|
|
|
|
2018-07-13 11:33:43 +00:00
|
|
|
return err;
|
2018-08-29 09:56:55 +00:00
|
|
|
}
|
2018-07-13 11:33:43 +00:00
|
|
|
} else {
|
|
|
|
*zc = false;
|
|
|
|
}
|
2018-07-13 11:33:40 +00:00
|
|
|
|
|
|
|
rxm->offset += tls_ctx->rx.prepend_size;
|
|
|
|
rxm->full_len -= tls_ctx->rx.overhead_size;
|
|
|
|
tls_advance_record_sn(sk, &tls_ctx->rx);
|
|
|
|
ctx->decrypted = true;
|
|
|
|
ctx->saved_data_ready(sk);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int decrypt_skb(struct sock *sk, struct sk_buff *skb,
|
|
|
|
struct scatterlist *sgout)
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
{
|
2018-08-10 15:16:41 +00:00
|
|
|
bool zc = true;
|
|
|
|
int chunk;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
2018-08-10 15:16:41 +00:00
|
|
|
return decrypt_internal(sk, skb, NULL, sgout, &chunk, &zc);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool tls_sw_advance_skb(struct sock *sk, struct sk_buff *skb,
|
|
|
|
unsigned int len)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
2018-08-29 09:56:55 +00:00
|
|
|
if (skb) {
|
|
|
|
struct strp_msg *rxm = strp_msg(skb);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
2018-08-29 09:56:55 +00:00
|
|
|
if (len < rxm->full_len) {
|
|
|
|
rxm->offset += len;
|
|
|
|
rxm->full_len -= len;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
kfree_skb(skb);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Finished with message */
|
|
|
|
ctx->recv_pkt = NULL;
|
2018-06-06 16:33:28 +00:00
|
|
|
__strp_unpause(&ctx->strp);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int tls_sw_recvmsg(struct sock *sk,
|
|
|
|
struct msghdr *msg,
|
|
|
|
size_t len,
|
|
|
|
int nonblock,
|
|
|
|
int flags,
|
|
|
|
int *addr_len)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
unsigned char control;
|
|
|
|
struct strp_msg *rxm;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
ssize_t copied = 0;
|
|
|
|
bool cmsg = false;
|
2018-06-15 01:07:46 +00:00
|
|
|
int target, err = 0;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
long timeo;
|
2018-07-25 21:48:21 +00:00
|
|
|
bool is_kvec = msg->msg_iter.type & ITER_KVEC;
|
2018-08-29 09:56:55 +00:00
|
|
|
int num_async = 0;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
|
|
|
flags |= nonblock;
|
|
|
|
|
|
|
|
if (unlikely(flags & MSG_ERRQUEUE))
|
|
|
|
return sock_recv_errqueue(sk, msg, len, SOL_IP, IP_RECVERR);
|
|
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
|
2018-06-15 01:07:46 +00:00
|
|
|
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
|
|
|
|
do {
|
|
|
|
bool zc = false;
|
2018-08-29 09:56:55 +00:00
|
|
|
bool async = false;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
int chunk = 0;
|
|
|
|
|
|
|
|
skb = tls_wait_data(sk, flags, timeo, &err);
|
|
|
|
if (!skb)
|
|
|
|
goto recv_end;
|
|
|
|
|
|
|
|
rxm = strp_msg(skb);
|
2018-08-29 09:56:55 +00:00
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
if (!cmsg) {
|
|
|
|
int cerr;
|
|
|
|
|
|
|
|
cerr = put_cmsg(msg, SOL_TLS, TLS_GET_RECORD_TYPE,
|
|
|
|
sizeof(ctx->control), &ctx->control);
|
|
|
|
cmsg = true;
|
|
|
|
control = ctx->control;
|
|
|
|
if (ctx->control != TLS_RECORD_TYPE_DATA) {
|
|
|
|
if (cerr || msg->msg_flags & MSG_CTRUNC) {
|
|
|
|
err = -EIO;
|
|
|
|
goto recv_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (control != ctx->control) {
|
|
|
|
goto recv_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ctx->decrypted) {
|
2018-08-10 15:16:41 +00:00
|
|
|
int to_copy = rxm->full_len - tls_ctx->rx.overhead_size;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
2018-08-10 15:16:41 +00:00
|
|
|
if (!is_kvec && to_copy <= len &&
|
|
|
|
likely(!(flags & MSG_PEEK)))
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
zc = true;
|
2018-08-10 15:16:41 +00:00
|
|
|
|
|
|
|
err = decrypt_skb_update(sk, skb, &msg->msg_iter,
|
|
|
|
&chunk, &zc);
|
2018-08-29 09:56:55 +00:00
|
|
|
if (err < 0 && err != -EINPROGRESS) {
|
2018-08-10 15:16:41 +00:00
|
|
|
tls_err_abort(sk, EBADMSG);
|
|
|
|
goto recv_end;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
2018-08-29 09:56:55 +00:00
|
|
|
|
|
|
|
if (err == -EINPROGRESS) {
|
|
|
|
async = true;
|
|
|
|
num_async++;
|
|
|
|
goto pick_next_record;
|
|
|
|
}
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
ctx->decrypted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!zc) {
|
|
|
|
chunk = min_t(unsigned int, rxm->full_len, len);
|
2018-08-29 09:56:55 +00:00
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
err = skb_copy_datagram_msg(skb, rxm->offset, msg,
|
|
|
|
chunk);
|
|
|
|
if (err < 0)
|
|
|
|
goto recv_end;
|
|
|
|
}
|
|
|
|
|
2018-08-29 09:56:55 +00:00
|
|
|
pick_next_record:
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
copied += chunk;
|
|
|
|
len -= chunk;
|
|
|
|
if (likely(!(flags & MSG_PEEK))) {
|
|
|
|
u8 control = ctx->control;
|
|
|
|
|
2018-08-29 09:56:55 +00:00
|
|
|
/* For async, drop current skb reference */
|
|
|
|
if (async)
|
|
|
|
skb = NULL;
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
if (tls_sw_advance_skb(sk, skb, chunk)) {
|
|
|
|
/* Return full control message to
|
|
|
|
* userspace before trying to parse
|
|
|
|
* another message type
|
|
|
|
*/
|
|
|
|
msg->msg_flags |= MSG_EOR;
|
|
|
|
if (control != TLS_RECORD_TYPE_DATA)
|
|
|
|
goto recv_end;
|
2018-08-29 09:56:55 +00:00
|
|
|
} else {
|
|
|
|
break;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
tls: fix currently broken MSG_PEEK behavior
In kTLS MSG_PEEK behavior is currently failing, strace example:
[pid 2430] socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
[pid 2430] socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 4
[pid 2430] bind(4, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
[pid 2430] listen(4, 10) = 0
[pid 2430] getsockname(4, {sa_family=AF_INET, sin_port=htons(38855), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
[pid 2430] connect(3, {sa_family=AF_INET, sin_port=htons(38855), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
[pid 2430] setsockopt(3, SOL_TCP, 0x1f /* TCP_??? */, [7564404], 4) = 0
[pid 2430] setsockopt(3, 0x11a /* SOL_?? */, 1, "\3\0033\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 40) = 0
[pid 2430] accept(4, {sa_family=AF_INET, sin_port=htons(49636), sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
[pid 2430] setsockopt(5, SOL_TCP, 0x1f /* TCP_??? */, [7564404], 4) = 0
[pid 2430] setsockopt(5, 0x11a /* SOL_?? */, 2, "\3\0033\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 40) = 0
[pid 2430] close(4) = 0
[pid 2430] sendto(3, "test_read_peek", 14, 0, NULL, 0) = 14
[pid 2430] sendto(3, "_mult_recs\0", 11, 0, NULL, 0) = 11
[pid 2430] recvfrom(5, "test_read_peektest_read_peektest"..., 64, MSG_PEEK, NULL, NULL) = 64
As can be seen from strace, there are two TLS records sent,
i) 'test_read_peek' and ii) '_mult_recs\0' where we end up
peeking 'test_read_peektest_read_peektest'. This is clearly
wrong, and what happens is that given peek cannot call into
tls_sw_advance_skb() to unpause strparser and proceed with
the next skb, we end up looping over the current one, copying
the 'test_read_peek' over and over into the user provided
buffer.
Here, we can only peek into the currently held skb (current,
full TLS record) as otherwise we would end up having to hold
all the original skb(s) (depending on the peek depth) in a
separate queue when unpausing strparser to process next
records, minimally intrusive is to return only up to the
current record's size (which likely was what c46234ebb4d1
("tls: RX path for ktls") originally intended as well). Thus,
after patch we properly peek the first record:
[pid 2046] wait4(2075, <unfinished ...>
[pid 2075] socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
[pid 2075] socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 4
[pid 2075] bind(4, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
[pid 2075] listen(4, 10) = 0
[pid 2075] getsockname(4, {sa_family=AF_INET, sin_port=htons(55115), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
[pid 2075] connect(3, {sa_family=AF_INET, sin_port=htons(55115), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
[pid 2075] setsockopt(3, SOL_TCP, 0x1f /* TCP_??? */, [7564404], 4) = 0
[pid 2075] setsockopt(3, 0x11a /* SOL_?? */, 1, "\3\0033\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 40) = 0
[pid 2075] accept(4, {sa_family=AF_INET, sin_port=htons(45732), sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
[pid 2075] setsockopt(5, SOL_TCP, 0x1f /* TCP_??? */, [7564404], 4) = 0
[pid 2075] setsockopt(5, 0x11a /* SOL_?? */, 2, "\3\0033\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 40) = 0
[pid 2075] close(4) = 0
[pid 2075] sendto(3, "test_read_peek", 14, 0, NULL, 0) = 14
[pid 2075] sendto(3, "_mult_recs\0", 11, 0, NULL, 0) = 11
[pid 2075] recvfrom(5, "test_read_peek", 64, MSG_PEEK, NULL, NULL) = 14
Fixes: c46234ebb4d1 ("tls: RX path for ktls")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-14 21:00:55 +00:00
|
|
|
} else {
|
|
|
|
/* MSG_PEEK right now cannot look beyond current skb
|
|
|
|
* from strparser, meaning we cannot advance skb here
|
|
|
|
* and thus unpause strparser since we'd loose original
|
|
|
|
* one.
|
|
|
|
*/
|
|
|
|
break;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
2018-08-29 09:56:55 +00:00
|
|
|
|
2018-06-15 01:07:46 +00:00
|
|
|
/* If we have a new message from strparser, continue now. */
|
|
|
|
if (copied >= target && !ctx->recv_pkt)
|
|
|
|
break;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
} while (len);
|
|
|
|
|
|
|
|
recv_end:
|
2018-08-29 09:56:55 +00:00
|
|
|
if (num_async) {
|
|
|
|
/* Wait for all previously submitted records to be decrypted */
|
|
|
|
smp_store_mb(ctx->async_notify, true);
|
|
|
|
if (atomic_read(&ctx->decrypt_pending)) {
|
|
|
|
err = crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
|
|
|
|
if (err) {
|
|
|
|
/* one of async decrypt failed */
|
|
|
|
tls_err_abort(sk, err);
|
|
|
|
copied = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
reinit_completion(&ctx->async_wait.completion);
|
|
|
|
}
|
|
|
|
WRITE_ONCE(ctx->async_notify, false);
|
|
|
|
}
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
release_sock(sk);
|
|
|
|
return copied ? : err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
|
|
|
|
struct pipe_inode_info *pipe,
|
|
|
|
size_t len, unsigned int flags)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sock->sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
struct strp_msg *rxm = NULL;
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
ssize_t copied = 0;
|
|
|
|
int err = 0;
|
|
|
|
long timeo;
|
|
|
|
int chunk;
|
2018-08-10 15:16:41 +00:00
|
|
|
bool zc = false;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
|
|
|
|
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
|
|
|
|
|
|
|
|
skb = tls_wait_data(sk, flags, timeo, &err);
|
|
|
|
if (!skb)
|
|
|
|
goto splice_read_end;
|
|
|
|
|
|
|
|
/* splice does not support reading control messages */
|
|
|
|
if (ctx->control != TLS_RECORD_TYPE_DATA) {
|
|
|
|
err = -ENOTSUPP;
|
|
|
|
goto splice_read_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ctx->decrypted) {
|
2018-08-10 15:16:41 +00:00
|
|
|
err = decrypt_skb_update(sk, skb, NULL, &chunk, &zc);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
|
|
|
if (err < 0) {
|
|
|
|
tls_err_abort(sk, EBADMSG);
|
|
|
|
goto splice_read_end;
|
|
|
|
}
|
|
|
|
ctx->decrypted = true;
|
|
|
|
}
|
|
|
|
rxm = strp_msg(skb);
|
|
|
|
|
|
|
|
chunk = min_t(unsigned int, rxm->full_len, len);
|
|
|
|
copied = skb_splice_bits(skb, sk, rxm->offset, pipe, chunk, flags);
|
|
|
|
if (copied < 0)
|
|
|
|
goto splice_read_end;
|
|
|
|
|
|
|
|
if (likely(!(flags & MSG_PEEK)))
|
|
|
|
tls_sw_advance_skb(sk, skb, copied);
|
|
|
|
|
|
|
|
splice_read_end:
|
|
|
|
release_sock(sk);
|
|
|
|
return copied ? : err;
|
|
|
|
}
|
|
|
|
|
2018-06-28 16:43:44 +00:00
|
|
|
unsigned int tls_sw_poll(struct file *file, struct socket *sock,
|
|
|
|
struct poll_table_struct *wait)
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
{
|
2018-06-28 16:43:44 +00:00
|
|
|
unsigned int ret;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
2018-06-28 16:43:44 +00:00
|
|
|
/* Grab POLLOUT and POLLHUP from the underlying socket */
|
|
|
|
ret = ctx->sk_poll(file, sock, wait);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
2018-06-28 16:43:44 +00:00
|
|
|
/* Clear POLLIN bits, and set based on recv_pkt */
|
|
|
|
ret &= ~(POLLIN | POLLRDNORM);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
if (ctx->recv_pkt)
|
2018-06-28 16:43:44 +00:00
|
|
|
ret |= POLLIN | POLLRDNORM;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
2018-06-28 16:43:44 +00:00
|
|
|
return ret;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int tls_read_size(struct strparser *strp, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(strp->sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
2018-06-25 23:55:05 +00:00
|
|
|
char header[TLS_HEADER_SIZE + MAX_IV_SIZE];
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
struct strp_msg *rxm = strp_msg(skb);
|
|
|
|
size_t cipher_overhead;
|
|
|
|
size_t data_len = 0;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Verify that we have a full TLS header, or wait for more data */
|
|
|
|
if (rxm->offset + tls_ctx->rx.prepend_size > skb->len)
|
|
|
|
return 0;
|
|
|
|
|
2018-06-25 23:55:05 +00:00
|
|
|
/* Sanity-check size of on-stack buffer. */
|
|
|
|
if (WARN_ON(tls_ctx->rx.prepend_size > sizeof(header))) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto read_failure;
|
|
|
|
}
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
/* Linearize header to local buffer */
|
|
|
|
ret = skb_copy_bits(skb, rxm->offset, header, tls_ctx->rx.prepend_size);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
goto read_failure;
|
|
|
|
|
|
|
|
ctx->control = header[0];
|
|
|
|
|
|
|
|
data_len = ((header[4] & 0xFF) | (header[3] << 8));
|
|
|
|
|
|
|
|
cipher_overhead = tls_ctx->rx.tag_size + tls_ctx->rx.iv_size;
|
|
|
|
|
|
|
|
if (data_len > TLS_MAX_PAYLOAD_SIZE + cipher_overhead) {
|
|
|
|
ret = -EMSGSIZE;
|
|
|
|
goto read_failure;
|
|
|
|
}
|
|
|
|
if (data_len < cipher_overhead) {
|
|
|
|
ret = -EBADMSG;
|
|
|
|
goto read_failure;
|
|
|
|
}
|
|
|
|
|
2018-09-12 15:44:42 +00:00
|
|
|
if (header[1] != TLS_VERSION_MINOR(tls_ctx->crypto_recv.info.version) ||
|
|
|
|
header[2] != TLS_VERSION_MAJOR(tls_ctx->crypto_recv.info.version)) {
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
ret = -EINVAL;
|
|
|
|
goto read_failure;
|
|
|
|
}
|
|
|
|
|
2018-07-13 11:33:43 +00:00
|
|
|
#ifdef CONFIG_TLS_DEVICE
|
|
|
|
handle_device_resync(strp->sk, TCP_SKB_CB(skb)->seq + rxm->offset,
|
|
|
|
*(u64*)tls_ctx->rx.rec_seq);
|
|
|
|
#endif
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
return data_len + TLS_HEADER_SIZE;
|
|
|
|
|
|
|
|
read_failure:
|
|
|
|
tls_err_abort(strp->sk, ret);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tls_queue(struct strparser *strp, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(strp->sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
|
|
|
ctx->decrypted = false;
|
|
|
|
|
|
|
|
ctx->recv_pkt = skb;
|
|
|
|
strp_pause(strp);
|
|
|
|
|
2018-07-30 10:38:33 +00:00
|
|
|
ctx->saved_data_ready(strp->sk);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tls_data_ready(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
|
|
|
strp_data_ready(&ctx->strp);
|
|
|
|
}
|
|
|
|
|
2018-04-30 07:16:15 +00:00
|
|
|
void tls_sw_free_resources_tx(struct sock *sk)
|
2017-06-14 18:37:39 +00:00
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec *rec, *tmp;
|
|
|
|
|
|
|
|
/* Wait for any pending async encryptions to complete */
|
|
|
|
smp_store_mb(ctx->async_notify, true);
|
|
|
|
if (atomic_read(&ctx->encrypt_pending))
|
|
|
|
crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
|
|
|
|
|
|
|
|
cancel_delayed_work_sync(&ctx->tx_work.work);
|
|
|
|
|
|
|
|
/* Tx whatever records we can transmit and abandon the rest */
|
|
|
|
tls_tx_records(sk, -1);
|
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
/* Free up un-sent records in tx_list. First, free
|
2018-09-21 04:16:13 +00:00
|
|
|
* the partially sent record if any at head of tx_list.
|
|
|
|
*/
|
|
|
|
if (tls_ctx->partially_sent_record) {
|
|
|
|
struct scatterlist *sg = tls_ctx->partially_sent_record;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
put_page(sg_page(sg));
|
|
|
|
sk_mem_uncharge(sk, sg->length);
|
|
|
|
|
|
|
|
if (sg_is_last(sg))
|
|
|
|
break;
|
|
|
|
sg++;
|
|
|
|
}
|
|
|
|
|
|
|
|
tls_ctx->partially_sent_record = NULL;
|
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
rec = list_first_entry(&ctx->tx_list,
|
2018-09-21 04:16:13 +00:00
|
|
|
struct tls_rec, list);
|
2018-09-25 10:56:17 +00:00
|
|
|
|
|
|
|
free_sg(sk, rec->sg_plaintext_data,
|
|
|
|
&rec->sg_plaintext_num_elem,
|
|
|
|
&rec->sg_plaintext_size);
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
list_del(&rec->list);
|
|
|
|
kfree(rec);
|
|
|
|
}
|
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
list_for_each_entry_safe(rec, tmp, &ctx->tx_list, list) {
|
2018-09-21 04:16:13 +00:00
|
|
|
free_sg(sk, rec->sg_encrypted_data,
|
|
|
|
&rec->sg_encrypted_num_elem,
|
|
|
|
&rec->sg_encrypted_size);
|
|
|
|
|
2018-09-25 10:56:17 +00:00
|
|
|
free_sg(sk, rec->sg_plaintext_data,
|
|
|
|
&rec->sg_plaintext_num_elem,
|
|
|
|
&rec->sg_plaintext_size);
|
|
|
|
|
2018-09-21 04:16:13 +00:00
|
|
|
list_del(&rec->list);
|
|
|
|
kfree(rec);
|
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
|
2018-07-24 11:24:27 +00:00
|
|
|
crypto_free_aead(ctx->aead_send);
|
2018-09-25 14:51:51 +00:00
|
|
|
tls_free_open_rec(sk);
|
2018-04-30 07:16:15 +00:00
|
|
|
|
|
|
|
kfree(ctx);
|
|
|
|
}
|
|
|
|
|
2018-07-13 11:33:41 +00:00
|
|
|
void tls_sw_release_resources_rx(struct sock *sk)
|
2018-04-30 07:16:15 +00:00
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
if (ctx->aead_recv) {
|
2018-07-24 11:24:27 +00:00
|
|
|
kfree_skb(ctx->recv_pkt);
|
|
|
|
ctx->recv_pkt = NULL;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
crypto_free_aead(ctx->aead_recv);
|
|
|
|
strp_stop(&ctx->strp);
|
|
|
|
write_lock_bh(&sk->sk_callback_lock);
|
|
|
|
sk->sk_data_ready = ctx->saved_data_ready;
|
|
|
|
write_unlock_bh(&sk->sk_callback_lock);
|
|
|
|
release_sock(sk);
|
|
|
|
strp_done(&ctx->strp);
|
|
|
|
lock_sock(sk);
|
|
|
|
}
|
2018-07-13 11:33:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tls_sw_free_resources_rx(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
|
|
|
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
|
|
|
|
|
|
|
|
tls_sw_release_resources_rx(sk);
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
kfree(ctx);
|
|
|
|
}
|
|
|
|
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
/* The work handler to transmitt the encrypted records in tx_list */
|
2018-09-21 04:16:13 +00:00
|
|
|
static void tx_work_handler(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct delayed_work *delayed_work = to_delayed_work(work);
|
|
|
|
struct tx_work *tx_work = container_of(delayed_work,
|
|
|
|
struct tx_work, work);
|
|
|
|
struct sock *sk = tx_work->sk;
|
|
|
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
|
|
|
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
|
|
|
|
|
|
|
|
if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
|
|
|
|
return;
|
|
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
tls_tx_records(sk, -1);
|
|
|
|
release_sock(sk);
|
|
|
|
}
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
|
2017-06-14 18:37:39 +00:00
|
|
|
{
|
|
|
|
struct tls_crypto_info *crypto_info;
|
|
|
|
struct tls12_crypto_info_aes_gcm_128 *gcm_128_info;
|
2018-04-30 07:16:15 +00:00
|
|
|
struct tls_sw_context_tx *sw_ctx_tx = NULL;
|
|
|
|
struct tls_sw_context_rx *sw_ctx_rx = NULL;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
struct cipher_context *cctx;
|
|
|
|
struct crypto_aead **aead;
|
|
|
|
struct strp_callbacks cb;
|
2017-06-14 18:37:39 +00:00
|
|
|
u16 nonce_size, tag_size, iv_size, rec_seq_size;
|
|
|
|
char *iv, *rec_seq;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (!ctx) {
|
|
|
|
rc = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2018-04-30 07:16:15 +00:00
|
|
|
if (tx) {
|
2018-07-13 11:33:42 +00:00
|
|
|
if (!ctx->priv_ctx_tx) {
|
|
|
|
sw_ctx_tx = kzalloc(sizeof(*sw_ctx_tx), GFP_KERNEL);
|
|
|
|
if (!sw_ctx_tx) {
|
|
|
|
rc = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
ctx->priv_ctx_tx = sw_ctx_tx;
|
|
|
|
} else {
|
|
|
|
sw_ctx_tx =
|
|
|
|
(struct tls_sw_context_tx *)ctx->priv_ctx_tx;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-07-13 11:33:42 +00:00
|
|
|
if (!ctx->priv_ctx_rx) {
|
|
|
|
sw_ctx_rx = kzalloc(sizeof(*sw_ctx_rx), GFP_KERNEL);
|
|
|
|
if (!sw_ctx_rx) {
|
|
|
|
rc = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
ctx->priv_ctx_rx = sw_ctx_rx;
|
|
|
|
} else {
|
|
|
|
sw_ctx_rx =
|
|
|
|
(struct tls_sw_context_rx *)ctx->priv_ctx_rx;
|
2018-04-30 07:16:15 +00:00
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
if (tx) {
|
2018-07-13 11:33:42 +00:00
|
|
|
crypto_init_wait(&sw_ctx_tx->async_wait);
|
2018-09-12 15:44:42 +00:00
|
|
|
crypto_info = &ctx->crypto_send.info;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
cctx = &ctx->tx;
|
2018-04-30 07:16:15 +00:00
|
|
|
aead = &sw_ctx_tx->aead_send;
|
net/tls: Fixed race condition in async encryption
On processors with multi-engine crypto accelerators, it is possible that
multiple records get encrypted in parallel and their encryption
completion is notified to different cpus in multicore processor. This
leads to the situation where tls_encrypt_done() starts executing in
parallel on different cores. In current implementation, encrypted
records are queued to tx_ready_list in tls_encrypt_done(). This requires
addition to linked list 'tx_ready_list' to be protected. As
tls_decrypt_done() could be executing in irq content, it is not possible
to protect linked list addition operation using a lock.
To fix the problem, we remove linked list addition operation from the
irq context. We do tx_ready_list addition/removal operation from
application context only and get rid of possible multiple access to
the linked list. Before starting encryption on the record, we add it to
the tail of tx_ready_list. To prevent tls_tx_records() from transmitting
it, we mark the record with a new flag 'tx_ready' in 'struct tls_rec'.
When record encryption gets completed, tls_encrypt_done() has to only
update the 'tx_ready' flag to true & linked list add operation is not
required.
The changed logic brings some other side benefits. Since the records
are always submitted in tls sequence number order for encryption, the
tx_ready_list always remains sorted and addition of new records to it
does not have to traverse the linked list.
Lastly, we renamed tx_ready_list in 'struct tls_sw_context_tx' to
'tx_list'. This is because now, the some of the records at the tail are
not ready to transmit.
Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-09-24 10:05:56 +00:00
|
|
|
INIT_LIST_HEAD(&sw_ctx_tx->tx_list);
|
2018-09-21 04:16:13 +00:00
|
|
|
INIT_DELAYED_WORK(&sw_ctx_tx->tx_work.work, tx_work_handler);
|
|
|
|
sw_ctx_tx->tx_work.sk = sk;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
} else {
|
2018-07-13 11:33:42 +00:00
|
|
|
crypto_init_wait(&sw_ctx_rx->async_wait);
|
2018-09-12 15:44:42 +00:00
|
|
|
crypto_info = &ctx->crypto_recv.info;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
cctx = &ctx->rx;
|
2018-04-30 07:16:15 +00:00
|
|
|
aead = &sw_ctx_rx->aead_recv;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
|
|
|
|
2017-06-14 18:37:39 +00:00
|
|
|
switch (crypto_info->cipher_type) {
|
|
|
|
case TLS_CIPHER_AES_GCM_128: {
|
|
|
|
nonce_size = TLS_CIPHER_AES_GCM_128_IV_SIZE;
|
|
|
|
tag_size = TLS_CIPHER_AES_GCM_128_TAG_SIZE;
|
|
|
|
iv_size = TLS_CIPHER_AES_GCM_128_IV_SIZE;
|
|
|
|
iv = ((struct tls12_crypto_info_aes_gcm_128 *)crypto_info)->iv;
|
|
|
|
rec_seq_size = TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE;
|
|
|
|
rec_seq =
|
|
|
|
((struct tls12_crypto_info_aes_gcm_128 *)crypto_info)->rec_seq;
|
|
|
|
gcm_128_info =
|
|
|
|
(struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
rc = -EINVAL;
|
2018-01-16 15:04:26 +00:00
|
|
|
goto free_priv;
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
|
|
|
|
2018-04-11 00:52:34 +00:00
|
|
|
/* Sanity-check the IV size for stack allocations. */
|
2018-06-25 23:55:05 +00:00
|
|
|
if (iv_size > MAX_IV_SIZE || nonce_size > MAX_IV_SIZE) {
|
2018-04-11 00:52:34 +00:00
|
|
|
rc = -EINVAL;
|
|
|
|
goto free_priv;
|
|
|
|
}
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
cctx->prepend_size = TLS_HEADER_SIZE + nonce_size;
|
|
|
|
cctx->tag_size = tag_size;
|
|
|
|
cctx->overhead_size = cctx->prepend_size + cctx->tag_size;
|
|
|
|
cctx->iv_size = iv_size;
|
|
|
|
cctx->iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!cctx->iv) {
|
2017-06-14 18:37:39 +00:00
|
|
|
rc = -ENOMEM;
|
2018-01-16 15:04:26 +00:00
|
|
|
goto free_priv;
|
2017-06-14 18:37:39 +00:00
|
|
|
}
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
memcpy(cctx->iv, gcm_128_info->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
|
|
|
|
memcpy(cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv, iv_size);
|
|
|
|
cctx->rec_seq_size = rec_seq_size;
|
2018-07-31 16:50:24 +00:00
|
|
|
cctx->rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
if (!cctx->rec_seq) {
|
2017-06-14 18:37:39 +00:00
|
|
|
rc = -ENOMEM;
|
|
|
|
goto free_iv;
|
|
|
|
}
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
|
|
|
if (!*aead) {
|
|
|
|
*aead = crypto_alloc_aead("gcm(aes)", 0, 0);
|
|
|
|
if (IS_ERR(*aead)) {
|
|
|
|
rc = PTR_ERR(*aead);
|
|
|
|
*aead = NULL;
|
2017-06-14 18:37:39 +00:00
|
|
|
goto free_rec_seq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->push_pending_record = tls_sw_push_pending_record;
|
|
|
|
|
2018-09-12 15:44:41 +00:00
|
|
|
rc = crypto_aead_setkey(*aead, gcm_128_info->key,
|
2017-06-14 18:37:39 +00:00
|
|
|
TLS_CIPHER_AES_GCM_128_KEY_SIZE);
|
|
|
|
if (rc)
|
|
|
|
goto free_aead;
|
|
|
|
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
rc = crypto_aead_setauthsize(*aead, cctx->tag_size);
|
|
|
|
if (rc)
|
|
|
|
goto free_aead;
|
|
|
|
|
2018-04-30 07:16:15 +00:00
|
|
|
if (sw_ctx_rx) {
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
/* Set up strparser */
|
|
|
|
memset(&cb, 0, sizeof(cb));
|
|
|
|
cb.rcv_msg = tls_queue;
|
|
|
|
cb.parse_msg = tls_read_size;
|
|
|
|
|
2018-04-30 07:16:15 +00:00
|
|
|
strp_init(&sw_ctx_rx->strp, sk, &cb);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
|
|
|
write_lock_bh(&sk->sk_callback_lock);
|
2018-04-30 07:16:15 +00:00
|
|
|
sw_ctx_rx->saved_data_ready = sk->sk_data_ready;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
sk->sk_data_ready = tls_data_ready;
|
|
|
|
write_unlock_bh(&sk->sk_callback_lock);
|
|
|
|
|
2018-06-28 16:43:44 +00:00
|
|
|
sw_ctx_rx->sk_poll = sk->sk_socket->ops->poll;
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
|
2018-04-30 07:16:15 +00:00
|
|
|
strp_check_rcv(&sw_ctx_rx->strp);
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
goto out;
|
2017-06-14 18:37:39 +00:00
|
|
|
|
|
|
|
free_aead:
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
crypto_free_aead(*aead);
|
|
|
|
*aead = NULL;
|
2017-06-14 18:37:39 +00:00
|
|
|
free_rec_seq:
|
tls: RX path for ktls
Add rx path for tls software implementation.
recvmsg, splice_read, and poll implemented.
An additional sockopt TLS_RX is added, with the same interface as
TLS_TX. Either TLX_RX or TLX_TX may be provided separately, or
together (with two different setsockopt calls with appropriate keys).
Control messages are passed via CMSG in a similar way to transmit.
If no cmsg buffer is passed, then only application data records
will be passed to userspace, and EIO is returned for other types of
alerts.
EBADMSG is passed for decryption errors, and EMSGSIZE is passed for
framing too big, and EBADMSG for framing too small (matching openssl
semantics). EINVAL is returned for TLS versions that do not match the
original setsockopt call. All are unrecoverable.
strparser is used to parse TLS framing. Decryption is done directly
in to userspace buffers if they are large enough to support it, otherwise
sk_cow_data is called (similar to ipsec), and buffers are decrypted in
place and copied. splice_read always decrypts in place, since no
buffers are provided to decrypt in to.
sk_poll is overridden, and only returns POLLIN if a full TLS message is
received. Otherwise we wait for strparser to finish reading a full frame.
Actual decryption is only done during recvmsg or splice_read calls.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-03-22 17:10:35 +00:00
|
|
|
kfree(cctx->rec_seq);
|
|
|
|
cctx->rec_seq = NULL;
|
2017-06-14 18:37:39 +00:00
|
|
|
free_iv:
|
2018-04-30 07:16:15 +00:00
|
|
|
kfree(cctx->iv);
|
|
|
|
cctx->iv = NULL;
|
2018-01-16 15:04:26 +00:00
|
|
|
free_priv:
|
2018-04-30 07:16:15 +00:00
|
|
|
if (tx) {
|
|
|
|
kfree(ctx->priv_ctx_tx);
|
|
|
|
ctx->priv_ctx_tx = NULL;
|
|
|
|
} else {
|
|
|
|
kfree(ctx->priv_ctx_rx);
|
|
|
|
ctx->priv_ctx_rx = NULL;
|
|
|
|
}
|
2017-06-14 18:37:39 +00:00
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
}
|