algif_skcipher.c 10.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * algif_skcipher: User-space interface for skcipher algorithms
 *
 * This file provides the user-space API for symmetric key ciphers.
 *
 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * The following concept of the memory management is used:
 *
 * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is
 * filled by user space with the data submitted via sendpage/sendmsg. Filling
 * up the TX SGL does not cause a crypto operation -- the data will only be
 * tracked by the kernel. Upon receipt of one recvmsg call, the caller must
 * provide a buffer which is tracked with the RX SGL.
 *
 * During the processing of the recvmsg operation, the cipher request is
 * allocated and prepared. As part of the recvmsg operation, the processed
 * TX buffers are extracted from the TX SGL into a separate SGL.
 *
 * After the completion of the crypto operation, the RX SGL and the cipher
 * request is released. The extracted TX SGL parts are released together with
 * the RX SGL release.
28 29 30 31 32 33 34 35 36 37 38 39 40
 */

#include <crypto/scatterwalk.h>
#include <crypto/skcipher.h>
#include <crypto/if_alg.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/net.h>
#include <net/sock.h>

41 42 43 44 45
struct skcipher_tfm {
	struct crypto_skcipher *skcipher;
	bool has_key;
};

46 47
static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
			    size_t size)
48 49 50
{
	struct sock *sk = sock->sk;
	struct alg_sock *ask = alg_sk(sk);
51 52 53 54
	struct sock *psk = ask->parent;
	struct alg_sock *pask = alg_sk(psk);
	struct skcipher_tfm *skc = pask->private;
	struct crypto_skcipher *tfm = skc->skcipher;
55
	unsigned ivsize = crypto_skcipher_ivsize(tfm);
56

57
	return af_alg_sendmsg(sock, msg, size, ivsize);
58 59
}

60 61
static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
			     size_t ignored, int flags)
62 63 64
{
	struct sock *sk = sock->sk;
	struct alg_sock *ask = alg_sk(sk);
65 66
	struct sock *psk = ask->parent;
	struct alg_sock *pask = alg_sk(psk);
67
	struct af_alg_ctx *ctx = ask->private;
68 69
	struct skcipher_tfm *skc = pask->private;
	struct crypto_skcipher *tfm = skc->skcipher;
70
	unsigned int bs = crypto_skcipher_blocksize(tfm);
71
	struct af_alg_async_req *areq;
72 73
	int err = 0;
	size_t len = 0;
74

75 76 77 78 79 80
	if (!ctx->used) {
		err = af_alg_wait_for_data(sk, flags);
		if (err)
			return err;
	}

81
	/* Allocate cipher request for current operation. */
82 83 84 85
	areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
				     crypto_skcipher_reqsize(tfm));
	if (IS_ERR(areq))
		return PTR_ERR(areq);
86

87
	/* convert iovecs of output buffers into RX SGL */
88 89 90
	err = af_alg_get_rsgl(sk, msg, flags, areq, -1, &len);
	if (err)
		goto free;
91

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
	/* Process only as much RX buffers for which we have TX data */
	if (len > ctx->used)
		len = ctx->used;

	/*
	 * If more buffers are to be expected to be processed, process only
	 * full block size buffers.
	 */
	if (ctx->more || len < ctx->used)
		len -= len % bs;

	/*
	 * Create a per request TX SGL for this request which tracks the
	 * SG entries from the global TX SGL.
	 */
107
	areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
108 109 110 111 112 113 114 115 116
	if (!areq->tsgl_entries)
		areq->tsgl_entries = 1;
	areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * areq->tsgl_entries,
				  GFP_KERNEL);
	if (!areq->tsgl) {
		err = -ENOMEM;
		goto free;
	}
	sg_init_table(areq->tsgl, areq->tsgl_entries);
117
	af_alg_pull_tsgl(sk, len, areq->tsgl, 0);
118 119

	/* Initialize the crypto operation */
120 121 122
	skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
	skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
				   areq->first_rsgl.sgl.sg, len, ctx->iv);
123 124 125

	if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
		/* AIO operation */
126
		sock_hold(sk);
127
		areq->iocb = msg->msg_iocb;
128 129 130 131

		/* Remember output size that will be generated. */
		areq->outlen = len;

132
		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
133
					      CRYPTO_TFM_REQ_MAY_SLEEP,
134 135 136 137
					      af_alg_async_cb, areq);
		err = ctx->enc ?
			crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
138 139

		/* AIO operation in progress */
140
		if (err == -EINPROGRESS || err == -EBUSY)
141 142 143
			return -EIOCBQUEUED;

		sock_put(sk);
144 145
	} else {
		/* Synchronous operation */
146
		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
147 148 149 150 151
					      CRYPTO_TFM_REQ_MAY_SLEEP |
					      CRYPTO_TFM_REQ_MAY_BACKLOG,
					      af_alg_complete,
					      &ctx->completion);
		err = af_alg_wait_for_completion(ctx->enc ?
152 153
			crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
154 155
						 &ctx->completion);
	}
156

157

158
free:
159
	af_alg_free_resources(areq);
160 161

	return err ? err : len;
162 163
}

164 165
static int skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
			    size_t ignored, int flags)
166 167
{
	struct sock *sk = sock->sk;
168
	int ret = 0;
169 170

	lock_sock(sk);
Al Viro's avatar
Al Viro committed
171
	while (msg_data_left(msg)) {
172 173 174 175 176 177 178
		int err = _skcipher_recvmsg(sock, msg, ignored, flags);

		/*
		 * This error covers -EIOCBQUEUED which implies that we can
		 * only handle one AIO request. If the caller wants to have
		 * multiple AIO requests in parallel, he must make multiple
		 * separate AIO calls.
179 180
		 *
		 * Also return the error if no data has been processed so far.
181 182
		 */
		if (err <= 0) {
183
			if (err == -EIOCBQUEUED || !ret)
184 185
				ret = err;
			goto out;
186 187
		}

188
		ret += err;
189 190
	}

191
out:
192
	af_alg_wmem_wakeup(sk);
193
	release_sock(sk);
194
	return ret;
195
}
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214


static struct proto_ops algif_skcipher_ops = {
	.family		=	PF_ALG,

	.connect	=	sock_no_connect,
	.socketpair	=	sock_no_socketpair,
	.getname	=	sock_no_getname,
	.ioctl		=	sock_no_ioctl,
	.listen		=	sock_no_listen,
	.shutdown	=	sock_no_shutdown,
	.getsockopt	=	sock_no_getsockopt,
	.mmap		=	sock_no_mmap,
	.bind		=	sock_no_bind,
	.accept		=	sock_no_accept,
	.setsockopt	=	sock_no_setsockopt,

	.release	=	af_alg_release,
	.sendmsg	=	skcipher_sendmsg,
215
	.sendpage	=	af_alg_sendpage,
216
	.recvmsg	=	skcipher_recvmsg,
217
	.poll		=	af_alg_poll,
218 219
};

220 221
static int skcipher_check_key(struct socket *sock)
{
222
	int err = 0;
223 224 225 226 227 228
	struct sock *psk;
	struct alg_sock *pask;
	struct skcipher_tfm *tfm;
	struct sock *sk = sock->sk;
	struct alg_sock *ask = alg_sk(sk);

229
	lock_sock(sk);
230
	if (ask->refcnt)
231
		goto unlock_child;
232 233 234 235 236 237

	psk = ask->parent;
	pask = alg_sk(ask->parent);
	tfm = pask->private;

	err = -ENOKEY;
238
	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
239 240 241 242 243 244 245 246 247 248 249 250 251
	if (!tfm->has_key)
		goto unlock;

	if (!pask->refcnt++)
		sock_hold(psk);

	ask->refcnt = 1;
	sock_put(psk);

	err = 0;

unlock:
	release_sock(psk);
252 253
unlock_child:
	release_sock(sk);
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

	return err;
}

static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
				  size_t size)
{
	int err;

	err = skcipher_check_key(sock);
	if (err)
		return err;

	return skcipher_sendmsg(sock, msg, size);
}

static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
				       int offset, size_t size, int flags)
{
	int err;

	err = skcipher_check_key(sock);
	if (err)
		return err;

279
	return af_alg_sendpage(sock, page, offset, size, flags);
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
}

static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
				  size_t ignored, int flags)
{
	int err;

	err = skcipher_check_key(sock);
	if (err)
		return err;

	return skcipher_recvmsg(sock, msg, ignored, flags);
}

static struct proto_ops algif_skcipher_ops_nokey = {
	.family		=	PF_ALG,

	.connect	=	sock_no_connect,
	.socketpair	=	sock_no_socketpair,
	.getname	=	sock_no_getname,
	.ioctl		=	sock_no_ioctl,
	.listen		=	sock_no_listen,
	.shutdown	=	sock_no_shutdown,
	.getsockopt	=	sock_no_getsockopt,
	.mmap		=	sock_no_mmap,
	.bind		=	sock_no_bind,
	.accept		=	sock_no_accept,
	.setsockopt	=	sock_no_setsockopt,

	.release	=	af_alg_release,
	.sendmsg	=	skcipher_sendmsg_nokey,
	.sendpage	=	skcipher_sendpage_nokey,
	.recvmsg	=	skcipher_recvmsg_nokey,
313
	.poll		=	af_alg_poll,
314 315
};

316 317
static void *skcipher_bind(const char *name, u32 type, u32 mask)
{
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
	struct skcipher_tfm *tfm;
	struct crypto_skcipher *skcipher;

	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
	if (!tfm)
		return ERR_PTR(-ENOMEM);

	skcipher = crypto_alloc_skcipher(name, type, mask);
	if (IS_ERR(skcipher)) {
		kfree(tfm);
		return ERR_CAST(skcipher);
	}

	tfm->skcipher = skcipher;

	return tfm;
334 335 336 337
}

static void skcipher_release(void *private)
{
338 339 340 341
	struct skcipher_tfm *tfm = private;

	crypto_free_skcipher(tfm->skcipher);
	kfree(tfm);
342 343 344 345
}

static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
{
346 347 348 349 350 351 352
	struct skcipher_tfm *tfm = private;
	int err;

	err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
	tfm->has_key = !err;

	return err;
353 354 355 356 357
}

static void skcipher_sock_destruct(struct sock *sk)
{
	struct alg_sock *ask = alg_sk(sk);
358
	struct af_alg_ctx *ctx = ask->private;
359 360 361 362
	struct sock *psk = ask->parent;
	struct alg_sock *pask = alg_sk(psk);
	struct skcipher_tfm *skc = pask->private;
	struct crypto_skcipher *tfm = skc->skcipher;
363

364
	af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
365
	sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
366 367 368 369
	sock_kfree_s(sk, ctx, ctx->len);
	af_alg_release_parent(sk);
}

370
static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
371
{
372
	struct af_alg_ctx *ctx;
373
	struct alg_sock *ask = alg_sk(sk);
374 375
	struct skcipher_tfm *tfm = private;
	struct crypto_skcipher *skcipher = tfm->skcipher;
376
	unsigned int len = sizeof(*ctx);
377 378 379 380 381

	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

382
	ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
383 384 385 386 387 388
			       GFP_KERNEL);
	if (!ctx->iv) {
		sock_kfree_s(sk, ctx, len);
		return -ENOMEM;
	}

389
	memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
390

391
	INIT_LIST_HEAD(&ctx->tsgl_list);
392 393
	ctx->len = len;
	ctx->used = 0;
394
	atomic_set(&ctx->rcvused, 0);
395 396 397 398 399 400 401 402 403 404 405 406
	ctx->more = 0;
	ctx->merge = 0;
	ctx->enc = 0;
	af_alg_init_completion(&ctx->completion);

	ask->private = ctx;

	sk->sk_destruct = skcipher_sock_destruct;

	return 0;
}

407 408 409 410
static int skcipher_accept_parent(void *private, struct sock *sk)
{
	struct skcipher_tfm *tfm = private;

411
	if (!tfm->has_key && crypto_skcipher_has_setkey(tfm->skcipher))
412 413
		return -ENOKEY;

414
	return skcipher_accept_parent_nokey(private, sk);
415 416
}

417 418 419 420 421
static const struct af_alg_type algif_type_skcipher = {
	.bind		=	skcipher_bind,
	.release	=	skcipher_release,
	.setkey		=	skcipher_setkey,
	.accept		=	skcipher_accept_parent,
422
	.accept_nokey	=	skcipher_accept_parent_nokey,
423
	.ops		=	&algif_skcipher_ops,
424
	.ops_nokey	=	&algif_skcipher_ops_nokey,
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
	.name		=	"skcipher",
	.owner		=	THIS_MODULE
};

static int __init algif_skcipher_init(void)
{
	return af_alg_register_type(&algif_type_skcipher);
}

static void __exit algif_skcipher_exit(void)
{
	int err = af_alg_unregister_type(&algif_type_skcipher);
	BUG_ON(err);
}

module_init(algif_skcipher_init);
module_exit(algif_skcipher_exit);
MODULE_LICENSE("GPL");