From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f175.google.com (mail-pg1-f175.google.com [209.85.215.175]) (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 B3E1734CFB8 for ; Mon, 9 Mar 2026 05:54:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.175 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773035683; cv=none; b=lhfpL/OXvZOfFqAxT/zWc9NaFFEzFpOR6ZUWDLQVg4bjHVnGuLk+99wX+K0DhRxq4w3cUPyupJ1hYcd6P6fbv7qeVQSxn/DdGd3yg/+vzASHK1MRu2mCO1+xd+PqXETEmjuKqfWCc7fSsYWKjNqyXwF2q1rgMjwic/G/gNholJ8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773035683; c=relaxed/simple; bh=naXvgUL1vrrylA++ctQr+L9oQ71V0LFb27f4Yj4ef0M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Hw2IWeHoFZv9wvKHrh7Zkmc+ee6ioO74ky7rLUqwPuAI6xHIfc64UJoTOJJz344EzZA2q8/aqohi/0L/AIudIL5dDmpg5FvJzwI2hhJHr+kKI+3zclZ9kVDfFR19vG1DFunT7KYkvSkHZ1mTzjcC867d5jng1vQKqacEPJCLi84= 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=XHjUVd+v; arc=none smtp.client-ip=209.85.215.175 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="XHjUVd+v" Received: by mail-pg1-f175.google.com with SMTP id 41be03b00d2f7-c2af7d09533so7159756a12.1 for ; Sun, 08 Mar 2026 22:54:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773035680; x=1773640480; 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=AZOR83ZELRZ96AOmva1kehfsvl1uJwm5zQkZMO8Il2Y=; b=XHjUVd+vX7DcB+Fj7synsk8LCV3UWf+1e66c906/v23ZdJ/zJStor8Bbf9TTQ7aEDz iiXNwAYiGpKi+6UTqVRpQL8VUgAUs/qAfgBGWhPOcmbyMVXux9oWwYxGgKnyTmOSFRwl u/+xnYaTuFgcxCbEYuxd9hZZrXCCm3dqsRr+w967bOxDrE5toqCnNUH4Wfh3td8Ss4U8 K+CHHDwKrSDbKbxIpn0HJUhlL4BlTuIUJiAwjMX3aESfrpLsgT2Itc8Wxzdxf99ZaqVa 1kGLJ9cNWgE6Aefdn9BU1KmRboXWQjjkWJbk8zCoEKSGtE9xxKOvk5k2wa/2Dbw/rfXg 2SBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773035680; x=1773640480; 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=AZOR83ZELRZ96AOmva1kehfsvl1uJwm5zQkZMO8Il2Y=; b=NZ5Hd65w6rMFKQTcz3xjU+qSw9oZI1qDyeB4Hq4/2Qco3TR3n7D238DEZq7CliCL5C 8EgPMQRTY8U74a/rXg6e3AF8DyhA9HWXHrg8vblc86/p88hhrCS1PAEx11k5S1QpFp6u A7Z2rjVw5ZYcuC3UsZqJ5nJ0E7qM+PgXahCsV4f6+FCpZMq6p01Mp3315bFM26i3lV+R 60j/Mhx3z9ih2QXYs+xX+CuHeCeObzO/VNeB5xnz9sdRD7tMqB623l8ZzbXIb62aorpF XkEy4bmhPG6H1HNSUVg0gRkUg1e2uksUL055G4d5IMfnFgepbSjyv8mCFVh1s2Uyqi4F gnqQ== X-Forwarded-Encrypted: i=1; AJvYcCX/2sD1nRBX1IiPLbj3fX+l18WzYxEzGZA69uiA6rCnT469YqzDJDycfCQqkKHGBBhn1dHYNSZL//3V/4U=@vger.kernel.org X-Gm-Message-State: AOJu0YzOj6Xg/+1KsnfpkNUom1NeFtGVa4JIMOa/KZCQTJuQ3dCD9Zc7 Bwvp7+VsdXR/5iaruuQfTh6yj4jk4Cyh+gUexRSCUD6vEsoq5XHljs7g X-Gm-Gg: ATEYQzwP4N+P8OQ2bgaqoxQwDicIxzPcl0D3Xb5/Mlc5+KPABfxqYdZryOyDgiRnivs tqH98gIlNCufPIBVUOV5ooqcZsBN+OZR8c4esQvRFlpb6gmwGpK+0jwvGViewjeHC5hXIcHAzyi NL6tUIAkMEXqE61Y2AjiCiqWuVYhjPkrddZtA50xIhx8AwuqdmCq3RjvMRMuYmYH6lcwjKz+ont +HlU/8lvOVSQ5gIPWxTI94ZRIj/5JKpQLszCAj8VsxZTTXNnqrv0fNCv19CpZAxTNWun1OZVtrp pgyWGoHpvWu4Q6hGQpawTCxQZELc7X36FPM5A4qS+vD+K1woEt69ERV1foso1p7p1OJRu40T3Iv RGepDHP4py1jY1aAPgKVdeconDrNpXv5Kqkuxr0U3V0Kg97Osj71CAkD82zUH+4AWRW3XWtnKbl VV1tNZw4qBYoOuMn16GdAtivD/7UV4xYW8J2/N7gOAQ6POqLfIFGlF69dE0Pkx2PJqG3WNlsY= X-Received: by 2002:a05:6a20:a10e:b0:398:7853:c495 with SMTP id adf61e73a8af0-3987853c6d0mr5367983637.3.1773035679994; Sun, 08 Mar 2026 22:54:39 -0700 (PDT) Received: from zenbook ([159.196.5.243]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c739e170923sm7933716a12.17.2026.03.08.22.54.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 Mar 2026 22:54:39 -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 1/3] net/tls_sw: support randomized zero padding Date: Mon, 9 Mar 2026 15:48:36 +1000 Message-ID: <20260309054837.2299732-3-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-kernel@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]. Thus, for TX, add support to appending a randomized number of zero padding bytes to end-of-record (EOR) records that are not full. The number of zero padding bytes to append is determined by the remaining record room and the user specified upper bound (minimum of the two). That is rand([0, min(record_room, upper_bound)]). For TLS 1.3, zero padding is added after the content type byte, as such, if the record in context meets the above conditions for zero padding, attach a zero padding buffer to the content type byte before a record is encrypted. The padding buffer is freed when the record is freed. By default, record zero padding is disabled, and userspace may enable it by using the setsockopt TLS_TX_RANDOM_PAD option. [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 --- include/net/tls.h | 1 + net/tls/tls.h | 6 ++++- net/tls/tls_main.c | 2 ++ net/tls/tls_sw.c | 58 ++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/include/net/tls.h b/include/net/tls.h index ebd2550280ae..1feef72cc339 100644 --- a/include/net/tls.h +++ b/include/net/tls.h @@ -229,6 +229,7 @@ struct tls_context { u8 zerocopy_sendfile:1; u8 rx_no_pad:1; u16 tx_max_payload_len; + u16 tx_record_zero_pad; int (*push_pending_record)(struct sock *sk, int flags); void (*sk_write_space)(struct sock *sk); diff --git a/net/tls/tls.h b/net/tls/tls.h index e8f81a006520..3a86eb145332 100644 --- a/net/tls/tls.h +++ b/net/tls/tls.h @@ -121,8 +121,12 @@ struct tls_rec { /* AAD | msg_encrypted.sg.data (data contains overhead for hdr & iv & tag) */ struct scatterlist sg_aead_out[2]; + /* TLS 1.3 record zero padding */ + char *zero_padding; + u16 zero_padding_len; + char content_type; - struct scatterlist sg_content_type; + struct scatterlist sg_content_trail[2]; struct sock *sk; diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index fd39acf41a61..b0702effbc26 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -1076,6 +1076,8 @@ static int tls_init(struct sock *sk) ctx->tx_conf = TLS_BASE; ctx->rx_conf = TLS_BASE; ctx->tx_max_payload_len = TLS_MAX_PAYLOAD_SIZE; + /* TX record zero padding is disabled by default */ + ctx->tx_record_zero_pad = 0; update_sk_prot(sk, ctx); out: write_unlock_bh(&sk->sk_callback_lock); diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index a656ce235758..84b167607e1f 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -389,6 +389,7 @@ static void tls_free_rec(struct sock *sk, struct tls_rec *rec) { sk_msg_free(sk, &rec->msg_encrypted); sk_msg_free(sk, &rec->msg_plaintext); + kfree(rec->zero_padding); kfree(rec); } @@ -430,6 +431,7 @@ int tls_tx_records(struct sock *sk, int flags) */ list_del(&rec->list); sk_msg_free(sk, &rec->msg_plaintext); + kfree(rec->zero_padding); kfree(rec); } @@ -450,6 +452,7 @@ int tls_tx_records(struct sock *sk, int flags) list_del(&rec->list); sk_msg_free(sk, &rec->msg_plaintext); + kfree(rec->zero_padding); kfree(rec); } else { break; @@ -779,12 +782,29 @@ static int tls_push_record(struct sock *sk, int flags, sk_msg_iter_var_prev(i); rec->content_type = record_type; + if (prot->version == TLS_1_3_VERSION) { - /* Add content type to end of message. No padding added */ - sg_set_buf(&rec->sg_content_type, &rec->content_type, 1); - sg_mark_end(&rec->sg_content_type); + /* + * Add content type to end of message with zero padding + * if available. + */ + sg_init_table(rec->sg_content_trail, 2); + sg_set_buf(&rec->sg_content_trail[0], &rec->content_type, 1); + if (rec->zero_padding_len) { + rec->zero_padding = kzalloc(rec->zero_padding_len, + sk->sk_allocation); + if (!rec->zero_padding) + return -ENOMEM; + + sg_set_buf(&rec->sg_content_trail[1], + rec->zero_padding, rec->zero_padding_len); + sg_mark_end(&rec->sg_content_trail[1]); + } else { + sg_mark_end(&rec->sg_content_trail[0]); + } + sg_chain(msg_pl->sg.data, msg_pl->sg.end + 1, - &rec->sg_content_type); + rec->sg_content_trail); } else { sg_mark_end(sk_msg_elem(msg_pl, i)); } @@ -805,19 +825,21 @@ static int tls_push_record(struct sock *sk, int flags, i = msg_en->sg.start; sg_chain(rec->sg_aead_out, 2, &msg_en->sg.data[i]); - tls_make_aad(rec->aad_space, msg_pl->sg.size + prot->tail_size, - tls_ctx->tx.rec_seq, record_type, prot); + tls_make_aad(rec->aad_space, msg_pl->sg.size + prot->tail_size + + rec->zero_padding_len, tls_ctx->tx.rec_seq, + record_type, prot); tls_fill_prepend(tls_ctx, page_address(sg_page(&msg_en->sg.data[i])) + msg_en->sg.data[i].offset, - msg_pl->sg.size + prot->tail_size, - record_type); + msg_pl->sg.size + prot->tail_size + + rec->zero_padding_len, record_type); tls_ctx->pending_open_record_frags = false; rc = tls_do_encryption(sk, tls_ctx, ctx, req, - msg_pl->sg.size + prot->tail_size, i); + msg_pl->sg.size + prot->tail_size + + rec->zero_padding_len, i); if (rc < 0) { if (rc != -EINPROGRESS) { tls_err_abort(sk, -EBADMSG); @@ -1033,6 +1055,8 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg, unsigned char record_type = TLS_RECORD_TYPE_DATA; bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); bool eor = !(msg->msg_flags & MSG_MORE); + bool tls_13 = (prot->version == TLS_1_3_VERSION); + bool rec_zero_pad = eor && tls_13 && tls_ctx->tx_record_zero_pad; size_t try_to_copy; ssize_t copied = 0; struct sk_msg *msg_pl, *msg_en; @@ -1043,6 +1067,7 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg, int record_room; int num_zc = 0; int orig_size; + int max_zero_pad_len, zero_pad_len = 0; int ret = 0; if (!eor && (msg->msg_flags & MSG_EOR)) @@ -1085,8 +1110,19 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg, full_record = true; } + if (rec_zero_pad && !full_record) + zero_pad_len = record_room - try_to_copy; + + if (zero_pad_len > prot->tail_size) { + max_zero_pad_len = min(zero_pad_len, + tls_ctx->tx_record_zero_pad); + zero_pad_len = + get_random_u32_inclusive(0, max_zero_pad_len); + rec->zero_padding_len = zero_pad_len; + } + required_size = msg_pl->sg.size + try_to_copy + - prot->overhead_size; + prot->overhead_size + rec->zero_padding_len; if (!sk_stream_memory_free(sk)) goto wait_for_sndbuf; @@ -2555,6 +2591,7 @@ void tls_sw_release_resources_tx(struct sock *sk) struct tls_rec, list); list_del(&rec->list); sk_msg_free(sk, &rec->msg_plaintext); + kfree(rec->zero_padding); kfree(rec); } @@ -2562,6 +2599,7 @@ void tls_sw_release_resources_tx(struct sock *sk) list_del(&rec->list); sk_msg_free(sk, &rec->msg_encrypted); sk_msg_free(sk, &rec->msg_plaintext); + kfree(rec->zero_padding); kfree(rec); } -- 2.53.0