tls: rx: add sockopt for enabling optimistic decrypt with TLS 1.3

Since optimisitic decrypt may add extra load in case of retries
require socket owner to explicitly opt-in.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jakub Kicinski 2022-07-05 16:59:24 -07:00 committed by David S. Miller
parent ce61327ce9
commit 88527790c0
8 changed files with 122 additions and 7 deletions

View file

@ -533,6 +533,37 @@ static int do_tls_getsockopt_tx_zc(struct sock *sk, char __user *optval,
return 0;
}
static int do_tls_getsockopt_no_pad(struct sock *sk, char __user *optval,
int __user *optlen)
{
struct tls_context *ctx = tls_get_ctx(sk);
unsigned int value;
int err, len;
if (ctx->prot_info.version != TLS_1_3_VERSION)
return -EINVAL;
if (get_user(len, optlen))
return -EFAULT;
if (len < sizeof(value))
return -EINVAL;
lock_sock(sk);
err = -EINVAL;
if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW)
value = ctx->rx_no_pad;
release_sock(sk);
if (err)
return err;
if (put_user(sizeof(value), optlen))
return -EFAULT;
if (copy_to_user(optval, &value, sizeof(value)))
return -EFAULT;
return 0;
}
static int do_tls_getsockopt(struct sock *sk, int optname,
char __user *optval, int __user *optlen)
{
@ -547,6 +578,9 @@ static int do_tls_getsockopt(struct sock *sk, int optname,
case TLS_TX_ZEROCOPY_RO:
rc = do_tls_getsockopt_tx_zc(sk, optval, optlen);
break;
case TLS_RX_EXPECT_NO_PAD:
rc = do_tls_getsockopt_no_pad(sk, optval, optlen);
break;
default:
rc = -ENOPROTOOPT;
break;
@ -718,6 +752,38 @@ static int do_tls_setsockopt_tx_zc(struct sock *sk, sockptr_t optval,
return 0;
}
static int do_tls_setsockopt_no_pad(struct sock *sk, sockptr_t optval,
unsigned int optlen)
{
struct tls_context *ctx = tls_get_ctx(sk);
u32 val;
int rc;
if (ctx->prot_info.version != TLS_1_3_VERSION ||
sockptr_is_null(optval) || optlen < sizeof(val))
return -EINVAL;
rc = copy_from_sockptr(&val, optval, sizeof(val));
if (rc)
return -EFAULT;
if (val > 1)
return -EINVAL;
rc = check_zeroed_sockptr(optval, sizeof(val), optlen - sizeof(val));
if (rc < 1)
return rc == 0 ? -EINVAL : rc;
lock_sock(sk);
rc = -EINVAL;
if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW) {
ctx->rx_no_pad = val;
tls_update_rx_zc_capable(ctx);
rc = 0;
}
release_sock(sk);
return rc;
}
static int do_tls_setsockopt(struct sock *sk, int optname, sockptr_t optval,
unsigned int optlen)
{
@ -736,6 +802,9 @@ static int do_tls_setsockopt(struct sock *sk, int optname, sockptr_t optval,
rc = do_tls_setsockopt_tx_zc(sk, optval, optlen);
release_sock(sk);
break;
case TLS_RX_EXPECT_NO_PAD:
rc = do_tls_setsockopt_no_pad(sk, optval, optlen);
break;
default:
rc = -ENOPROTOOPT;
break;
@ -976,6 +1045,11 @@ static int tls_get_info(const struct sock *sk, struct sk_buff *skb)
if (err)
goto nla_failure;
}
if (ctx->rx_no_pad) {
err = nla_put_flag(skb, TLS_INFO_RX_NO_PAD);
if (err)
goto nla_failure;
}
rcu_read_unlock();
nla_nest_end(skb, start);
@ -997,6 +1071,7 @@ static size_t tls_get_info_size(const struct sock *sk)
nla_total_size(sizeof(u16)) + /* TLS_INFO_RXCONF */
nla_total_size(sizeof(u16)) + /* TLS_INFO_TXCONF */
nla_total_size(0) + /* TLS_INFO_ZC_RO_TX */
nla_total_size(0) + /* TLS_INFO_RX_NO_PAD */
0;
return size;