File Index
Files and directories
Sign in
FILE

algif_aead.c

File preview with syntax highlighting.

linux-6.19.14/crypto/algif_aead.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * algif_aead: User-space interface for AEAD algorithms
  4 *
  5 * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
  6 *
  7 * This file provides the user-space API for AEAD ciphers.
  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 sendmsg (maybe with
 13 * MSG_SPLICE_PAGES).  Filling up the TX SGL does not cause a crypto operation
 14 * -- the data will only be tracked by the kernel. Upon receipt of one recvmsg
 15 * call, the caller must 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/internal/aead.h>
 27#include <crypto/scatterwalk.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 inline bool aead_sufficient_data(struct sock *sk)
 38{
 39	struct alg_sock *ask = alg_sk(sk);
 40	struct sock *psk = ask->parent;
 41	struct alg_sock *pask = alg_sk(psk);
 42	struct af_alg_ctx *ctx = ask->private;
 43	struct crypto_aead *tfm = pask->private;
 44	unsigned int as = crypto_aead_authsize(tfm);
 45
 46	/*
 47	 * The minimum amount of memory needed for an AEAD cipher is
 48	 * the AAD and in case of decryption the tag.
 49	 */
 50	return ctx->used >= ctx->aead_assoclen + (ctx->enc ? 0 : as);
 51}
 52
 53static int aead_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 54{
 55	struct sock *sk = sock->sk;
 56	struct alg_sock *ask = alg_sk(sk);
 57	struct sock *psk = ask->parent;
 58	struct alg_sock *pask = alg_sk(psk);
 59	struct crypto_aead *tfm = pask->private;
 60	unsigned int ivsize = crypto_aead_ivsize(tfm);
 61
 62	return af_alg_sendmsg(sock, msg, size, ivsize);
 63}
 64
 65static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
 66			 size_t ignored, int flags)
 67{
 68	struct sock *sk = sock->sk;
 69	struct alg_sock *ask = alg_sk(sk);
 70	struct sock *psk = ask->parent;
 71	struct alg_sock *pask = alg_sk(psk);
 72	struct af_alg_ctx *ctx = ask->private;
 73	struct crypto_aead *tfm = pask->private;
 74	unsigned int as = crypto_aead_authsize(tfm);
 75	struct af_alg_async_req *areq;
 76	struct scatterlist *rsgl_src, *tsgl_src = NULL;
 77	int err = 0;
 78	size_t used = 0;		/* [in]  TX bufs to be en/decrypted */
 79	size_t outlen = 0;		/* [out] RX bufs produced by kernel */
 80	size_t usedpages = 0;		/* [in]  RX bufs to be used from user */
 81	size_t processed = 0;		/* [in]  TX bufs to be consumed */
 82
 83	if (!ctx->init || ctx->more) {
 84		err = af_alg_wait_for_data(sk, flags, 0);
 85		if (err)
 86			return err;
 87	}
 88
 89	/*
 90	 * Data length provided by caller via sendmsg that has not yet been
 91	 * processed.
 92	 */
 93	used = ctx->used;
 94
 95	/*
 96	 * Make sure sufficient data is present -- note, the same check is also
 97	 * present in sendmsg. The checks in sendmsg shall provide an
 98	 * information to the data sender that something is wrong, but they are
 99	 * irrelevant to maintain the kernel integrity.  We need this check
100	 * here too in case user space decides to not honor the error message
101	 * in sendmsg and still call recvmsg. This check here protects the
102	 * kernel integrity.
103	 */
104	if (!aead_sufficient_data(sk))
105		return -EINVAL;
106
107	/*
108	 * Calculate the minimum output buffer size holding the result of the
109	 * cipher operation. When encrypting data, the receiving buffer is
110	 * larger by the tag length compared to the input buffer as the
111	 * encryption operation generates the tag. For decryption, the input
112	 * buffer provides the tag which is consumed resulting in only the
113	 * plaintext without a buffer for the tag returned to the caller.
114	 */
115	if (ctx->enc)
116		outlen = used + as;
117	else
118		outlen = used - as;
119
120	/*
121	 * The cipher operation input data is reduced by the associated data
122	 * length as this data is processed separately later on.
123	 */
124	used -= ctx->aead_assoclen;
125
126	/* Allocate cipher request for current operation. */
127	areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
128				     crypto_aead_reqsize(tfm));
129	if (IS_ERR(areq))
130		return PTR_ERR(areq);
131
132	/* convert iovecs of output buffers into RX SGL */
133	err = af_alg_get_rsgl(sk, msg, flags, areq, outlen, &usedpages);
134	if (err)
135		goto free;
136
137	/*
138	 * Ensure output buffer is sufficiently large. If the caller provides
139	 * less buffer space, only use the relative required input size. This
140	 * allows AIO operation where the caller sent all data to be processed
141	 * and the AIO operation performs the operation on the different chunks
142	 * of the input data.
143	 */
144	if (usedpages < outlen) {
145		size_t less = outlen - usedpages;
146
147		if (used < less + (ctx->enc ? 0 : as)) {
148			err = -EINVAL;
149			goto free;
150		}
151		used -= less;
152		outlen -= less;
153	}
154
155	/*
156	 * Create a per request TX SGL for this request which tracks the
157	 * SG entries from the global TX SGL.
158	 */
159	processed = used + ctx->aead_assoclen;
160	areq->tsgl_entries = af_alg_count_tsgl(sk, processed);
161	if (!areq->tsgl_entries)
162		areq->tsgl_entries = 1;
163	areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
164					         areq->tsgl_entries),
165				  GFP_KERNEL);
166	if (!areq->tsgl) {
167		err = -ENOMEM;
168		goto free;
169	}
170	sg_init_table(areq->tsgl, areq->tsgl_entries);
171	af_alg_pull_tsgl(sk, processed, areq->tsgl);
172	tsgl_src = areq->tsgl;
173
174	/*
175	 * Copy of AAD from source to destination
176	 *
177	 * The AAD is copied to the destination buffer without change. Even
178	 * when user space uses an in-place cipher operation, the kernel
179	 * will copy the data as it does not see whether such in-place operation
180	 * is initiated.
181	 */
182
183	/* Use the RX SGL as source (and destination) for crypto op. */
184	rsgl_src = areq->first_rsgl.sgl.sgt.sgl;
185
186	memcpy_sglist(rsgl_src, tsgl_src, ctx->aead_assoclen);
187
188	/* Initialize the crypto operation */
189	aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
190			       areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv);
191	aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
192	aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
193
194	if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
195		/* AIO operation */
196		sock_hold(sk);
197		areq->iocb = msg->msg_iocb;
198
199		/* Remember output size that will be generated. */
200		areq->outlen = outlen;
201
202		aead_request_set_callback(&areq->cra_u.aead_req,
203					  CRYPTO_TFM_REQ_MAY_SLEEP,
204					  af_alg_async_cb, areq);
205		err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) :
206				 crypto_aead_decrypt(&areq->cra_u.aead_req);
207
208		/* AIO operation in progress */
209		if (err == -EINPROGRESS)
210			return -EIOCBQUEUED;
211
212		sock_put(sk);
213	} else {
214		/* Synchronous operation */
215		aead_request_set_callback(&areq->cra_u.aead_req,
216					  CRYPTO_TFM_REQ_MAY_SLEEP |
217					  CRYPTO_TFM_REQ_MAY_BACKLOG,
218					  crypto_req_done, &ctx->wait);
219		err = crypto_wait_req(ctx->enc ?
220				crypto_aead_encrypt(&areq->cra_u.aead_req) :
221				crypto_aead_decrypt(&areq->cra_u.aead_req),
222				&ctx->wait);
223	}
224
225
226free:
227	af_alg_free_resources(areq);
228
229	return err ? err : outlen;
230}
231
232static int aead_recvmsg(struct socket *sock, struct msghdr *msg,
233			size_t ignored, int flags)
234{
235	struct sock *sk = sock->sk;
236	int ret = 0;
237
238	lock_sock(sk);
239	while (msg_data_left(msg)) {
240		int err = _aead_recvmsg(sock, msg, ignored, flags);
241
242		/*
243		 * This error covers -EIOCBQUEUED which implies that we can
244		 * only handle one AIO request. If the caller wants to have
245		 * multiple AIO requests in parallel, he must make multiple
246		 * separate AIO calls.
247		 *
248		 * Also return the error if no data has been processed so far.
249		 */
250		if (err <= 0) {
251			if (err == -EIOCBQUEUED || err == -EBADMSG || !ret)
252				ret = err;
253			goto out;
254		}
255
256		ret += err;
257	}
258
259out:
260	af_alg_wmem_wakeup(sk);
261	release_sock(sk);
262	return ret;
263}
264
265static struct proto_ops algif_aead_ops = {
266	.family		=	PF_ALG,
267
268	.connect	=	sock_no_connect,
269	.socketpair	=	sock_no_socketpair,
270	.getname	=	sock_no_getname,
271	.ioctl		=	sock_no_ioctl,
272	.listen		=	sock_no_listen,
273	.shutdown	=	sock_no_shutdown,
274	.mmap		=	sock_no_mmap,
275	.bind		=	sock_no_bind,
276	.accept		=	sock_no_accept,
277
278	.release	=	af_alg_release,
279	.sendmsg	=	aead_sendmsg,
280	.recvmsg	=	aead_recvmsg,
281	.poll		=	af_alg_poll,
282};
283
284static int aead_check_key(struct socket *sock)
285{
286	int err = 0;
287	struct sock *psk;
288	struct alg_sock *pask;
289	struct crypto_aead *tfm;
290	struct sock *sk = sock->sk;
291	struct alg_sock *ask = alg_sk(sk);
292
293	lock_sock(sk);
294	if (!atomic_read(&ask->nokey_refcnt))
295		goto unlock_child;
296
297	psk = ask->parent;
298	pask = alg_sk(ask->parent);
299	tfm = pask->private;
300
301	err = -ENOKEY;
302	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
303	if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
304		goto unlock;
305
306	atomic_dec(&pask->nokey_refcnt);
307	atomic_set(&ask->nokey_refcnt, 0);
308
309	err = 0;
310
311unlock:
312	release_sock(psk);
313unlock_child:
314	release_sock(sk);
315
316	return err;
317}
318
319static int aead_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
320				  size_t size)
321{
322	int err;
323
324	err = aead_check_key(sock);
325	if (err)
326		return err;
327
328	return aead_sendmsg(sock, msg, size);
329}
330
331static int aead_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
332				  size_t ignored, int flags)
333{
334	int err;
335
336	err = aead_check_key(sock);
337	if (err)
338		return err;
339
340	return aead_recvmsg(sock, msg, ignored, flags);
341}
342
343static struct proto_ops algif_aead_ops_nokey = {
344	.family		=	PF_ALG,
345
346	.connect	=	sock_no_connect,
347	.socketpair	=	sock_no_socketpair,
348	.getname	=	sock_no_getname,
349	.ioctl		=	sock_no_ioctl,
350	.listen		=	sock_no_listen,
351	.shutdown	=	sock_no_shutdown,
352	.mmap		=	sock_no_mmap,
353	.bind		=	sock_no_bind,
354	.accept		=	sock_no_accept,
355
356	.release	=	af_alg_release,
357	.sendmsg	=	aead_sendmsg_nokey,
358	.recvmsg	=	aead_recvmsg_nokey,
359	.poll		=	af_alg_poll,
360};
361
362static void *aead_bind(const char *name, u32 type, u32 mask)
363{
364	return crypto_alloc_aead(name, type, mask);
365}
366
367static void aead_release(void *private)
368{
369	crypto_free_aead(private);
370}
371
372static int aead_setauthsize(void *private, unsigned int authsize)
373{
374	return crypto_aead_setauthsize(private, authsize);
375}
376
377static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
378{
379	return crypto_aead_setkey(private, key, keylen);
380}
381
382static void aead_sock_destruct(struct sock *sk)
383{
384	struct alg_sock *ask = alg_sk(sk);
385	struct af_alg_ctx *ctx = ask->private;
386	struct sock *psk = ask->parent;
387	struct alg_sock *pask = alg_sk(psk);
388	struct crypto_aead *tfm = pask->private;
389	unsigned int ivlen = crypto_aead_ivsize(tfm);
390
391	af_alg_pull_tsgl(sk, ctx->used, NULL);
392	sock_kzfree_s(sk, ctx->iv, ivlen);
393	sock_kfree_s(sk, ctx, ctx->len);
394	af_alg_release_parent(sk);
395}
396
397static int aead_accept_parent_nokey(void *private, struct sock *sk)
398{
399	struct af_alg_ctx *ctx;
400	struct alg_sock *ask = alg_sk(sk);
401	struct crypto_aead *tfm = private;
402	unsigned int len = sizeof(*ctx);
403	unsigned int ivlen = crypto_aead_ivsize(tfm);
404
405	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
406	if (!ctx)
407		return -ENOMEM;
408	memset(ctx, 0, len);
409
410	ctx->iv = sock_kmalloc(sk, ivlen, GFP_KERNEL);
411	if (!ctx->iv) {
412		sock_kfree_s(sk, ctx, len);
413		return -ENOMEM;
414	}
415	memset(ctx->iv, 0, ivlen);
416
417	INIT_LIST_HEAD(&ctx->tsgl_list);
418	ctx->len = len;
419	crypto_init_wait(&ctx->wait);
420
421	ask->private = ctx;
422
423	sk->sk_destruct = aead_sock_destruct;
424
425	return 0;
426}
427
428static int aead_accept_parent(void *private, struct sock *sk)
429{
430	struct crypto_aead *tfm = private;
431
432	if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
433		return -ENOKEY;
434
435	return aead_accept_parent_nokey(private, sk);
436}
437
438static const struct af_alg_type algif_type_aead = {
439	.bind		=	aead_bind,
440	.release	=	aead_release,
441	.setkey		=	aead_setkey,
442	.setauthsize	=	aead_setauthsize,
443	.accept		=	aead_accept_parent,
444	.accept_nokey	=	aead_accept_parent_nokey,
445	.ops		=	&algif_aead_ops,
446	.ops_nokey	=	&algif_aead_ops_nokey,
447	.name		=	"aead",
448	.owner		=	THIS_MODULE
449};
450
451static int __init algif_aead_init(void)
452{
453	return af_alg_register_type(&algif_type_aead);
454}
455
456static void __exit algif_aead_exit(void)
457{
458	int err = af_alg_unregister_type(&algif_type_aead);
459	BUG_ON(err);
460}
461
462module_init(algif_aead_init);
463module_exit(algif_aead_exit);
464MODULE_LICENSE("GPL");
465MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
466MODULE_DESCRIPTION("AEAD kernel crypto API user space interface");
~/ Read-only file preview.