cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

algif_skcipher.c (9830B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * algif_skcipher: User-space interface for skcipher algorithms
      4 *
      5 * This file provides the user-space API for symmetric key ciphers.
      6 *
      7 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
      8 *
      9 * The following concept of the memory management is used:
     10 *
     11 * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is
     12 * filled by user space with the data submitted via sendpage/sendmsg. Filling
     13 * up the TX SGL does not cause a crypto operation -- the data will only be
     14 * tracked by the kernel. Upon receipt of one recvmsg call, the caller must
     15 * provide a buffer which is tracked with the RX SGL.
     16 *
     17 * During the processing of the recvmsg operation, the cipher request is
     18 * allocated and prepared. As part of the recvmsg operation, the processed
     19 * TX buffers are extracted from the TX SGL into a separate SGL.
     20 *
     21 * After the completion of the crypto operation, the RX SGL and the cipher
     22 * request is released. The extracted TX SGL parts are released together with
     23 * the RX SGL release.
     24 */
     25
     26#include <crypto/scatterwalk.h>
     27#include <crypto/skcipher.h>
     28#include <crypto/if_alg.h>
     29#include <linux/init.h>
     30#include <linux/list.h>
     31#include <linux/kernel.h>
     32#include <linux/mm.h>
     33#include <linux/module.h>
     34#include <linux/net.h>
     35#include <net/sock.h>
     36
     37static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
     38			    size_t size)
     39{
     40	struct sock *sk = sock->sk;
     41	struct alg_sock *ask = alg_sk(sk);
     42	struct sock *psk = ask->parent;
     43	struct alg_sock *pask = alg_sk(psk);
     44	struct crypto_skcipher *tfm = pask->private;
     45	unsigned ivsize = crypto_skcipher_ivsize(tfm);
     46
     47	return af_alg_sendmsg(sock, msg, size, ivsize);
     48}
     49
     50static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
     51			     size_t ignored, int flags)
     52{
     53	struct sock *sk = sock->sk;
     54	struct alg_sock *ask = alg_sk(sk);
     55	struct sock *psk = ask->parent;
     56	struct alg_sock *pask = alg_sk(psk);
     57	struct af_alg_ctx *ctx = ask->private;
     58	struct crypto_skcipher *tfm = pask->private;
     59	unsigned int bs = crypto_skcipher_chunksize(tfm);
     60	struct af_alg_async_req *areq;
     61	int err = 0;
     62	size_t len = 0;
     63
     64	if (!ctx->init || (ctx->more && ctx->used < bs)) {
     65		err = af_alg_wait_for_data(sk, flags, bs);
     66		if (err)
     67			return err;
     68	}
     69
     70	/* Allocate cipher request for current operation. */
     71	areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
     72				     crypto_skcipher_reqsize(tfm));
     73	if (IS_ERR(areq))
     74		return PTR_ERR(areq);
     75
     76	/* convert iovecs of output buffers into RX SGL */
     77	err = af_alg_get_rsgl(sk, msg, flags, areq, ctx->used, &len);
     78	if (err)
     79		goto free;
     80
     81	/*
     82	 * If more buffers are to be expected to be processed, process only
     83	 * full block size buffers.
     84	 */
     85	if (ctx->more || len < ctx->used)
     86		len -= len % bs;
     87
     88	/*
     89	 * Create a per request TX SGL for this request which tracks the
     90	 * SG entries from the global TX SGL.
     91	 */
     92	areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
     93	if (!areq->tsgl_entries)
     94		areq->tsgl_entries = 1;
     95	areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
     96						 areq->tsgl_entries),
     97				  GFP_KERNEL);
     98	if (!areq->tsgl) {
     99		err = -ENOMEM;
    100		goto free;
    101	}
    102	sg_init_table(areq->tsgl, areq->tsgl_entries);
    103	af_alg_pull_tsgl(sk, len, areq->tsgl, 0);
    104
    105	/* Initialize the crypto operation */
    106	skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
    107	skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
    108				   areq->first_rsgl.sgl.sg, len, ctx->iv);
    109
    110	if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
    111		/* AIO operation */
    112		sock_hold(sk);
    113		areq->iocb = msg->msg_iocb;
    114
    115		/* Remember output size that will be generated. */
    116		areq->outlen = len;
    117
    118		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
    119					      CRYPTO_TFM_REQ_MAY_SLEEP,
    120					      af_alg_async_cb, areq);
    121		err = ctx->enc ?
    122			crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
    123			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
    124
    125		/* AIO operation in progress */
    126		if (err == -EINPROGRESS)
    127			return -EIOCBQUEUED;
    128
    129		sock_put(sk);
    130	} else {
    131		/* Synchronous operation */
    132		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
    133					      CRYPTO_TFM_REQ_MAY_SLEEP |
    134					      CRYPTO_TFM_REQ_MAY_BACKLOG,
    135					      crypto_req_done, &ctx->wait);
    136		err = crypto_wait_req(ctx->enc ?
    137			crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
    138			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
    139						 &ctx->wait);
    140	}
    141
    142
    143free:
    144	af_alg_free_resources(areq);
    145
    146	return err ? err : len;
    147}
    148
    149static int skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
    150			    size_t ignored, int flags)
    151{
    152	struct sock *sk = sock->sk;
    153	int ret = 0;
    154
    155	lock_sock(sk);
    156	while (msg_data_left(msg)) {
    157		int err = _skcipher_recvmsg(sock, msg, ignored, flags);
    158
    159		/*
    160		 * This error covers -EIOCBQUEUED which implies that we can
    161		 * only handle one AIO request. If the caller wants to have
    162		 * multiple AIO requests in parallel, he must make multiple
    163		 * separate AIO calls.
    164		 *
    165		 * Also return the error if no data has been processed so far.
    166		 */
    167		if (err <= 0) {
    168			if (err == -EIOCBQUEUED || !ret)
    169				ret = err;
    170			goto out;
    171		}
    172
    173		ret += err;
    174	}
    175
    176out:
    177	af_alg_wmem_wakeup(sk);
    178	release_sock(sk);
    179	return ret;
    180}
    181
    182static struct proto_ops algif_skcipher_ops = {
    183	.family		=	PF_ALG,
    184
    185	.connect	=	sock_no_connect,
    186	.socketpair	=	sock_no_socketpair,
    187	.getname	=	sock_no_getname,
    188	.ioctl		=	sock_no_ioctl,
    189	.listen		=	sock_no_listen,
    190	.shutdown	=	sock_no_shutdown,
    191	.mmap		=	sock_no_mmap,
    192	.bind		=	sock_no_bind,
    193	.accept		=	sock_no_accept,
    194
    195	.release	=	af_alg_release,
    196	.sendmsg	=	skcipher_sendmsg,
    197	.sendpage	=	af_alg_sendpage,
    198	.recvmsg	=	skcipher_recvmsg,
    199	.poll		=	af_alg_poll,
    200};
    201
    202static int skcipher_check_key(struct socket *sock)
    203{
    204	int err = 0;
    205	struct sock *psk;
    206	struct alg_sock *pask;
    207	struct crypto_skcipher *tfm;
    208	struct sock *sk = sock->sk;
    209	struct alg_sock *ask = alg_sk(sk);
    210
    211	lock_sock(sk);
    212	if (!atomic_read(&ask->nokey_refcnt))
    213		goto unlock_child;
    214
    215	psk = ask->parent;
    216	pask = alg_sk(ask->parent);
    217	tfm = pask->private;
    218
    219	err = -ENOKEY;
    220	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
    221	if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
    222		goto unlock;
    223
    224	atomic_dec(&pask->nokey_refcnt);
    225	atomic_set(&ask->nokey_refcnt, 0);
    226
    227	err = 0;
    228
    229unlock:
    230	release_sock(psk);
    231unlock_child:
    232	release_sock(sk);
    233
    234	return err;
    235}
    236
    237static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
    238				  size_t size)
    239{
    240	int err;
    241
    242	err = skcipher_check_key(sock);
    243	if (err)
    244		return err;
    245
    246	return skcipher_sendmsg(sock, msg, size);
    247}
    248
    249static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
    250				       int offset, size_t size, int flags)
    251{
    252	int err;
    253
    254	err = skcipher_check_key(sock);
    255	if (err)
    256		return err;
    257
    258	return af_alg_sendpage(sock, page, offset, size, flags);
    259}
    260
    261static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
    262				  size_t ignored, int flags)
    263{
    264	int err;
    265
    266	err = skcipher_check_key(sock);
    267	if (err)
    268		return err;
    269
    270	return skcipher_recvmsg(sock, msg, ignored, flags);
    271}
    272
    273static struct proto_ops algif_skcipher_ops_nokey = {
    274	.family		=	PF_ALG,
    275
    276	.connect	=	sock_no_connect,
    277	.socketpair	=	sock_no_socketpair,
    278	.getname	=	sock_no_getname,
    279	.ioctl		=	sock_no_ioctl,
    280	.listen		=	sock_no_listen,
    281	.shutdown	=	sock_no_shutdown,
    282	.mmap		=	sock_no_mmap,
    283	.bind		=	sock_no_bind,
    284	.accept		=	sock_no_accept,
    285
    286	.release	=	af_alg_release,
    287	.sendmsg	=	skcipher_sendmsg_nokey,
    288	.sendpage	=	skcipher_sendpage_nokey,
    289	.recvmsg	=	skcipher_recvmsg_nokey,
    290	.poll		=	af_alg_poll,
    291};
    292
    293static void *skcipher_bind(const char *name, u32 type, u32 mask)
    294{
    295	return crypto_alloc_skcipher(name, type, mask);
    296}
    297
    298static void skcipher_release(void *private)
    299{
    300	crypto_free_skcipher(private);
    301}
    302
    303static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
    304{
    305	return crypto_skcipher_setkey(private, key, keylen);
    306}
    307
    308static void skcipher_sock_destruct(struct sock *sk)
    309{
    310	struct alg_sock *ask = alg_sk(sk);
    311	struct af_alg_ctx *ctx = ask->private;
    312	struct sock *psk = ask->parent;
    313	struct alg_sock *pask = alg_sk(psk);
    314	struct crypto_skcipher *tfm = pask->private;
    315
    316	af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
    317	sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
    318	sock_kfree_s(sk, ctx, ctx->len);
    319	af_alg_release_parent(sk);
    320}
    321
    322static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
    323{
    324	struct af_alg_ctx *ctx;
    325	struct alg_sock *ask = alg_sk(sk);
    326	struct crypto_skcipher *tfm = private;
    327	unsigned int len = sizeof(*ctx);
    328
    329	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
    330	if (!ctx)
    331		return -ENOMEM;
    332	memset(ctx, 0, len);
    333
    334	ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(tfm),
    335			       GFP_KERNEL);
    336	if (!ctx->iv) {
    337		sock_kfree_s(sk, ctx, len);
    338		return -ENOMEM;
    339	}
    340	memset(ctx->iv, 0, crypto_skcipher_ivsize(tfm));
    341
    342	INIT_LIST_HEAD(&ctx->tsgl_list);
    343	ctx->len = len;
    344	crypto_init_wait(&ctx->wait);
    345
    346	ask->private = ctx;
    347
    348	sk->sk_destruct = skcipher_sock_destruct;
    349
    350	return 0;
    351}
    352
    353static int skcipher_accept_parent(void *private, struct sock *sk)
    354{
    355	struct crypto_skcipher *tfm = private;
    356
    357	if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
    358		return -ENOKEY;
    359
    360	return skcipher_accept_parent_nokey(private, sk);
    361}
    362
    363static const struct af_alg_type algif_type_skcipher = {
    364	.bind		=	skcipher_bind,
    365	.release	=	skcipher_release,
    366	.setkey		=	skcipher_setkey,
    367	.accept		=	skcipher_accept_parent,
    368	.accept_nokey	=	skcipher_accept_parent_nokey,
    369	.ops		=	&algif_skcipher_ops,
    370	.ops_nokey	=	&algif_skcipher_ops_nokey,
    371	.name		=	"skcipher",
    372	.owner		=	THIS_MODULE
    373};
    374
    375static int __init algif_skcipher_init(void)
    376{
    377	return af_alg_register_type(&algif_type_skcipher);
    378}
    379
    380static void __exit algif_skcipher_exit(void)
    381{
    382	int err = af_alg_unregister_type(&algif_type_skcipher);
    383	BUG_ON(err);
    384}
    385
    386module_init(algif_skcipher_init);
    387module_exit(algif_skcipher_exit);
    388MODULE_LICENSE("GPL");