From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f180.google.com (mail-pg1-f180.google.com [209.85.215.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B1871E834E for ; Mon, 9 Mar 2026 05:54:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.180 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773035688; cv=none; b=E5sJSYT8C5EfdZ+M7ubg3V2al823EMZYQVQU1ScceUm7MEhuLW7ObDEzocMITD4QP3V4INWPsxNHpcNV92t2tyM7Vs4PW9ad7XD7ltg6PmIMO2+KJjRYGGu78izrDpEh6MGtY88+Oud4Lt1IrZWLnllAn2Q1rjPgqqctktygPPc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773035688; c=relaxed/simple; bh=UreViDwj5CK4brJrjfQ7EURHubCS5eOib6jZhMepOdk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nxd7F3rRdFAd1OxtCC2Ocn2fRN8Z3ZKeNQigPvjRn9X6wl8xQlswySLERoitaoqaoV1MtVghHpZUAVpBLAIBv/X4xRR0OUcnafKVMlVE9hYAepIpErqGjabcyrhEyaSitPLkEdZpeu36KyntGEx5Ut9SOHh2gjCcmRH8MaJO6XI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=diN4NXLb; arc=none smtp.client-ip=209.85.215.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="diN4NXLb" Received: by mail-pg1-f180.google.com with SMTP id 41be03b00d2f7-c7358a7a8d1so5081403a12.3 for ; Sun, 08 Mar 2026 22:54:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773035687; x=1773640487; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+eXVlNI+VPppaY/morooabCwuSYEtf9ABnZ29jfqnh4=; b=diN4NXLbF4APbkdr50c/3buNpeiadWd82VxtjgPvoGcoRutc3j2Nu6wHNgxkIkqdBW YpXtsql8z0v6B5UM1N/XMPUdZ+HiZ9WoYIAMyAN7Nogld0k4WR4b0qmEW3gihjzXvLlt rGxenB7Pof6NqcF9rrbN6olzW6/MUZNQP/EA1n4AYKKND2xdCdKG2Kq9UtrC7lPlFDtT tZPnZmxaeAzXJVtdjiEQu1u0mzcySl7jJEZxGw6svm2rf1Rsdy69EP0sn5rS8tDx+1/J OTnrdUSrzf6ye0uEAJILUDvQoTxLo6qHy6pjaZtqoFWAUGLC8h3uH9lrTNC9/p5TllkG 5QrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773035687; x=1773640487; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=+eXVlNI+VPppaY/morooabCwuSYEtf9ABnZ29jfqnh4=; b=BBB9sVMlbWuFPA2TGqzwL/5ZK++JWS3MjU9RhWsHhiQB98LQDAE1+9l6MmjGvwGVtx WhMNDlQiT/xMfAPsaf2i0cHIOJBjjSNmrxRA5j55ldjijuuGq+kC8APbVA+hOMUfYzKn 7ocVaG/p9sibthaCm0HOBDLWz+rpAUoOhVyyImdMJp/zVTquVnGi2PkOWtJt85sFanbA CZFW1V86/DIhQH7iXqvNp9Z074znzxL679PxgPvMDbuIhAotQ802covchpvyL7MCsHIw x/MPQuMgsG1urmDgxTskJhyUbVXzFfQSH+jDC/K6lv/mylsrLL/4iFithEqGzUaQf27b dp4A== X-Forwarded-Encrypted: i=1; AJvYcCU7BiUjhHlnP+PspNt5sr0p1+1b5Q+iKVGkahxFwAE4U5s5mbrKLhecQxAmUtJ+o1GmQHyU2eE4ZaU=@vger.kernel.org X-Gm-Message-State: AOJu0Yze0iJ8GAhLW6kbl//gTGI43AKqSN1GAlR4tC7LXpGpYetxo06F 64XulHGkVL4yBJlUe0GnHquHevxvR+qo+ZrXWWOzdx0HTjHg2f92nr80 X-Gm-Gg: ATEYQzwhGESr+XaoVg3LssbQbAGi0Lv8DsOu+pjWHzK27GyOcF3VJAbpgugdopraigU xrJTF9UvbQC9HhsV2kCNzRIhwIZK/ZkaTkiq8/3lkiLWbjN9Snz9z0N6ubDjEjncgftV93NYOyU wKCiVa3YXMbYkhTWNU0sDxt9RrZPy5oQGJ99XTar20hylie3l03GpvuHAZakHH6f0R7dW50syVX uRYHY5Ygjt27AeB8aKRKr1GdvSzvkF42LsX5GMf2P+LS76nPQPx3jFEWjuuSF44voKEOj05beIR rkXDzpwsnweUCv7u7d1FE52FZ1p9AKmXxHPB0SyzFpXgtGncFE/yVoVB2JWk3vaKmXZ0Jzygg8B 5ayeMhJkRtwpKa/oQp4pVwfJoRsWeBjRZN4S2vB+Tef3DO1vEHPTAroYfU2Yq7MPZk6cVmm1x1L 9q9QbZQgVMPwHa39wNuCUEs57DdE2Ha+RoXSFbH4j5ZrdonZ+Gpt2R+Kw1Zvme X-Received: by 2002:a05:6a20:cf8b:b0:38e:90ca:5a4b with SMTP id adf61e73a8af0-39859089f98mr9851848637.45.1773035686645; Sun, 08 Mar 2026 22:54:46 -0700 (PDT) Received: from zenbook ([159.196.5.243]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c739e170923sm7933716a12.17.2026.03.08.22.54.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 Mar 2026 22:54:46 -0700 (PDT) From: Wilfred Mallawa To: John Fastabend , Jakub Kicinski , Sabrina Dubroca , "David S . Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Alistair Francis , Damien Le'Moal , Wilfred Mallawa Subject: [RFC net-next 2/3] net/tls: add randomized zero padding socket option Date: Mon, 9 Mar 2026 15:48:37 +1000 Message-ID: <20260309054837.2299732-4-wilfred.opensource@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260309054837.2299732-2-wilfred.opensource@gmail.com> References: <20260309054837.2299732-2-wilfred.opensource@gmail.com> Precedence: bulk X-Mailing-List: linux-doc@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Wilfred Mallawa Currently, for TLS 1.3, ktls does not support record zero padding [1]. Record zero padding is used to allow the sender to hide the size of the traffic patterns from an observer. TLS is susceptible to a variety of traffic analysis attacks based on observing the length and timing of encrypted packets [2]. Upcoming Western Digital NVMe-TCP hardware controllers implement TLS 1.3. Which from a security perspective, can benefit from having record zero padding enabled to mitigate against traffic analysis attacks [2]. Add a new TLS_TX_RANDOM_PAD ktls socket option that allows userspace to enable and specify an upperbound for randomized record zero padding in TLS 1.3. When this value is set and non-zero, ktls will append a randomized amount of [0, min(record_room, upper_bound)] bytes to records that are end-of-record (EOR) and aren't full. This can be set back to zero to disable appending zero padding. By default, no record zero padding is added. The number of zero padding bytes is randomised primarilly to reduce some of the throughput overhead of using a fixed zero padding amount up to the record size limit. [1] https://datatracker.ietf.org/doc/html/rfc8446#section-5.4l [2] https://datatracker.ietf.org/doc/html/rfc8446#appendix-E.3 Signed-off-by: Wilfred Mallawa --- Documentation/networking/tls.rst | 21 ++++++++++ include/uapi/linux/tls.h | 2 + net/tls/tls_main.c | 70 ++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/Documentation/networking/tls.rst b/Documentation/networking/tls.rst index 980c442d7161..e112a68a9bfb 100644 --- a/Documentation/networking/tls.rst +++ b/Documentation/networking/tls.rst @@ -300,6 +300,27 @@ extra byte used by the ContentType field. [1] https://datatracker.ietf.org/doc/html/rfc8449 +TLS_TX_RANDOM_PAD +~~~~~~~~~~~~~~~~~ + +Enable and set the limit for randomized zero padding [1] of outgoing +TLS records. + +When enabled, TLS records that are not full and are end of record (EOR) +will be padded with a randomly chosen amount of zero padding up to the remaining +record capacity or the limit provided by this option (smaller of the two). +Randomized zero padding can reduce information leakage via observable TLS +record lengths and mitigates traffic analysis based on message size. + +Padding never exceeds the protocol maximum record size and full-sized records +are unchanged. + +This increases bandwidth usage and may add CPU overhead due to padding +generation and larger encryption operations. For workloads with small records, +the bandwidth overhead may be significant. + +[1] https://datatracker.ietf.org/doc/html/rfc8446#section-5.4 + Statistics ========== diff --git a/include/uapi/linux/tls.h b/include/uapi/linux/tls.h index b8b9c42f848c..42a318cb5eb8 100644 --- a/include/uapi/linux/tls.h +++ b/include/uapi/linux/tls.h @@ -42,6 +42,7 @@ #define TLS_TX_ZEROCOPY_RO 3 /* TX zerocopy (only sendfile now) */ #define TLS_RX_EXPECT_NO_PAD 4 /* Attempt opportunistic zero-copy */ #define TLS_TX_MAX_PAYLOAD_LEN 5 /* Maximum plaintext size */ +#define TLS_TX_RANDOM_PAD 6 /* TLS TX randomized record zero padding */ /* Supported versions */ #define TLS_VERSION_MINOR(ver) ((ver) & 0xFF) @@ -196,6 +197,7 @@ enum { TLS_INFO_ZC_RO_TX, TLS_INFO_RX_NO_PAD, TLS_INFO_TX_MAX_PAYLOAD_LEN, + TLS_INFO_TX_RANDOM_PAD, __TLS_INFO_MAX, }; #define TLS_INFO_MAX (__TLS_INFO_MAX - 1) diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index b0702effbc26..62c525afbc14 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -563,6 +563,30 @@ static int do_tls_getsockopt_tx_payload_len(struct sock *sk, char __user *optval return 0; } +static int do_tls_getsockopt_tx_random_pad(struct sock *sk, char __user *optval, + int __user *optlen) +{ + struct tls_context *ctx = tls_get_ctx(sk); + u16 pad_limit = ctx->tx_record_zero_pad; + int len; + + if (ctx->prot_info.version != TLS_1_3_VERSION) + return -EOPNOTSUPP; + + if (get_user(len, optlen)) + return -EFAULT; + + if (len < sizeof(pad_limit)) + return -EINVAL; + + if (put_user(sizeof(pad_limit), optlen)) + return -EFAULT; + + if (copy_to_user(optval, &pad_limit, sizeof(pad_limit))) + return -EFAULT; + + return 0; +} static int do_tls_getsockopt(struct sock *sk, int optname, char __user *optval, int __user *optlen) { @@ -585,6 +609,9 @@ static int do_tls_getsockopt(struct sock *sk, int optname, case TLS_TX_MAX_PAYLOAD_LEN: rc = do_tls_getsockopt_tx_payload_len(sk, optval, optlen); break; + case TLS_TX_RANDOM_PAD: + rc = do_tls_getsockopt_tx_random_pad(sk, optval, optlen); + break; default: rc = -ENOPROTOOPT; break; @@ -860,6 +887,33 @@ static int do_tls_setsockopt_tx_payload_len(struct sock *sk, sockptr_t optval, return 0; } +static int do_tls_setsockopt_tx_random_pad(struct sock *sk, sockptr_t optval, + unsigned int optlen) +{ + struct tls_context *ctx = tls_get_ctx(sk); + struct tls_sw_context_tx *sw_ctx = tls_sw_ctx_tx(ctx); + u16 value; + + if (ctx->prot_info.version != TLS_1_3_VERSION) + return -EOPNOTSUPP; + + if (sw_ctx && sw_ctx->open_rec) + return -EBUSY; + + if (sockptr_is_null(optval) || optlen != sizeof(value)) + return -EINVAL; + + if (copy_from_sockptr(&value, optval, sizeof(value))) + return -EFAULT; + + if (value >= ctx->tx_max_payload_len) + return -EINVAL; + + ctx->tx_record_zero_pad = value; + + return 0; +} + static int do_tls_setsockopt(struct sock *sk, int optname, sockptr_t optval, unsigned int optlen) { @@ -886,6 +940,11 @@ static int do_tls_setsockopt(struct sock *sk, int optname, sockptr_t optval, rc = do_tls_setsockopt_tx_payload_len(sk, optval, optlen); release_sock(sk); break; + case TLS_TX_RANDOM_PAD: + lock_sock(sk); + rc = do_tls_setsockopt_tx_random_pad(sk, optval, optlen); + release_sock(sk); + break; default: rc = -ENOPROTOOPT; break; @@ -1173,6 +1232,13 @@ static int tls_get_info(struct sock *sk, struct sk_buff *skb, bool net_admin) if (err) goto nla_failure; + if (version != TLS_1_3_VERSION) { + err = nla_put_u16(skb, TLS_INFO_TX_RANDOM_PAD, + ctx->tx_record_zero_pad); + if (err) + goto nla_failure; + } + rcu_read_unlock(); nla_nest_end(skb, start); return 0; @@ -1185,6 +1251,7 @@ static int tls_get_info(struct sock *sk, struct sk_buff *skb, bool net_admin) static size_t tls_get_info_size(const struct sock *sk, bool net_admin) { + struct tls_context *ctx = tls_get_ctx(sk); size_t size = 0; size += nla_total_size(0) + /* INET_ULP_INFO_TLS */ @@ -1197,6 +1264,9 @@ static size_t tls_get_info_size(const struct sock *sk, bool net_admin) nla_total_size(sizeof(u16)) + /* TLS_INFO_TX_MAX_PAYLOAD_LEN */ 0; + if (ctx->prot_info.version == TLS_1_3_VERSION) + size += nla_total_size(sizeof(u16)); /* TLS_INFO_TX_RANDOM_PAD */ + return size; } -- 2.53.0