18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * algif_skcipher: User-space interface for skcipher algorithms 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file provides the user-space API for symmetric key ciphers. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * The following concept of the memory management is used: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is 128c2ecf20Sopenharmony_ci * filled by user space with the data submitted via sendpage/sendmsg. Filling 138c2ecf20Sopenharmony_ci * up the TX SGL does not cause a crypto operation -- the data will only be 148c2ecf20Sopenharmony_ci * tracked by the kernel. Upon receipt of one recvmsg call, the caller must 158c2ecf20Sopenharmony_ci * provide a buffer which is tracked with the RX SGL. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * During the processing of the recvmsg operation, the cipher request is 188c2ecf20Sopenharmony_ci * allocated and prepared. As part of the recvmsg operation, the processed 198c2ecf20Sopenharmony_ci * TX buffers are extracted from the TX SGL into a separate SGL. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * After the completion of the crypto operation, the RX SGL and the cipher 228c2ecf20Sopenharmony_ci * request is released. The extracted TX SGL parts are released together with 238c2ecf20Sopenharmony_ci * the RX SGL release. 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 278c2ecf20Sopenharmony_ci#include <crypto/skcipher.h> 288c2ecf20Sopenharmony_ci#include <crypto/if_alg.h> 298c2ecf20Sopenharmony_ci#include <linux/init.h> 308c2ecf20Sopenharmony_ci#include <linux/list.h> 318c2ecf20Sopenharmony_ci#include <linux/kernel.h> 328c2ecf20Sopenharmony_ci#include <linux/mm.h> 338c2ecf20Sopenharmony_ci#include <linux/module.h> 348c2ecf20Sopenharmony_ci#include <linux/net.h> 358c2ecf20Sopenharmony_ci#include <net/sock.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic int skcipher_sendmsg(struct socket *sock, struct msghdr *msg, 388c2ecf20Sopenharmony_ci size_t size) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci struct sock *sk = sock->sk; 418c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 428c2ecf20Sopenharmony_ci struct sock *psk = ask->parent; 438c2ecf20Sopenharmony_ci struct alg_sock *pask = alg_sk(psk); 448c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = pask->private; 458c2ecf20Sopenharmony_ci unsigned ivsize = crypto_skcipher_ivsize(tfm); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci return af_alg_sendmsg(sock, msg, size, ivsize); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, 518c2ecf20Sopenharmony_ci size_t ignored, int flags) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci struct sock *sk = sock->sk; 548c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 558c2ecf20Sopenharmony_ci struct sock *psk = ask->parent; 568c2ecf20Sopenharmony_ci struct alg_sock *pask = alg_sk(psk); 578c2ecf20Sopenharmony_ci struct af_alg_ctx *ctx = ask->private; 588c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = pask->private; 598c2ecf20Sopenharmony_ci unsigned int bs = crypto_skcipher_chunksize(tfm); 608c2ecf20Sopenharmony_ci struct af_alg_async_req *areq; 618c2ecf20Sopenharmony_ci int err = 0; 628c2ecf20Sopenharmony_ci size_t len = 0; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (!ctx->init || (ctx->more && ctx->used < bs)) { 658c2ecf20Sopenharmony_ci err = af_alg_wait_for_data(sk, flags, bs); 668c2ecf20Sopenharmony_ci if (err) 678c2ecf20Sopenharmony_ci return err; 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* Allocate cipher request for current operation. */ 718c2ecf20Sopenharmony_ci areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) + 728c2ecf20Sopenharmony_ci crypto_skcipher_reqsize(tfm)); 738c2ecf20Sopenharmony_ci if (IS_ERR(areq)) 748c2ecf20Sopenharmony_ci return PTR_ERR(areq); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* convert iovecs of output buffers into RX SGL */ 778c2ecf20Sopenharmony_ci err = af_alg_get_rsgl(sk, msg, flags, areq, ctx->used, &len); 788c2ecf20Sopenharmony_ci if (err) 798c2ecf20Sopenharmony_ci goto free; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* 828c2ecf20Sopenharmony_ci * If more buffers are to be expected to be processed, process only 838c2ecf20Sopenharmony_ci * full block size buffers. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci if (ctx->more || len < ctx->used) 868c2ecf20Sopenharmony_ci len -= len % bs; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * Create a per request TX SGL for this request which tracks the 908c2ecf20Sopenharmony_ci * SG entries from the global TX SGL. 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_ci areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0); 938c2ecf20Sopenharmony_ci if (!areq->tsgl_entries) 948c2ecf20Sopenharmony_ci areq->tsgl_entries = 1; 958c2ecf20Sopenharmony_ci areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl), 968c2ecf20Sopenharmony_ci areq->tsgl_entries), 978c2ecf20Sopenharmony_ci GFP_KERNEL); 988c2ecf20Sopenharmony_ci if (!areq->tsgl) { 998c2ecf20Sopenharmony_ci err = -ENOMEM; 1008c2ecf20Sopenharmony_ci goto free; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci sg_init_table(areq->tsgl, areq->tsgl_entries); 1038c2ecf20Sopenharmony_ci af_alg_pull_tsgl(sk, len, areq->tsgl, 0); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* Initialize the crypto operation */ 1068c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm); 1078c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl, 1088c2ecf20Sopenharmony_ci areq->first_rsgl.sgl.sg, len, ctx->iv); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { 1118c2ecf20Sopenharmony_ci /* AIO operation */ 1128c2ecf20Sopenharmony_ci sock_hold(sk); 1138c2ecf20Sopenharmony_ci areq->iocb = msg->msg_iocb; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci /* Remember output size that will be generated. */ 1168c2ecf20Sopenharmony_ci areq->outlen = len; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci skcipher_request_set_callback(&areq->cra_u.skcipher_req, 1198c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP, 1208c2ecf20Sopenharmony_ci af_alg_async_cb, areq); 1218c2ecf20Sopenharmony_ci err = ctx->enc ? 1228c2ecf20Sopenharmony_ci crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) : 1238c2ecf20Sopenharmony_ci crypto_skcipher_decrypt(&areq->cra_u.skcipher_req); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* AIO operation in progress */ 1268c2ecf20Sopenharmony_ci if (err == -EINPROGRESS) 1278c2ecf20Sopenharmony_ci return -EIOCBQUEUED; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci sock_put(sk); 1308c2ecf20Sopenharmony_ci } else { 1318c2ecf20Sopenharmony_ci /* Synchronous operation */ 1328c2ecf20Sopenharmony_ci skcipher_request_set_callback(&areq->cra_u.skcipher_req, 1338c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP | 1348c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_BACKLOG, 1358c2ecf20Sopenharmony_ci crypto_req_done, &ctx->wait); 1368c2ecf20Sopenharmony_ci err = crypto_wait_req(ctx->enc ? 1378c2ecf20Sopenharmony_ci crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) : 1388c2ecf20Sopenharmony_ci crypto_skcipher_decrypt(&areq->cra_u.skcipher_req), 1398c2ecf20Sopenharmony_ci &ctx->wait); 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cifree: 1448c2ecf20Sopenharmony_ci af_alg_free_resources(areq); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci return err ? err : len; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic int skcipher_recvmsg(struct socket *sock, struct msghdr *msg, 1508c2ecf20Sopenharmony_ci size_t ignored, int flags) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci struct sock *sk = sock->sk; 1538c2ecf20Sopenharmony_ci int ret = 0; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci lock_sock(sk); 1568c2ecf20Sopenharmony_ci while (msg_data_left(msg)) { 1578c2ecf20Sopenharmony_ci int err = _skcipher_recvmsg(sock, msg, ignored, flags); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* 1608c2ecf20Sopenharmony_ci * This error covers -EIOCBQUEUED which implies that we can 1618c2ecf20Sopenharmony_ci * only handle one AIO request. If the caller wants to have 1628c2ecf20Sopenharmony_ci * multiple AIO requests in parallel, he must make multiple 1638c2ecf20Sopenharmony_ci * separate AIO calls. 1648c2ecf20Sopenharmony_ci * 1658c2ecf20Sopenharmony_ci * Also return the error if no data has been processed so far. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci if (err <= 0) { 1688c2ecf20Sopenharmony_ci if (err == -EIOCBQUEUED || !ret) 1698c2ecf20Sopenharmony_ci ret = err; 1708c2ecf20Sopenharmony_ci goto out; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci ret += err; 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ciout: 1778c2ecf20Sopenharmony_ci af_alg_wmem_wakeup(sk); 1788c2ecf20Sopenharmony_ci release_sock(sk); 1798c2ecf20Sopenharmony_ci return ret; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic struct proto_ops algif_skcipher_ops = { 1838c2ecf20Sopenharmony_ci .family = PF_ALG, 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci .connect = sock_no_connect, 1868c2ecf20Sopenharmony_ci .socketpair = sock_no_socketpair, 1878c2ecf20Sopenharmony_ci .getname = sock_no_getname, 1888c2ecf20Sopenharmony_ci .ioctl = sock_no_ioctl, 1898c2ecf20Sopenharmony_ci .listen = sock_no_listen, 1908c2ecf20Sopenharmony_ci .shutdown = sock_no_shutdown, 1918c2ecf20Sopenharmony_ci .mmap = sock_no_mmap, 1928c2ecf20Sopenharmony_ci .bind = sock_no_bind, 1938c2ecf20Sopenharmony_ci .accept = sock_no_accept, 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci .release = af_alg_release, 1968c2ecf20Sopenharmony_ci .sendmsg = skcipher_sendmsg, 1978c2ecf20Sopenharmony_ci .sendpage = af_alg_sendpage, 1988c2ecf20Sopenharmony_ci .recvmsg = skcipher_recvmsg, 1998c2ecf20Sopenharmony_ci .poll = af_alg_poll, 2008c2ecf20Sopenharmony_ci}; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic int skcipher_check_key(struct socket *sock) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci int err = 0; 2058c2ecf20Sopenharmony_ci struct sock *psk; 2068c2ecf20Sopenharmony_ci struct alg_sock *pask; 2078c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm; 2088c2ecf20Sopenharmony_ci struct sock *sk = sock->sk; 2098c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci lock_sock(sk); 2128c2ecf20Sopenharmony_ci if (!atomic_read(&ask->nokey_refcnt)) 2138c2ecf20Sopenharmony_ci goto unlock_child; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci psk = ask->parent; 2168c2ecf20Sopenharmony_ci pask = alg_sk(ask->parent); 2178c2ecf20Sopenharmony_ci tfm = pask->private; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci err = -ENOKEY; 2208c2ecf20Sopenharmony_ci lock_sock_nested(psk, SINGLE_DEPTH_NESTING); 2218c2ecf20Sopenharmony_ci if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 2228c2ecf20Sopenharmony_ci goto unlock; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci atomic_dec(&pask->nokey_refcnt); 2258c2ecf20Sopenharmony_ci atomic_set(&ask->nokey_refcnt, 0); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci err = 0; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ciunlock: 2308c2ecf20Sopenharmony_ci release_sock(psk); 2318c2ecf20Sopenharmony_ciunlock_child: 2328c2ecf20Sopenharmony_ci release_sock(sk); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci return err; 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg, 2388c2ecf20Sopenharmony_ci size_t size) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci int err; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci err = skcipher_check_key(sock); 2438c2ecf20Sopenharmony_ci if (err) 2448c2ecf20Sopenharmony_ci return err; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci return skcipher_sendmsg(sock, msg, size); 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page, 2508c2ecf20Sopenharmony_ci int offset, size_t size, int flags) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci int err; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci err = skcipher_check_key(sock); 2558c2ecf20Sopenharmony_ci if (err) 2568c2ecf20Sopenharmony_ci return err; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci return af_alg_sendpage(sock, page, offset, size, flags); 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg, 2628c2ecf20Sopenharmony_ci size_t ignored, int flags) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci int err; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci err = skcipher_check_key(sock); 2678c2ecf20Sopenharmony_ci if (err) 2688c2ecf20Sopenharmony_ci return err; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci return skcipher_recvmsg(sock, msg, ignored, flags); 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic struct proto_ops algif_skcipher_ops_nokey = { 2748c2ecf20Sopenharmony_ci .family = PF_ALG, 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci .connect = sock_no_connect, 2778c2ecf20Sopenharmony_ci .socketpair = sock_no_socketpair, 2788c2ecf20Sopenharmony_ci .getname = sock_no_getname, 2798c2ecf20Sopenharmony_ci .ioctl = sock_no_ioctl, 2808c2ecf20Sopenharmony_ci .listen = sock_no_listen, 2818c2ecf20Sopenharmony_ci .shutdown = sock_no_shutdown, 2828c2ecf20Sopenharmony_ci .mmap = sock_no_mmap, 2838c2ecf20Sopenharmony_ci .bind = sock_no_bind, 2848c2ecf20Sopenharmony_ci .accept = sock_no_accept, 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci .release = af_alg_release, 2878c2ecf20Sopenharmony_ci .sendmsg = skcipher_sendmsg_nokey, 2888c2ecf20Sopenharmony_ci .sendpage = skcipher_sendpage_nokey, 2898c2ecf20Sopenharmony_ci .recvmsg = skcipher_recvmsg_nokey, 2908c2ecf20Sopenharmony_ci .poll = af_alg_poll, 2918c2ecf20Sopenharmony_ci}; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic void *skcipher_bind(const char *name, u32 type, u32 mask) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci return crypto_alloc_skcipher(name, type, mask); 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic void skcipher_release(void *private) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci crypto_free_skcipher(private); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic int skcipher_setkey(void *private, const u8 *key, unsigned int keylen) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci return crypto_skcipher_setkey(private, key, keylen); 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic void skcipher_sock_destruct(struct sock *sk) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 3118c2ecf20Sopenharmony_ci struct af_alg_ctx *ctx = ask->private; 3128c2ecf20Sopenharmony_ci struct sock *psk = ask->parent; 3138c2ecf20Sopenharmony_ci struct alg_sock *pask = alg_sk(psk); 3148c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = pask->private; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci af_alg_pull_tsgl(sk, ctx->used, NULL, 0); 3178c2ecf20Sopenharmony_ci sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm)); 3188c2ecf20Sopenharmony_ci sock_kfree_s(sk, ctx, ctx->len); 3198c2ecf20Sopenharmony_ci af_alg_release_parent(sk); 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic int skcipher_accept_parent_nokey(void *private, struct sock *sk) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci struct af_alg_ctx *ctx; 3258c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 3268c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = private; 3278c2ecf20Sopenharmony_ci unsigned int len = sizeof(*ctx); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci ctx = sock_kmalloc(sk, len, GFP_KERNEL); 3308c2ecf20Sopenharmony_ci if (!ctx) 3318c2ecf20Sopenharmony_ci return -ENOMEM; 3328c2ecf20Sopenharmony_ci memset(ctx, 0, len); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(tfm), 3358c2ecf20Sopenharmony_ci GFP_KERNEL); 3368c2ecf20Sopenharmony_ci if (!ctx->iv) { 3378c2ecf20Sopenharmony_ci sock_kfree_s(sk, ctx, len); 3388c2ecf20Sopenharmony_ci return -ENOMEM; 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci memset(ctx->iv, 0, crypto_skcipher_ivsize(tfm)); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ctx->tsgl_list); 3438c2ecf20Sopenharmony_ci ctx->len = len; 3448c2ecf20Sopenharmony_ci crypto_init_wait(&ctx->wait); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci ask->private = ctx; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci sk->sk_destruct = skcipher_sock_destruct; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci return 0; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic int skcipher_accept_parent(void *private, struct sock *sk) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = private; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 3588c2ecf20Sopenharmony_ci return -ENOKEY; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci return skcipher_accept_parent_nokey(private, sk); 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic const struct af_alg_type algif_type_skcipher = { 3648c2ecf20Sopenharmony_ci .bind = skcipher_bind, 3658c2ecf20Sopenharmony_ci .release = skcipher_release, 3668c2ecf20Sopenharmony_ci .setkey = skcipher_setkey, 3678c2ecf20Sopenharmony_ci .accept = skcipher_accept_parent, 3688c2ecf20Sopenharmony_ci .accept_nokey = skcipher_accept_parent_nokey, 3698c2ecf20Sopenharmony_ci .ops = &algif_skcipher_ops, 3708c2ecf20Sopenharmony_ci .ops_nokey = &algif_skcipher_ops_nokey, 3718c2ecf20Sopenharmony_ci .name = "skcipher", 3728c2ecf20Sopenharmony_ci .owner = THIS_MODULE 3738c2ecf20Sopenharmony_ci}; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic int __init algif_skcipher_init(void) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci return af_alg_register_type(&algif_type_skcipher); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic void __exit algif_skcipher_exit(void) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci int err = af_alg_unregister_type(&algif_type_skcipher); 3838c2ecf20Sopenharmony_ci BUG_ON(err); 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cimodule_init(algif_skcipher_init); 3878c2ecf20Sopenharmony_cimodule_exit(algif_skcipher_exit); 3888c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 389