18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2016-2017, Mellanox Technologies. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2016-2017, Dave Watson <davejwatson@fb.com>. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) 2016-2017, Lance Chao <lancerchao@fb.com>. All rights reserved. 58c2ecf20Sopenharmony_ci * Copyright (c) 2016, Fridolin Pokorny <fridolin.pokorny@gmail.com>. All rights reserved. 68c2ecf20Sopenharmony_ci * Copyright (c) 2016, Nikos Mavrogiannopoulos <nmav@gnutls.org>. All rights reserved. 78c2ecf20Sopenharmony_ci * Copyright (c) 2018, Covalent IO, Inc. http://covalent.io 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 108c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 118c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 128c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 138c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 168c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 178c2ecf20Sopenharmony_ci * conditions are met: 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 208c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 218c2ecf20Sopenharmony_ci * disclaimer. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 248c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 258c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 268c2ecf20Sopenharmony_ci * provided with the distribution. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 298c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 308c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 318c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 328c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 338c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 348c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 358c2ecf20Sopenharmony_ci * SOFTWARE. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include <linux/bug.h> 398c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 408c2ecf20Sopenharmony_ci#include <linux/module.h> 418c2ecf20Sopenharmony_ci#include <linux/splice.h> 428c2ecf20Sopenharmony_ci#include <crypto/aead.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#include <net/strparser.h> 458c2ecf20Sopenharmony_ci#include <net/tls.h> 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cinoinline void tls_err_abort(struct sock *sk, int err) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci WARN_ON_ONCE(err >= 0); 508c2ecf20Sopenharmony_ci /* sk->sk_err should contain a positive error code. */ 518c2ecf20Sopenharmony_ci sk->sk_err = -err; 528c2ecf20Sopenharmony_ci sk->sk_error_report(sk); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic int __skb_nsg(struct sk_buff *skb, int offset, int len, 568c2ecf20Sopenharmony_ci unsigned int recursion_level) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci int start = skb_headlen(skb); 598c2ecf20Sopenharmony_ci int i, chunk = start - offset; 608c2ecf20Sopenharmony_ci struct sk_buff *frag_iter; 618c2ecf20Sopenharmony_ci int elt = 0; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (unlikely(recursion_level >= 24)) 648c2ecf20Sopenharmony_ci return -EMSGSIZE; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci if (chunk > 0) { 678c2ecf20Sopenharmony_ci if (chunk > len) 688c2ecf20Sopenharmony_ci chunk = len; 698c2ecf20Sopenharmony_ci elt++; 708c2ecf20Sopenharmony_ci len -= chunk; 718c2ecf20Sopenharmony_ci if (len == 0) 728c2ecf20Sopenharmony_ci return elt; 738c2ecf20Sopenharmony_ci offset += chunk; 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 778c2ecf20Sopenharmony_ci int end; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]); 828c2ecf20Sopenharmony_ci chunk = end - offset; 838c2ecf20Sopenharmony_ci if (chunk > 0) { 848c2ecf20Sopenharmony_ci if (chunk > len) 858c2ecf20Sopenharmony_ci chunk = len; 868c2ecf20Sopenharmony_ci elt++; 878c2ecf20Sopenharmony_ci len -= chunk; 888c2ecf20Sopenharmony_ci if (len == 0) 898c2ecf20Sopenharmony_ci return elt; 908c2ecf20Sopenharmony_ci offset += chunk; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci start = end; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (unlikely(skb_has_frag_list(skb))) { 968c2ecf20Sopenharmony_ci skb_walk_frags(skb, frag_iter) { 978c2ecf20Sopenharmony_ci int end, ret; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci end = start + frag_iter->len; 1028c2ecf20Sopenharmony_ci chunk = end - offset; 1038c2ecf20Sopenharmony_ci if (chunk > 0) { 1048c2ecf20Sopenharmony_ci if (chunk > len) 1058c2ecf20Sopenharmony_ci chunk = len; 1068c2ecf20Sopenharmony_ci ret = __skb_nsg(frag_iter, offset - start, chunk, 1078c2ecf20Sopenharmony_ci recursion_level + 1); 1088c2ecf20Sopenharmony_ci if (unlikely(ret < 0)) 1098c2ecf20Sopenharmony_ci return ret; 1108c2ecf20Sopenharmony_ci elt += ret; 1118c2ecf20Sopenharmony_ci len -= chunk; 1128c2ecf20Sopenharmony_ci if (len == 0) 1138c2ecf20Sopenharmony_ci return elt; 1148c2ecf20Sopenharmony_ci offset += chunk; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci start = end; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci BUG_ON(len); 1208c2ecf20Sopenharmony_ci return elt; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/* Return the number of scatterlist elements required to completely map the 1248c2ecf20Sopenharmony_ci * skb, or -EMSGSIZE if the recursion depth is exceeded. 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_cistatic int skb_nsg(struct sk_buff *skb, int offset, int len) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci return __skb_nsg(skb, offset, len, 0); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic int padding_length(struct tls_sw_context_rx *ctx, 1328c2ecf20Sopenharmony_ci struct tls_prot_info *prot, struct sk_buff *skb) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci struct strp_msg *rxm = strp_msg(skb); 1358c2ecf20Sopenharmony_ci int sub = 0; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* Determine zero-padding length */ 1388c2ecf20Sopenharmony_ci if (prot->version == TLS_1_3_VERSION) { 1398c2ecf20Sopenharmony_ci char content_type = 0; 1408c2ecf20Sopenharmony_ci int err; 1418c2ecf20Sopenharmony_ci int back = 17; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci while (content_type == 0) { 1448c2ecf20Sopenharmony_ci if (back > rxm->full_len - prot->prepend_size) 1458c2ecf20Sopenharmony_ci return -EBADMSG; 1468c2ecf20Sopenharmony_ci err = skb_copy_bits(skb, 1478c2ecf20Sopenharmony_ci rxm->offset + rxm->full_len - back, 1488c2ecf20Sopenharmony_ci &content_type, 1); 1498c2ecf20Sopenharmony_ci if (err) 1508c2ecf20Sopenharmony_ci return err; 1518c2ecf20Sopenharmony_ci if (content_type) 1528c2ecf20Sopenharmony_ci break; 1538c2ecf20Sopenharmony_ci sub++; 1548c2ecf20Sopenharmony_ci back++; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci ctx->control = content_type; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci return sub; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic void tls_decrypt_done(struct crypto_async_request *req, int err) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci struct aead_request *aead_req = (struct aead_request *)req; 1648c2ecf20Sopenharmony_ci struct scatterlist *sgout = aead_req->dst; 1658c2ecf20Sopenharmony_ci struct scatterlist *sgin = aead_req->src; 1668c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx; 1678c2ecf20Sopenharmony_ci struct tls_context *tls_ctx; 1688c2ecf20Sopenharmony_ci struct tls_prot_info *prot; 1698c2ecf20Sopenharmony_ci struct scatterlist *sg; 1708c2ecf20Sopenharmony_ci struct sk_buff *skb; 1718c2ecf20Sopenharmony_ci unsigned int pages; 1728c2ecf20Sopenharmony_ci int pending; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci skb = (struct sk_buff *)req->data; 1758c2ecf20Sopenharmony_ci tls_ctx = tls_get_ctx(skb->sk); 1768c2ecf20Sopenharmony_ci ctx = tls_sw_ctx_rx(tls_ctx); 1778c2ecf20Sopenharmony_ci prot = &tls_ctx->prot_info; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* Propagate if there was an err */ 1808c2ecf20Sopenharmony_ci if (err) { 1818c2ecf20Sopenharmony_ci if (err == -EBADMSG) 1828c2ecf20Sopenharmony_ci TLS_INC_STATS(sock_net(skb->sk), 1838c2ecf20Sopenharmony_ci LINUX_MIB_TLSDECRYPTERROR); 1848c2ecf20Sopenharmony_ci ctx->async_wait.err = err; 1858c2ecf20Sopenharmony_ci tls_err_abort(skb->sk, err); 1868c2ecf20Sopenharmony_ci } else { 1878c2ecf20Sopenharmony_ci struct strp_msg *rxm = strp_msg(skb); 1888c2ecf20Sopenharmony_ci int pad; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci pad = padding_length(ctx, prot, skb); 1918c2ecf20Sopenharmony_ci if (pad < 0) { 1928c2ecf20Sopenharmony_ci ctx->async_wait.err = pad; 1938c2ecf20Sopenharmony_ci tls_err_abort(skb->sk, pad); 1948c2ecf20Sopenharmony_ci } else { 1958c2ecf20Sopenharmony_ci rxm->full_len -= pad; 1968c2ecf20Sopenharmony_ci rxm->offset += prot->prepend_size; 1978c2ecf20Sopenharmony_ci rxm->full_len -= prot->overhead_size; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* After using skb->sk to propagate sk through crypto async callback 2028c2ecf20Sopenharmony_ci * we need to NULL it again. 2038c2ecf20Sopenharmony_ci */ 2048c2ecf20Sopenharmony_ci skb->sk = NULL; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* Free the destination pages if skb was not decrypted inplace */ 2088c2ecf20Sopenharmony_ci if (sgout != sgin) { 2098c2ecf20Sopenharmony_ci /* Skip the first S/G entry as it points to AAD */ 2108c2ecf20Sopenharmony_ci for_each_sg(sg_next(sgout), sg, UINT_MAX, pages) { 2118c2ecf20Sopenharmony_ci if (!sg) 2128c2ecf20Sopenharmony_ci break; 2138c2ecf20Sopenharmony_ci put_page(sg_page(sg)); 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci kfree(aead_req); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci spin_lock_bh(&ctx->decrypt_compl_lock); 2208c2ecf20Sopenharmony_ci pending = atomic_dec_return(&ctx->decrypt_pending); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci if (!pending && ctx->async_notify) 2238c2ecf20Sopenharmony_ci complete(&ctx->async_wait.completion); 2248c2ecf20Sopenharmony_ci spin_unlock_bh(&ctx->decrypt_compl_lock); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic int tls_do_decryption(struct sock *sk, 2288c2ecf20Sopenharmony_ci struct sk_buff *skb, 2298c2ecf20Sopenharmony_ci struct scatterlist *sgin, 2308c2ecf20Sopenharmony_ci struct scatterlist *sgout, 2318c2ecf20Sopenharmony_ci char *iv_recv, 2328c2ecf20Sopenharmony_ci size_t data_len, 2338c2ecf20Sopenharmony_ci struct aead_request *aead_req, 2348c2ecf20Sopenharmony_ci bool async) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 2378c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 2388c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 2398c2ecf20Sopenharmony_ci int ret; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci aead_request_set_tfm(aead_req, ctx->aead_recv); 2428c2ecf20Sopenharmony_ci aead_request_set_ad(aead_req, prot->aad_size); 2438c2ecf20Sopenharmony_ci aead_request_set_crypt(aead_req, sgin, sgout, 2448c2ecf20Sopenharmony_ci data_len + prot->tag_size, 2458c2ecf20Sopenharmony_ci (u8 *)iv_recv); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (async) { 2488c2ecf20Sopenharmony_ci /* Using skb->sk to push sk through to crypto async callback 2498c2ecf20Sopenharmony_ci * handler. This allows propagating errors up to the socket 2508c2ecf20Sopenharmony_ci * if needed. It _must_ be cleared in the async handler 2518c2ecf20Sopenharmony_ci * before consume_skb is called. We _know_ skb->sk is NULL 2528c2ecf20Sopenharmony_ci * because it is a clone from strparser. 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ci skb->sk = sk; 2558c2ecf20Sopenharmony_ci aead_request_set_callback(aead_req, 2568c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_BACKLOG, 2578c2ecf20Sopenharmony_ci tls_decrypt_done, skb); 2588c2ecf20Sopenharmony_ci atomic_inc(&ctx->decrypt_pending); 2598c2ecf20Sopenharmony_ci } else { 2608c2ecf20Sopenharmony_ci aead_request_set_callback(aead_req, 2618c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_BACKLOG, 2628c2ecf20Sopenharmony_ci crypto_req_done, &ctx->async_wait); 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci ret = crypto_aead_decrypt(aead_req); 2668c2ecf20Sopenharmony_ci if (ret == -EINPROGRESS) { 2678c2ecf20Sopenharmony_ci if (async) 2688c2ecf20Sopenharmony_ci return ret; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci ret = crypto_wait_req(ret, &ctx->async_wait); 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (async) 2748c2ecf20Sopenharmony_ci atomic_dec(&ctx->decrypt_pending); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci return ret; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic void tls_trim_both_msgs(struct sock *sk, int target_size) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 2828c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 2838c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 2848c2ecf20Sopenharmony_ci struct tls_rec *rec = ctx->open_rec; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci sk_msg_trim(sk, &rec->msg_plaintext, target_size); 2878c2ecf20Sopenharmony_ci if (target_size > 0) 2888c2ecf20Sopenharmony_ci target_size += prot->overhead_size; 2898c2ecf20Sopenharmony_ci sk_msg_trim(sk, &rec->msg_encrypted, target_size); 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic int tls_alloc_encrypted_msg(struct sock *sk, int len) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 2958c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 2968c2ecf20Sopenharmony_ci struct tls_rec *rec = ctx->open_rec; 2978c2ecf20Sopenharmony_ci struct sk_msg *msg_en = &rec->msg_encrypted; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci return sk_msg_alloc(sk, msg_en, len, 0); 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int tls_clone_plaintext_msg(struct sock *sk, int required) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 3058c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 3068c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 3078c2ecf20Sopenharmony_ci struct tls_rec *rec = ctx->open_rec; 3088c2ecf20Sopenharmony_ci struct sk_msg *msg_pl = &rec->msg_plaintext; 3098c2ecf20Sopenharmony_ci struct sk_msg *msg_en = &rec->msg_encrypted; 3108c2ecf20Sopenharmony_ci int skip, len; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* We add page references worth len bytes from encrypted sg 3138c2ecf20Sopenharmony_ci * at the end of plaintext sg. It is guaranteed that msg_en 3148c2ecf20Sopenharmony_ci * has enough required room (ensured by caller). 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_ci len = required - msg_pl->sg.size; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* Skip initial bytes in msg_en's data to be able to use 3198c2ecf20Sopenharmony_ci * same offset of both plain and encrypted data. 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_ci skip = prot->prepend_size + msg_pl->sg.size; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci return sk_msg_clone(sk, msg_pl, msg_en, skip, len); 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic struct tls_rec *tls_get_rec(struct sock *sk) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 3298c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 3308c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 3318c2ecf20Sopenharmony_ci struct sk_msg *msg_pl, *msg_en; 3328c2ecf20Sopenharmony_ci struct tls_rec *rec; 3338c2ecf20Sopenharmony_ci int mem_size; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci mem_size = sizeof(struct tls_rec) + crypto_aead_reqsize(ctx->aead_send); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci rec = kzalloc(mem_size, sk->sk_allocation); 3388c2ecf20Sopenharmony_ci if (!rec) 3398c2ecf20Sopenharmony_ci return NULL; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci msg_pl = &rec->msg_plaintext; 3428c2ecf20Sopenharmony_ci msg_en = &rec->msg_encrypted; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci sk_msg_init(msg_pl); 3458c2ecf20Sopenharmony_ci sk_msg_init(msg_en); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci sg_init_table(rec->sg_aead_in, 2); 3488c2ecf20Sopenharmony_ci sg_set_buf(&rec->sg_aead_in[0], rec->aad_space, prot->aad_size); 3498c2ecf20Sopenharmony_ci sg_unmark_end(&rec->sg_aead_in[1]); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci sg_init_table(rec->sg_aead_out, 2); 3528c2ecf20Sopenharmony_ci sg_set_buf(&rec->sg_aead_out[0], rec->aad_space, prot->aad_size); 3538c2ecf20Sopenharmony_ci sg_unmark_end(&rec->sg_aead_out[1]); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci return rec; 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic void tls_free_rec(struct sock *sk, struct tls_rec *rec) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci sk_msg_free(sk, &rec->msg_encrypted); 3618c2ecf20Sopenharmony_ci sk_msg_free(sk, &rec->msg_plaintext); 3628c2ecf20Sopenharmony_ci kfree(rec); 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic void tls_free_open_rec(struct sock *sk) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 3688c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 3698c2ecf20Sopenharmony_ci struct tls_rec *rec = ctx->open_rec; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci if (rec) { 3728c2ecf20Sopenharmony_ci tls_free_rec(sk, rec); 3738c2ecf20Sopenharmony_ci ctx->open_rec = NULL; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ciint tls_tx_records(struct sock *sk, int flags) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 3808c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 3818c2ecf20Sopenharmony_ci struct tls_rec *rec, *tmp; 3828c2ecf20Sopenharmony_ci struct sk_msg *msg_en; 3838c2ecf20Sopenharmony_ci int tx_flags, rc = 0; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (tls_is_partially_sent_record(tls_ctx)) { 3868c2ecf20Sopenharmony_ci rec = list_first_entry(&ctx->tx_list, 3878c2ecf20Sopenharmony_ci struct tls_rec, list); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (flags == -1) 3908c2ecf20Sopenharmony_ci tx_flags = rec->tx_flags; 3918c2ecf20Sopenharmony_ci else 3928c2ecf20Sopenharmony_ci tx_flags = flags; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci rc = tls_push_partial_record(sk, tls_ctx, tx_flags); 3958c2ecf20Sopenharmony_ci if (rc) 3968c2ecf20Sopenharmony_ci goto tx_err; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* Full record has been transmitted. 3998c2ecf20Sopenharmony_ci * Remove the head of tx_list 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_ci list_del(&rec->list); 4028c2ecf20Sopenharmony_ci sk_msg_free(sk, &rec->msg_plaintext); 4038c2ecf20Sopenharmony_ci kfree(rec); 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci /* Tx all ready records */ 4078c2ecf20Sopenharmony_ci list_for_each_entry_safe(rec, tmp, &ctx->tx_list, list) { 4088c2ecf20Sopenharmony_ci if (READ_ONCE(rec->tx_ready)) { 4098c2ecf20Sopenharmony_ci if (flags == -1) 4108c2ecf20Sopenharmony_ci tx_flags = rec->tx_flags; 4118c2ecf20Sopenharmony_ci else 4128c2ecf20Sopenharmony_ci tx_flags = flags; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci msg_en = &rec->msg_encrypted; 4158c2ecf20Sopenharmony_ci rc = tls_push_sg(sk, tls_ctx, 4168c2ecf20Sopenharmony_ci &msg_en->sg.data[msg_en->sg.curr], 4178c2ecf20Sopenharmony_ci 0, tx_flags); 4188c2ecf20Sopenharmony_ci if (rc) 4198c2ecf20Sopenharmony_ci goto tx_err; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci list_del(&rec->list); 4228c2ecf20Sopenharmony_ci sk_msg_free(sk, &rec->msg_plaintext); 4238c2ecf20Sopenharmony_ci kfree(rec); 4248c2ecf20Sopenharmony_ci } else { 4258c2ecf20Sopenharmony_ci break; 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_citx_err: 4308c2ecf20Sopenharmony_ci if (rc < 0 && rc != -EAGAIN) 4318c2ecf20Sopenharmony_ci tls_err_abort(sk, -EBADMSG); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci return rc; 4348c2ecf20Sopenharmony_ci} 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_cistatic void tls_encrypt_done(struct crypto_async_request *req, int err) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci struct aead_request *aead_req = (struct aead_request *)req; 4398c2ecf20Sopenharmony_ci struct sock *sk = req->data; 4408c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 4418c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 4428c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 4438c2ecf20Sopenharmony_ci struct scatterlist *sge; 4448c2ecf20Sopenharmony_ci struct sk_msg *msg_en; 4458c2ecf20Sopenharmony_ci struct tls_rec *rec; 4468c2ecf20Sopenharmony_ci int pending; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci rec = container_of(aead_req, struct tls_rec, aead_req); 4498c2ecf20Sopenharmony_ci msg_en = &rec->msg_encrypted; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci sge = sk_msg_elem(msg_en, msg_en->sg.curr); 4528c2ecf20Sopenharmony_ci sge->offset -= prot->prepend_size; 4538c2ecf20Sopenharmony_ci sge->length += prot->prepend_size; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci /* Check if error is previously set on socket */ 4568c2ecf20Sopenharmony_ci if (err || sk->sk_err) { 4578c2ecf20Sopenharmony_ci rec = NULL; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci /* If err is already set on socket, return the same code */ 4608c2ecf20Sopenharmony_ci if (sk->sk_err) { 4618c2ecf20Sopenharmony_ci ctx->async_wait.err = -sk->sk_err; 4628c2ecf20Sopenharmony_ci } else { 4638c2ecf20Sopenharmony_ci ctx->async_wait.err = err; 4648c2ecf20Sopenharmony_ci tls_err_abort(sk, err); 4658c2ecf20Sopenharmony_ci } 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci if (rec) { 4698c2ecf20Sopenharmony_ci struct tls_rec *first_rec; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* Mark the record as ready for transmission */ 4728c2ecf20Sopenharmony_ci smp_store_mb(rec->tx_ready, true); 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci /* If received record is at head of tx_list, schedule tx */ 4758c2ecf20Sopenharmony_ci first_rec = list_first_entry(&ctx->tx_list, 4768c2ecf20Sopenharmony_ci struct tls_rec, list); 4778c2ecf20Sopenharmony_ci if (rec == first_rec) { 4788c2ecf20Sopenharmony_ci /* Schedule the transmission */ 4798c2ecf20Sopenharmony_ci if (!test_and_set_bit(BIT_TX_SCHEDULED, 4808c2ecf20Sopenharmony_ci &ctx->tx_bitmask)) 4818c2ecf20Sopenharmony_ci schedule_delayed_work(&ctx->tx_work.work, 1); 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci spin_lock_bh(&ctx->encrypt_compl_lock); 4868c2ecf20Sopenharmony_ci pending = atomic_dec_return(&ctx->encrypt_pending); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci if (!pending && ctx->async_notify) 4898c2ecf20Sopenharmony_ci complete(&ctx->async_wait.completion); 4908c2ecf20Sopenharmony_ci spin_unlock_bh(&ctx->encrypt_compl_lock); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic int tls_do_encryption(struct sock *sk, 4948c2ecf20Sopenharmony_ci struct tls_context *tls_ctx, 4958c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx, 4968c2ecf20Sopenharmony_ci struct aead_request *aead_req, 4978c2ecf20Sopenharmony_ci size_t data_len, u32 start) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 5008c2ecf20Sopenharmony_ci struct tls_rec *rec = ctx->open_rec; 5018c2ecf20Sopenharmony_ci struct sk_msg *msg_en = &rec->msg_encrypted; 5028c2ecf20Sopenharmony_ci struct scatterlist *sge = sk_msg_elem(msg_en, start); 5038c2ecf20Sopenharmony_ci int rc, iv_offset = 0; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* For CCM based ciphers, first byte of IV is a constant */ 5068c2ecf20Sopenharmony_ci if (prot->cipher_type == TLS_CIPHER_AES_CCM_128) { 5078c2ecf20Sopenharmony_ci rec->iv_data[0] = TLS_AES_CCM_IV_B0_BYTE; 5088c2ecf20Sopenharmony_ci iv_offset = 1; 5098c2ecf20Sopenharmony_ci } 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci memcpy(&rec->iv_data[iv_offset], tls_ctx->tx.iv, 5128c2ecf20Sopenharmony_ci prot->iv_size + prot->salt_size); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci xor_iv_with_seq(prot->version, rec->iv_data + iv_offset, tls_ctx->tx.rec_seq); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci sge->offset += prot->prepend_size; 5178c2ecf20Sopenharmony_ci sge->length -= prot->prepend_size; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci msg_en->sg.curr = start; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci aead_request_set_tfm(aead_req, ctx->aead_send); 5228c2ecf20Sopenharmony_ci aead_request_set_ad(aead_req, prot->aad_size); 5238c2ecf20Sopenharmony_ci aead_request_set_crypt(aead_req, rec->sg_aead_in, 5248c2ecf20Sopenharmony_ci rec->sg_aead_out, 5258c2ecf20Sopenharmony_ci data_len, rec->iv_data); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG, 5288c2ecf20Sopenharmony_ci tls_encrypt_done, sk); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* Add the record in tx_list */ 5318c2ecf20Sopenharmony_ci list_add_tail((struct list_head *)&rec->list, &ctx->tx_list); 5328c2ecf20Sopenharmony_ci atomic_inc(&ctx->encrypt_pending); 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci rc = crypto_aead_encrypt(aead_req); 5358c2ecf20Sopenharmony_ci if (!rc || rc != -EINPROGRESS) { 5368c2ecf20Sopenharmony_ci atomic_dec(&ctx->encrypt_pending); 5378c2ecf20Sopenharmony_ci sge->offset -= prot->prepend_size; 5388c2ecf20Sopenharmony_ci sge->length += prot->prepend_size; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci if (!rc) { 5428c2ecf20Sopenharmony_ci WRITE_ONCE(rec->tx_ready, true); 5438c2ecf20Sopenharmony_ci } else if (rc != -EINPROGRESS) { 5448c2ecf20Sopenharmony_ci list_del(&rec->list); 5458c2ecf20Sopenharmony_ci return rc; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* Unhook the record from context if encryption is not failure */ 5498c2ecf20Sopenharmony_ci ctx->open_rec = NULL; 5508c2ecf20Sopenharmony_ci tls_advance_record_sn(sk, prot, &tls_ctx->tx); 5518c2ecf20Sopenharmony_ci return rc; 5528c2ecf20Sopenharmony_ci} 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_cistatic int tls_split_open_record(struct sock *sk, struct tls_rec *from, 5558c2ecf20Sopenharmony_ci struct tls_rec **to, struct sk_msg *msg_opl, 5568c2ecf20Sopenharmony_ci struct sk_msg *msg_oen, u32 split_point, 5578c2ecf20Sopenharmony_ci u32 tx_overhead_size, u32 *orig_end) 5588c2ecf20Sopenharmony_ci{ 5598c2ecf20Sopenharmony_ci u32 i, j, bytes = 0, apply = msg_opl->apply_bytes; 5608c2ecf20Sopenharmony_ci struct scatterlist *sge, *osge, *nsge; 5618c2ecf20Sopenharmony_ci u32 orig_size = msg_opl->sg.size; 5628c2ecf20Sopenharmony_ci struct scatterlist tmp = { }; 5638c2ecf20Sopenharmony_ci struct sk_msg *msg_npl; 5648c2ecf20Sopenharmony_ci struct tls_rec *new; 5658c2ecf20Sopenharmony_ci int ret; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci new = tls_get_rec(sk); 5688c2ecf20Sopenharmony_ci if (!new) 5698c2ecf20Sopenharmony_ci return -ENOMEM; 5708c2ecf20Sopenharmony_ci ret = sk_msg_alloc(sk, &new->msg_encrypted, msg_opl->sg.size + 5718c2ecf20Sopenharmony_ci tx_overhead_size, 0); 5728c2ecf20Sopenharmony_ci if (ret < 0) { 5738c2ecf20Sopenharmony_ci tls_free_rec(sk, new); 5748c2ecf20Sopenharmony_ci return ret; 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci *orig_end = msg_opl->sg.end; 5788c2ecf20Sopenharmony_ci i = msg_opl->sg.start; 5798c2ecf20Sopenharmony_ci sge = sk_msg_elem(msg_opl, i); 5808c2ecf20Sopenharmony_ci while (apply && sge->length) { 5818c2ecf20Sopenharmony_ci if (sge->length > apply) { 5828c2ecf20Sopenharmony_ci u32 len = sge->length - apply; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci get_page(sg_page(sge)); 5858c2ecf20Sopenharmony_ci sg_set_page(&tmp, sg_page(sge), len, 5868c2ecf20Sopenharmony_ci sge->offset + apply); 5878c2ecf20Sopenharmony_ci sge->length = apply; 5888c2ecf20Sopenharmony_ci bytes += apply; 5898c2ecf20Sopenharmony_ci apply = 0; 5908c2ecf20Sopenharmony_ci } else { 5918c2ecf20Sopenharmony_ci apply -= sge->length; 5928c2ecf20Sopenharmony_ci bytes += sge->length; 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci sk_msg_iter_var_next(i); 5968c2ecf20Sopenharmony_ci if (i == msg_opl->sg.end) 5978c2ecf20Sopenharmony_ci break; 5988c2ecf20Sopenharmony_ci sge = sk_msg_elem(msg_opl, i); 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci msg_opl->sg.end = i; 6028c2ecf20Sopenharmony_ci msg_opl->sg.curr = i; 6038c2ecf20Sopenharmony_ci msg_opl->sg.copybreak = 0; 6048c2ecf20Sopenharmony_ci msg_opl->apply_bytes = 0; 6058c2ecf20Sopenharmony_ci msg_opl->sg.size = bytes; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci msg_npl = &new->msg_plaintext; 6088c2ecf20Sopenharmony_ci msg_npl->apply_bytes = apply; 6098c2ecf20Sopenharmony_ci msg_npl->sg.size = orig_size - bytes; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci j = msg_npl->sg.start; 6128c2ecf20Sopenharmony_ci nsge = sk_msg_elem(msg_npl, j); 6138c2ecf20Sopenharmony_ci if (tmp.length) { 6148c2ecf20Sopenharmony_ci memcpy(nsge, &tmp, sizeof(*nsge)); 6158c2ecf20Sopenharmony_ci sk_msg_iter_var_next(j); 6168c2ecf20Sopenharmony_ci nsge = sk_msg_elem(msg_npl, j); 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci osge = sk_msg_elem(msg_opl, i); 6208c2ecf20Sopenharmony_ci while (osge->length) { 6218c2ecf20Sopenharmony_ci memcpy(nsge, osge, sizeof(*nsge)); 6228c2ecf20Sopenharmony_ci sg_unmark_end(nsge); 6238c2ecf20Sopenharmony_ci sk_msg_iter_var_next(i); 6248c2ecf20Sopenharmony_ci sk_msg_iter_var_next(j); 6258c2ecf20Sopenharmony_ci if (i == *orig_end) 6268c2ecf20Sopenharmony_ci break; 6278c2ecf20Sopenharmony_ci osge = sk_msg_elem(msg_opl, i); 6288c2ecf20Sopenharmony_ci nsge = sk_msg_elem(msg_npl, j); 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci msg_npl->sg.end = j; 6328c2ecf20Sopenharmony_ci msg_npl->sg.curr = j; 6338c2ecf20Sopenharmony_ci msg_npl->sg.copybreak = 0; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci *to = new; 6368c2ecf20Sopenharmony_ci return 0; 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistatic void tls_merge_open_record(struct sock *sk, struct tls_rec *to, 6408c2ecf20Sopenharmony_ci struct tls_rec *from, u32 orig_end) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci struct sk_msg *msg_npl = &from->msg_plaintext; 6438c2ecf20Sopenharmony_ci struct sk_msg *msg_opl = &to->msg_plaintext; 6448c2ecf20Sopenharmony_ci struct scatterlist *osge, *nsge; 6458c2ecf20Sopenharmony_ci u32 i, j; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci i = msg_opl->sg.end; 6488c2ecf20Sopenharmony_ci sk_msg_iter_var_prev(i); 6498c2ecf20Sopenharmony_ci j = msg_npl->sg.start; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci osge = sk_msg_elem(msg_opl, i); 6528c2ecf20Sopenharmony_ci nsge = sk_msg_elem(msg_npl, j); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci if (sg_page(osge) == sg_page(nsge) && 6558c2ecf20Sopenharmony_ci osge->offset + osge->length == nsge->offset) { 6568c2ecf20Sopenharmony_ci osge->length += nsge->length; 6578c2ecf20Sopenharmony_ci put_page(sg_page(nsge)); 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci msg_opl->sg.end = orig_end; 6618c2ecf20Sopenharmony_ci msg_opl->sg.curr = orig_end; 6628c2ecf20Sopenharmony_ci msg_opl->sg.copybreak = 0; 6638c2ecf20Sopenharmony_ci msg_opl->apply_bytes = msg_opl->sg.size + msg_npl->sg.size; 6648c2ecf20Sopenharmony_ci msg_opl->sg.size += msg_npl->sg.size; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci sk_msg_free(sk, &to->msg_encrypted); 6678c2ecf20Sopenharmony_ci sk_msg_xfer_full(&to->msg_encrypted, &from->msg_encrypted); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci kfree(from); 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cistatic int tls_push_record(struct sock *sk, int flags, 6738c2ecf20Sopenharmony_ci unsigned char record_type) 6748c2ecf20Sopenharmony_ci{ 6758c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 6768c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 6778c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 6788c2ecf20Sopenharmony_ci struct tls_rec *rec = ctx->open_rec, *tmp = NULL; 6798c2ecf20Sopenharmony_ci u32 i, split_point, orig_end; 6808c2ecf20Sopenharmony_ci struct sk_msg *msg_pl, *msg_en; 6818c2ecf20Sopenharmony_ci struct aead_request *req; 6828c2ecf20Sopenharmony_ci bool split; 6838c2ecf20Sopenharmony_ci int rc; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci if (!rec) 6868c2ecf20Sopenharmony_ci return 0; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci msg_pl = &rec->msg_plaintext; 6898c2ecf20Sopenharmony_ci msg_en = &rec->msg_encrypted; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci split_point = msg_pl->apply_bytes; 6928c2ecf20Sopenharmony_ci split = split_point && split_point < msg_pl->sg.size; 6938c2ecf20Sopenharmony_ci if (unlikely((!split && 6948c2ecf20Sopenharmony_ci msg_pl->sg.size + 6958c2ecf20Sopenharmony_ci prot->overhead_size > msg_en->sg.size) || 6968c2ecf20Sopenharmony_ci (split && 6978c2ecf20Sopenharmony_ci split_point + 6988c2ecf20Sopenharmony_ci prot->overhead_size > msg_en->sg.size))) { 6998c2ecf20Sopenharmony_ci split = true; 7008c2ecf20Sopenharmony_ci split_point = msg_en->sg.size; 7018c2ecf20Sopenharmony_ci } 7028c2ecf20Sopenharmony_ci if (split) { 7038c2ecf20Sopenharmony_ci rc = tls_split_open_record(sk, rec, &tmp, msg_pl, msg_en, 7048c2ecf20Sopenharmony_ci split_point, prot->overhead_size, 7058c2ecf20Sopenharmony_ci &orig_end); 7068c2ecf20Sopenharmony_ci if (rc < 0) 7078c2ecf20Sopenharmony_ci return rc; 7088c2ecf20Sopenharmony_ci /* This can happen if above tls_split_open_record allocates 7098c2ecf20Sopenharmony_ci * a single large encryption buffer instead of two smaller 7108c2ecf20Sopenharmony_ci * ones. In this case adjust pointers and continue without 7118c2ecf20Sopenharmony_ci * split. 7128c2ecf20Sopenharmony_ci */ 7138c2ecf20Sopenharmony_ci if (!msg_pl->sg.size) { 7148c2ecf20Sopenharmony_ci tls_merge_open_record(sk, rec, tmp, orig_end); 7158c2ecf20Sopenharmony_ci msg_pl = &rec->msg_plaintext; 7168c2ecf20Sopenharmony_ci msg_en = &rec->msg_encrypted; 7178c2ecf20Sopenharmony_ci split = false; 7188c2ecf20Sopenharmony_ci } 7198c2ecf20Sopenharmony_ci sk_msg_trim(sk, msg_en, msg_pl->sg.size + 7208c2ecf20Sopenharmony_ci prot->overhead_size); 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci rec->tx_flags = flags; 7248c2ecf20Sopenharmony_ci req = &rec->aead_req; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci i = msg_pl->sg.end; 7278c2ecf20Sopenharmony_ci sk_msg_iter_var_prev(i); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci rec->content_type = record_type; 7308c2ecf20Sopenharmony_ci if (prot->version == TLS_1_3_VERSION) { 7318c2ecf20Sopenharmony_ci /* Add content type to end of message. No padding added */ 7328c2ecf20Sopenharmony_ci sg_set_buf(&rec->sg_content_type, &rec->content_type, 1); 7338c2ecf20Sopenharmony_ci sg_mark_end(&rec->sg_content_type); 7348c2ecf20Sopenharmony_ci sg_chain(msg_pl->sg.data, msg_pl->sg.end + 1, 7358c2ecf20Sopenharmony_ci &rec->sg_content_type); 7368c2ecf20Sopenharmony_ci } else { 7378c2ecf20Sopenharmony_ci sg_mark_end(sk_msg_elem(msg_pl, i)); 7388c2ecf20Sopenharmony_ci } 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci if (msg_pl->sg.end < msg_pl->sg.start) { 7418c2ecf20Sopenharmony_ci sg_chain(&msg_pl->sg.data[msg_pl->sg.start], 7428c2ecf20Sopenharmony_ci MAX_SKB_FRAGS - msg_pl->sg.start + 1, 7438c2ecf20Sopenharmony_ci msg_pl->sg.data); 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci i = msg_pl->sg.start; 7478c2ecf20Sopenharmony_ci sg_chain(rec->sg_aead_in, 2, &msg_pl->sg.data[i]); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci i = msg_en->sg.end; 7508c2ecf20Sopenharmony_ci sk_msg_iter_var_prev(i); 7518c2ecf20Sopenharmony_ci sg_mark_end(sk_msg_elem(msg_en, i)); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci i = msg_en->sg.start; 7548c2ecf20Sopenharmony_ci sg_chain(rec->sg_aead_out, 2, &msg_en->sg.data[i]); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci tls_make_aad(rec->aad_space, msg_pl->sg.size + prot->tail_size, 7578c2ecf20Sopenharmony_ci tls_ctx->tx.rec_seq, prot->rec_seq_size, 7588c2ecf20Sopenharmony_ci record_type, prot->version); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci tls_fill_prepend(tls_ctx, 7618c2ecf20Sopenharmony_ci page_address(sg_page(&msg_en->sg.data[i])) + 7628c2ecf20Sopenharmony_ci msg_en->sg.data[i].offset, 7638c2ecf20Sopenharmony_ci msg_pl->sg.size + prot->tail_size, 7648c2ecf20Sopenharmony_ci record_type, prot->version); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci tls_ctx->pending_open_record_frags = false; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci rc = tls_do_encryption(sk, tls_ctx, ctx, req, 7698c2ecf20Sopenharmony_ci msg_pl->sg.size + prot->tail_size, i); 7708c2ecf20Sopenharmony_ci if (rc < 0) { 7718c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS) { 7728c2ecf20Sopenharmony_ci tls_err_abort(sk, -EBADMSG); 7738c2ecf20Sopenharmony_ci if (split) { 7748c2ecf20Sopenharmony_ci tls_ctx->pending_open_record_frags = true; 7758c2ecf20Sopenharmony_ci tls_merge_open_record(sk, rec, tmp, orig_end); 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci ctx->async_capable = 1; 7798c2ecf20Sopenharmony_ci return rc; 7808c2ecf20Sopenharmony_ci } else if (split) { 7818c2ecf20Sopenharmony_ci msg_pl = &tmp->msg_plaintext; 7828c2ecf20Sopenharmony_ci msg_en = &tmp->msg_encrypted; 7838c2ecf20Sopenharmony_ci sk_msg_trim(sk, msg_en, msg_pl->sg.size + prot->overhead_size); 7848c2ecf20Sopenharmony_ci tls_ctx->pending_open_record_frags = true; 7858c2ecf20Sopenharmony_ci ctx->open_rec = tmp; 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci return tls_tx_records(sk, flags); 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_cistatic int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, 7928c2ecf20Sopenharmony_ci bool full_record, u8 record_type, 7938c2ecf20Sopenharmony_ci ssize_t *copied, int flags) 7948c2ecf20Sopenharmony_ci{ 7958c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 7968c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 7978c2ecf20Sopenharmony_ci struct sk_msg msg_redir = { }; 7988c2ecf20Sopenharmony_ci struct sk_psock *psock; 7998c2ecf20Sopenharmony_ci struct sock *sk_redir; 8008c2ecf20Sopenharmony_ci struct tls_rec *rec; 8018c2ecf20Sopenharmony_ci bool enospc, policy; 8028c2ecf20Sopenharmony_ci int err = 0, send; 8038c2ecf20Sopenharmony_ci u32 delta = 0; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci policy = !(flags & MSG_SENDPAGE_NOPOLICY); 8068c2ecf20Sopenharmony_ci psock = sk_psock_get(sk); 8078c2ecf20Sopenharmony_ci if (!psock || !policy) { 8088c2ecf20Sopenharmony_ci err = tls_push_record(sk, flags, record_type); 8098c2ecf20Sopenharmony_ci if (err && err != -EINPROGRESS && sk->sk_err == EBADMSG) { 8108c2ecf20Sopenharmony_ci *copied -= sk_msg_free(sk, msg); 8118c2ecf20Sopenharmony_ci tls_free_open_rec(sk); 8128c2ecf20Sopenharmony_ci err = -sk->sk_err; 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci if (psock) 8158c2ecf20Sopenharmony_ci sk_psock_put(sk, psock); 8168c2ecf20Sopenharmony_ci return err; 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_cimore_data: 8198c2ecf20Sopenharmony_ci enospc = sk_msg_full(msg); 8208c2ecf20Sopenharmony_ci if (psock->eval == __SK_NONE) { 8218c2ecf20Sopenharmony_ci delta = msg->sg.size; 8228c2ecf20Sopenharmony_ci psock->eval = sk_psock_msg_verdict(sk, psock, msg); 8238c2ecf20Sopenharmony_ci delta -= msg->sg.size; 8248c2ecf20Sopenharmony_ci } 8258c2ecf20Sopenharmony_ci if (msg->cork_bytes && msg->cork_bytes > msg->sg.size && 8268c2ecf20Sopenharmony_ci !enospc && !full_record) { 8278c2ecf20Sopenharmony_ci err = -ENOSPC; 8288c2ecf20Sopenharmony_ci goto out_err; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci msg->cork_bytes = 0; 8318c2ecf20Sopenharmony_ci send = msg->sg.size; 8328c2ecf20Sopenharmony_ci if (msg->apply_bytes && msg->apply_bytes < send) 8338c2ecf20Sopenharmony_ci send = msg->apply_bytes; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci switch (psock->eval) { 8368c2ecf20Sopenharmony_ci case __SK_PASS: 8378c2ecf20Sopenharmony_ci err = tls_push_record(sk, flags, record_type); 8388c2ecf20Sopenharmony_ci if (err && err != -EINPROGRESS && sk->sk_err == EBADMSG) { 8398c2ecf20Sopenharmony_ci *copied -= sk_msg_free(sk, msg); 8408c2ecf20Sopenharmony_ci tls_free_open_rec(sk); 8418c2ecf20Sopenharmony_ci err = -sk->sk_err; 8428c2ecf20Sopenharmony_ci goto out_err; 8438c2ecf20Sopenharmony_ci } 8448c2ecf20Sopenharmony_ci break; 8458c2ecf20Sopenharmony_ci case __SK_REDIRECT: 8468c2ecf20Sopenharmony_ci sk_redir = psock->sk_redir; 8478c2ecf20Sopenharmony_ci memcpy(&msg_redir, msg, sizeof(*msg)); 8488c2ecf20Sopenharmony_ci if (msg->apply_bytes < send) 8498c2ecf20Sopenharmony_ci msg->apply_bytes = 0; 8508c2ecf20Sopenharmony_ci else 8518c2ecf20Sopenharmony_ci msg->apply_bytes -= send; 8528c2ecf20Sopenharmony_ci sk_msg_return_zero(sk, msg, send); 8538c2ecf20Sopenharmony_ci msg->sg.size -= send; 8548c2ecf20Sopenharmony_ci release_sock(sk); 8558c2ecf20Sopenharmony_ci err = tcp_bpf_sendmsg_redir(sk_redir, &msg_redir, send, flags); 8568c2ecf20Sopenharmony_ci lock_sock(sk); 8578c2ecf20Sopenharmony_ci if (err < 0) { 8588c2ecf20Sopenharmony_ci *copied -= sk_msg_free_nocharge(sk, &msg_redir); 8598c2ecf20Sopenharmony_ci msg->sg.size = 0; 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci if (msg->sg.size == 0) 8628c2ecf20Sopenharmony_ci tls_free_open_rec(sk); 8638c2ecf20Sopenharmony_ci break; 8648c2ecf20Sopenharmony_ci case __SK_DROP: 8658c2ecf20Sopenharmony_ci default: 8668c2ecf20Sopenharmony_ci sk_msg_free_partial(sk, msg, send); 8678c2ecf20Sopenharmony_ci if (msg->apply_bytes < send) 8688c2ecf20Sopenharmony_ci msg->apply_bytes = 0; 8698c2ecf20Sopenharmony_ci else 8708c2ecf20Sopenharmony_ci msg->apply_bytes -= send; 8718c2ecf20Sopenharmony_ci if (msg->sg.size == 0) 8728c2ecf20Sopenharmony_ci tls_free_open_rec(sk); 8738c2ecf20Sopenharmony_ci *copied -= (send + delta); 8748c2ecf20Sopenharmony_ci err = -EACCES; 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci if (likely(!err)) { 8788c2ecf20Sopenharmony_ci bool reset_eval = !ctx->open_rec; 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci rec = ctx->open_rec; 8818c2ecf20Sopenharmony_ci if (rec) { 8828c2ecf20Sopenharmony_ci msg = &rec->msg_plaintext; 8838c2ecf20Sopenharmony_ci if (!msg->apply_bytes) 8848c2ecf20Sopenharmony_ci reset_eval = true; 8858c2ecf20Sopenharmony_ci } 8868c2ecf20Sopenharmony_ci if (reset_eval) { 8878c2ecf20Sopenharmony_ci psock->eval = __SK_NONE; 8888c2ecf20Sopenharmony_ci if (psock->sk_redir) { 8898c2ecf20Sopenharmony_ci sock_put(psock->sk_redir); 8908c2ecf20Sopenharmony_ci psock->sk_redir = NULL; 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci if (rec) 8948c2ecf20Sopenharmony_ci goto more_data; 8958c2ecf20Sopenharmony_ci } 8968c2ecf20Sopenharmony_ci out_err: 8978c2ecf20Sopenharmony_ci sk_psock_put(sk, psock); 8988c2ecf20Sopenharmony_ci return err; 8998c2ecf20Sopenharmony_ci} 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_cistatic int tls_sw_push_pending_record(struct sock *sk, int flags) 9028c2ecf20Sopenharmony_ci{ 9038c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 9048c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 9058c2ecf20Sopenharmony_ci struct tls_rec *rec = ctx->open_rec; 9068c2ecf20Sopenharmony_ci struct sk_msg *msg_pl; 9078c2ecf20Sopenharmony_ci size_t copied; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci if (!rec) 9108c2ecf20Sopenharmony_ci return 0; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci msg_pl = &rec->msg_plaintext; 9138c2ecf20Sopenharmony_ci copied = msg_pl->sg.size; 9148c2ecf20Sopenharmony_ci if (!copied) 9158c2ecf20Sopenharmony_ci return 0; 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci return bpf_exec_tx_verdict(msg_pl, sk, true, TLS_RECORD_TYPE_DATA, 9188c2ecf20Sopenharmony_ci &copied, flags); 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ciint tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) 9228c2ecf20Sopenharmony_ci{ 9238c2ecf20Sopenharmony_ci long timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); 9248c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 9258c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 9268c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 9278c2ecf20Sopenharmony_ci bool async_capable = ctx->async_capable; 9288c2ecf20Sopenharmony_ci unsigned char record_type = TLS_RECORD_TYPE_DATA; 9298c2ecf20Sopenharmony_ci bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); 9308c2ecf20Sopenharmony_ci bool eor = !(msg->msg_flags & MSG_MORE); 9318c2ecf20Sopenharmony_ci size_t try_to_copy; 9328c2ecf20Sopenharmony_ci ssize_t copied = 0; 9338c2ecf20Sopenharmony_ci struct sk_msg *msg_pl, *msg_en; 9348c2ecf20Sopenharmony_ci struct tls_rec *rec; 9358c2ecf20Sopenharmony_ci int required_size; 9368c2ecf20Sopenharmony_ci int num_async = 0; 9378c2ecf20Sopenharmony_ci bool full_record; 9388c2ecf20Sopenharmony_ci int record_room; 9398c2ecf20Sopenharmony_ci int num_zc = 0; 9408c2ecf20Sopenharmony_ci int orig_size; 9418c2ecf20Sopenharmony_ci int ret = 0; 9428c2ecf20Sopenharmony_ci int pending; 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL | 9458c2ecf20Sopenharmony_ci MSG_CMSG_COMPAT)) 9468c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci ret = mutex_lock_interruptible(&tls_ctx->tx_lock); 9498c2ecf20Sopenharmony_ci if (ret) 9508c2ecf20Sopenharmony_ci return ret; 9518c2ecf20Sopenharmony_ci lock_sock(sk); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci if (unlikely(msg->msg_controllen)) { 9548c2ecf20Sopenharmony_ci ret = tls_proccess_cmsg(sk, msg, &record_type); 9558c2ecf20Sopenharmony_ci if (ret) { 9568c2ecf20Sopenharmony_ci if (ret == -EINPROGRESS) 9578c2ecf20Sopenharmony_ci num_async++; 9588c2ecf20Sopenharmony_ci else if (ret != -EAGAIN) 9598c2ecf20Sopenharmony_ci goto send_end; 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci while (msg_data_left(msg)) { 9648c2ecf20Sopenharmony_ci if (sk->sk_err) { 9658c2ecf20Sopenharmony_ci ret = -sk->sk_err; 9668c2ecf20Sopenharmony_ci goto send_end; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (ctx->open_rec) 9708c2ecf20Sopenharmony_ci rec = ctx->open_rec; 9718c2ecf20Sopenharmony_ci else 9728c2ecf20Sopenharmony_ci rec = ctx->open_rec = tls_get_rec(sk); 9738c2ecf20Sopenharmony_ci if (!rec) { 9748c2ecf20Sopenharmony_ci ret = -ENOMEM; 9758c2ecf20Sopenharmony_ci goto send_end; 9768c2ecf20Sopenharmony_ci } 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci msg_pl = &rec->msg_plaintext; 9798c2ecf20Sopenharmony_ci msg_en = &rec->msg_encrypted; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci orig_size = msg_pl->sg.size; 9828c2ecf20Sopenharmony_ci full_record = false; 9838c2ecf20Sopenharmony_ci try_to_copy = msg_data_left(msg); 9848c2ecf20Sopenharmony_ci record_room = TLS_MAX_PAYLOAD_SIZE - msg_pl->sg.size; 9858c2ecf20Sopenharmony_ci if (try_to_copy >= record_room) { 9868c2ecf20Sopenharmony_ci try_to_copy = record_room; 9878c2ecf20Sopenharmony_ci full_record = true; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci required_size = msg_pl->sg.size + try_to_copy + 9918c2ecf20Sopenharmony_ci prot->overhead_size; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci if (!sk_stream_memory_free(sk)) 9948c2ecf20Sopenharmony_ci goto wait_for_sndbuf; 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_cialloc_encrypted: 9978c2ecf20Sopenharmony_ci ret = tls_alloc_encrypted_msg(sk, required_size); 9988c2ecf20Sopenharmony_ci if (ret) { 9998c2ecf20Sopenharmony_ci if (ret != -ENOSPC) 10008c2ecf20Sopenharmony_ci goto wait_for_memory; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci /* Adjust try_to_copy according to the amount that was 10038c2ecf20Sopenharmony_ci * actually allocated. The difference is due 10048c2ecf20Sopenharmony_ci * to max sg elements limit 10058c2ecf20Sopenharmony_ci */ 10068c2ecf20Sopenharmony_ci try_to_copy -= required_size - msg_en->sg.size; 10078c2ecf20Sopenharmony_ci full_record = true; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci if (!is_kvec && (full_record || eor) && !async_capable) { 10118c2ecf20Sopenharmony_ci u32 first = msg_pl->sg.end; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci ret = sk_msg_zerocopy_from_iter(sk, &msg->msg_iter, 10148c2ecf20Sopenharmony_ci msg_pl, try_to_copy); 10158c2ecf20Sopenharmony_ci if (ret) 10168c2ecf20Sopenharmony_ci goto fallback_to_reg_send; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci num_zc++; 10198c2ecf20Sopenharmony_ci copied += try_to_copy; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci sk_msg_sg_copy_set(msg_pl, first); 10228c2ecf20Sopenharmony_ci ret = bpf_exec_tx_verdict(msg_pl, sk, full_record, 10238c2ecf20Sopenharmony_ci record_type, &copied, 10248c2ecf20Sopenharmony_ci msg->msg_flags); 10258c2ecf20Sopenharmony_ci if (ret) { 10268c2ecf20Sopenharmony_ci if (ret == -EINPROGRESS) 10278c2ecf20Sopenharmony_ci num_async++; 10288c2ecf20Sopenharmony_ci else if (ret == -ENOMEM) 10298c2ecf20Sopenharmony_ci goto wait_for_memory; 10308c2ecf20Sopenharmony_ci else if (ctx->open_rec && ret == -ENOSPC) 10318c2ecf20Sopenharmony_ci goto rollback_iter; 10328c2ecf20Sopenharmony_ci else if (ret != -EAGAIN) 10338c2ecf20Sopenharmony_ci goto send_end; 10348c2ecf20Sopenharmony_ci } 10358c2ecf20Sopenharmony_ci continue; 10368c2ecf20Sopenharmony_cirollback_iter: 10378c2ecf20Sopenharmony_ci copied -= try_to_copy; 10388c2ecf20Sopenharmony_ci sk_msg_sg_copy_clear(msg_pl, first); 10398c2ecf20Sopenharmony_ci iov_iter_revert(&msg->msg_iter, 10408c2ecf20Sopenharmony_ci msg_pl->sg.size - orig_size); 10418c2ecf20Sopenharmony_cifallback_to_reg_send: 10428c2ecf20Sopenharmony_ci sk_msg_trim(sk, msg_pl, orig_size); 10438c2ecf20Sopenharmony_ci } 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci required_size = msg_pl->sg.size + try_to_copy; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci ret = tls_clone_plaintext_msg(sk, required_size); 10488c2ecf20Sopenharmony_ci if (ret) { 10498c2ecf20Sopenharmony_ci if (ret != -ENOSPC) 10508c2ecf20Sopenharmony_ci goto send_end; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci /* Adjust try_to_copy according to the amount that was 10538c2ecf20Sopenharmony_ci * actually allocated. The difference is due 10548c2ecf20Sopenharmony_ci * to max sg elements limit 10558c2ecf20Sopenharmony_ci */ 10568c2ecf20Sopenharmony_ci try_to_copy -= required_size - msg_pl->sg.size; 10578c2ecf20Sopenharmony_ci full_record = true; 10588c2ecf20Sopenharmony_ci sk_msg_trim(sk, msg_en, 10598c2ecf20Sopenharmony_ci msg_pl->sg.size + prot->overhead_size); 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci if (try_to_copy) { 10638c2ecf20Sopenharmony_ci ret = sk_msg_memcopy_from_iter(sk, &msg->msg_iter, 10648c2ecf20Sopenharmony_ci msg_pl, try_to_copy); 10658c2ecf20Sopenharmony_ci if (ret < 0) 10668c2ecf20Sopenharmony_ci goto trim_sgl; 10678c2ecf20Sopenharmony_ci } 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci /* Open records defined only if successfully copied, otherwise 10708c2ecf20Sopenharmony_ci * we would trim the sg but not reset the open record frags. 10718c2ecf20Sopenharmony_ci */ 10728c2ecf20Sopenharmony_ci tls_ctx->pending_open_record_frags = true; 10738c2ecf20Sopenharmony_ci copied += try_to_copy; 10748c2ecf20Sopenharmony_ci if (full_record || eor) { 10758c2ecf20Sopenharmony_ci ret = bpf_exec_tx_verdict(msg_pl, sk, full_record, 10768c2ecf20Sopenharmony_ci record_type, &copied, 10778c2ecf20Sopenharmony_ci msg->msg_flags); 10788c2ecf20Sopenharmony_ci if (ret) { 10798c2ecf20Sopenharmony_ci if (ret == -EINPROGRESS) 10808c2ecf20Sopenharmony_ci num_async++; 10818c2ecf20Sopenharmony_ci else if (ret == -ENOMEM) 10828c2ecf20Sopenharmony_ci goto wait_for_memory; 10838c2ecf20Sopenharmony_ci else if (ret != -EAGAIN) { 10848c2ecf20Sopenharmony_ci if (ret == -ENOSPC) 10858c2ecf20Sopenharmony_ci ret = 0; 10868c2ecf20Sopenharmony_ci goto send_end; 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci continue; 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ciwait_for_sndbuf: 10948c2ecf20Sopenharmony_ci set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); 10958c2ecf20Sopenharmony_ciwait_for_memory: 10968c2ecf20Sopenharmony_ci ret = sk_stream_wait_memory(sk, &timeo); 10978c2ecf20Sopenharmony_ci if (ret) { 10988c2ecf20Sopenharmony_citrim_sgl: 10998c2ecf20Sopenharmony_ci if (ctx->open_rec) 11008c2ecf20Sopenharmony_ci tls_trim_both_msgs(sk, orig_size); 11018c2ecf20Sopenharmony_ci goto send_end; 11028c2ecf20Sopenharmony_ci } 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci if (ctx->open_rec && msg_en->sg.size < required_size) 11058c2ecf20Sopenharmony_ci goto alloc_encrypted; 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci if (!num_async) { 11098c2ecf20Sopenharmony_ci goto send_end; 11108c2ecf20Sopenharmony_ci } else if (num_zc) { 11118c2ecf20Sopenharmony_ci /* Wait for pending encryptions to get completed */ 11128c2ecf20Sopenharmony_ci spin_lock_bh(&ctx->encrypt_compl_lock); 11138c2ecf20Sopenharmony_ci ctx->async_notify = true; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci pending = atomic_read(&ctx->encrypt_pending); 11168c2ecf20Sopenharmony_ci spin_unlock_bh(&ctx->encrypt_compl_lock); 11178c2ecf20Sopenharmony_ci if (pending) 11188c2ecf20Sopenharmony_ci crypto_wait_req(-EINPROGRESS, &ctx->async_wait); 11198c2ecf20Sopenharmony_ci else 11208c2ecf20Sopenharmony_ci reinit_completion(&ctx->async_wait.completion); 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci /* There can be no concurrent accesses, since we have no 11238c2ecf20Sopenharmony_ci * pending encrypt operations 11248c2ecf20Sopenharmony_ci */ 11258c2ecf20Sopenharmony_ci WRITE_ONCE(ctx->async_notify, false); 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci if (ctx->async_wait.err) { 11288c2ecf20Sopenharmony_ci ret = ctx->async_wait.err; 11298c2ecf20Sopenharmony_ci copied = 0; 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci /* Transmit if any encryptions have completed */ 11348c2ecf20Sopenharmony_ci if (test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) { 11358c2ecf20Sopenharmony_ci cancel_delayed_work(&ctx->tx_work.work); 11368c2ecf20Sopenharmony_ci tls_tx_records(sk, msg->msg_flags); 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_cisend_end: 11408c2ecf20Sopenharmony_ci ret = sk_stream_error(sk, msg->msg_flags, ret); 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci release_sock(sk); 11438c2ecf20Sopenharmony_ci mutex_unlock(&tls_ctx->tx_lock); 11448c2ecf20Sopenharmony_ci return copied > 0 ? copied : ret; 11458c2ecf20Sopenharmony_ci} 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_cistatic int tls_sw_do_sendpage(struct sock *sk, struct page *page, 11488c2ecf20Sopenharmony_ci int offset, size_t size, int flags) 11498c2ecf20Sopenharmony_ci{ 11508c2ecf20Sopenharmony_ci long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); 11518c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 11528c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 11538c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 11548c2ecf20Sopenharmony_ci unsigned char record_type = TLS_RECORD_TYPE_DATA; 11558c2ecf20Sopenharmony_ci struct sk_msg *msg_pl; 11568c2ecf20Sopenharmony_ci struct tls_rec *rec; 11578c2ecf20Sopenharmony_ci int num_async = 0; 11588c2ecf20Sopenharmony_ci ssize_t copied = 0; 11598c2ecf20Sopenharmony_ci bool full_record; 11608c2ecf20Sopenharmony_ci int record_room; 11618c2ecf20Sopenharmony_ci int ret = 0; 11628c2ecf20Sopenharmony_ci bool eor; 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci eor = !(flags & MSG_SENDPAGE_NOTLAST); 11658c2ecf20Sopenharmony_ci sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci /* Call the sk_stream functions to manage the sndbuf mem. */ 11688c2ecf20Sopenharmony_ci while (size > 0) { 11698c2ecf20Sopenharmony_ci size_t copy, required_size; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci if (sk->sk_err) { 11728c2ecf20Sopenharmony_ci ret = -sk->sk_err; 11738c2ecf20Sopenharmony_ci goto sendpage_end; 11748c2ecf20Sopenharmony_ci } 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci if (ctx->open_rec) 11778c2ecf20Sopenharmony_ci rec = ctx->open_rec; 11788c2ecf20Sopenharmony_ci else 11798c2ecf20Sopenharmony_ci rec = ctx->open_rec = tls_get_rec(sk); 11808c2ecf20Sopenharmony_ci if (!rec) { 11818c2ecf20Sopenharmony_ci ret = -ENOMEM; 11828c2ecf20Sopenharmony_ci goto sendpage_end; 11838c2ecf20Sopenharmony_ci } 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci msg_pl = &rec->msg_plaintext; 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci full_record = false; 11888c2ecf20Sopenharmony_ci record_room = TLS_MAX_PAYLOAD_SIZE - msg_pl->sg.size; 11898c2ecf20Sopenharmony_ci copy = size; 11908c2ecf20Sopenharmony_ci if (copy >= record_room) { 11918c2ecf20Sopenharmony_ci copy = record_room; 11928c2ecf20Sopenharmony_ci full_record = true; 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci required_size = msg_pl->sg.size + copy + prot->overhead_size; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci if (!sk_stream_memory_free(sk)) 11988c2ecf20Sopenharmony_ci goto wait_for_sndbuf; 11998c2ecf20Sopenharmony_cialloc_payload: 12008c2ecf20Sopenharmony_ci ret = tls_alloc_encrypted_msg(sk, required_size); 12018c2ecf20Sopenharmony_ci if (ret) { 12028c2ecf20Sopenharmony_ci if (ret != -ENOSPC) 12038c2ecf20Sopenharmony_ci goto wait_for_memory; 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci /* Adjust copy according to the amount that was 12068c2ecf20Sopenharmony_ci * actually allocated. The difference is due 12078c2ecf20Sopenharmony_ci * to max sg elements limit 12088c2ecf20Sopenharmony_ci */ 12098c2ecf20Sopenharmony_ci copy -= required_size - msg_pl->sg.size; 12108c2ecf20Sopenharmony_ci full_record = true; 12118c2ecf20Sopenharmony_ci } 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci sk_msg_page_add(msg_pl, page, copy, offset); 12148c2ecf20Sopenharmony_ci msg_pl->sg.copybreak = 0; 12158c2ecf20Sopenharmony_ci msg_pl->sg.curr = msg_pl->sg.end; 12168c2ecf20Sopenharmony_ci sk_mem_charge(sk, copy); 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci offset += copy; 12198c2ecf20Sopenharmony_ci size -= copy; 12208c2ecf20Sopenharmony_ci copied += copy; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci tls_ctx->pending_open_record_frags = true; 12238c2ecf20Sopenharmony_ci if (full_record || eor || sk_msg_full(msg_pl)) { 12248c2ecf20Sopenharmony_ci ret = bpf_exec_tx_verdict(msg_pl, sk, full_record, 12258c2ecf20Sopenharmony_ci record_type, &copied, flags); 12268c2ecf20Sopenharmony_ci if (ret) { 12278c2ecf20Sopenharmony_ci if (ret == -EINPROGRESS) 12288c2ecf20Sopenharmony_ci num_async++; 12298c2ecf20Sopenharmony_ci else if (ret == -ENOMEM) 12308c2ecf20Sopenharmony_ci goto wait_for_memory; 12318c2ecf20Sopenharmony_ci else if (ret != -EAGAIN) { 12328c2ecf20Sopenharmony_ci if (ret == -ENOSPC) 12338c2ecf20Sopenharmony_ci ret = 0; 12348c2ecf20Sopenharmony_ci goto sendpage_end; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci continue; 12398c2ecf20Sopenharmony_ciwait_for_sndbuf: 12408c2ecf20Sopenharmony_ci set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); 12418c2ecf20Sopenharmony_ciwait_for_memory: 12428c2ecf20Sopenharmony_ci ret = sk_stream_wait_memory(sk, &timeo); 12438c2ecf20Sopenharmony_ci if (ret) { 12448c2ecf20Sopenharmony_ci if (ctx->open_rec) 12458c2ecf20Sopenharmony_ci tls_trim_both_msgs(sk, msg_pl->sg.size); 12468c2ecf20Sopenharmony_ci goto sendpage_end; 12478c2ecf20Sopenharmony_ci } 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci if (ctx->open_rec) 12508c2ecf20Sopenharmony_ci goto alloc_payload; 12518c2ecf20Sopenharmony_ci } 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci if (num_async) { 12548c2ecf20Sopenharmony_ci /* Transmit if any encryptions have completed */ 12558c2ecf20Sopenharmony_ci if (test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) { 12568c2ecf20Sopenharmony_ci cancel_delayed_work(&ctx->tx_work.work); 12578c2ecf20Sopenharmony_ci tls_tx_records(sk, flags); 12588c2ecf20Sopenharmony_ci } 12598c2ecf20Sopenharmony_ci } 12608c2ecf20Sopenharmony_cisendpage_end: 12618c2ecf20Sopenharmony_ci ret = sk_stream_error(sk, flags, ret); 12628c2ecf20Sopenharmony_ci return copied > 0 ? copied : ret; 12638c2ecf20Sopenharmony_ci} 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ciint tls_sw_sendpage_locked(struct sock *sk, struct page *page, 12668c2ecf20Sopenharmony_ci int offset, size_t size, int flags) 12678c2ecf20Sopenharmony_ci{ 12688c2ecf20Sopenharmony_ci if (flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL | 12698c2ecf20Sopenharmony_ci MSG_SENDPAGE_NOTLAST | MSG_SENDPAGE_NOPOLICY | 12708c2ecf20Sopenharmony_ci MSG_NO_SHARED_FRAGS)) 12718c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci return tls_sw_do_sendpage(sk, page, offset, size, flags); 12748c2ecf20Sopenharmony_ci} 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ciint tls_sw_sendpage(struct sock *sk, struct page *page, 12778c2ecf20Sopenharmony_ci int offset, size_t size, int flags) 12788c2ecf20Sopenharmony_ci{ 12798c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 12808c2ecf20Sopenharmony_ci int ret; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci if (flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL | 12838c2ecf20Sopenharmony_ci MSG_SENDPAGE_NOTLAST | MSG_SENDPAGE_NOPOLICY)) 12848c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci ret = mutex_lock_interruptible(&tls_ctx->tx_lock); 12878c2ecf20Sopenharmony_ci if (ret) 12888c2ecf20Sopenharmony_ci return ret; 12898c2ecf20Sopenharmony_ci lock_sock(sk); 12908c2ecf20Sopenharmony_ci ret = tls_sw_do_sendpage(sk, page, offset, size, flags); 12918c2ecf20Sopenharmony_ci release_sock(sk); 12928c2ecf20Sopenharmony_ci mutex_unlock(&tls_ctx->tx_lock); 12938c2ecf20Sopenharmony_ci return ret; 12948c2ecf20Sopenharmony_ci} 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_cistatic struct sk_buff *tls_wait_data(struct sock *sk, struct sk_psock *psock, 12978c2ecf20Sopenharmony_ci bool nonblock, long timeo, int *err) 12988c2ecf20Sopenharmony_ci{ 12998c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 13008c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 13018c2ecf20Sopenharmony_ci struct sk_buff *skb; 13028c2ecf20Sopenharmony_ci DEFINE_WAIT_FUNC(wait, woken_wake_function); 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci while (!(skb = ctx->recv_pkt) && sk_psock_queue_empty(psock)) { 13058c2ecf20Sopenharmony_ci if (sk->sk_err) { 13068c2ecf20Sopenharmony_ci *err = sock_error(sk); 13078c2ecf20Sopenharmony_ci return NULL; 13088c2ecf20Sopenharmony_ci } 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci if (!skb_queue_empty(&sk->sk_receive_queue)) { 13118c2ecf20Sopenharmony_ci __strp_unpause(&ctx->strp); 13128c2ecf20Sopenharmony_ci if (ctx->recv_pkt) 13138c2ecf20Sopenharmony_ci return ctx->recv_pkt; 13148c2ecf20Sopenharmony_ci } 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci if (sk->sk_shutdown & RCV_SHUTDOWN) 13178c2ecf20Sopenharmony_ci return NULL; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci if (sock_flag(sk, SOCK_DONE)) 13208c2ecf20Sopenharmony_ci return NULL; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci if (nonblock || !timeo) { 13238c2ecf20Sopenharmony_ci *err = -EAGAIN; 13248c2ecf20Sopenharmony_ci return NULL; 13258c2ecf20Sopenharmony_ci } 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci add_wait_queue(sk_sleep(sk), &wait); 13288c2ecf20Sopenharmony_ci sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); 13298c2ecf20Sopenharmony_ci sk_wait_event(sk, &timeo, 13308c2ecf20Sopenharmony_ci ctx->recv_pkt != skb || 13318c2ecf20Sopenharmony_ci !sk_psock_queue_empty(psock), 13328c2ecf20Sopenharmony_ci &wait); 13338c2ecf20Sopenharmony_ci sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); 13348c2ecf20Sopenharmony_ci remove_wait_queue(sk_sleep(sk), &wait); 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci /* Handle signals */ 13378c2ecf20Sopenharmony_ci if (signal_pending(current)) { 13388c2ecf20Sopenharmony_ci *err = sock_intr_errno(timeo); 13398c2ecf20Sopenharmony_ci return NULL; 13408c2ecf20Sopenharmony_ci } 13418c2ecf20Sopenharmony_ci } 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci return skb; 13448c2ecf20Sopenharmony_ci} 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_cistatic int tls_setup_from_iter(struct sock *sk, struct iov_iter *from, 13478c2ecf20Sopenharmony_ci int length, int *pages_used, 13488c2ecf20Sopenharmony_ci unsigned int *size_used, 13498c2ecf20Sopenharmony_ci struct scatterlist *to, 13508c2ecf20Sopenharmony_ci int to_max_pages) 13518c2ecf20Sopenharmony_ci{ 13528c2ecf20Sopenharmony_ci int rc = 0, i = 0, num_elem = *pages_used, maxpages; 13538c2ecf20Sopenharmony_ci struct page *pages[MAX_SKB_FRAGS]; 13548c2ecf20Sopenharmony_ci unsigned int size = *size_used; 13558c2ecf20Sopenharmony_ci ssize_t copied, use; 13568c2ecf20Sopenharmony_ci size_t offset; 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci while (length > 0) { 13598c2ecf20Sopenharmony_ci i = 0; 13608c2ecf20Sopenharmony_ci maxpages = to_max_pages - num_elem; 13618c2ecf20Sopenharmony_ci if (maxpages == 0) { 13628c2ecf20Sopenharmony_ci rc = -EFAULT; 13638c2ecf20Sopenharmony_ci goto out; 13648c2ecf20Sopenharmony_ci } 13658c2ecf20Sopenharmony_ci copied = iov_iter_get_pages(from, pages, 13668c2ecf20Sopenharmony_ci length, 13678c2ecf20Sopenharmony_ci maxpages, &offset); 13688c2ecf20Sopenharmony_ci if (copied <= 0) { 13698c2ecf20Sopenharmony_ci rc = -EFAULT; 13708c2ecf20Sopenharmony_ci goto out; 13718c2ecf20Sopenharmony_ci } 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci iov_iter_advance(from, copied); 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci length -= copied; 13768c2ecf20Sopenharmony_ci size += copied; 13778c2ecf20Sopenharmony_ci while (copied) { 13788c2ecf20Sopenharmony_ci use = min_t(int, copied, PAGE_SIZE - offset); 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci sg_set_page(&to[num_elem], 13818c2ecf20Sopenharmony_ci pages[i], use, offset); 13828c2ecf20Sopenharmony_ci sg_unmark_end(&to[num_elem]); 13838c2ecf20Sopenharmony_ci /* We do not uncharge memory from this API */ 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci offset = 0; 13868c2ecf20Sopenharmony_ci copied -= use; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci i++; 13898c2ecf20Sopenharmony_ci num_elem++; 13908c2ecf20Sopenharmony_ci } 13918c2ecf20Sopenharmony_ci } 13928c2ecf20Sopenharmony_ci /* Mark the end in the last sg entry if newly added */ 13938c2ecf20Sopenharmony_ci if (num_elem > *pages_used) 13948c2ecf20Sopenharmony_ci sg_mark_end(&to[num_elem - 1]); 13958c2ecf20Sopenharmony_ciout: 13968c2ecf20Sopenharmony_ci if (rc) 13978c2ecf20Sopenharmony_ci iov_iter_revert(from, size - *size_used); 13988c2ecf20Sopenharmony_ci *size_used = size; 13998c2ecf20Sopenharmony_ci *pages_used = num_elem; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci return rc; 14028c2ecf20Sopenharmony_ci} 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci/* This function decrypts the input skb into either out_iov or in out_sg 14058c2ecf20Sopenharmony_ci * or in skb buffers itself. The input parameter 'zc' indicates if 14068c2ecf20Sopenharmony_ci * zero-copy mode needs to be tried or not. With zero-copy mode, either 14078c2ecf20Sopenharmony_ci * out_iov or out_sg must be non-NULL. In case both out_iov and out_sg are 14088c2ecf20Sopenharmony_ci * NULL, then the decryption happens inside skb buffers itself, i.e. 14098c2ecf20Sopenharmony_ci * zero-copy gets disabled and 'zc' is updated. 14108c2ecf20Sopenharmony_ci */ 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic int decrypt_internal(struct sock *sk, struct sk_buff *skb, 14138c2ecf20Sopenharmony_ci struct iov_iter *out_iov, 14148c2ecf20Sopenharmony_ci struct scatterlist *out_sg, 14158c2ecf20Sopenharmony_ci int *chunk, bool *zc, bool async) 14168c2ecf20Sopenharmony_ci{ 14178c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 14188c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 14198c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 14208c2ecf20Sopenharmony_ci struct strp_msg *rxm = strp_msg(skb); 14218c2ecf20Sopenharmony_ci int n_sgin, n_sgout, nsg, mem_size, aead_size, err, pages = 0; 14228c2ecf20Sopenharmony_ci struct aead_request *aead_req; 14238c2ecf20Sopenharmony_ci struct sk_buff *unused; 14248c2ecf20Sopenharmony_ci u8 *aad, *iv, *mem = NULL; 14258c2ecf20Sopenharmony_ci struct scatterlist *sgin = NULL; 14268c2ecf20Sopenharmony_ci struct scatterlist *sgout = NULL; 14278c2ecf20Sopenharmony_ci const int data_len = rxm->full_len - prot->overhead_size + 14288c2ecf20Sopenharmony_ci prot->tail_size; 14298c2ecf20Sopenharmony_ci int iv_offset = 0; 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci if (*zc && (out_iov || out_sg)) { 14328c2ecf20Sopenharmony_ci if (out_iov) 14338c2ecf20Sopenharmony_ci n_sgout = iov_iter_npages(out_iov, INT_MAX) + 1; 14348c2ecf20Sopenharmony_ci else 14358c2ecf20Sopenharmony_ci n_sgout = sg_nents(out_sg); 14368c2ecf20Sopenharmony_ci n_sgin = skb_nsg(skb, rxm->offset + prot->prepend_size, 14378c2ecf20Sopenharmony_ci rxm->full_len - prot->prepend_size); 14388c2ecf20Sopenharmony_ci } else { 14398c2ecf20Sopenharmony_ci n_sgout = 0; 14408c2ecf20Sopenharmony_ci *zc = false; 14418c2ecf20Sopenharmony_ci n_sgin = skb_cow_data(skb, 0, &unused); 14428c2ecf20Sopenharmony_ci } 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci if (n_sgin < 1) 14458c2ecf20Sopenharmony_ci return -EBADMSG; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci /* Increment to accommodate AAD */ 14488c2ecf20Sopenharmony_ci n_sgin = n_sgin + 1; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci nsg = n_sgin + n_sgout; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci aead_size = sizeof(*aead_req) + crypto_aead_reqsize(ctx->aead_recv); 14538c2ecf20Sopenharmony_ci mem_size = aead_size + (nsg * sizeof(struct scatterlist)); 14548c2ecf20Sopenharmony_ci mem_size = mem_size + prot->aad_size; 14558c2ecf20Sopenharmony_ci mem_size = mem_size + crypto_aead_ivsize(ctx->aead_recv); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci /* Allocate a single block of memory which contains 14588c2ecf20Sopenharmony_ci * aead_req || sgin[] || sgout[] || aad || iv. 14598c2ecf20Sopenharmony_ci * This order achieves correct alignment for aead_req, sgin, sgout. 14608c2ecf20Sopenharmony_ci */ 14618c2ecf20Sopenharmony_ci mem = kmalloc(mem_size, sk->sk_allocation); 14628c2ecf20Sopenharmony_ci if (!mem) 14638c2ecf20Sopenharmony_ci return -ENOMEM; 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci /* Segment the allocated memory */ 14668c2ecf20Sopenharmony_ci aead_req = (struct aead_request *)mem; 14678c2ecf20Sopenharmony_ci sgin = (struct scatterlist *)(mem + aead_size); 14688c2ecf20Sopenharmony_ci sgout = sgin + n_sgin; 14698c2ecf20Sopenharmony_ci aad = (u8 *)(sgout + n_sgout); 14708c2ecf20Sopenharmony_ci iv = aad + prot->aad_size; 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci /* For CCM based ciphers, first byte of nonce+iv is always '2' */ 14738c2ecf20Sopenharmony_ci if (prot->cipher_type == TLS_CIPHER_AES_CCM_128) { 14748c2ecf20Sopenharmony_ci iv[0] = 2; 14758c2ecf20Sopenharmony_ci iv_offset = 1; 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci /* Prepare IV */ 14798c2ecf20Sopenharmony_ci err = skb_copy_bits(skb, rxm->offset + TLS_HEADER_SIZE, 14808c2ecf20Sopenharmony_ci iv + iv_offset + prot->salt_size, 14818c2ecf20Sopenharmony_ci prot->iv_size); 14828c2ecf20Sopenharmony_ci if (err < 0) { 14838c2ecf20Sopenharmony_ci kfree(mem); 14848c2ecf20Sopenharmony_ci return err; 14858c2ecf20Sopenharmony_ci } 14868c2ecf20Sopenharmony_ci if (prot->version == TLS_1_3_VERSION) 14878c2ecf20Sopenharmony_ci memcpy(iv + iv_offset, tls_ctx->rx.iv, 14888c2ecf20Sopenharmony_ci prot->iv_size + prot->salt_size); 14898c2ecf20Sopenharmony_ci else 14908c2ecf20Sopenharmony_ci memcpy(iv + iv_offset, tls_ctx->rx.iv, prot->salt_size); 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci xor_iv_with_seq(prot->version, iv + iv_offset, tls_ctx->rx.rec_seq); 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci /* Prepare AAD */ 14958c2ecf20Sopenharmony_ci tls_make_aad(aad, rxm->full_len - prot->overhead_size + 14968c2ecf20Sopenharmony_ci prot->tail_size, 14978c2ecf20Sopenharmony_ci tls_ctx->rx.rec_seq, prot->rec_seq_size, 14988c2ecf20Sopenharmony_ci ctx->control, prot->version); 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci /* Prepare sgin */ 15018c2ecf20Sopenharmony_ci sg_init_table(sgin, n_sgin); 15028c2ecf20Sopenharmony_ci sg_set_buf(&sgin[0], aad, prot->aad_size); 15038c2ecf20Sopenharmony_ci err = skb_to_sgvec(skb, &sgin[1], 15048c2ecf20Sopenharmony_ci rxm->offset + prot->prepend_size, 15058c2ecf20Sopenharmony_ci rxm->full_len - prot->prepend_size); 15068c2ecf20Sopenharmony_ci if (err < 0) { 15078c2ecf20Sopenharmony_ci kfree(mem); 15088c2ecf20Sopenharmony_ci return err; 15098c2ecf20Sopenharmony_ci } 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci if (n_sgout) { 15128c2ecf20Sopenharmony_ci if (out_iov) { 15138c2ecf20Sopenharmony_ci sg_init_table(sgout, n_sgout); 15148c2ecf20Sopenharmony_ci sg_set_buf(&sgout[0], aad, prot->aad_size); 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci *chunk = 0; 15178c2ecf20Sopenharmony_ci err = tls_setup_from_iter(sk, out_iov, data_len, 15188c2ecf20Sopenharmony_ci &pages, chunk, &sgout[1], 15198c2ecf20Sopenharmony_ci (n_sgout - 1)); 15208c2ecf20Sopenharmony_ci if (err < 0) 15218c2ecf20Sopenharmony_ci goto fallback_to_reg_recv; 15228c2ecf20Sopenharmony_ci } else if (out_sg) { 15238c2ecf20Sopenharmony_ci memcpy(sgout, out_sg, n_sgout * sizeof(*sgout)); 15248c2ecf20Sopenharmony_ci } else { 15258c2ecf20Sopenharmony_ci goto fallback_to_reg_recv; 15268c2ecf20Sopenharmony_ci } 15278c2ecf20Sopenharmony_ci } else { 15288c2ecf20Sopenharmony_cifallback_to_reg_recv: 15298c2ecf20Sopenharmony_ci sgout = sgin; 15308c2ecf20Sopenharmony_ci pages = 0; 15318c2ecf20Sopenharmony_ci *chunk = data_len; 15328c2ecf20Sopenharmony_ci *zc = false; 15338c2ecf20Sopenharmony_ci } 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci /* Prepare and submit AEAD request */ 15368c2ecf20Sopenharmony_ci err = tls_do_decryption(sk, skb, sgin, sgout, iv, 15378c2ecf20Sopenharmony_ci data_len, aead_req, async); 15388c2ecf20Sopenharmony_ci if (err == -EINPROGRESS) 15398c2ecf20Sopenharmony_ci return err; 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci /* Release the pages in case iov was mapped to pages */ 15428c2ecf20Sopenharmony_ci for (; pages > 0; pages--) 15438c2ecf20Sopenharmony_ci put_page(sg_page(&sgout[pages])); 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci kfree(mem); 15468c2ecf20Sopenharmony_ci return err; 15478c2ecf20Sopenharmony_ci} 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_cistatic int decrypt_skb_update(struct sock *sk, struct sk_buff *skb, 15508c2ecf20Sopenharmony_ci struct iov_iter *dest, int *chunk, bool *zc, 15518c2ecf20Sopenharmony_ci bool async) 15528c2ecf20Sopenharmony_ci{ 15538c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 15548c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 15558c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 15568c2ecf20Sopenharmony_ci struct strp_msg *rxm = strp_msg(skb); 15578c2ecf20Sopenharmony_ci int pad, err = 0; 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci if (!ctx->decrypted) { 15608c2ecf20Sopenharmony_ci if (tls_ctx->rx_conf == TLS_HW) { 15618c2ecf20Sopenharmony_ci err = tls_device_decrypted(sk, tls_ctx, skb, rxm); 15628c2ecf20Sopenharmony_ci if (err < 0) 15638c2ecf20Sopenharmony_ci return err; 15648c2ecf20Sopenharmony_ci } 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci /* Still not decrypted after tls_device */ 15678c2ecf20Sopenharmony_ci if (!ctx->decrypted) { 15688c2ecf20Sopenharmony_ci err = decrypt_internal(sk, skb, dest, NULL, chunk, zc, 15698c2ecf20Sopenharmony_ci async); 15708c2ecf20Sopenharmony_ci if (err < 0) { 15718c2ecf20Sopenharmony_ci if (err == -EINPROGRESS) 15728c2ecf20Sopenharmony_ci tls_advance_record_sn(sk, prot, 15738c2ecf20Sopenharmony_ci &tls_ctx->rx); 15748c2ecf20Sopenharmony_ci else if (err == -EBADMSG) 15758c2ecf20Sopenharmony_ci TLS_INC_STATS(sock_net(sk), 15768c2ecf20Sopenharmony_ci LINUX_MIB_TLSDECRYPTERROR); 15778c2ecf20Sopenharmony_ci return err; 15788c2ecf20Sopenharmony_ci } 15798c2ecf20Sopenharmony_ci } else { 15808c2ecf20Sopenharmony_ci *zc = false; 15818c2ecf20Sopenharmony_ci } 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci pad = padding_length(ctx, prot, skb); 15848c2ecf20Sopenharmony_ci if (pad < 0) 15858c2ecf20Sopenharmony_ci return pad; 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci rxm->full_len -= pad; 15888c2ecf20Sopenharmony_ci rxm->offset += prot->prepend_size; 15898c2ecf20Sopenharmony_ci rxm->full_len -= prot->overhead_size; 15908c2ecf20Sopenharmony_ci tls_advance_record_sn(sk, prot, &tls_ctx->rx); 15918c2ecf20Sopenharmony_ci ctx->decrypted = 1; 15928c2ecf20Sopenharmony_ci ctx->saved_data_ready(sk); 15938c2ecf20Sopenharmony_ci } else { 15948c2ecf20Sopenharmony_ci *zc = false; 15958c2ecf20Sopenharmony_ci } 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci return err; 15988c2ecf20Sopenharmony_ci} 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ciint decrypt_skb(struct sock *sk, struct sk_buff *skb, 16018c2ecf20Sopenharmony_ci struct scatterlist *sgout) 16028c2ecf20Sopenharmony_ci{ 16038c2ecf20Sopenharmony_ci bool zc = true; 16048c2ecf20Sopenharmony_ci int chunk; 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci return decrypt_internal(sk, skb, NULL, sgout, &chunk, &zc, false); 16078c2ecf20Sopenharmony_ci} 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_cistatic bool tls_sw_advance_skb(struct sock *sk, struct sk_buff *skb, 16108c2ecf20Sopenharmony_ci unsigned int len) 16118c2ecf20Sopenharmony_ci{ 16128c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 16138c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci if (skb) { 16168c2ecf20Sopenharmony_ci struct strp_msg *rxm = strp_msg(skb); 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci if (len < rxm->full_len) { 16198c2ecf20Sopenharmony_ci rxm->offset += len; 16208c2ecf20Sopenharmony_ci rxm->full_len -= len; 16218c2ecf20Sopenharmony_ci return false; 16228c2ecf20Sopenharmony_ci } 16238c2ecf20Sopenharmony_ci consume_skb(skb); 16248c2ecf20Sopenharmony_ci } 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci /* Finished with message */ 16278c2ecf20Sopenharmony_ci ctx->recv_pkt = NULL; 16288c2ecf20Sopenharmony_ci __strp_unpause(&ctx->strp); 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci return true; 16318c2ecf20Sopenharmony_ci} 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci/* This function traverses the rx_list in tls receive context to copies the 16348c2ecf20Sopenharmony_ci * decrypted records into the buffer provided by caller zero copy is not 16358c2ecf20Sopenharmony_ci * true. Further, the records are removed from the rx_list if it is not a peek 16368c2ecf20Sopenharmony_ci * case and the record has been consumed completely. 16378c2ecf20Sopenharmony_ci */ 16388c2ecf20Sopenharmony_cistatic int process_rx_list(struct tls_sw_context_rx *ctx, 16398c2ecf20Sopenharmony_ci struct msghdr *msg, 16408c2ecf20Sopenharmony_ci u8 *control, 16418c2ecf20Sopenharmony_ci bool *cmsg, 16428c2ecf20Sopenharmony_ci size_t skip, 16438c2ecf20Sopenharmony_ci size_t len, 16448c2ecf20Sopenharmony_ci bool zc, 16458c2ecf20Sopenharmony_ci bool is_peek) 16468c2ecf20Sopenharmony_ci{ 16478c2ecf20Sopenharmony_ci struct sk_buff *skb = skb_peek(&ctx->rx_list); 16488c2ecf20Sopenharmony_ci u8 ctrl = *control; 16498c2ecf20Sopenharmony_ci u8 msgc = *cmsg; 16508c2ecf20Sopenharmony_ci struct tls_msg *tlm; 16518c2ecf20Sopenharmony_ci ssize_t copied = 0; 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci /* Set the record type in 'control' if caller didn't pass it */ 16548c2ecf20Sopenharmony_ci if (!ctrl && skb) { 16558c2ecf20Sopenharmony_ci tlm = tls_msg(skb); 16568c2ecf20Sopenharmony_ci ctrl = tlm->control; 16578c2ecf20Sopenharmony_ci } 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci while (skip && skb) { 16608c2ecf20Sopenharmony_ci struct strp_msg *rxm = strp_msg(skb); 16618c2ecf20Sopenharmony_ci tlm = tls_msg(skb); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci /* Cannot process a record of different type */ 16648c2ecf20Sopenharmony_ci if (ctrl != tlm->control) 16658c2ecf20Sopenharmony_ci return 0; 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (skip < rxm->full_len) 16688c2ecf20Sopenharmony_ci break; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci skip = skip - rxm->full_len; 16718c2ecf20Sopenharmony_ci skb = skb_peek_next(skb, &ctx->rx_list); 16728c2ecf20Sopenharmony_ci } 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_ci while (len && skb) { 16758c2ecf20Sopenharmony_ci struct sk_buff *next_skb; 16768c2ecf20Sopenharmony_ci struct strp_msg *rxm = strp_msg(skb); 16778c2ecf20Sopenharmony_ci int chunk = min_t(unsigned int, rxm->full_len - skip, len); 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci tlm = tls_msg(skb); 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci /* Cannot process a record of different type */ 16828c2ecf20Sopenharmony_ci if (ctrl != tlm->control) 16838c2ecf20Sopenharmony_ci return 0; 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci /* Set record type if not already done. For a non-data record, 16868c2ecf20Sopenharmony_ci * do not proceed if record type could not be copied. 16878c2ecf20Sopenharmony_ci */ 16888c2ecf20Sopenharmony_ci if (!msgc) { 16898c2ecf20Sopenharmony_ci int cerr = put_cmsg(msg, SOL_TLS, TLS_GET_RECORD_TYPE, 16908c2ecf20Sopenharmony_ci sizeof(ctrl), &ctrl); 16918c2ecf20Sopenharmony_ci msgc = true; 16928c2ecf20Sopenharmony_ci if (ctrl != TLS_RECORD_TYPE_DATA) { 16938c2ecf20Sopenharmony_ci if (cerr || msg->msg_flags & MSG_CTRUNC) 16948c2ecf20Sopenharmony_ci return -EIO; 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci *cmsg = msgc; 16978c2ecf20Sopenharmony_ci } 16988c2ecf20Sopenharmony_ci } 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci if (!zc || (rxm->full_len - skip) > len) { 17018c2ecf20Sopenharmony_ci int err = skb_copy_datagram_msg(skb, rxm->offset + skip, 17028c2ecf20Sopenharmony_ci msg, chunk); 17038c2ecf20Sopenharmony_ci if (err < 0) 17048c2ecf20Sopenharmony_ci return err; 17058c2ecf20Sopenharmony_ci } 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci len = len - chunk; 17088c2ecf20Sopenharmony_ci copied = copied + chunk; 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci /* Consume the data from record if it is non-peek case*/ 17118c2ecf20Sopenharmony_ci if (!is_peek) { 17128c2ecf20Sopenharmony_ci rxm->offset = rxm->offset + chunk; 17138c2ecf20Sopenharmony_ci rxm->full_len = rxm->full_len - chunk; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci /* Return if there is unconsumed data in the record */ 17168c2ecf20Sopenharmony_ci if (rxm->full_len - skip) 17178c2ecf20Sopenharmony_ci break; 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci /* The remaining skip-bytes must lie in 1st record in rx_list. 17218c2ecf20Sopenharmony_ci * So from the 2nd record, 'skip' should be 0. 17228c2ecf20Sopenharmony_ci */ 17238c2ecf20Sopenharmony_ci skip = 0; 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci if (msg) 17268c2ecf20Sopenharmony_ci msg->msg_flags |= MSG_EOR; 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci next_skb = skb_peek_next(skb, &ctx->rx_list); 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci if (!is_peek) { 17318c2ecf20Sopenharmony_ci skb_unlink(skb, &ctx->rx_list); 17328c2ecf20Sopenharmony_ci consume_skb(skb); 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci skb = next_skb; 17368c2ecf20Sopenharmony_ci } 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci *control = ctrl; 17398c2ecf20Sopenharmony_ci return copied; 17408c2ecf20Sopenharmony_ci} 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ciint tls_sw_recvmsg(struct sock *sk, 17438c2ecf20Sopenharmony_ci struct msghdr *msg, 17448c2ecf20Sopenharmony_ci size_t len, 17458c2ecf20Sopenharmony_ci int nonblock, 17468c2ecf20Sopenharmony_ci int flags, 17478c2ecf20Sopenharmony_ci int *addr_len) 17488c2ecf20Sopenharmony_ci{ 17498c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 17508c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 17518c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 17528c2ecf20Sopenharmony_ci struct sk_psock *psock; 17538c2ecf20Sopenharmony_ci unsigned char control = 0; 17548c2ecf20Sopenharmony_ci ssize_t decrypted = 0; 17558c2ecf20Sopenharmony_ci struct strp_msg *rxm; 17568c2ecf20Sopenharmony_ci struct tls_msg *tlm; 17578c2ecf20Sopenharmony_ci struct sk_buff *skb; 17588c2ecf20Sopenharmony_ci ssize_t copied = 0; 17598c2ecf20Sopenharmony_ci bool cmsg = false; 17608c2ecf20Sopenharmony_ci int target, err = 0; 17618c2ecf20Sopenharmony_ci long timeo; 17628c2ecf20Sopenharmony_ci bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); 17638c2ecf20Sopenharmony_ci bool is_peek = flags & MSG_PEEK; 17648c2ecf20Sopenharmony_ci bool bpf_strp_enabled; 17658c2ecf20Sopenharmony_ci int num_async = 0; 17668c2ecf20Sopenharmony_ci int pending; 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_ci flags |= nonblock; 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci if (unlikely(flags & MSG_ERRQUEUE)) 17718c2ecf20Sopenharmony_ci return sock_recv_errqueue(sk, msg, len, SOL_IP, IP_RECVERR); 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci psock = sk_psock_get(sk); 17748c2ecf20Sopenharmony_ci lock_sock(sk); 17758c2ecf20Sopenharmony_ci bpf_strp_enabled = sk_psock_strp_enabled(psock); 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci /* Process pending decrypted records. It must be non-zero-copy */ 17788c2ecf20Sopenharmony_ci err = process_rx_list(ctx, msg, &control, &cmsg, 0, len, false, 17798c2ecf20Sopenharmony_ci is_peek); 17808c2ecf20Sopenharmony_ci if (err < 0) { 17818c2ecf20Sopenharmony_ci tls_err_abort(sk, err); 17828c2ecf20Sopenharmony_ci goto end; 17838c2ecf20Sopenharmony_ci } else { 17848c2ecf20Sopenharmony_ci copied = err; 17858c2ecf20Sopenharmony_ci } 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci if (len <= copied) 17888c2ecf20Sopenharmony_ci goto recv_end; 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); 17918c2ecf20Sopenharmony_ci len = len - copied; 17928c2ecf20Sopenharmony_ci timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci while (len && (decrypted + copied < target || ctx->recv_pkt)) { 17958c2ecf20Sopenharmony_ci bool retain_skb = false; 17968c2ecf20Sopenharmony_ci bool zc = false; 17978c2ecf20Sopenharmony_ci int to_decrypt; 17988c2ecf20Sopenharmony_ci int chunk = 0; 17998c2ecf20Sopenharmony_ci bool async_capable; 18008c2ecf20Sopenharmony_ci bool async = false; 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci skb = tls_wait_data(sk, psock, flags & MSG_DONTWAIT, timeo, &err); 18038c2ecf20Sopenharmony_ci if (!skb) { 18048c2ecf20Sopenharmony_ci if (psock) { 18058c2ecf20Sopenharmony_ci int ret = __tcp_bpf_recvmsg(sk, psock, 18068c2ecf20Sopenharmony_ci msg, len, flags); 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci if (ret > 0) { 18098c2ecf20Sopenharmony_ci decrypted += ret; 18108c2ecf20Sopenharmony_ci len -= ret; 18118c2ecf20Sopenharmony_ci continue; 18128c2ecf20Sopenharmony_ci } 18138c2ecf20Sopenharmony_ci } 18148c2ecf20Sopenharmony_ci goto recv_end; 18158c2ecf20Sopenharmony_ci } else { 18168c2ecf20Sopenharmony_ci tlm = tls_msg(skb); 18178c2ecf20Sopenharmony_ci if (prot->version == TLS_1_3_VERSION) 18188c2ecf20Sopenharmony_ci tlm->control = 0; 18198c2ecf20Sopenharmony_ci else 18208c2ecf20Sopenharmony_ci tlm->control = ctx->control; 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci rxm = strp_msg(skb); 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci to_decrypt = rxm->full_len - prot->overhead_size; 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci if (to_decrypt <= len && !is_kvec && !is_peek && 18288c2ecf20Sopenharmony_ci ctx->control == TLS_RECORD_TYPE_DATA && 18298c2ecf20Sopenharmony_ci prot->version != TLS_1_3_VERSION && 18308c2ecf20Sopenharmony_ci !bpf_strp_enabled) 18318c2ecf20Sopenharmony_ci zc = true; 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci /* Do not use async mode if record is non-data */ 18348c2ecf20Sopenharmony_ci if (ctx->control == TLS_RECORD_TYPE_DATA && !bpf_strp_enabled) 18358c2ecf20Sopenharmony_ci async_capable = ctx->async_capable; 18368c2ecf20Sopenharmony_ci else 18378c2ecf20Sopenharmony_ci async_capable = false; 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci err = decrypt_skb_update(sk, skb, &msg->msg_iter, 18408c2ecf20Sopenharmony_ci &chunk, &zc, async_capable); 18418c2ecf20Sopenharmony_ci if (err < 0 && err != -EINPROGRESS) { 18428c2ecf20Sopenharmony_ci tls_err_abort(sk, -EBADMSG); 18438c2ecf20Sopenharmony_ci goto recv_end; 18448c2ecf20Sopenharmony_ci } 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci if (err == -EINPROGRESS) { 18478c2ecf20Sopenharmony_ci async = true; 18488c2ecf20Sopenharmony_ci num_async++; 18498c2ecf20Sopenharmony_ci } else if (prot->version == TLS_1_3_VERSION) { 18508c2ecf20Sopenharmony_ci tlm->control = ctx->control; 18518c2ecf20Sopenharmony_ci } 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci /* If the type of records being processed is not known yet, 18548c2ecf20Sopenharmony_ci * set it to record type just dequeued. If it is already known, 18558c2ecf20Sopenharmony_ci * but does not match the record type just dequeued, go to end. 18568c2ecf20Sopenharmony_ci * We always get record type here since for tls1.2, record type 18578c2ecf20Sopenharmony_ci * is known just after record is dequeued from stream parser. 18588c2ecf20Sopenharmony_ci * For tls1.3, we disable async. 18598c2ecf20Sopenharmony_ci */ 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci if (!control) 18628c2ecf20Sopenharmony_ci control = tlm->control; 18638c2ecf20Sopenharmony_ci else if (control != tlm->control) 18648c2ecf20Sopenharmony_ci goto recv_end; 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci if (!cmsg) { 18678c2ecf20Sopenharmony_ci int cerr; 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci cerr = put_cmsg(msg, SOL_TLS, TLS_GET_RECORD_TYPE, 18708c2ecf20Sopenharmony_ci sizeof(control), &control); 18718c2ecf20Sopenharmony_ci cmsg = true; 18728c2ecf20Sopenharmony_ci if (control != TLS_RECORD_TYPE_DATA) { 18738c2ecf20Sopenharmony_ci if (cerr || msg->msg_flags & MSG_CTRUNC) { 18748c2ecf20Sopenharmony_ci err = -EIO; 18758c2ecf20Sopenharmony_ci goto recv_end; 18768c2ecf20Sopenharmony_ci } 18778c2ecf20Sopenharmony_ci } 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci if (async) 18818c2ecf20Sopenharmony_ci goto pick_next_record; 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci if (!zc) { 18848c2ecf20Sopenharmony_ci if (bpf_strp_enabled) { 18858c2ecf20Sopenharmony_ci err = sk_psock_tls_strp_read(psock, skb); 18868c2ecf20Sopenharmony_ci if (err != __SK_PASS) { 18878c2ecf20Sopenharmony_ci rxm->offset = rxm->offset + rxm->full_len; 18888c2ecf20Sopenharmony_ci rxm->full_len = 0; 18898c2ecf20Sopenharmony_ci if (err == __SK_DROP) 18908c2ecf20Sopenharmony_ci consume_skb(skb); 18918c2ecf20Sopenharmony_ci ctx->recv_pkt = NULL; 18928c2ecf20Sopenharmony_ci __strp_unpause(&ctx->strp); 18938c2ecf20Sopenharmony_ci continue; 18948c2ecf20Sopenharmony_ci } 18958c2ecf20Sopenharmony_ci } 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci if (rxm->full_len > len) { 18988c2ecf20Sopenharmony_ci retain_skb = true; 18998c2ecf20Sopenharmony_ci chunk = len; 19008c2ecf20Sopenharmony_ci } else { 19018c2ecf20Sopenharmony_ci chunk = rxm->full_len; 19028c2ecf20Sopenharmony_ci } 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci err = skb_copy_datagram_msg(skb, rxm->offset, 19058c2ecf20Sopenharmony_ci msg, chunk); 19068c2ecf20Sopenharmony_ci if (err < 0) 19078c2ecf20Sopenharmony_ci goto recv_end; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci if (!is_peek) { 19108c2ecf20Sopenharmony_ci rxm->offset = rxm->offset + chunk; 19118c2ecf20Sopenharmony_ci rxm->full_len = rxm->full_len - chunk; 19128c2ecf20Sopenharmony_ci } 19138c2ecf20Sopenharmony_ci } 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_cipick_next_record: 19168c2ecf20Sopenharmony_ci if (chunk > len) 19178c2ecf20Sopenharmony_ci chunk = len; 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci decrypted += chunk; 19208c2ecf20Sopenharmony_ci len -= chunk; 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci /* For async or peek case, queue the current skb */ 19238c2ecf20Sopenharmony_ci if (async || is_peek || retain_skb) { 19248c2ecf20Sopenharmony_ci skb_queue_tail(&ctx->rx_list, skb); 19258c2ecf20Sopenharmony_ci skb = NULL; 19268c2ecf20Sopenharmony_ci } 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci if (tls_sw_advance_skb(sk, skb, chunk)) { 19298c2ecf20Sopenharmony_ci /* Return full control message to 19308c2ecf20Sopenharmony_ci * userspace before trying to parse 19318c2ecf20Sopenharmony_ci * another message type 19328c2ecf20Sopenharmony_ci */ 19338c2ecf20Sopenharmony_ci msg->msg_flags |= MSG_EOR; 19348c2ecf20Sopenharmony_ci if (control != TLS_RECORD_TYPE_DATA) 19358c2ecf20Sopenharmony_ci goto recv_end; 19368c2ecf20Sopenharmony_ci } else { 19378c2ecf20Sopenharmony_ci break; 19388c2ecf20Sopenharmony_ci } 19398c2ecf20Sopenharmony_ci } 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_cirecv_end: 19428c2ecf20Sopenharmony_ci if (num_async) { 19438c2ecf20Sopenharmony_ci /* Wait for all previously submitted records to be decrypted */ 19448c2ecf20Sopenharmony_ci spin_lock_bh(&ctx->decrypt_compl_lock); 19458c2ecf20Sopenharmony_ci ctx->async_notify = true; 19468c2ecf20Sopenharmony_ci pending = atomic_read(&ctx->decrypt_pending); 19478c2ecf20Sopenharmony_ci spin_unlock_bh(&ctx->decrypt_compl_lock); 19488c2ecf20Sopenharmony_ci if (pending) { 19498c2ecf20Sopenharmony_ci err = crypto_wait_req(-EINPROGRESS, &ctx->async_wait); 19508c2ecf20Sopenharmony_ci if (err) { 19518c2ecf20Sopenharmony_ci /* one of async decrypt failed */ 19528c2ecf20Sopenharmony_ci tls_err_abort(sk, err); 19538c2ecf20Sopenharmony_ci copied = 0; 19548c2ecf20Sopenharmony_ci decrypted = 0; 19558c2ecf20Sopenharmony_ci goto end; 19568c2ecf20Sopenharmony_ci } 19578c2ecf20Sopenharmony_ci } else { 19588c2ecf20Sopenharmony_ci reinit_completion(&ctx->async_wait.completion); 19598c2ecf20Sopenharmony_ci } 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci /* There can be no concurrent accesses, since we have no 19628c2ecf20Sopenharmony_ci * pending decrypt operations 19638c2ecf20Sopenharmony_ci */ 19648c2ecf20Sopenharmony_ci WRITE_ONCE(ctx->async_notify, false); 19658c2ecf20Sopenharmony_ci 19668c2ecf20Sopenharmony_ci /* Drain records from the rx_list & copy if required */ 19678c2ecf20Sopenharmony_ci if (is_peek || is_kvec) 19688c2ecf20Sopenharmony_ci err = process_rx_list(ctx, msg, &control, &cmsg, copied, 19698c2ecf20Sopenharmony_ci decrypted, false, is_peek); 19708c2ecf20Sopenharmony_ci else 19718c2ecf20Sopenharmony_ci err = process_rx_list(ctx, msg, &control, &cmsg, 0, 19728c2ecf20Sopenharmony_ci decrypted, true, is_peek); 19738c2ecf20Sopenharmony_ci if (err < 0) { 19748c2ecf20Sopenharmony_ci tls_err_abort(sk, err); 19758c2ecf20Sopenharmony_ci copied = 0; 19768c2ecf20Sopenharmony_ci goto end; 19778c2ecf20Sopenharmony_ci } 19788c2ecf20Sopenharmony_ci } 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_ci copied += decrypted; 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ciend: 19838c2ecf20Sopenharmony_ci release_sock(sk); 19848c2ecf20Sopenharmony_ci if (psock) 19858c2ecf20Sopenharmony_ci sk_psock_put(sk, psock); 19868c2ecf20Sopenharmony_ci return copied ? : err; 19878c2ecf20Sopenharmony_ci} 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_cissize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, 19908c2ecf20Sopenharmony_ci struct pipe_inode_info *pipe, 19918c2ecf20Sopenharmony_ci size_t len, unsigned int flags) 19928c2ecf20Sopenharmony_ci{ 19938c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sock->sk); 19948c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 19958c2ecf20Sopenharmony_ci struct strp_msg *rxm = NULL; 19968c2ecf20Sopenharmony_ci struct sock *sk = sock->sk; 19978c2ecf20Sopenharmony_ci struct sk_buff *skb; 19988c2ecf20Sopenharmony_ci ssize_t copied = 0; 19998c2ecf20Sopenharmony_ci int err = 0; 20008c2ecf20Sopenharmony_ci long timeo; 20018c2ecf20Sopenharmony_ci int chunk; 20028c2ecf20Sopenharmony_ci bool zc = false; 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci lock_sock(sk); 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci timeo = sock_rcvtimeo(sk, flags & SPLICE_F_NONBLOCK); 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci skb = tls_wait_data(sk, NULL, flags & SPLICE_F_NONBLOCK, timeo, &err); 20098c2ecf20Sopenharmony_ci if (!skb) 20108c2ecf20Sopenharmony_ci goto splice_read_end; 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci err = decrypt_skb_update(sk, skb, NULL, &chunk, &zc, false); 20138c2ecf20Sopenharmony_ci if (err < 0) { 20148c2ecf20Sopenharmony_ci tls_err_abort(sk, -EBADMSG); 20158c2ecf20Sopenharmony_ci goto splice_read_end; 20168c2ecf20Sopenharmony_ci } 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci /* splice does not support reading control messages */ 20198c2ecf20Sopenharmony_ci if (ctx->control != TLS_RECORD_TYPE_DATA) { 20208c2ecf20Sopenharmony_ci err = -EINVAL; 20218c2ecf20Sopenharmony_ci goto splice_read_end; 20228c2ecf20Sopenharmony_ci } 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_ci rxm = strp_msg(skb); 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci chunk = min_t(unsigned int, rxm->full_len, len); 20278c2ecf20Sopenharmony_ci copied = skb_splice_bits(skb, sk, rxm->offset, pipe, chunk, flags); 20288c2ecf20Sopenharmony_ci if (copied < 0) 20298c2ecf20Sopenharmony_ci goto splice_read_end; 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci if (likely(!(flags & MSG_PEEK))) 20328c2ecf20Sopenharmony_ci tls_sw_advance_skb(sk, skb, copied); 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_cisplice_read_end: 20358c2ecf20Sopenharmony_ci release_sock(sk); 20368c2ecf20Sopenharmony_ci return copied ? : err; 20378c2ecf20Sopenharmony_ci} 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_cibool tls_sw_stream_read(const struct sock *sk) 20408c2ecf20Sopenharmony_ci{ 20418c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 20428c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 20438c2ecf20Sopenharmony_ci bool ingress_empty = true; 20448c2ecf20Sopenharmony_ci struct sk_psock *psock; 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_ci rcu_read_lock(); 20478c2ecf20Sopenharmony_ci psock = sk_psock(sk); 20488c2ecf20Sopenharmony_ci if (psock) 20498c2ecf20Sopenharmony_ci ingress_empty = list_empty(&psock->ingress_msg); 20508c2ecf20Sopenharmony_ci rcu_read_unlock(); 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci return !ingress_empty || ctx->recv_pkt || 20538c2ecf20Sopenharmony_ci !skb_queue_empty(&ctx->rx_list); 20548c2ecf20Sopenharmony_ci} 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_cistatic int tls_read_size(struct strparser *strp, struct sk_buff *skb) 20578c2ecf20Sopenharmony_ci{ 20588c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(strp->sk); 20598c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 20608c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 20618c2ecf20Sopenharmony_ci char header[TLS_HEADER_SIZE + MAX_IV_SIZE]; 20628c2ecf20Sopenharmony_ci struct strp_msg *rxm = strp_msg(skb); 20638c2ecf20Sopenharmony_ci size_t cipher_overhead; 20648c2ecf20Sopenharmony_ci size_t data_len = 0; 20658c2ecf20Sopenharmony_ci int ret; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci /* Verify that we have a full TLS header, or wait for more data */ 20688c2ecf20Sopenharmony_ci if (rxm->offset + prot->prepend_size > skb->len) 20698c2ecf20Sopenharmony_ci return 0; 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci /* Sanity-check size of on-stack buffer. */ 20728c2ecf20Sopenharmony_ci if (WARN_ON(prot->prepend_size > sizeof(header))) { 20738c2ecf20Sopenharmony_ci ret = -EINVAL; 20748c2ecf20Sopenharmony_ci goto read_failure; 20758c2ecf20Sopenharmony_ci } 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci /* Linearize header to local buffer */ 20788c2ecf20Sopenharmony_ci ret = skb_copy_bits(skb, rxm->offset, header, prot->prepend_size); 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_ci if (ret < 0) 20818c2ecf20Sopenharmony_ci goto read_failure; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci ctx->control = header[0]; 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci data_len = ((header[4] & 0xFF) | (header[3] << 8)); 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci cipher_overhead = prot->tag_size; 20888c2ecf20Sopenharmony_ci if (prot->version != TLS_1_3_VERSION) 20898c2ecf20Sopenharmony_ci cipher_overhead += prot->iv_size; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci if (data_len > TLS_MAX_PAYLOAD_SIZE + cipher_overhead + 20928c2ecf20Sopenharmony_ci prot->tail_size) { 20938c2ecf20Sopenharmony_ci ret = -EMSGSIZE; 20948c2ecf20Sopenharmony_ci goto read_failure; 20958c2ecf20Sopenharmony_ci } 20968c2ecf20Sopenharmony_ci if (data_len < cipher_overhead) { 20978c2ecf20Sopenharmony_ci ret = -EBADMSG; 20988c2ecf20Sopenharmony_ci goto read_failure; 20998c2ecf20Sopenharmony_ci } 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci /* Note that both TLS1.3 and TLS1.2 use TLS_1_2 version here */ 21028c2ecf20Sopenharmony_ci if (header[1] != TLS_1_2_VERSION_MINOR || 21038c2ecf20Sopenharmony_ci header[2] != TLS_1_2_VERSION_MAJOR) { 21048c2ecf20Sopenharmony_ci ret = -EINVAL; 21058c2ecf20Sopenharmony_ci goto read_failure; 21068c2ecf20Sopenharmony_ci } 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci tls_device_rx_resync_new_rec(strp->sk, data_len + TLS_HEADER_SIZE, 21098c2ecf20Sopenharmony_ci TCP_SKB_CB(skb)->seq + rxm->offset); 21108c2ecf20Sopenharmony_ci return data_len + TLS_HEADER_SIZE; 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ciread_failure: 21138c2ecf20Sopenharmony_ci tls_err_abort(strp->sk, ret); 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci return ret; 21168c2ecf20Sopenharmony_ci} 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_cistatic void tls_queue(struct strparser *strp, struct sk_buff *skb) 21198c2ecf20Sopenharmony_ci{ 21208c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(strp->sk); 21218c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_ci ctx->decrypted = 0; 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci ctx->recv_pkt = skb; 21268c2ecf20Sopenharmony_ci strp_pause(strp); 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci ctx->saved_data_ready(strp->sk); 21298c2ecf20Sopenharmony_ci} 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_cistatic void tls_data_ready(struct sock *sk) 21328c2ecf20Sopenharmony_ci{ 21338c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 21348c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 21358c2ecf20Sopenharmony_ci struct sk_psock *psock; 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_ci strp_data_ready(&ctx->strp); 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci psock = sk_psock_get(sk); 21408c2ecf20Sopenharmony_ci if (psock) { 21418c2ecf20Sopenharmony_ci if (!list_empty(&psock->ingress_msg)) 21428c2ecf20Sopenharmony_ci ctx->saved_data_ready(sk); 21438c2ecf20Sopenharmony_ci sk_psock_put(sk, psock); 21448c2ecf20Sopenharmony_ci } 21458c2ecf20Sopenharmony_ci} 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_civoid tls_sw_cancel_work_tx(struct tls_context *tls_ctx) 21488c2ecf20Sopenharmony_ci{ 21498c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci set_bit(BIT_TX_CLOSING, &ctx->tx_bitmask); 21528c2ecf20Sopenharmony_ci set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask); 21538c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&ctx->tx_work.work); 21548c2ecf20Sopenharmony_ci} 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_civoid tls_sw_release_resources_tx(struct sock *sk) 21578c2ecf20Sopenharmony_ci{ 21588c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 21598c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 21608c2ecf20Sopenharmony_ci struct tls_rec *rec, *tmp; 21618c2ecf20Sopenharmony_ci int pending; 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci /* Wait for any pending async encryptions to complete */ 21648c2ecf20Sopenharmony_ci spin_lock_bh(&ctx->encrypt_compl_lock); 21658c2ecf20Sopenharmony_ci ctx->async_notify = true; 21668c2ecf20Sopenharmony_ci pending = atomic_read(&ctx->encrypt_pending); 21678c2ecf20Sopenharmony_ci spin_unlock_bh(&ctx->encrypt_compl_lock); 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci if (pending) 21708c2ecf20Sopenharmony_ci crypto_wait_req(-EINPROGRESS, &ctx->async_wait); 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci tls_tx_records(sk, -1); 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci /* Free up un-sent records in tx_list. First, free 21758c2ecf20Sopenharmony_ci * the partially sent record if any at head of tx_list. 21768c2ecf20Sopenharmony_ci */ 21778c2ecf20Sopenharmony_ci if (tls_ctx->partially_sent_record) { 21788c2ecf20Sopenharmony_ci tls_free_partial_record(sk, tls_ctx); 21798c2ecf20Sopenharmony_ci rec = list_first_entry(&ctx->tx_list, 21808c2ecf20Sopenharmony_ci struct tls_rec, list); 21818c2ecf20Sopenharmony_ci list_del(&rec->list); 21828c2ecf20Sopenharmony_ci sk_msg_free(sk, &rec->msg_plaintext); 21838c2ecf20Sopenharmony_ci kfree(rec); 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci list_for_each_entry_safe(rec, tmp, &ctx->tx_list, list) { 21878c2ecf20Sopenharmony_ci list_del(&rec->list); 21888c2ecf20Sopenharmony_ci sk_msg_free(sk, &rec->msg_encrypted); 21898c2ecf20Sopenharmony_ci sk_msg_free(sk, &rec->msg_plaintext); 21908c2ecf20Sopenharmony_ci kfree(rec); 21918c2ecf20Sopenharmony_ci } 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_ci crypto_free_aead(ctx->aead_send); 21948c2ecf20Sopenharmony_ci tls_free_open_rec(sk); 21958c2ecf20Sopenharmony_ci} 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_civoid tls_sw_free_ctx_tx(struct tls_context *tls_ctx) 21988c2ecf20Sopenharmony_ci{ 21998c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci kfree(ctx); 22028c2ecf20Sopenharmony_ci} 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_civoid tls_sw_release_resources_rx(struct sock *sk) 22058c2ecf20Sopenharmony_ci{ 22068c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 22078c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci kfree(tls_ctx->rx.rec_seq); 22108c2ecf20Sopenharmony_ci kfree(tls_ctx->rx.iv); 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_ci if (ctx->aead_recv) { 22138c2ecf20Sopenharmony_ci kfree_skb(ctx->recv_pkt); 22148c2ecf20Sopenharmony_ci ctx->recv_pkt = NULL; 22158c2ecf20Sopenharmony_ci skb_queue_purge(&ctx->rx_list); 22168c2ecf20Sopenharmony_ci crypto_free_aead(ctx->aead_recv); 22178c2ecf20Sopenharmony_ci strp_stop(&ctx->strp); 22188c2ecf20Sopenharmony_ci /* If tls_sw_strparser_arm() was not called (cleanup paths) 22198c2ecf20Sopenharmony_ci * we still want to strp_stop(), but sk->sk_data_ready was 22208c2ecf20Sopenharmony_ci * never swapped. 22218c2ecf20Sopenharmony_ci */ 22228c2ecf20Sopenharmony_ci if (ctx->saved_data_ready) { 22238c2ecf20Sopenharmony_ci write_lock_bh(&sk->sk_callback_lock); 22248c2ecf20Sopenharmony_ci sk->sk_data_ready = ctx->saved_data_ready; 22258c2ecf20Sopenharmony_ci write_unlock_bh(&sk->sk_callback_lock); 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci } 22288c2ecf20Sopenharmony_ci} 22298c2ecf20Sopenharmony_ci 22308c2ecf20Sopenharmony_civoid tls_sw_strparser_done(struct tls_context *tls_ctx) 22318c2ecf20Sopenharmony_ci{ 22328c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci strp_done(&ctx->strp); 22358c2ecf20Sopenharmony_ci} 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_civoid tls_sw_free_ctx_rx(struct tls_context *tls_ctx) 22388c2ecf20Sopenharmony_ci{ 22398c2ecf20Sopenharmony_ci struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci kfree(ctx); 22428c2ecf20Sopenharmony_ci} 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_civoid tls_sw_free_resources_rx(struct sock *sk) 22458c2ecf20Sopenharmony_ci{ 22468c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci tls_sw_release_resources_rx(sk); 22498c2ecf20Sopenharmony_ci tls_sw_free_ctx_rx(tls_ctx); 22508c2ecf20Sopenharmony_ci} 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci/* The work handler to transmitt the encrypted records in tx_list */ 22538c2ecf20Sopenharmony_cistatic void tx_work_handler(struct work_struct *work) 22548c2ecf20Sopenharmony_ci{ 22558c2ecf20Sopenharmony_ci struct delayed_work *delayed_work = to_delayed_work(work); 22568c2ecf20Sopenharmony_ci struct tx_work *tx_work = container_of(delayed_work, 22578c2ecf20Sopenharmony_ci struct tx_work, work); 22588c2ecf20Sopenharmony_ci struct sock *sk = tx_work->sk; 22598c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 22608c2ecf20Sopenharmony_ci struct tls_sw_context_tx *ctx; 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_ci if (unlikely(!tls_ctx)) 22638c2ecf20Sopenharmony_ci return; 22648c2ecf20Sopenharmony_ci 22658c2ecf20Sopenharmony_ci ctx = tls_sw_ctx_tx(tls_ctx); 22668c2ecf20Sopenharmony_ci if (test_bit(BIT_TX_CLOSING, &ctx->tx_bitmask)) 22678c2ecf20Sopenharmony_ci return; 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) 22708c2ecf20Sopenharmony_ci return; 22718c2ecf20Sopenharmony_ci 22728c2ecf20Sopenharmony_ci if (mutex_trylock(&tls_ctx->tx_lock)) { 22738c2ecf20Sopenharmony_ci lock_sock(sk); 22748c2ecf20Sopenharmony_ci tls_tx_records(sk, -1); 22758c2ecf20Sopenharmony_ci release_sock(sk); 22768c2ecf20Sopenharmony_ci mutex_unlock(&tls_ctx->tx_lock); 22778c2ecf20Sopenharmony_ci } else if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) { 22788c2ecf20Sopenharmony_ci /* Someone is holding the tx_lock, they will likely run Tx 22798c2ecf20Sopenharmony_ci * and cancel the work on their way out of the lock section. 22808c2ecf20Sopenharmony_ci * Schedule a long delay just in case. 22818c2ecf20Sopenharmony_ci */ 22828c2ecf20Sopenharmony_ci schedule_delayed_work(&ctx->tx_work.work, msecs_to_jiffies(10)); 22838c2ecf20Sopenharmony_ci } 22848c2ecf20Sopenharmony_ci} 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_civoid tls_sw_write_space(struct sock *sk, struct tls_context *ctx) 22878c2ecf20Sopenharmony_ci{ 22888c2ecf20Sopenharmony_ci struct tls_sw_context_tx *tx_ctx = tls_sw_ctx_tx(ctx); 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci /* Schedule the transmission if tx list is ready */ 22918c2ecf20Sopenharmony_ci if (is_tx_ready(tx_ctx) && 22928c2ecf20Sopenharmony_ci !test_and_set_bit(BIT_TX_SCHEDULED, &tx_ctx->tx_bitmask)) 22938c2ecf20Sopenharmony_ci schedule_delayed_work(&tx_ctx->tx_work.work, 0); 22948c2ecf20Sopenharmony_ci} 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_civoid tls_sw_strparser_arm(struct sock *sk, struct tls_context *tls_ctx) 22978c2ecf20Sopenharmony_ci{ 22988c2ecf20Sopenharmony_ci struct tls_sw_context_rx *rx_ctx = tls_sw_ctx_rx(tls_ctx); 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci write_lock_bh(&sk->sk_callback_lock); 23018c2ecf20Sopenharmony_ci rx_ctx->saved_data_ready = sk->sk_data_ready; 23028c2ecf20Sopenharmony_ci sk->sk_data_ready = tls_data_ready; 23038c2ecf20Sopenharmony_ci write_unlock_bh(&sk->sk_callback_lock); 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci strp_check_rcv(&rx_ctx->strp); 23068c2ecf20Sopenharmony_ci} 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ciint tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) 23098c2ecf20Sopenharmony_ci{ 23108c2ecf20Sopenharmony_ci struct tls_context *tls_ctx = tls_get_ctx(sk); 23118c2ecf20Sopenharmony_ci struct tls_prot_info *prot = &tls_ctx->prot_info; 23128c2ecf20Sopenharmony_ci struct tls_crypto_info *crypto_info; 23138c2ecf20Sopenharmony_ci struct tls12_crypto_info_aes_gcm_128 *gcm_128_info; 23148c2ecf20Sopenharmony_ci struct tls12_crypto_info_aes_gcm_256 *gcm_256_info; 23158c2ecf20Sopenharmony_ci struct tls12_crypto_info_aes_ccm_128 *ccm_128_info; 23168c2ecf20Sopenharmony_ci struct tls_sw_context_tx *sw_ctx_tx = NULL; 23178c2ecf20Sopenharmony_ci struct tls_sw_context_rx *sw_ctx_rx = NULL; 23188c2ecf20Sopenharmony_ci struct cipher_context *cctx; 23198c2ecf20Sopenharmony_ci struct crypto_aead **aead; 23208c2ecf20Sopenharmony_ci struct strp_callbacks cb; 23218c2ecf20Sopenharmony_ci u16 nonce_size, tag_size, iv_size, rec_seq_size, salt_size; 23228c2ecf20Sopenharmony_ci struct crypto_tfm *tfm; 23238c2ecf20Sopenharmony_ci char *iv, *rec_seq, *key, *salt, *cipher_name; 23248c2ecf20Sopenharmony_ci size_t keysize; 23258c2ecf20Sopenharmony_ci int rc = 0; 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci if (!ctx) { 23288c2ecf20Sopenharmony_ci rc = -EINVAL; 23298c2ecf20Sopenharmony_ci goto out; 23308c2ecf20Sopenharmony_ci } 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci if (tx) { 23338c2ecf20Sopenharmony_ci if (!ctx->priv_ctx_tx) { 23348c2ecf20Sopenharmony_ci sw_ctx_tx = kzalloc(sizeof(*sw_ctx_tx), GFP_KERNEL); 23358c2ecf20Sopenharmony_ci if (!sw_ctx_tx) { 23368c2ecf20Sopenharmony_ci rc = -ENOMEM; 23378c2ecf20Sopenharmony_ci goto out; 23388c2ecf20Sopenharmony_ci } 23398c2ecf20Sopenharmony_ci ctx->priv_ctx_tx = sw_ctx_tx; 23408c2ecf20Sopenharmony_ci } else { 23418c2ecf20Sopenharmony_ci sw_ctx_tx = 23428c2ecf20Sopenharmony_ci (struct tls_sw_context_tx *)ctx->priv_ctx_tx; 23438c2ecf20Sopenharmony_ci } 23448c2ecf20Sopenharmony_ci } else { 23458c2ecf20Sopenharmony_ci if (!ctx->priv_ctx_rx) { 23468c2ecf20Sopenharmony_ci sw_ctx_rx = kzalloc(sizeof(*sw_ctx_rx), GFP_KERNEL); 23478c2ecf20Sopenharmony_ci if (!sw_ctx_rx) { 23488c2ecf20Sopenharmony_ci rc = -ENOMEM; 23498c2ecf20Sopenharmony_ci goto out; 23508c2ecf20Sopenharmony_ci } 23518c2ecf20Sopenharmony_ci ctx->priv_ctx_rx = sw_ctx_rx; 23528c2ecf20Sopenharmony_ci } else { 23538c2ecf20Sopenharmony_ci sw_ctx_rx = 23548c2ecf20Sopenharmony_ci (struct tls_sw_context_rx *)ctx->priv_ctx_rx; 23558c2ecf20Sopenharmony_ci } 23568c2ecf20Sopenharmony_ci } 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci if (tx) { 23598c2ecf20Sopenharmony_ci crypto_init_wait(&sw_ctx_tx->async_wait); 23608c2ecf20Sopenharmony_ci spin_lock_init(&sw_ctx_tx->encrypt_compl_lock); 23618c2ecf20Sopenharmony_ci crypto_info = &ctx->crypto_send.info; 23628c2ecf20Sopenharmony_ci cctx = &ctx->tx; 23638c2ecf20Sopenharmony_ci aead = &sw_ctx_tx->aead_send; 23648c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sw_ctx_tx->tx_list); 23658c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&sw_ctx_tx->tx_work.work, tx_work_handler); 23668c2ecf20Sopenharmony_ci sw_ctx_tx->tx_work.sk = sk; 23678c2ecf20Sopenharmony_ci } else { 23688c2ecf20Sopenharmony_ci crypto_init_wait(&sw_ctx_rx->async_wait); 23698c2ecf20Sopenharmony_ci spin_lock_init(&sw_ctx_rx->decrypt_compl_lock); 23708c2ecf20Sopenharmony_ci crypto_info = &ctx->crypto_recv.info; 23718c2ecf20Sopenharmony_ci cctx = &ctx->rx; 23728c2ecf20Sopenharmony_ci skb_queue_head_init(&sw_ctx_rx->rx_list); 23738c2ecf20Sopenharmony_ci aead = &sw_ctx_rx->aead_recv; 23748c2ecf20Sopenharmony_ci } 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_ci switch (crypto_info->cipher_type) { 23778c2ecf20Sopenharmony_ci case TLS_CIPHER_AES_GCM_128: { 23788c2ecf20Sopenharmony_ci nonce_size = TLS_CIPHER_AES_GCM_128_IV_SIZE; 23798c2ecf20Sopenharmony_ci tag_size = TLS_CIPHER_AES_GCM_128_TAG_SIZE; 23808c2ecf20Sopenharmony_ci iv_size = TLS_CIPHER_AES_GCM_128_IV_SIZE; 23818c2ecf20Sopenharmony_ci iv = ((struct tls12_crypto_info_aes_gcm_128 *)crypto_info)->iv; 23828c2ecf20Sopenharmony_ci rec_seq_size = TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE; 23838c2ecf20Sopenharmony_ci rec_seq = 23848c2ecf20Sopenharmony_ci ((struct tls12_crypto_info_aes_gcm_128 *)crypto_info)->rec_seq; 23858c2ecf20Sopenharmony_ci gcm_128_info = 23868c2ecf20Sopenharmony_ci (struct tls12_crypto_info_aes_gcm_128 *)crypto_info; 23878c2ecf20Sopenharmony_ci keysize = TLS_CIPHER_AES_GCM_128_KEY_SIZE; 23888c2ecf20Sopenharmony_ci key = gcm_128_info->key; 23898c2ecf20Sopenharmony_ci salt = gcm_128_info->salt; 23908c2ecf20Sopenharmony_ci salt_size = TLS_CIPHER_AES_GCM_128_SALT_SIZE; 23918c2ecf20Sopenharmony_ci cipher_name = "gcm(aes)"; 23928c2ecf20Sopenharmony_ci break; 23938c2ecf20Sopenharmony_ci } 23948c2ecf20Sopenharmony_ci case TLS_CIPHER_AES_GCM_256: { 23958c2ecf20Sopenharmony_ci nonce_size = TLS_CIPHER_AES_GCM_256_IV_SIZE; 23968c2ecf20Sopenharmony_ci tag_size = TLS_CIPHER_AES_GCM_256_TAG_SIZE; 23978c2ecf20Sopenharmony_ci iv_size = TLS_CIPHER_AES_GCM_256_IV_SIZE; 23988c2ecf20Sopenharmony_ci iv = ((struct tls12_crypto_info_aes_gcm_256 *)crypto_info)->iv; 23998c2ecf20Sopenharmony_ci rec_seq_size = TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE; 24008c2ecf20Sopenharmony_ci rec_seq = 24018c2ecf20Sopenharmony_ci ((struct tls12_crypto_info_aes_gcm_256 *)crypto_info)->rec_seq; 24028c2ecf20Sopenharmony_ci gcm_256_info = 24038c2ecf20Sopenharmony_ci (struct tls12_crypto_info_aes_gcm_256 *)crypto_info; 24048c2ecf20Sopenharmony_ci keysize = TLS_CIPHER_AES_GCM_256_KEY_SIZE; 24058c2ecf20Sopenharmony_ci key = gcm_256_info->key; 24068c2ecf20Sopenharmony_ci salt = gcm_256_info->salt; 24078c2ecf20Sopenharmony_ci salt_size = TLS_CIPHER_AES_GCM_256_SALT_SIZE; 24088c2ecf20Sopenharmony_ci cipher_name = "gcm(aes)"; 24098c2ecf20Sopenharmony_ci break; 24108c2ecf20Sopenharmony_ci } 24118c2ecf20Sopenharmony_ci case TLS_CIPHER_AES_CCM_128: { 24128c2ecf20Sopenharmony_ci nonce_size = TLS_CIPHER_AES_CCM_128_IV_SIZE; 24138c2ecf20Sopenharmony_ci tag_size = TLS_CIPHER_AES_CCM_128_TAG_SIZE; 24148c2ecf20Sopenharmony_ci iv_size = TLS_CIPHER_AES_CCM_128_IV_SIZE; 24158c2ecf20Sopenharmony_ci iv = ((struct tls12_crypto_info_aes_ccm_128 *)crypto_info)->iv; 24168c2ecf20Sopenharmony_ci rec_seq_size = TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE; 24178c2ecf20Sopenharmony_ci rec_seq = 24188c2ecf20Sopenharmony_ci ((struct tls12_crypto_info_aes_ccm_128 *)crypto_info)->rec_seq; 24198c2ecf20Sopenharmony_ci ccm_128_info = 24208c2ecf20Sopenharmony_ci (struct tls12_crypto_info_aes_ccm_128 *)crypto_info; 24218c2ecf20Sopenharmony_ci keysize = TLS_CIPHER_AES_CCM_128_KEY_SIZE; 24228c2ecf20Sopenharmony_ci key = ccm_128_info->key; 24238c2ecf20Sopenharmony_ci salt = ccm_128_info->salt; 24248c2ecf20Sopenharmony_ci salt_size = TLS_CIPHER_AES_CCM_128_SALT_SIZE; 24258c2ecf20Sopenharmony_ci cipher_name = "ccm(aes)"; 24268c2ecf20Sopenharmony_ci break; 24278c2ecf20Sopenharmony_ci } 24288c2ecf20Sopenharmony_ci default: 24298c2ecf20Sopenharmony_ci rc = -EINVAL; 24308c2ecf20Sopenharmony_ci goto free_priv; 24318c2ecf20Sopenharmony_ci } 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci /* Sanity-check the sizes for stack allocations. */ 24348c2ecf20Sopenharmony_ci if (iv_size > MAX_IV_SIZE || nonce_size > MAX_IV_SIZE || 24358c2ecf20Sopenharmony_ci rec_seq_size > TLS_MAX_REC_SEQ_SIZE) { 24368c2ecf20Sopenharmony_ci rc = -EINVAL; 24378c2ecf20Sopenharmony_ci goto free_priv; 24388c2ecf20Sopenharmony_ci } 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci if (crypto_info->version == TLS_1_3_VERSION) { 24418c2ecf20Sopenharmony_ci nonce_size = 0; 24428c2ecf20Sopenharmony_ci prot->aad_size = TLS_HEADER_SIZE; 24438c2ecf20Sopenharmony_ci prot->tail_size = 1; 24448c2ecf20Sopenharmony_ci } else { 24458c2ecf20Sopenharmony_ci prot->aad_size = TLS_AAD_SPACE_SIZE; 24468c2ecf20Sopenharmony_ci prot->tail_size = 0; 24478c2ecf20Sopenharmony_ci } 24488c2ecf20Sopenharmony_ci 24498c2ecf20Sopenharmony_ci prot->version = crypto_info->version; 24508c2ecf20Sopenharmony_ci prot->cipher_type = crypto_info->cipher_type; 24518c2ecf20Sopenharmony_ci prot->prepend_size = TLS_HEADER_SIZE + nonce_size; 24528c2ecf20Sopenharmony_ci prot->tag_size = tag_size; 24538c2ecf20Sopenharmony_ci prot->overhead_size = prot->prepend_size + 24548c2ecf20Sopenharmony_ci prot->tag_size + prot->tail_size; 24558c2ecf20Sopenharmony_ci prot->iv_size = iv_size; 24568c2ecf20Sopenharmony_ci prot->salt_size = salt_size; 24578c2ecf20Sopenharmony_ci cctx->iv = kmalloc(iv_size + salt_size, GFP_KERNEL); 24588c2ecf20Sopenharmony_ci if (!cctx->iv) { 24598c2ecf20Sopenharmony_ci rc = -ENOMEM; 24608c2ecf20Sopenharmony_ci goto free_priv; 24618c2ecf20Sopenharmony_ci } 24628c2ecf20Sopenharmony_ci /* Note: 128 & 256 bit salt are the same size */ 24638c2ecf20Sopenharmony_ci prot->rec_seq_size = rec_seq_size; 24648c2ecf20Sopenharmony_ci memcpy(cctx->iv, salt, salt_size); 24658c2ecf20Sopenharmony_ci memcpy(cctx->iv + salt_size, iv, iv_size); 24668c2ecf20Sopenharmony_ci cctx->rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL); 24678c2ecf20Sopenharmony_ci if (!cctx->rec_seq) { 24688c2ecf20Sopenharmony_ci rc = -ENOMEM; 24698c2ecf20Sopenharmony_ci goto free_iv; 24708c2ecf20Sopenharmony_ci } 24718c2ecf20Sopenharmony_ci 24728c2ecf20Sopenharmony_ci if (!*aead) { 24738c2ecf20Sopenharmony_ci *aead = crypto_alloc_aead(cipher_name, 0, 0); 24748c2ecf20Sopenharmony_ci if (IS_ERR(*aead)) { 24758c2ecf20Sopenharmony_ci rc = PTR_ERR(*aead); 24768c2ecf20Sopenharmony_ci *aead = NULL; 24778c2ecf20Sopenharmony_ci goto free_rec_seq; 24788c2ecf20Sopenharmony_ci } 24798c2ecf20Sopenharmony_ci } 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci ctx->push_pending_record = tls_sw_push_pending_record; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci rc = crypto_aead_setkey(*aead, key, keysize); 24848c2ecf20Sopenharmony_ci 24858c2ecf20Sopenharmony_ci if (rc) 24868c2ecf20Sopenharmony_ci goto free_aead; 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci rc = crypto_aead_setauthsize(*aead, prot->tag_size); 24898c2ecf20Sopenharmony_ci if (rc) 24908c2ecf20Sopenharmony_ci goto free_aead; 24918c2ecf20Sopenharmony_ci 24928c2ecf20Sopenharmony_ci if (sw_ctx_rx) { 24938c2ecf20Sopenharmony_ci tfm = crypto_aead_tfm(sw_ctx_rx->aead_recv); 24948c2ecf20Sopenharmony_ci 24958c2ecf20Sopenharmony_ci if (crypto_info->version == TLS_1_3_VERSION) 24968c2ecf20Sopenharmony_ci sw_ctx_rx->async_capable = 0; 24978c2ecf20Sopenharmony_ci else 24988c2ecf20Sopenharmony_ci sw_ctx_rx->async_capable = 24998c2ecf20Sopenharmony_ci !!(tfm->__crt_alg->cra_flags & 25008c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC); 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci /* Set up strparser */ 25038c2ecf20Sopenharmony_ci memset(&cb, 0, sizeof(cb)); 25048c2ecf20Sopenharmony_ci cb.rcv_msg = tls_queue; 25058c2ecf20Sopenharmony_ci cb.parse_msg = tls_read_size; 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci strp_init(&sw_ctx_rx->strp, sk, &cb); 25088c2ecf20Sopenharmony_ci } 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_ci goto out; 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_cifree_aead: 25138c2ecf20Sopenharmony_ci crypto_free_aead(*aead); 25148c2ecf20Sopenharmony_ci *aead = NULL; 25158c2ecf20Sopenharmony_cifree_rec_seq: 25168c2ecf20Sopenharmony_ci kfree(cctx->rec_seq); 25178c2ecf20Sopenharmony_ci cctx->rec_seq = NULL; 25188c2ecf20Sopenharmony_cifree_iv: 25198c2ecf20Sopenharmony_ci kfree(cctx->iv); 25208c2ecf20Sopenharmony_ci cctx->iv = NULL; 25218c2ecf20Sopenharmony_cifree_priv: 25228c2ecf20Sopenharmony_ci if (tx) { 25238c2ecf20Sopenharmony_ci kfree(ctx->priv_ctx_tx); 25248c2ecf20Sopenharmony_ci ctx->priv_ctx_tx = NULL; 25258c2ecf20Sopenharmony_ci } else { 25268c2ecf20Sopenharmony_ci kfree(ctx->priv_ctx_rx); 25278c2ecf20Sopenharmony_ci ctx->priv_ctx_rx = NULL; 25288c2ecf20Sopenharmony_ci } 25298c2ecf20Sopenharmony_ciout: 25308c2ecf20Sopenharmony_ci return rc; 25318c2ecf20Sopenharmony_ci} 2532