source: src/linux/universal/linux-4.9/crypto/algif_aead.c @ 31885

Last change on this file since 31885 was 31885, checked in by brainslayer, 2 months ago

update

File size: 19.3 KB
Line 
1/*
2 * algif_aead: User-space interface for AEAD algorithms
3 *
4 * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
5 *
6 * This file provides the user-space API for AEAD ciphers.
7 *
8 * This file is derived from algif_skcipher.c.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
14 */
15
16#include <crypto/internal/aead.h>
17#include <crypto/scatterwalk.h>
18#include <crypto/if_alg.h>
19#include <linux/init.h>
20#include <linux/list.h>
21#include <linux/kernel.h>
22#include <linux/mm.h>
23#include <linux/module.h>
24#include <linux/net.h>
25#include <net/sock.h>
26
27struct aead_sg_list {
28        unsigned int cur;
29        struct scatterlist sg[ALG_MAX_PAGES];
30};
31
32struct aead_async_rsgl {
33        struct af_alg_sgl sgl;
34        struct list_head list;
35};
36
37struct aead_async_req {
38        struct scatterlist *tsgl;
39        struct aead_async_rsgl first_rsgl;
40        struct list_head list;
41        struct kiocb *iocb;
42        struct sock *sk;
43        unsigned int tsgls;
44        char iv[];
45};
46
47struct aead_ctx {
48        struct aead_sg_list tsgl;
49        struct aead_async_rsgl first_rsgl;
50        struct list_head list;
51
52        void *iv;
53
54        struct af_alg_completion completion;
55
56        unsigned long used;
57
58        unsigned int len;
59        bool more;
60        bool merge;
61        bool enc;
62
63        size_t aead_assoclen;
64        struct aead_request aead_req;
65};
66
67static inline int aead_sndbuf(struct sock *sk)
68{
69        struct alg_sock *ask = alg_sk(sk);
70        struct aead_ctx *ctx = ask->private;
71
72        return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) -
73                          ctx->used, 0);
74}
75
76static inline bool aead_writable(struct sock *sk)
77{
78        return PAGE_SIZE <= aead_sndbuf(sk);
79}
80
81static inline bool aead_sufficient_data(struct aead_ctx *ctx)
82{
83        unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
84
85        /*
86         * The minimum amount of memory needed for an AEAD cipher is
87         * the AAD and in case of decryption the tag.
88         */
89        return ctx->used >= ctx->aead_assoclen + (ctx->enc ? 0 : as);
90}
91
92static void aead_reset_ctx(struct aead_ctx *ctx)
93{
94        struct aead_sg_list *sgl = &ctx->tsgl;
95
96        sg_init_table(sgl->sg, ALG_MAX_PAGES);
97        sgl->cur = 0;
98        ctx->used = 0;
99        ctx->more = 0;
100        ctx->merge = 0;
101}
102
103static void aead_put_sgl(struct sock *sk)
104{
105        struct alg_sock *ask = alg_sk(sk);
106        struct aead_ctx *ctx = ask->private;
107        struct aead_sg_list *sgl = &ctx->tsgl;
108        struct scatterlist *sg = sgl->sg;
109        unsigned int i;
110
111        for (i = 0; i < sgl->cur; i++) {
112                if (!sg_page(sg + i))
113                        continue;
114
115                put_page(sg_page(sg + i));
116                sg_assign_page(sg + i, NULL);
117        }
118        aead_reset_ctx(ctx);
119}
120
121static void aead_wmem_wakeup(struct sock *sk)
122{
123        struct socket_wq *wq;
124
125        if (!aead_writable(sk))
126                return;
127
128        rcu_read_lock();
129        wq = rcu_dereference(sk->sk_wq);
130        if (skwq_has_sleeper(wq))
131                wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
132                                                           POLLRDNORM |
133                                                           POLLRDBAND);
134        sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
135        rcu_read_unlock();
136}
137
138static int aead_wait_for_data(struct sock *sk, unsigned flags)
139{
140        struct alg_sock *ask = alg_sk(sk);
141        struct aead_ctx *ctx = ask->private;
142        long timeout;
143        DEFINE_WAIT(wait);
144        int err = -ERESTARTSYS;
145
146        if (flags & MSG_DONTWAIT)
147                return -EAGAIN;
148
149        sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
150
151        for (;;) {
152                if (signal_pending(current))
153                        break;
154                prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
155                timeout = MAX_SCHEDULE_TIMEOUT;
156                if (sk_wait_event(sk, &timeout, !ctx->more)) {
157                        err = 0;
158                        break;
159                }
160        }
161        finish_wait(sk_sleep(sk), &wait);
162
163        sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
164
165        return err;
166}
167
168static void aead_data_wakeup(struct sock *sk)
169{
170        struct alg_sock *ask = alg_sk(sk);
171        struct aead_ctx *ctx = ask->private;
172        struct socket_wq *wq;
173
174        if (ctx->more)
175                return;
176        if (!ctx->used)
177                return;
178
179        rcu_read_lock();
180        wq = rcu_dereference(sk->sk_wq);
181        if (skwq_has_sleeper(wq))
182                wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
183                                                           POLLRDNORM |
184                                                           POLLRDBAND);
185        sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
186        rcu_read_unlock();
187}
188
189static int aead_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
190{
191        struct sock *sk = sock->sk;
192        struct alg_sock *ask = alg_sk(sk);
193        struct aead_ctx *ctx = ask->private;
194        unsigned ivsize =
195                crypto_aead_ivsize(crypto_aead_reqtfm(&ctx->aead_req));
196        struct aead_sg_list *sgl = &ctx->tsgl;
197        struct af_alg_control con = {};
198        long copied = 0;
199        bool enc = 0;
200        bool init = 0;
201        int err = -EINVAL;
202
203        if (msg->msg_controllen) {
204                err = af_alg_cmsg_send(msg, &con);
205                if (err)
206                        return err;
207
208                init = 1;
209                switch (con.op) {
210                case ALG_OP_ENCRYPT:
211                        enc = 1;
212                        break;
213                case ALG_OP_DECRYPT:
214                        enc = 0;
215                        break;
216                default:
217                        return -EINVAL;
218                }
219
220                if (con.iv && con.iv->ivlen != ivsize)
221                        return -EINVAL;
222        }
223
224        lock_sock(sk);
225        if (!ctx->more && ctx->used)
226                goto unlock;
227
228        if (init) {
229                ctx->enc = enc;
230                if (con.iv)
231                        memcpy(ctx->iv, con.iv->iv, ivsize);
232
233                ctx->aead_assoclen = con.aead_assoclen;
234        }
235
236        while (size) {
237                size_t len = size;
238                struct scatterlist *sg = NULL;
239
240                /* use the existing memory in an allocated page */
241                if (ctx->merge) {
242                        sg = sgl->sg + sgl->cur - 1;
243                        len = min_t(unsigned long, len,
244                                    PAGE_SIZE - sg->offset - sg->length);
245                        err = memcpy_from_msg(page_address(sg_page(sg)) +
246                                              sg->offset + sg->length,
247                                              msg, len);
248                        if (err)
249                                goto unlock;
250
251                        sg->length += len;
252                        ctx->merge = (sg->offset + sg->length) &
253                                     (PAGE_SIZE - 1);
254
255                        ctx->used += len;
256                        copied += len;
257                        size -= len;
258                        continue;
259                }
260
261                if (!aead_writable(sk)) {
262                        /* user space sent too much data */
263                        aead_put_sgl(sk);
264                        err = -EMSGSIZE;
265                        goto unlock;
266                }
267
268                /* allocate a new page */
269                len = min_t(unsigned long, size, aead_sndbuf(sk));
270                while (len) {
271                        size_t plen = 0;
272
273                        if (sgl->cur >= ALG_MAX_PAGES) {
274                                aead_put_sgl(sk);
275                                err = -E2BIG;
276                                goto unlock;
277                        }
278
279                        sg = sgl->sg + sgl->cur;
280                        plen = min_t(size_t, len, PAGE_SIZE);
281
282                        sg_assign_page(sg, alloc_page(GFP_KERNEL));
283                        err = -ENOMEM;
284                        if (!sg_page(sg))
285                                goto unlock;
286
287                        err = memcpy_from_msg(page_address(sg_page(sg)),
288                                              msg, plen);
289                        if (err) {
290                                __free_page(sg_page(sg));
291                                sg_assign_page(sg, NULL);
292                                goto unlock;
293                        }
294
295                        sg->offset = 0;
296                        sg->length = plen;
297                        len -= plen;
298                        ctx->used += plen;
299                        copied += plen;
300                        sgl->cur++;
301                        size -= plen;
302                        ctx->merge = plen & (PAGE_SIZE - 1);
303                }
304        }
305
306        err = 0;
307
308        ctx->more = msg->msg_flags & MSG_MORE;
309        if (!ctx->more && !aead_sufficient_data(ctx)) {
310                aead_put_sgl(sk);
311                err = -EMSGSIZE;
312        }
313
314unlock:
315        aead_data_wakeup(sk);
316        release_sock(sk);
317
318        return err ?: copied;
319}
320
321static ssize_t aead_sendpage(struct socket *sock, struct page *page,
322                             int offset, size_t size, int flags)
323{
324        struct sock *sk = sock->sk;
325        struct alg_sock *ask = alg_sk(sk);
326        struct aead_ctx *ctx = ask->private;
327        struct aead_sg_list *sgl = &ctx->tsgl;
328        int err = -EINVAL;
329
330        if (flags & MSG_SENDPAGE_NOTLAST)
331                flags |= MSG_MORE;
332
333        if (sgl->cur >= ALG_MAX_PAGES)
334                return -E2BIG;
335
336        lock_sock(sk);
337        if (!ctx->more && ctx->used)
338                goto unlock;
339
340        if (!size)
341                goto done;
342
343        if (!aead_writable(sk)) {
344                /* user space sent too much data */
345                aead_put_sgl(sk);
346                err = -EMSGSIZE;
347                goto unlock;
348        }
349
350        ctx->merge = 0;
351
352        get_page(page);
353        sg_set_page(sgl->sg + sgl->cur, page, size, offset);
354        sgl->cur++;
355        ctx->used += size;
356
357        err = 0;
358
359done:
360        ctx->more = flags & MSG_MORE;
361        if (!ctx->more && !aead_sufficient_data(ctx)) {
362                aead_put_sgl(sk);
363                err = -EMSGSIZE;
364        }
365
366unlock:
367        aead_data_wakeup(sk);
368        release_sock(sk);
369
370        return err ?: size;
371}
372
373#define GET_ASYM_REQ(req, tfm) (struct aead_async_req *) \
374                ((char *)req + sizeof(struct aead_request) + \
375                 crypto_aead_reqsize(tfm))
376
377 #define GET_REQ_SIZE(tfm) sizeof(struct aead_async_req) + \
378        crypto_aead_reqsize(tfm) + crypto_aead_ivsize(tfm) + \
379        sizeof(struct aead_request)
380
381static void aead_async_cb(struct crypto_async_request *_req, int err)
382{
383        struct aead_request *req = _req->data;
384        struct crypto_aead *tfm = crypto_aead_reqtfm(req);
385        struct aead_async_req *areq = GET_ASYM_REQ(req, tfm);
386        struct sock *sk = areq->sk;
387        struct scatterlist *sg = areq->tsgl;
388        struct aead_async_rsgl *rsgl;
389        struct kiocb *iocb = areq->iocb;
390        unsigned int i, reqlen = GET_REQ_SIZE(tfm);
391
392        list_for_each_entry(rsgl, &areq->list, list) {
393                af_alg_free_sg(&rsgl->sgl);
394                if (rsgl != &areq->first_rsgl)
395                        sock_kfree_s(sk, rsgl, sizeof(*rsgl));
396        }
397
398        for (i = 0; i < areq->tsgls; i++)
399                put_page(sg_page(sg + i));
400
401        sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls);
402        sock_kfree_s(sk, req, reqlen);
403        __sock_put(sk);
404        iocb->ki_complete(iocb, err, err);
405}
406
407static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
408                              int flags)
409{
410        struct sock *sk = sock->sk;
411        struct alg_sock *ask = alg_sk(sk);
412        struct aead_ctx *ctx = ask->private;
413        struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req);
414        struct aead_async_req *areq;
415        struct aead_request *req = NULL;
416        struct aead_sg_list *sgl = &ctx->tsgl;
417        struct aead_async_rsgl *last_rsgl = NULL, *rsgl;
418        unsigned int as = crypto_aead_authsize(tfm);
419        unsigned int i, reqlen = GET_REQ_SIZE(tfm);
420        int err = -ENOMEM;
421        unsigned long used;
422        size_t outlen = 0;
423        size_t usedpages = 0;
424
425        lock_sock(sk);
426        if (ctx->more) {
427                err = aead_wait_for_data(sk, flags);
428                if (err)
429                        goto unlock;
430        }
431
432        if (!aead_sufficient_data(ctx))
433                goto unlock;
434
435        used = ctx->used;
436        if (ctx->enc)
437                outlen = used + as;
438        else
439                outlen = used - as;
440
441        req = sock_kmalloc(sk, reqlen, GFP_KERNEL);
442        if (unlikely(!req))
443                goto unlock;
444
445        areq = GET_ASYM_REQ(req, tfm);
446        memset(&areq->first_rsgl, '\0', sizeof(areq->first_rsgl));
447        INIT_LIST_HEAD(&areq->list);
448        areq->iocb = msg->msg_iocb;
449        areq->sk = sk;
450        memcpy(areq->iv, ctx->iv, crypto_aead_ivsize(tfm));
451        aead_request_set_tfm(req, tfm);
452        aead_request_set_ad(req, ctx->aead_assoclen);
453        aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
454                                  aead_async_cb, req);
455        used -= ctx->aead_assoclen;
456
457        /* take over all tx sgls from ctx */
458        areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur,
459                                  GFP_KERNEL);
460        if (unlikely(!areq->tsgl))
461                goto free;
462
463        sg_init_table(areq->tsgl, sgl->cur);
464        for (i = 0; i < sgl->cur; i++)
465                sg_set_page(&areq->tsgl[i], sg_page(&sgl->sg[i]),
466                            sgl->sg[i].length, sgl->sg[i].offset);
467
468        areq->tsgls = sgl->cur;
469
470        /* create rx sgls */
471        while (outlen > usedpages && iov_iter_count(&msg->msg_iter)) {
472                size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
473                                      (outlen - usedpages));
474
475                if (list_empty(&areq->list)) {
476                        rsgl = &areq->first_rsgl;
477
478                } else {
479                        rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL);
480                        if (unlikely(!rsgl)) {
481                                err = -ENOMEM;
482                                goto free;
483                        }
484                }
485                rsgl->sgl.npages = 0;
486                list_add_tail(&rsgl->list, &areq->list);
487
488                /* make one iovec available as scatterlist */
489                err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen);
490                if (err < 0)
491                        goto free;
492
493                usedpages += err;
494
495                /* chain the new scatterlist with previous one */
496                if (last_rsgl)
497                        af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl);
498
499                last_rsgl = rsgl;
500
501                iov_iter_advance(&msg->msg_iter, err);
502        }
503
504        /* ensure output buffer is sufficiently large */
505        if (usedpages < outlen) {
506                err = -EINVAL;
507                goto unlock;
508        }
509
510        aead_request_set_crypt(req, areq->tsgl, areq->first_rsgl.sgl.sg, used,
511                               areq->iv);
512        err = ctx->enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
513        if (err) {
514                if (err == -EINPROGRESS) {
515                        sock_hold(sk);
516                        err = -EIOCBQUEUED;
517                        aead_reset_ctx(ctx);
518                        goto unlock;
519                } else if (err == -EBADMSG) {
520                        aead_put_sgl(sk);
521                }
522                goto free;
523        }
524        aead_put_sgl(sk);
525
526free:
527        list_for_each_entry(rsgl, &areq->list, list) {
528                af_alg_free_sg(&rsgl->sgl);
529                if (rsgl != &areq->first_rsgl)
530                        sock_kfree_s(sk, rsgl, sizeof(*rsgl));
531        }
532        if (areq->tsgl)
533                sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls);
534        if (req)
535                sock_kfree_s(sk, req, reqlen);
536unlock:
537        aead_wmem_wakeup(sk);
538        release_sock(sk);
539        return err ? err : outlen;
540}
541
542static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
543{
544        struct sock *sk = sock->sk;
545        struct alg_sock *ask = alg_sk(sk);
546        struct aead_ctx *ctx = ask->private;
547        unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
548        struct aead_sg_list *sgl = &ctx->tsgl;
549        struct aead_async_rsgl *last_rsgl = NULL;
550        struct aead_async_rsgl *rsgl, *tmp;
551        int err = -EINVAL;
552        unsigned long used = 0;
553        size_t outlen = 0;
554        size_t usedpages = 0;
555
556        lock_sock(sk);
557
558        /*
559         * AEAD memory structure: For encryption, the tag is appended to the
560         * ciphertext which implies that the memory allocated for the ciphertext
561         * must be increased by the tag length. For decryption, the tag
562         * is expected to be concatenated to the ciphertext. The plaintext
563         * therefore has a memory size of the ciphertext minus the tag length.
564         *
565         * The memory structure for cipher operation has the following
566         * structure:
567         *      AEAD encryption input:  assoc data || plaintext
568         *      AEAD encryption output: cipherntext || auth tag
569         *      AEAD decryption input:  assoc data || ciphertext || auth tag
570         *      AEAD decryption output: plaintext
571         */
572
573        if (ctx->more) {
574                err = aead_wait_for_data(sk, flags);
575                if (err)
576                        goto unlock;
577        }
578
579        /* data length provided by caller via sendmsg/sendpage */
580        used = ctx->used;
581
582        /*
583         * Make sure sufficient data is present -- note, the same check is
584         * is also present in sendmsg/sendpage. The checks in sendpage/sendmsg
585         * shall provide an information to the data sender that something is
586         * wrong, but they are irrelevant to maintain the kernel integrity.
587         * We need this check here too in case user space decides to not honor
588         * the error message in sendmsg/sendpage and still call recvmsg. This
589         * check here protects the kernel integrity.
590         */
591        if (!aead_sufficient_data(ctx))
592                goto unlock;
593
594        /*
595         * Calculate the minimum output buffer size holding the result of the
596         * cipher operation. When encrypting data, the receiving buffer is
597         * larger by the tag length compared to the input buffer as the
598         * encryption operation generates the tag. For decryption, the input
599         * buffer provides the tag which is consumed resulting in only the
600         * plaintext without a buffer for the tag returned to the caller.
601         */
602        if (ctx->enc)
603                outlen = used + as;
604        else
605                outlen = used - as;
606
607        /*
608         * The cipher operation input data is reduced by the associated data
609         * length as this data is processed separately later on.
610         */
611        used -= ctx->aead_assoclen;
612
613        /* convert iovecs of output buffers into scatterlists */
614        while (outlen > usedpages && iov_iter_count(&msg->msg_iter)) {
615                size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
616                                      (outlen - usedpages));
617
618                if (list_empty(&ctx->list)) {
619                        rsgl = &ctx->first_rsgl;
620                } else {
621                        rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL);
622                        if (unlikely(!rsgl)) {
623                                err = -ENOMEM;
624                                goto unlock;
625                        }
626                }
627                rsgl->sgl.npages = 0;
628                list_add_tail(&rsgl->list, &ctx->list);
629
630                /* make one iovec available as scatterlist */
631                err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen);
632                if (err < 0)
633                        goto unlock;
634                usedpages += err;
635                /* chain the new scatterlist with previous one */
636                if (last_rsgl)
637                        af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl);
638
639                last_rsgl = rsgl;
640
641                iov_iter_advance(&msg->msg_iter, err);
642        }
643
644        /* ensure output buffer is sufficiently large */
645        if (usedpages < outlen) {
646                err = -EINVAL;
647                goto unlock;
648        }
649
650        sg_mark_end(sgl->sg + sgl->cur - 1);
651        aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->first_rsgl.sgl.sg,
652                               used, ctx->iv);
653        aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen);
654
655        err = af_alg_wait_for_completion(ctx->enc ?
656                                         crypto_aead_encrypt(&ctx->aead_req) :
657                                         crypto_aead_decrypt(&ctx->aead_req),
658                                         &ctx->completion);
659
660        if (err) {
661                /* EBADMSG implies a valid cipher operation took place */
662                if (err == -EBADMSG)
663                        aead_put_sgl(sk);
664
665                goto unlock;
666        }
667
668        aead_put_sgl(sk);
669        err = 0;
670
671unlock:
672        list_for_each_entry_safe(rsgl, tmp, &ctx->list, list) {
673                af_alg_free_sg(&rsgl->sgl);
674                list_del(&rsgl->list);
675                if (rsgl != &ctx->first_rsgl)
676                        sock_kfree_s(sk, rsgl, sizeof(*rsgl));
677        }
678        INIT_LIST_HEAD(&ctx->list);
679        aead_wmem_wakeup(sk);
680        release_sock(sk);
681
682        return err ? err : outlen;
683}
684
685static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
686                        int flags)
687{
688        return (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) ?
689                aead_recvmsg_async(sock, msg, flags) :
690                aead_recvmsg_sync(sock, msg, flags);
691}
692
693static unsigned int aead_poll(struct file *file, struct socket *sock,
694                              poll_table *wait)
695{
696        struct sock *sk = sock->sk;
697        struct alg_sock *ask = alg_sk(sk);
698        struct aead_ctx *ctx = ask->private;
699        unsigned int mask;
700
701        sock_poll_wait(file, sk_sleep(sk), wait);
702        mask = 0;
703
704        if (!ctx->more)
705                mask |= POLLIN | POLLRDNORM;
706
707        if (aead_writable(sk))
708                mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
709
710        return mask;
711}
712
713static struct proto_ops algif_aead_ops = {
714        .family         =       PF_ALG,
715
716        .connect        =       sock_no_connect,
717        .socketpair     =       sock_no_socketpair,
718        .getname        =       sock_no_getname,
719        .ioctl          =       sock_no_ioctl,
720        .listen         =       sock_no_listen,
721        .shutdown       =       sock_no_shutdown,
722        .getsockopt     =       sock_no_getsockopt,
723        .mmap           =       sock_no_mmap,
724        .bind           =       sock_no_bind,
725        .accept         =       sock_no_accept,
726        .setsockopt     =       sock_no_setsockopt,
727
728        .release        =       af_alg_release,
729        .sendmsg        =       aead_sendmsg,
730        .sendpage       =       aead_sendpage,
731        .recvmsg        =       aead_recvmsg,
732        .poll           =       aead_poll,
733};
734
735static void *aead_bind(const char *name, u32 type, u32 mask)
736{
737        return crypto_alloc_aead(name, type, mask);
738}
739
740static void aead_release(void *private)
741{
742        crypto_free_aead(private);
743}
744
745static int aead_setauthsize(void *private, unsigned int authsize)
746{
747        return crypto_aead_setauthsize(private, authsize);
748}
749
750static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
751{
752        return crypto_aead_setkey(private, key, keylen);
753}
754
755static void aead_sock_destruct(struct sock *sk)
756{
757        struct alg_sock *ask = alg_sk(sk);
758        struct aead_ctx *ctx = ask->private;
759        unsigned int ivlen = crypto_aead_ivsize(
760                                crypto_aead_reqtfm(&ctx->aead_req));
761
762        WARN_ON(atomic_read(&sk->sk_refcnt) != 0);
763        aead_put_sgl(sk);
764        sock_kzfree_s(sk, ctx->iv, ivlen);
765        sock_kfree_s(sk, ctx, ctx->len);
766        af_alg_release_parent(sk);
767}
768
769static int aead_accept_parent(void *private, struct sock *sk)
770{
771        struct aead_ctx *ctx;
772        struct alg_sock *ask = alg_sk(sk);
773        unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(private);
774        unsigned int ivlen = crypto_aead_ivsize(private);
775
776        ctx = sock_kmalloc(sk, len, GFP_KERNEL);
777        if (!ctx)
778                return -ENOMEM;
779        memset(ctx, 0, len);
780
781        ctx->iv = sock_kmalloc(sk, ivlen, GFP_KERNEL);
782        if (!ctx->iv) {
783                sock_kfree_s(sk, ctx, len);
784                return -ENOMEM;
785        }
786        memset(ctx->iv, 0, ivlen);
787
788        ctx->len = len;
789        ctx->used = 0;
790        ctx->more = 0;
791        ctx->merge = 0;
792        ctx->enc = 0;
793        ctx->tsgl.cur = 0;
794        ctx->aead_assoclen = 0;
795        af_alg_init_completion(&ctx->completion);
796        sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES);
797        INIT_LIST_HEAD(&ctx->list);
798
799        ask->private = ctx;
800
801        aead_request_set_tfm(&ctx->aead_req, private);
802        aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
803                                  af_alg_complete, &ctx->completion);
804
805        sk->sk_destruct = aead_sock_destruct;
806
807        return 0;
808}
809
810static const struct af_alg_type algif_type_aead = {
811        .bind           =       aead_bind,
812        .release        =       aead_release,
813        .setkey         =       aead_setkey,
814        .setauthsize    =       aead_setauthsize,
815        .accept         =       aead_accept_parent,
816        .ops            =       &algif_aead_ops,
817        .name           =       "aead",
818        .owner          =       THIS_MODULE
819};
820
821static int __init algif_aead_init(void)
822{
823        return af_alg_register_type(&algif_type_aead);
824}
825
826static void __exit algif_aead_exit(void)
827{
828        int err = af_alg_unregister_type(&algif_type_aead);
829        BUG_ON(err);
830}
831
832module_init(algif_aead_init);
833module_exit(algif_aead_exit);
834MODULE_LICENSE("GPL");
835MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
836MODULE_DESCRIPTION("AEAD kernel crypto API user space interface");
Note: See TracBrowser for help on using the repository browser.