From patchwork Tue Feb 14 11:17:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sabrina Dubroca X-Patchwork-Id: 13139914 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E98A2C05027 for ; Tue, 14 Feb 2023 11:19:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231909AbjBNLTt convert rfc822-to-8bit (ORCPT ); Tue, 14 Feb 2023 06:19:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34600 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229848AbjBNLTr (ORCPT ); Tue, 14 Feb 2023 06:19:47 -0500 Received: from us-smtp-delivery-44.mimecast.com (us-smtp-delivery-44.mimecast.com [205.139.111.44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7EF64BBAD for ; Tue, 14 Feb 2023 03:19:46 -0800 (PST) Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-410-yByEjJv7M6y_MDimh--lMQ-1; Tue, 14 Feb 2023 06:19:38 -0500 X-MC-Unique: yByEjJv7M6y_MDimh--lMQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2AD103C0F191; Tue, 14 Feb 2023 11:19:38 +0000 (UTC) Received: from hog.localdomain (ovpn-195-113.brq.redhat.com [10.40.195.113]) by smtp.corp.redhat.com (Postfix) with ESMTP id 34D8240C1423; Tue, 14 Feb 2023 11:19:36 +0000 (UTC) From: Sabrina Dubroca To: netdev@vger.kernel.org Cc: Sabrina Dubroca , Vadim Fedorenko , Frantisek Krenzelok , Jakub Kicinski , Kuniyuki Iwashima , Apoorv Kothari , Boris Pismenny , John Fastabend , Shuah Khan , linux-kselftest@vger.kernel.org, Gal Pressman , Marcel Holtmann Subject: [PATCH net-next v2 1/5] tls: remove tls_context argument from tls_set_sw_offload Date: Tue, 14 Feb 2023 12:17:38 +0100 Message-Id: <95bbcbfd16dcc1f44fe1f8be69f4a946149027e4.1676052788.git.sd@queasysnail.net> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: queasysnail.net Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org It's not really needed since we end up refetching it as tls_ctx. We can also remove the NULL check, since we have already dereferenced ctx in do_tls_setsockopt_conf. v2: reverse xmas tree Signed-off-by: Sabrina Dubroca --- net/tls/tls.h | 2 +- net/tls/tls_device.c | 2 +- net/tls/tls_main.c | 4 ++-- net/tls/tls_sw.c | 17 +++++++---------- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/net/tls/tls.h b/net/tls/tls.h index 0e840a0c3437..34d0fe814600 100644 --- a/net/tls/tls.h +++ b/net/tls/tls.h @@ -90,7 +90,7 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval, unsigned int optlen); void tls_err_abort(struct sock *sk, int err); -int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx); +int tls_set_sw_offload(struct sock *sk, int tx); void tls_update_rx_zc_capable(struct tls_context *tls_ctx); void tls_sw_strparser_arm(struct sock *sk, struct tls_context *ctx); void tls_sw_strparser_done(struct tls_context *tls_ctx); diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index 6c593788dc25..c149f36b42ee 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c @@ -1291,7 +1291,7 @@ int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx) context->resync_nh_reset = 1; ctx->priv_ctx_rx = context; - rc = tls_set_sw_offload(sk, ctx, 0); + rc = tls_set_sw_offload(sk, 0); if (rc) goto release_ctx; diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 3735cb00905d..fb1da1780f50 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -772,7 +772,7 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXDEVICE); TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRTXDEVICE); } else { - rc = tls_set_sw_offload(sk, ctx, 1); + rc = tls_set_sw_offload(sk, 1); if (rc) goto err_crypto_info; TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXSW); @@ -786,7 +786,7 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXDEVICE); TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRRXDEVICE); } else { - rc = tls_set_sw_offload(sk, ctx, 0); + rc = tls_set_sw_offload(sk, 0); if (rc) goto err_crypto_info; TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXSW); diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 6d0a534b7baa..238bd18c5eb6 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -2465,25 +2465,22 @@ void tls_update_rx_zc_capable(struct tls_context *tls_ctx) tls_ctx->prot_info.version != TLS_1_3_VERSION; } -int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) +int tls_set_sw_offload(struct sock *sk, int tx) { - struct tls_context *tls_ctx = tls_get_ctx(sk); - struct tls_prot_info *prot = &tls_ctx->prot_info; - struct tls_crypto_info *crypto_info; + u16 nonce_size, tag_size, iv_size, rec_seq_size, salt_size; + char *iv, *rec_seq, *key, *salt, *cipher_name; struct tls_sw_context_tx *sw_ctx_tx = NULL; struct tls_sw_context_rx *sw_ctx_rx = NULL; + struct tls_context *ctx = tls_get_ctx(sk); + struct tls_crypto_info *crypto_info; struct cipher_context *cctx; + struct tls_prot_info *prot; struct crypto_aead **aead; - u16 nonce_size, tag_size, iv_size, rec_seq_size, salt_size; struct crypto_tfm *tfm; - char *iv, *rec_seq, *key, *salt, *cipher_name; size_t keysize; int rc = 0; - if (!ctx) { - rc = -EINVAL; - goto out; - } + prot = &ctx->prot_info; if (tx) { if (!ctx->priv_ctx_tx) { From patchwork Tue Feb 14 11:17:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sabrina Dubroca X-Patchwork-Id: 13139915 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5CECCC6379F for ; Tue, 14 Feb 2023 11:19:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232029AbjBNLTt convert rfc822-to-8bit (ORCPT ); Tue, 14 Feb 2023 06:19:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34642 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231814AbjBNLTt (ORCPT ); Tue, 14 Feb 2023 06:19:49 -0500 Received: from us-smtp-delivery-44.mimecast.com (us-smtp-delivery-44.mimecast.com [205.139.111.44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B59451C7EC for ; Tue, 14 Feb 2023 03:19:47 -0800 (PST) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-110-Molc4eK-OEaTT-3dYfIEDw-1; Tue, 14 Feb 2023 06:19:41 -0500 X-MC-Unique: Molc4eK-OEaTT-3dYfIEDw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 60FB285A5A3; Tue, 14 Feb 2023 11:19:40 +0000 (UTC) Received: from hog.localdomain (ovpn-195-113.brq.redhat.com [10.40.195.113]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6A23940C945A; Tue, 14 Feb 2023 11:19:38 +0000 (UTC) From: Sabrina Dubroca To: netdev@vger.kernel.org Cc: Sabrina Dubroca , Vadim Fedorenko , Frantisek Krenzelok , Jakub Kicinski , Kuniyuki Iwashima , Apoorv Kothari , Boris Pismenny , John Fastabend , Shuah Khan , linux-kselftest@vger.kernel.org, Gal Pressman , Marcel Holtmann Subject: [PATCH net-next v2 2/5] tls: block decryption when a rekey is pending Date: Tue, 14 Feb 2023 12:17:39 +0100 Message-Id: <4a9a82a0eaa47319e0e7a7fe525bd37f25b61cb5.1676052788.git.sd@queasysnail.net> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: queasysnail.net Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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. Signed-off-by: Sabrina Dubroca --- include/net/tls.h | 4 ++++ net/tls/tls_sw.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/include/net/tls.h b/include/net/tls.h index 154949c7b0c8..297732f23804 100644 --- a/include/net/tls.h +++ b/include/net/tls.h @@ -69,8 +69,11 @@ extern const struct tls_cipher_size_desc tls_cipher_size_desc[]; #define TLS_CRYPTO_INFO_READY(info) ((info)->cipher_type) +#define TLS_RECORD_TYPE_HANDSHAKE 0x16 #define TLS_RECORD_TYPE_DATA 0x17 +#define TLS_HANDSHAKE_KEYUPDATE 24 /* rfc8446 B.3: Key update */ + #define TLS_AAD_SPACE_SIZE 13 #define MAX_IV_SIZE 16 @@ -145,6 +148,7 @@ struct tls_sw_context_rx { struct tls_strparser strp; + bool key_update_pending; atomic_t decrypt_pending; /* protect crypto_wait with decrypt_pending*/ spinlock_t decrypt_compl_lock; diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 238bd18c5eb6..149a39d9a56a 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -1687,6 +1687,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); + + 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) { @@ -1706,6 +1733,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; } @@ -1957,6 +1988,12 @@ int tls_sw_recvmsg(struct sock *sk, struct tls_decrypt_arg darg; int to_decrypt, chunk; + /* a rekey is pending, let userspace deal with it */ + if (unlikely(ctx->key_update_pending)) { + err = -EKEYEXPIRED; + break; + } + err = tls_rx_rec_wait(sk, psock, flags & MSG_DONTWAIT, released); if (err <= 0) { @@ -2141,6 +2178,12 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, if (err < 0) return err; + /* a rekey is pending, let userspace deal with it */ + if (unlikely(ctx->key_update_pending)) { + err = -EKEYEXPIRED; + goto splice_read_end; + } + if (!skb_queue_empty(&ctx->rx_list)) { skb = __skb_dequeue(&ctx->rx_list); } else { @@ -2526,6 +2569,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) { From patchwork Tue Feb 14 11:17:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sabrina Dubroca X-Patchwork-Id: 13139919 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34D43C05027 for ; Tue, 14 Feb 2023 11:23:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229723AbjBNLWs convert rfc822-to-8bit (ORCPT ); Tue, 14 Feb 2023 06:22:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232560AbjBNLWT (ORCPT ); Tue, 14 Feb 2023 06:22:19 -0500 Received: from us-smtp-delivery-44.mimecast.com (unknown [207.211.30.44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 61CC3BBAD for ; Tue, 14 Feb 2023 03:22:17 -0800 (PST) Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-589-V7dIMDnTONirCgLvYhHXwg-1; Tue, 14 Feb 2023 06:19:43 -0500 X-MC-Unique: V7dIMDnTONirCgLvYhHXwg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 957883C0F18C; Tue, 14 Feb 2023 11:19:42 +0000 (UTC) Received: from hog.localdomain (ovpn-195-113.brq.redhat.com [10.40.195.113]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9E569408573E; Tue, 14 Feb 2023 11:19:40 +0000 (UTC) From: Sabrina Dubroca To: netdev@vger.kernel.org Cc: Sabrina Dubroca , Vadim Fedorenko , Frantisek Krenzelok , Jakub Kicinski , Kuniyuki Iwashima , Apoorv Kothari , Boris Pismenny , John Fastabend , Shuah Khan , linux-kselftest@vger.kernel.org, Gal Pressman , Marcel Holtmann Subject: [PATCH net-next v2 3/5] tls: implement rekey for TLS1.3 Date: Tue, 14 Feb 2023 12:17:40 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: queasysnail.net Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org This adds the possibility to change the key and IV when using TLS1.3. Changing the cipher or TLS version is not supported. Once we have updated the RX key, we can unblock the receive side. If the rekey fails, the context is unmodified and userspace is free to retry the update or close the socket. This change only affects tls_sw, since 1.3 offload isn't supported. v2: reverse xmas tree turn the alt_crypto_info into an else if don't modify the context when rekey fails Signed-off-by: Sabrina Dubroca --- net/tls/tls.h | 3 +- net/tls/tls_device.c | 2 +- net/tls/tls_main.c | 37 +++++++++--- net/tls/tls_sw.c | 134 +++++++++++++++++++++++++++++++------------ 4 files changed, 129 insertions(+), 47 deletions(-) diff --git a/net/tls/tls.h b/net/tls/tls.h index 34d0fe814600..6f9c85eaa9c5 100644 --- a/net/tls/tls.h +++ b/net/tls/tls.h @@ -90,7 +90,8 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval, unsigned int optlen); void tls_err_abort(struct sock *sk, int err); -int tls_set_sw_offload(struct sock *sk, int tx); +int tls_set_sw_offload(struct sock *sk, int tx, + struct tls_crypto_info *new_crypto_info); void tls_update_rx_zc_capable(struct tls_context *tls_ctx); void tls_sw_strparser_arm(struct sock *sk, struct tls_context *ctx); void tls_sw_strparser_done(struct tls_context *tls_ctx); diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index c149f36b42ee..1ad50c253dfe 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c @@ -1291,7 +1291,7 @@ int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx) context->resync_nh_reset = 1; ctx->priv_ctx_rx = context; - rc = tls_set_sw_offload(sk, 0); + rc = tls_set_sw_offload(sk, 0, NULL); if (rc) goto release_ctx; diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index fb1da1780f50..24a4bdb54a53 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -669,9 +669,11 @@ static int tls_getsockopt(struct sock *sk, int level, int optname, static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, unsigned int optlen, int tx) { - struct tls_crypto_info *crypto_info; - struct tls_crypto_info *alt_crypto_info; + struct tls_crypto_info *crypto_info, *alt_crypto_info; + struct tls_crypto_info *old_crypto_info = NULL; struct tls_context *ctx = tls_get_ctx(sk); + union tls_crypto_context tmp = {}; + bool update = false; size_t optsize; int rc = 0; int conf; @@ -687,9 +689,17 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, alt_crypto_info = &ctx->crypto_send.info; } - /* Currently we don't support set crypto info more than one time */ - if (TLS_CRYPTO_INFO_READY(crypto_info)) - return -EBUSY; + if (TLS_CRYPTO_INFO_READY(crypto_info)) { + /* Currently we only support setting crypto info more + * than one time for TLS 1.3 + */ + if (crypto_info->version != TLS_1_3_VERSION) + return -EBUSY; + + update = true; + old_crypto_info = crypto_info; + crypto_info = &tmp.info; + } rc = copy_from_sockptr(crypto_info, optval, sizeof(*crypto_info)); if (rc) { @@ -704,8 +714,15 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, goto err_crypto_info; } - /* Ensure that TLS version and ciphers are same in both directions */ - if (TLS_CRYPTO_INFO_READY(alt_crypto_info)) { + if (update) { + /* Ensure that TLS version and ciphers are not modified */ + if (crypto_info->version != old_crypto_info->version || + crypto_info->cipher_type != old_crypto_info->cipher_type) { + rc = -EINVAL; + goto err_crypto_info; + } + } else if (TLS_CRYPTO_INFO_READY(alt_crypto_info)) { + /* Ensure that TLS version and ciphers are same in both directions */ if (alt_crypto_info->version != crypto_info->version || alt_crypto_info->cipher_type != crypto_info->cipher_type) { rc = -EINVAL; @@ -772,7 +789,8 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXDEVICE); TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRTXDEVICE); } else { - rc = tls_set_sw_offload(sk, 1); + rc = tls_set_sw_offload(sk, 1, + update ? crypto_info : NULL); if (rc) goto err_crypto_info; TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXSW); @@ -786,7 +804,8 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXDEVICE); TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRRXDEVICE); } else { - rc = tls_set_sw_offload(sk, 0); + rc = tls_set_sw_offload(sk, 0, + update ? crypto_info : NULL); if (rc) goto err_crypto_info; TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXSW); diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 149a39d9a56a..a35b3bfe5b47 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -2508,23 +2508,50 @@ void tls_update_rx_zc_capable(struct tls_context *tls_ctx) tls_ctx->prot_info.version != TLS_1_3_VERSION; } -int tls_set_sw_offload(struct sock *sk, int tx) +static void tls_finish_key_update(struct tls_context *tls_ctx) +{ + struct tls_sw_context_rx *ctx = tls_ctx->priv_ctx_rx; + + ctx->key_update_pending = false; +} + +int tls_set_sw_offload(struct sock *sk, int tx, + struct tls_crypto_info *new_crypto_info) { u16 nonce_size, tag_size, iv_size, rec_seq_size, salt_size; + struct tls_crypto_info *crypto_info, *src_crypto_info; char *iv, *rec_seq, *key, *salt, *cipher_name; struct tls_sw_context_tx *sw_ctx_tx = NULL; struct tls_sw_context_rx *sw_ctx_rx = NULL; struct tls_context *ctx = tls_get_ctx(sk); - struct tls_crypto_info *crypto_info; + size_t keysize, crypto_info_size; struct cipher_context *cctx; struct tls_prot_info *prot; struct crypto_aead **aead; struct crypto_tfm *tfm; - size_t keysize; int rc = 0; prot = &ctx->prot_info; + if (new_crypto_info) { + /* non-NULL new_crypto_info means rekey */ + src_crypto_info = new_crypto_info; + if (tx) { + sw_ctx_tx = ctx->priv_ctx_tx; + crypto_info = &ctx->crypto_send.info; + cctx = &ctx->tx; + aead = &sw_ctx_tx->aead_send; + sw_ctx_tx = NULL; + } else { + sw_ctx_rx = ctx->priv_ctx_rx; + crypto_info = &ctx->crypto_recv.info; + cctx = &ctx->rx; + aead = &sw_ctx_rx->aead_recv; + sw_ctx_rx = NULL; + } + goto skip_init; + } + if (tx) { if (!ctx->priv_ctx_tx) { sw_ctx_tx = kzalloc(sizeof(*sw_ctx_tx), GFP_KERNEL); @@ -2571,12 +2598,15 @@ int tls_set_sw_offload(struct sock *sk, int tx) aead = &sw_ctx_rx->aead_recv; sw_ctx_rx->key_update_pending = false; } + src_crypto_info = crypto_info; +skip_init: switch (crypto_info->cipher_type) { case TLS_CIPHER_AES_GCM_128: { struct tls12_crypto_info_aes_gcm_128 *gcm_128_info; - gcm_128_info = (void *)crypto_info; + crypto_info_size = sizeof(struct tls12_crypto_info_aes_gcm_128); + gcm_128_info = (void *)src_crypto_info; 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; @@ -2593,7 +2623,8 @@ int tls_set_sw_offload(struct sock *sk, int tx) case TLS_CIPHER_AES_GCM_256: { struct tls12_crypto_info_aes_gcm_256 *gcm_256_info; - gcm_256_info = (void *)crypto_info; + crypto_info_size = sizeof(struct tls12_crypto_info_aes_gcm_256); + gcm_256_info = (void *)src_crypto_info; nonce_size = TLS_CIPHER_AES_GCM_256_IV_SIZE; tag_size = TLS_CIPHER_AES_GCM_256_TAG_SIZE; iv_size = TLS_CIPHER_AES_GCM_256_IV_SIZE; @@ -2610,7 +2641,8 @@ int tls_set_sw_offload(struct sock *sk, int tx) case TLS_CIPHER_AES_CCM_128: { struct tls12_crypto_info_aes_ccm_128 *ccm_128_info; - ccm_128_info = (void *)crypto_info; + crypto_info_size = sizeof(struct tls12_crypto_info_aes_ccm_128); + ccm_128_info = (void *)src_crypto_info; nonce_size = TLS_CIPHER_AES_CCM_128_IV_SIZE; tag_size = TLS_CIPHER_AES_CCM_128_TAG_SIZE; iv_size = TLS_CIPHER_AES_CCM_128_IV_SIZE; @@ -2627,7 +2659,8 @@ int tls_set_sw_offload(struct sock *sk, int tx) case TLS_CIPHER_CHACHA20_POLY1305: { struct tls12_crypto_info_chacha20_poly1305 *chacha20_poly1305_info; - chacha20_poly1305_info = (void *)crypto_info; + crypto_info_size = sizeof(struct tls12_crypto_info_chacha20_poly1305); + chacha20_poly1305_info = (void *)src_crypto_info; nonce_size = 0; tag_size = TLS_CIPHER_CHACHA20_POLY1305_TAG_SIZE; iv_size = TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE; @@ -2644,7 +2677,8 @@ int tls_set_sw_offload(struct sock *sk, int tx) case TLS_CIPHER_SM4_GCM: { struct tls12_crypto_info_sm4_gcm *sm4_gcm_info; - sm4_gcm_info = (void *)crypto_info; + crypto_info_size = sizeof(struct tls12_crypto_info_sm4_gcm); + sm4_gcm_info = (void *)src_crypto_info; nonce_size = TLS_CIPHER_SM4_GCM_IV_SIZE; tag_size = TLS_CIPHER_SM4_GCM_TAG_SIZE; iv_size = TLS_CIPHER_SM4_GCM_IV_SIZE; @@ -2661,7 +2695,8 @@ int tls_set_sw_offload(struct sock *sk, int tx) case TLS_CIPHER_SM4_CCM: { struct tls12_crypto_info_sm4_ccm *sm4_ccm_info; - sm4_ccm_info = (void *)crypto_info; + crypto_info_size = sizeof(struct tls12_crypto_info_sm4_ccm); + sm4_ccm_info = (void *)src_crypto_info; nonce_size = TLS_CIPHER_SM4_CCM_IV_SIZE; tag_size = TLS_CIPHER_SM4_CCM_TAG_SIZE; iv_size = TLS_CIPHER_SM4_CCM_IV_SIZE; @@ -2678,7 +2713,8 @@ int tls_set_sw_offload(struct sock *sk, int tx) case TLS_CIPHER_ARIA_GCM_128: { struct tls12_crypto_info_aria_gcm_128 *aria_gcm_128_info; - aria_gcm_128_info = (void *)crypto_info; + crypto_info_size = sizeof(struct tls12_crypto_info_aria_gcm_128); + aria_gcm_128_info = (void *)src_crypto_info; nonce_size = TLS_CIPHER_ARIA_GCM_128_IV_SIZE; tag_size = TLS_CIPHER_ARIA_GCM_128_TAG_SIZE; iv_size = TLS_CIPHER_ARIA_GCM_128_IV_SIZE; @@ -2695,7 +2731,8 @@ int tls_set_sw_offload(struct sock *sk, int tx) case TLS_CIPHER_ARIA_GCM_256: { struct tls12_crypto_info_aria_gcm_256 *gcm_256_info; - gcm_256_info = (void *)crypto_info; + crypto_info_size = sizeof(struct tls12_crypto_info_aria_gcm_256); + gcm_256_info = (void *)src_crypto_info; nonce_size = TLS_CIPHER_ARIA_GCM_256_IV_SIZE; tag_size = TLS_CIPHER_ARIA_GCM_256_TAG_SIZE; iv_size = TLS_CIPHER_ARIA_GCM_256_IV_SIZE; @@ -2739,19 +2776,18 @@ int tls_set_sw_offload(struct sock *sk, int tx) prot->tag_size + prot->tail_size; prot->iv_size = iv_size; prot->salt_size = salt_size; - cctx->iv = kmalloc(iv_size + salt_size, GFP_KERNEL); - if (!cctx->iv) { - rc = -ENOMEM; - goto free_priv; - } - /* Note: 128 & 256 bit salt are the same size */ - prot->rec_seq_size = rec_seq_size; - memcpy(cctx->iv, salt, salt_size); - memcpy(cctx->iv + salt_size, iv, iv_size); - cctx->rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL); - if (!cctx->rec_seq) { - rc = -ENOMEM; - goto free_iv; + if (!new_crypto_info) { + cctx->iv = kmalloc(iv_size + salt_size, GFP_KERNEL); + if (!cctx->iv) { + rc = -ENOMEM; + goto free_priv; + } + + cctx->rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL); + if (!cctx->rec_seq) { + rc = -ENOMEM; + goto free_iv; + } } if (!*aead) { @@ -2765,14 +2801,24 @@ int tls_set_sw_offload(struct sock *sk, int tx) ctx->push_pending_record = tls_sw_push_pending_record; + /* setkey is the last operation that could fail during a + * rekey. if it succeeds, we can start modifying the + * context. + */ rc = crypto_aead_setkey(*aead, key, keysize); + if (rc) { + if (new_crypto_info) + goto out; + else + goto free_aead; + } - if (rc) - goto free_aead; - - rc = crypto_aead_setauthsize(*aead, prot->tag_size); - if (rc) - goto free_aead; + if (!new_crypto_info) { + rc = crypto_aead_setauthsize(*aead, prot->tag_size); + if (rc) { + goto free_aead; + } + } if (sw_ctx_rx) { tfm = crypto_aead_tfm(sw_ctx_rx->aead_recv); @@ -2787,6 +2833,20 @@ int tls_set_sw_offload(struct sock *sk, int tx) goto free_aead; } + /* Note: 128 & 256 bit salt are the same size */ + prot->rec_seq_size = rec_seq_size; + memcpy(cctx->iv, salt, salt_size); + memcpy(cctx->iv + salt_size, iv, iv_size); + + if (new_crypto_info) { + memcpy(cctx->rec_seq, rec_seq, rec_seq_size); + + memcpy(crypto_info, new_crypto_info, crypto_info_size); + memzero_explicit(new_crypto_info, crypto_info_size); + if (!tx) + tls_finish_key_update(ctx); + } + goto out; free_aead: @@ -2799,12 +2859,14 @@ int tls_set_sw_offload(struct sock *sk, int tx) kfree(cctx->iv); cctx->iv = NULL; free_priv: - if (tx) { - kfree(ctx->priv_ctx_tx); - ctx->priv_ctx_tx = NULL; - } else { - kfree(ctx->priv_ctx_rx); - ctx->priv_ctx_rx = NULL; + if (!new_crypto_info) { + if (tx) { + kfree(ctx->priv_ctx_tx); + ctx->priv_ctx_tx = NULL; + } else { + kfree(ctx->priv_ctx_rx); + ctx->priv_ctx_rx = NULL; + } } out: return rc; From patchwork Tue Feb 14 11:17:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sabrina Dubroca X-Patchwork-Id: 13139917 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 157A3C05027 for ; Tue, 14 Feb 2023 11:21:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232094AbjBNLVJ convert rfc822-to-8bit (ORCPT ); Tue, 14 Feb 2023 06:21:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231442AbjBNLVI (ORCPT ); Tue, 14 Feb 2023 06:21:08 -0500 Received: from us-smtp-delivery-44.mimecast.com (us-smtp-delivery-44.mimecast.com [205.139.111.44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6A622BBAD for ; Tue, 14 Feb 2023 03:21:07 -0800 (PST) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-651-L-YJ208QNV6HWN_AQVUleA-1; Tue, 14 Feb 2023 06:19:46 -0500 X-MC-Unique: L-YJ208QNV6HWN_AQVUleA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2C5B2800B24; Tue, 14 Feb 2023 11:19:45 +0000 (UTC) Received: from hog.localdomain (ovpn-195-113.brq.redhat.com [10.40.195.113]) by smtp.corp.redhat.com (Postfix) with ESMTP id D5B9A40C945A; Tue, 14 Feb 2023 11:19:42 +0000 (UTC) From: Sabrina Dubroca To: netdev@vger.kernel.org Cc: Sabrina Dubroca , Vadim Fedorenko , Frantisek Krenzelok , Jakub Kicinski , Kuniyuki Iwashima , Apoorv Kothari , Boris Pismenny , John Fastabend , Shuah Khan , linux-kselftest@vger.kernel.org, Gal Pressman , Marcel Holtmann Subject: [PATCH net-next v2 4/5] selftests: tls: add key_generation argument to tls_crypto_info_init Date: Tue, 14 Feb 2023 12:17:41 +0100 Message-Id: <798855c710dcbead2a9d32edb61a64cb0054fe60.1676052788.git.sd@queasysnail.net> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: queasysnail.net Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org This allows us to generate different keys, so that we can test that rekey is using the correct one. Signed-off-by: Sabrina Dubroca --- tools/testing/selftests/net/tls.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c index 2cbb12736596..5f3adb28fee1 100644 --- a/tools/testing/selftests/net/tls.c +++ b/tools/testing/selftests/net/tls.c @@ -38,9 +38,11 @@ struct tls_crypto_info_keys { }; static void tls_crypto_info_init(uint16_t tls_version, uint16_t cipher_type, - struct tls_crypto_info_keys *tls12) + struct tls_crypto_info_keys *tls12, + char key_generation) { - memset(tls12, 0, sizeof(*tls12)); + memset(tls12, key_generation, sizeof(*tls12)); + memset(tls12, 0, sizeof(struct tls_crypto_info)); switch (cipher_type) { case TLS_CIPHER_CHACHA20_POLY1305: @@ -312,7 +314,7 @@ FIXTURE_SETUP(tls) int ret; tls_crypto_info_init(variant->tls_version, variant->cipher_type, - &tls12); + &tls12, 0); ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls); @@ -1071,7 +1073,7 @@ TEST_F(tls, bidir) struct tls_crypto_info_keys tls12; tls_crypto_info_init(variant->tls_version, variant->cipher_type, - &tls12); + &tls12, 0); ret = setsockopt(self->fd, SOL_TLS, TLS_RX, &tls12, tls12.len); @@ -1479,7 +1481,7 @@ FIXTURE_SETUP(tls_err) int ret; tls_crypto_info_init(variant->tls_version, TLS_CIPHER_AES_GCM_128, - &tls12); + &tls12, 0); ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls); ulp_sock_pair(_metadata, &self->fd2, &self->cfd2, &self->notls); @@ -1771,7 +1773,7 @@ TEST(tls_v6ops) { int sfd, ret, fd; socklen_t len, len2; - tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_128, &tls12); + tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_128, &tls12, 0); addr.sin6_family = AF_INET6; addr.sin6_addr = in6addr_any; From patchwork Tue Feb 14 11:17:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sabrina Dubroca X-Patchwork-Id: 13139916 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16720C05027 for ; Tue, 14 Feb 2023 11:20:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231842AbjBNLUF convert rfc822-to-8bit (ORCPT ); Tue, 14 Feb 2023 06:20:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232531AbjBNLT5 (ORCPT ); Tue, 14 Feb 2023 06:19:57 -0500 Received: from us-smtp-delivery-44.mimecast.com (us-smtp-delivery-44.mimecast.com [205.139.111.44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC14F1420E for ; Tue, 14 Feb 2023 03:19:53 -0800 (PST) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-248-uA1s4dEUNAS_Qx29qX9l9Q-1; Tue, 14 Feb 2023 06:19:48 -0500 X-MC-Unique: uA1s4dEUNAS_Qx29qX9l9Q-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 62536101A52E; Tue, 14 Feb 2023 11:19:47 +0000 (UTC) Received: from hog.localdomain (ovpn-195-113.brq.redhat.com [10.40.195.113]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6BC0340C1423; Tue, 14 Feb 2023 11:19:45 +0000 (UTC) From: Sabrina Dubroca To: netdev@vger.kernel.org Cc: Sabrina Dubroca , Vadim Fedorenko , Frantisek Krenzelok , Jakub Kicinski , Kuniyuki Iwashima , Apoorv Kothari , Boris Pismenny , John Fastabend , Shuah Khan , linux-kselftest@vger.kernel.org, Gal Pressman , Marcel Holtmann Subject: [PATCH net-next v2 5/5] selftests: tls: add rekey tests Date: Tue, 14 Feb 2023 12:17:42 +0100 Message-Id: <6fd00910e368e98382783a25ef852197b74ca5ba.1676052788.git.sd@queasysnail.net> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: queasysnail.net Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org v2: add rekey_fail test (reject changing the version/cipher) Signed-off-by: Sabrina Dubroca --- tools/testing/selftests/net/tls.c | 322 ++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c index 5f3adb28fee1..098d52859521 100644 --- a/tools/testing/selftests/net/tls.c +++ b/tools/testing/selftests/net/tls.c @@ -1453,6 +1453,328 @@ TEST_F(tls, shutdown_reuse) EXPECT_EQ(errno, EISCONN); } +#define TLS_RECORD_TYPE_HANDSHAKE 0x16 +/* key_update, length 1, update_not_requested */ +static const char key_update_msg[] = "\x18\x00\x00\x01\x00"; +static void tls_send_keyupdate(struct __test_metadata *_metadata, int fd) +{ + size_t len = sizeof(key_update_msg); + + EXPECT_EQ(tls_send_cmsg(fd, TLS_RECORD_TYPE_HANDSHAKE, + (char *)key_update_msg, len, 0), + len); +} + +static void tls_recv_keyupdate(struct __test_metadata *_metadata, int fd, int flags) +{ + char buf[100]; + + EXPECT_EQ(tls_recv_cmsg(_metadata, fd, TLS_RECORD_TYPE_HANDSHAKE, buf, sizeof(buf), flags), + sizeof(key_update_msg)); + EXPECT_EQ(memcmp(buf, key_update_msg, sizeof(key_update_msg)), 0); +} + +/* set the key to 0 then 1 for RX, immediately to 1 for TX */ +TEST_F(tls_basic, rekey_rx) +{ + struct tls_crypto_info_keys tls12_0, tls12_1; + char const *test_str = "test_message"; + int send_len = strlen(test_str) + 1; + char buf[20]; + int ret; + + if (self->notls) + return; + + tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128, + &tls12_0, 0); + tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128, + &tls12_1, 1); + + + ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_1, tls12_1.len); + ASSERT_EQ(ret, 0); + + ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_0, tls12_0.len); + ASSERT_EQ(ret, 0); + + ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_1, tls12_1.len); + EXPECT_EQ(ret, 0); + + EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len); + EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); + EXPECT_EQ(memcmp(buf, test_str, send_len), 0); +} + +/* set the key to 0 then 1 for TX, immediately to 1 for RX */ +TEST_F(tls_basic, rekey_tx) +{ + struct tls_crypto_info_keys tls12_0, tls12_1; + char const *test_str = "test_message"; + int send_len = strlen(test_str) + 1; + char buf[20]; + int ret; + + if (self->notls) + return; + + tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128, + &tls12_0, 0); + tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128, + &tls12_1, 1); + + + ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_0, tls12_0.len); + ASSERT_EQ(ret, 0); + + ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_1, tls12_1.len); + ASSERT_EQ(ret, 0); + + ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_1, tls12_1.len); + EXPECT_EQ(ret, 0); + + EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len); + EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); + EXPECT_EQ(memcmp(buf, test_str, send_len), 0); +} + +TEST_F(tls, rekey) +{ + char const *test_str_1 = "test_message_before_rekey"; + char const *test_str_2 = "test_message_after_rekey"; + struct tls_crypto_info_keys tls12; + int send_len; + char buf[100]; + + if (variant->tls_version != TLS_1_3_VERSION) + return; + + /* initial send/recv */ + send_len = strlen(test_str_1) + 1; + EXPECT_EQ(send(self->fd, test_str_1, send_len, 0), send_len); + EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); + EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0); + + /* update TX key */ + tls_send_keyupdate(_metadata, self->fd); + tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1); + EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0); + + /* send after rekey */ + send_len = strlen(test_str_2) + 1; + EXPECT_EQ(send(self->fd, test_str_2, send_len, 0), send_len); + + /* can't receive the KeyUpdate without a control message */ + EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1); + + /* get KeyUpdate */ + tls_recv_keyupdate(_metadata, self->cfd, 0); + + /* recv blocking -> -EKEYEXPIRED */ + EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), 0), -1); + EXPECT_EQ(errno, EKEYEXPIRED); + + /* recv non-blocking -> -EKEYEXPIRED */ + EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_DONTWAIT), -1); + EXPECT_EQ(errno, EKEYEXPIRED); + + /* update RX key */ + EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0); + + /* recv after rekey */ + EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1); + EXPECT_EQ(memcmp(buf, test_str_2, send_len), 0); +} + +TEST_F(tls, rekey_fail) +{ + char const *test_str_1 = "test_message_before_rekey"; + char const *test_str_2 = "test_message_after_rekey"; + struct tls_crypto_info_keys tls12; + int send_len; + char buf[100]; + + if (variant->tls_version != TLS_1_3_VERSION) + return; + + /* initial send/recv */ + send_len = strlen(test_str_1) + 1; + EXPECT_EQ(send(self->fd, test_str_1, send_len, 0), send_len); + EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); + EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0); + + /* update TX key */ + tls_send_keyupdate(_metadata, self->fd); + + /* successful update */ + tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1); + EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0); + + /* invalid update: change of version */ + tls_crypto_info_init(TLS_1_2_VERSION, variant->cipher_type, &tls12, 1); + EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), -1); + EXPECT_EQ(errno, EINVAL); + + /* invalid update: change of cipher */ + if (variant->cipher_type == TLS_CIPHER_AES_GCM_256) + tls_crypto_info_init(variant->tls_version, TLS_CIPHER_CHACHA20_POLY1305, &tls12, 1); + else + tls_crypto_info_init(variant->tls_version, TLS_CIPHER_AES_GCM_256, &tls12, 1); + EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), -1); + EXPECT_EQ(errno, EINVAL); + + /* send after rekey, the invalid updates shouldn't have an effect */ + send_len = strlen(test_str_2) + 1; + EXPECT_EQ(send(self->fd, test_str_2, send_len, 0), send_len); + + /* can't receive the KeyUpdate without a control message */ + EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1); + + /* get KeyUpdate */ + tls_recv_keyupdate(_metadata, self->cfd, 0); + + /* recv blocking -> -EKEYEXPIRED */ + EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), 0), -1); + EXPECT_EQ(errno, EKEYEXPIRED); + + /* recv non-blocking -> -EKEYEXPIRED */ + EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_DONTWAIT), -1); + EXPECT_EQ(errno, EKEYEXPIRED); + + /* update RX key */ + tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1); + EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0); + + /* recv after rekey */ + EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1); + EXPECT_EQ(memcmp(buf, test_str_2, send_len), 0); +} + +TEST_F(tls, rekey_peek) +{ + char const *test_str_1 = "test_message_before_rekey"; + struct tls_crypto_info_keys tls12; + int send_len; + char buf[100]; + + if (variant->tls_version != TLS_1_3_VERSION) + return; + + send_len = strlen(test_str_1) + 1; + EXPECT_EQ(send(self->fd, test_str_1, send_len, 0), send_len); + + /* update TX key */ + tls_send_keyupdate(_metadata, self->fd); + tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1); + EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0); + + EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_PEEK), send_len); + EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0); + + EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len); + EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0); + + /* can't receive the KeyUpdate without a control message */ + EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_PEEK), -1); + + /* peek KeyUpdate */ + tls_recv_keyupdate(_metadata, self->cfd, MSG_PEEK); + + /* get KeyUpdate */ + tls_recv_keyupdate(_metadata, self->cfd, 0); + + /* update RX key */ + EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0); +} + +TEST_F(tls, splice_rekey) +{ + int send_len = TLS_PAYLOAD_MAX_LEN / 2; + char mem_send[TLS_PAYLOAD_MAX_LEN]; + char mem_recv[TLS_PAYLOAD_MAX_LEN]; + struct tls_crypto_info_keys tls12; + int p[2]; + + if (variant->tls_version != TLS_1_3_VERSION) + return; + + memrnd(mem_send, sizeof(mem_send)); + + ASSERT_GE(pipe(p), 0); + EXPECT_EQ(send(self->fd, mem_send, send_len, 0), send_len); + + /* update TX key */ + tls_send_keyupdate(_metadata, self->fd); + tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1); + EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0); + + EXPECT_EQ(send(self->fd, mem_send, send_len, 0), send_len); + + EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), send_len); + EXPECT_EQ(read(p[0], mem_recv, send_len), send_len); + EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0); + + /* can't splice the KeyUpdate */ + EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), -1); + EXPECT_EQ(errno, EINVAL); + + /* peek KeyUpdate */ + tls_recv_keyupdate(_metadata, self->cfd, MSG_PEEK); + + /* get KeyUpdate */ + tls_recv_keyupdate(_metadata, self->cfd, 0); + + /* can't splice before updating the key */ + EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), -1); + EXPECT_EQ(errno, EKEYEXPIRED); + + /* update RX key */ + EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0); + + EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), send_len); + EXPECT_EQ(read(p[0], mem_recv, send_len), send_len); + EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0); +} + +TEST_F(tls, rekey_getsockopt) +{ + struct tls_crypto_info_keys tls12; + struct tls_crypto_info_keys tls12_get; + socklen_t len; + + tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 0); + + len = tls12.len; + EXPECT_EQ(getsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_get, &len), 0); + EXPECT_EQ(len, tls12.len); + EXPECT_EQ(memcmp(&tls12_get, &tls12, tls12.len), 0); + + len = tls12.len; + EXPECT_EQ(getsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_get, &len), 0); + EXPECT_EQ(len, tls12.len); + EXPECT_EQ(memcmp(&tls12_get, &tls12, tls12.len), 0); + + if (variant->tls_version != TLS_1_3_VERSION) + return; + + tls_send_keyupdate(_metadata, self->fd); + tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1); + EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0); + + tls_recv_keyupdate(_metadata, self->cfd, 0); + EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0); + + len = tls12.len; + EXPECT_EQ(getsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_get, &len), 0); + EXPECT_EQ(len, tls12.len); + EXPECT_EQ(memcmp(&tls12_get, &tls12, tls12.len), 0); + + len = tls12.len; + EXPECT_EQ(getsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_get, &len), 0); + EXPECT_EQ(len, tls12.len); + EXPECT_EQ(memcmp(&tls12_get, &tls12, tls12.len), 0); +} + FIXTURE(tls_err) { int fd, cfd;