On Wed, Aug 09, 2023 at 02:58:51PM +0200, Sabrina Dubroca wrote:
When a TLS handshake record carrying a KeyUpdate message is received, all subsequent records will be encrypted with a new key. We need to stop decrypting incoming records with the old key, and wait until userspace provides a new key.
Make a note of this in the RX context just after decrypting that record, and stop recvmsg/splice calls with EKEYEXPIRED until the new key is available.
v3:
- move key_update_pending check into tls_rx_rec_wait (Jakub)
- TLS_RECORD_TYPE_HANDSHAKE was added to include/net/tls_prot.h by the tls handshake series, drop that from this patch
- move key_update_pending into an existing hole
Signed-off-by: Sabrina Dubroca sd@queasysnail.net
include/net/tls.h | 3 +++ net/tls/tls_sw.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+)
diff --git a/include/net/tls.h b/include/net/tls.h index 06fca9160346..219a4f38c0e4 100644 --- a/include/net/tls.h +++ b/include/net/tls.h @@ -69,6 +69,8 @@ extern const struct tls_cipher_size_desc tls_cipher_size_desc[]; #define TLS_CRYPTO_INFO_READY(info) ((info)->cipher_type) +#define TLS_HANDSHAKE_KEYUPDATE 24 /* rfc8446 B.3: Key update */
#define TLS_AAD_SPACE_SIZE 13 #define MAX_IV_SIZE 16 @@ -141,6 +143,7 @@ struct tls_sw_context_rx { u8 async_capable:1; u8 zc_capable:1; u8 reader_contended:1;
- bool key_update_pending;
Hi Sabrina,
Would it make sense for this to be
u8 key_update_pending:1;
struct tls_strparser strp; diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 2ca0eb90a2a5..497f56c5f169 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -1293,6 +1293,10 @@ tls_rx_rec_wait(struct sock *sk, struct sk_psock *psock, bool nonblock, DEFINE_WAIT_FUNC(wait, woken_wake_function); long timeo;
- /* a rekey is pending, let userspace deal with it */
- if (unlikely(ctx->key_update_pending))
return -EKEYEXPIRED;
- timeo = sock_rcvtimeo(sk, nonblock);
while (!tls_strp_msg_ready(ctx)) { @@ -1689,6 +1693,33 @@ tls_decrypt_device(struct sock *sk, struct msghdr *msg, return 1; } +static int tls_check_pending_rekey(struct sock *sk, struct sk_buff *skb) +{
- const struct tls_msg *tlm = tls_msg(skb);
- const struct strp_msg *rxm = strp_msg(skb);
nit: reverse xmas tree
- if (tlm->control == TLS_RECORD_TYPE_HANDSHAKE) {
char hs_type;
int err;
if (rxm->full_len < 1)
return -EINVAL;
err = skb_copy_bits(skb, rxm->offset, &hs_type, 1);
if (err < 0)
return err;
if (hs_type == TLS_HANDSHAKE_KEYUPDATE) {
struct tls_context *ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *rx_ctx = ctx->priv_ctx_rx;
rx_ctx->key_update_pending = true;
}
- }
- return 0;
+}
static int tls_rx_one_record(struct sock *sk, struct msghdr *msg, struct tls_decrypt_arg *darg) { @@ -1708,6 +1739,10 @@ static int tls_rx_one_record(struct sock *sk, struct msghdr *msg, rxm->full_len -= prot->overhead_size; tls_advance_record_sn(sk, prot, &tls_ctx->rx);
- err = tls_check_pending_rekey(sk, darg->skb);
- if (err < 0)
return err;
- return 0;
} @@ -2642,6 +2677,7 @@ int tls_set_sw_offload(struct sock *sk, int tx) skb_queue_head_init(&sw_ctx_rx->rx_list); skb_queue_head_init(&sw_ctx_rx->async_hold); aead = &sw_ctx_rx->aead_recv;
}sw_ctx_rx->key_update_pending = false;
switch (crypto_info->cipher_type) { -- 2.40.1