2 * algif_aead: User-space interface for AEAD algorithms
4 * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
6 * This file provides the user-space API for AEAD ciphers.
8 * This file is derived from algif_skcipher.c.
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)
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>
23 #include <linux/module.h>
24 #include <linux/net.h>
29 struct scatterlist sg
[ALG_MAX_PAGES
];
32 struct aead_async_rsgl
{
33 struct af_alg_sgl sgl
;
34 struct list_head list
;
37 struct aead_async_req
{
38 struct scatterlist
*tsgl
;
39 struct aead_async_rsgl first_rsgl
;
40 struct list_head list
;
48 struct crypto_aead
*aead
;
53 struct aead_sg_list tsgl
;
54 struct aead_async_rsgl first_rsgl
;
55 struct list_head list
;
59 struct af_alg_completion completion
;
69 struct aead_request aead_req
;
72 static inline int aead_sndbuf(struct sock
*sk
)
74 struct alg_sock
*ask
= alg_sk(sk
);
75 struct aead_ctx
*ctx
= ask
->private;
77 return max_t(int, max_t(int, sk
->sk_sndbuf
& PAGE_MASK
, PAGE_SIZE
) -
81 static inline bool aead_writable(struct sock
*sk
)
83 return PAGE_SIZE
<= aead_sndbuf(sk
);
86 static inline bool aead_sufficient_data(struct aead_ctx
*ctx
)
88 unsigned as
= crypto_aead_authsize(crypto_aead_reqtfm(&ctx
->aead_req
));
91 * The minimum amount of memory needed for an AEAD cipher is
92 * the AAD and in case of decryption the tag.
94 return ctx
->used
>= ctx
->aead_assoclen
+ (ctx
->enc
? 0 : as
);
97 static void aead_reset_ctx(struct aead_ctx
*ctx
)
99 struct aead_sg_list
*sgl
= &ctx
->tsgl
;
101 sg_init_table(sgl
->sg
, ALG_MAX_PAGES
);
108 static void aead_put_sgl(struct sock
*sk
)
110 struct alg_sock
*ask
= alg_sk(sk
);
111 struct aead_ctx
*ctx
= ask
->private;
112 struct aead_sg_list
*sgl
= &ctx
->tsgl
;
113 struct scatterlist
*sg
= sgl
->sg
;
116 for (i
= 0; i
< sgl
->cur
; i
++) {
117 if (!sg_page(sg
+ i
))
120 put_page(sg_page(sg
+ i
));
121 sg_assign_page(sg
+ i
, NULL
);
126 static void aead_wmem_wakeup(struct sock
*sk
)
128 struct socket_wq
*wq
;
130 if (!aead_writable(sk
))
134 wq
= rcu_dereference(sk
->sk_wq
);
135 if (skwq_has_sleeper(wq
))
136 wake_up_interruptible_sync_poll(&wq
->wait
, POLLIN
|
139 sk_wake_async(sk
, SOCK_WAKE_WAITD
, POLL_IN
);
143 static int aead_wait_for_data(struct sock
*sk
, unsigned flags
)
145 DEFINE_WAIT_FUNC(wait
, woken_wake_function
);
146 struct alg_sock
*ask
= alg_sk(sk
);
147 struct aead_ctx
*ctx
= ask
->private;
149 int err
= -ERESTARTSYS
;
151 if (flags
& MSG_DONTWAIT
)
154 sk_set_bit(SOCKWQ_ASYNC_WAITDATA
, sk
);
155 add_wait_queue(sk_sleep(sk
), &wait
);
157 if (signal_pending(current
))
159 timeout
= MAX_SCHEDULE_TIMEOUT
;
160 if (sk_wait_event(sk
, &timeout
, !ctx
->more
, &wait
)) {
165 remove_wait_queue(sk_sleep(sk
), &wait
);
167 sk_clear_bit(SOCKWQ_ASYNC_WAITDATA
, sk
);
172 static void aead_data_wakeup(struct sock
*sk
)
174 struct alg_sock
*ask
= alg_sk(sk
);
175 struct aead_ctx
*ctx
= ask
->private;
176 struct socket_wq
*wq
;
184 wq
= rcu_dereference(sk
->sk_wq
);
185 if (skwq_has_sleeper(wq
))
186 wake_up_interruptible_sync_poll(&wq
->wait
, POLLOUT
|
189 sk_wake_async(sk
, SOCK_WAKE_SPACE
, POLL_OUT
);
193 static int aead_sendmsg(struct socket
*sock
, struct msghdr
*msg
, size_t size
)
195 struct sock
*sk
= sock
->sk
;
196 struct alg_sock
*ask
= alg_sk(sk
);
197 struct aead_ctx
*ctx
= ask
->private;
199 crypto_aead_ivsize(crypto_aead_reqtfm(&ctx
->aead_req
));
200 struct aead_sg_list
*sgl
= &ctx
->tsgl
;
201 struct af_alg_control con
= {};
207 if (msg
->msg_controllen
) {
208 err
= af_alg_cmsg_send(msg
, &con
);
224 if (con
.iv
&& con
.iv
->ivlen
!= ivsize
)
229 if (!ctx
->more
&& ctx
->used
)
235 memcpy(ctx
->iv
, con
.iv
->iv
, ivsize
);
237 ctx
->aead_assoclen
= con
.aead_assoclen
;
242 struct scatterlist
*sg
= NULL
;
244 /* use the existing memory in an allocated page */
246 sg
= sgl
->sg
+ sgl
->cur
- 1;
247 len
= min_t(unsigned long, len
,
248 PAGE_SIZE
- sg
->offset
- sg
->length
);
249 err
= memcpy_from_msg(page_address(sg_page(sg
)) +
250 sg
->offset
+ sg
->length
,
256 ctx
->merge
= (sg
->offset
+ sg
->length
) &
265 if (!aead_writable(sk
)) {
266 /* user space sent too much data */
272 /* allocate a new page */
273 len
= min_t(unsigned long, size
, aead_sndbuf(sk
));
277 if (sgl
->cur
>= ALG_MAX_PAGES
) {
283 sg
= sgl
->sg
+ sgl
->cur
;
284 plen
= min_t(size_t, len
, PAGE_SIZE
);
286 sg_assign_page(sg
, alloc_page(GFP_KERNEL
));
291 err
= memcpy_from_msg(page_address(sg_page(sg
)),
294 __free_page(sg_page(sg
));
295 sg_assign_page(sg
, NULL
);
306 ctx
->merge
= plen
& (PAGE_SIZE
- 1);
312 ctx
->more
= msg
->msg_flags
& MSG_MORE
;
313 if (!ctx
->more
&& !aead_sufficient_data(ctx
)) {
319 aead_data_wakeup(sk
);
322 return err
?: copied
;
325 static ssize_t
aead_sendpage(struct socket
*sock
, struct page
*page
,
326 int offset
, size_t size
, int flags
)
328 struct sock
*sk
= sock
->sk
;
329 struct alg_sock
*ask
= alg_sk(sk
);
330 struct aead_ctx
*ctx
= ask
->private;
331 struct aead_sg_list
*sgl
= &ctx
->tsgl
;
334 if (flags
& MSG_SENDPAGE_NOTLAST
)
337 if (sgl
->cur
>= ALG_MAX_PAGES
)
341 if (!ctx
->more
&& ctx
->used
)
347 if (!aead_writable(sk
)) {
348 /* user space sent too much data */
357 sg_set_page(sgl
->sg
+ sgl
->cur
, page
, size
, offset
);
364 ctx
->more
= flags
& MSG_MORE
;
365 if (!ctx
->more
&& !aead_sufficient_data(ctx
)) {
371 aead_data_wakeup(sk
);
377 #define GET_ASYM_REQ(req, tfm) (struct aead_async_req *) \
378 ((char *)req + sizeof(struct aead_request) + \
379 crypto_aead_reqsize(tfm))
381 #define GET_REQ_SIZE(tfm) sizeof(struct aead_async_req) + \
382 crypto_aead_reqsize(tfm) + crypto_aead_ivsize(tfm) + \
383 sizeof(struct aead_request)
385 static void aead_async_cb(struct crypto_async_request
*_req
, int err
)
387 struct aead_request
*req
= _req
->data
;
388 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
389 struct aead_async_req
*areq
= GET_ASYM_REQ(req
, tfm
);
390 struct sock
*sk
= areq
->sk
;
391 struct scatterlist
*sg
= areq
->tsgl
;
392 struct aead_async_rsgl
*rsgl
;
393 struct kiocb
*iocb
= areq
->iocb
;
394 unsigned int i
, reqlen
= GET_REQ_SIZE(tfm
);
396 list_for_each_entry(rsgl
, &areq
->list
, list
) {
397 af_alg_free_sg(&rsgl
->sgl
);
398 if (rsgl
!= &areq
->first_rsgl
)
399 sock_kfree_s(sk
, rsgl
, sizeof(*rsgl
));
402 for (i
= 0; i
< areq
->tsgls
; i
++)
403 put_page(sg_page(sg
+ i
));
405 sock_kfree_s(sk
, areq
->tsgl
, sizeof(*areq
->tsgl
) * areq
->tsgls
);
406 sock_kfree_s(sk
, req
, reqlen
);
408 iocb
->ki_complete(iocb
, err
, err
);
411 static int aead_recvmsg_async(struct socket
*sock
, struct msghdr
*msg
,
414 struct sock
*sk
= sock
->sk
;
415 struct alg_sock
*ask
= alg_sk(sk
);
416 struct aead_ctx
*ctx
= ask
->private;
417 struct crypto_aead
*tfm
= crypto_aead_reqtfm(&ctx
->aead_req
);
418 struct aead_async_req
*areq
;
419 struct aead_request
*req
= NULL
;
420 struct aead_sg_list
*sgl
= &ctx
->tsgl
;
421 struct aead_async_rsgl
*last_rsgl
= NULL
, *rsgl
;
422 unsigned int as
= crypto_aead_authsize(tfm
);
423 unsigned int i
, reqlen
= GET_REQ_SIZE(tfm
);
427 size_t usedpages
= 0;
431 err
= aead_wait_for_data(sk
, flags
);
436 if (!aead_sufficient_data(ctx
))
445 req
= sock_kmalloc(sk
, reqlen
, GFP_KERNEL
);
449 areq
= GET_ASYM_REQ(req
, tfm
);
450 memset(&areq
->first_rsgl
, '\0', sizeof(areq
->first_rsgl
));
451 INIT_LIST_HEAD(&areq
->list
);
452 areq
->iocb
= msg
->msg_iocb
;
454 memcpy(areq
->iv
, ctx
->iv
, crypto_aead_ivsize(tfm
));
455 aead_request_set_tfm(req
, tfm
);
456 aead_request_set_ad(req
, ctx
->aead_assoclen
);
457 aead_request_set_callback(req
, CRYPTO_TFM_REQ_MAY_BACKLOG
,
459 used
-= ctx
->aead_assoclen
;
461 /* take over all tx sgls from ctx */
462 areq
->tsgl
= sock_kmalloc(sk
,
463 sizeof(*areq
->tsgl
) * max_t(u32
, sgl
->cur
, 1),
465 if (unlikely(!areq
->tsgl
))
468 sg_init_table(areq
->tsgl
, max_t(u32
, sgl
->cur
, 1));
469 for (i
= 0; i
< sgl
->cur
; i
++)
470 sg_set_page(&areq
->tsgl
[i
], sg_page(&sgl
->sg
[i
]),
471 sgl
->sg
[i
].length
, sgl
->sg
[i
].offset
);
473 areq
->tsgls
= sgl
->cur
;
476 while (outlen
> usedpages
&& iov_iter_count(&msg
->msg_iter
)) {
477 size_t seglen
= min_t(size_t, iov_iter_count(&msg
->msg_iter
),
478 (outlen
- usedpages
));
480 if (list_empty(&areq
->list
)) {
481 rsgl
= &areq
->first_rsgl
;
484 rsgl
= sock_kmalloc(sk
, sizeof(*rsgl
), GFP_KERNEL
);
485 if (unlikely(!rsgl
)) {
490 rsgl
->sgl
.npages
= 0;
491 list_add_tail(&rsgl
->list
, &areq
->list
);
493 /* make one iovec available as scatterlist */
494 err
= af_alg_make_sg(&rsgl
->sgl
, &msg
->msg_iter
, seglen
);
500 /* chain the new scatterlist with previous one */
502 af_alg_link_sg(&last_rsgl
->sgl
, &rsgl
->sgl
);
506 iov_iter_advance(&msg
->msg_iter
, err
);
509 /* ensure output buffer is sufficiently large */
510 if (usedpages
< outlen
) {
515 aead_request_set_crypt(req
, areq
->tsgl
, areq
->first_rsgl
.sgl
.sg
, used
,
517 err
= ctx
->enc
? crypto_aead_encrypt(req
) : crypto_aead_decrypt(req
);
519 if (err
== -EINPROGRESS
) {
524 } else if (err
== -EBADMSG
) {
532 list_for_each_entry(rsgl
, &areq
->list
, list
) {
533 af_alg_free_sg(&rsgl
->sgl
);
534 if (rsgl
!= &areq
->first_rsgl
)
535 sock_kfree_s(sk
, rsgl
, sizeof(*rsgl
));
538 sock_kfree_s(sk
, areq
->tsgl
, sizeof(*areq
->tsgl
) * areq
->tsgls
);
540 sock_kfree_s(sk
, req
, reqlen
);
542 aead_wmem_wakeup(sk
);
544 return err
? err
: outlen
;
547 static int aead_recvmsg_sync(struct socket
*sock
, struct msghdr
*msg
, int flags
)
549 struct sock
*sk
= sock
->sk
;
550 struct alg_sock
*ask
= alg_sk(sk
);
551 struct aead_ctx
*ctx
= ask
->private;
552 unsigned as
= crypto_aead_authsize(crypto_aead_reqtfm(&ctx
->aead_req
));
553 struct aead_sg_list
*sgl
= &ctx
->tsgl
;
554 struct aead_async_rsgl
*last_rsgl
= NULL
;
555 struct aead_async_rsgl
*rsgl
, *tmp
;
557 unsigned long used
= 0;
559 size_t usedpages
= 0;
564 * Please see documentation of aead_request_set_crypt for the
565 * description of the AEAD memory structure expected from the caller.
569 err
= aead_wait_for_data(sk
, flags
);
574 /* data length provided by caller via sendmsg/sendpage */
578 * Make sure sufficient data is present -- note, the same check is
579 * is also present in sendmsg/sendpage. The checks in sendpage/sendmsg
580 * shall provide an information to the data sender that something is
581 * wrong, but they are irrelevant to maintain the kernel integrity.
582 * We need this check here too in case user space decides to not honor
583 * the error message in sendmsg/sendpage and still call recvmsg. This
584 * check here protects the kernel integrity.
586 if (!aead_sufficient_data(ctx
))
590 * Calculate the minimum output buffer size holding the result of the
591 * cipher operation. When encrypting data, the receiving buffer is
592 * larger by the tag length compared to the input buffer as the
593 * encryption operation generates the tag. For decryption, the input
594 * buffer provides the tag which is consumed resulting in only the
595 * plaintext without a buffer for the tag returned to the caller.
603 * The cipher operation input data is reduced by the associated data
604 * length as this data is processed separately later on.
606 used
-= ctx
->aead_assoclen
;
608 /* convert iovecs of output buffers into scatterlists */
609 while (outlen
> usedpages
&& iov_iter_count(&msg
->msg_iter
)) {
610 size_t seglen
= min_t(size_t, iov_iter_count(&msg
->msg_iter
),
611 (outlen
- usedpages
));
613 if (list_empty(&ctx
->list
)) {
614 rsgl
= &ctx
->first_rsgl
;
616 rsgl
= sock_kmalloc(sk
, sizeof(*rsgl
), GFP_KERNEL
);
617 if (unlikely(!rsgl
)) {
622 rsgl
->sgl
.npages
= 0;
623 list_add_tail(&rsgl
->list
, &ctx
->list
);
625 /* make one iovec available as scatterlist */
626 err
= af_alg_make_sg(&rsgl
->sgl
, &msg
->msg_iter
, seglen
);
630 /* chain the new scatterlist with previous one */
632 af_alg_link_sg(&last_rsgl
->sgl
, &rsgl
->sgl
);
636 iov_iter_advance(&msg
->msg_iter
, err
);
639 /* ensure output buffer is sufficiently large */
640 if (usedpages
< outlen
) {
645 sg_mark_end(sgl
->sg
+ sgl
->cur
- 1);
646 aead_request_set_crypt(&ctx
->aead_req
, sgl
->sg
, ctx
->first_rsgl
.sgl
.sg
,
648 aead_request_set_ad(&ctx
->aead_req
, ctx
->aead_assoclen
);
650 err
= af_alg_wait_for_completion(ctx
->enc
?
651 crypto_aead_encrypt(&ctx
->aead_req
) :
652 crypto_aead_decrypt(&ctx
->aead_req
),
656 /* EBADMSG implies a valid cipher operation took place */
667 list_for_each_entry_safe(rsgl
, tmp
, &ctx
->list
, list
) {
668 af_alg_free_sg(&rsgl
->sgl
);
669 list_del(&rsgl
->list
);
670 if (rsgl
!= &ctx
->first_rsgl
)
671 sock_kfree_s(sk
, rsgl
, sizeof(*rsgl
));
673 INIT_LIST_HEAD(&ctx
->list
);
674 aead_wmem_wakeup(sk
);
677 return err
? err
: outlen
;
680 static int aead_recvmsg(struct socket
*sock
, struct msghdr
*msg
, size_t ignored
,
683 return (msg
->msg_iocb
&& !is_sync_kiocb(msg
->msg_iocb
)) ?
684 aead_recvmsg_async(sock
, msg
, flags
) :
685 aead_recvmsg_sync(sock
, msg
, flags
);
688 static unsigned int aead_poll(struct file
*file
, struct socket
*sock
,
691 struct sock
*sk
= sock
->sk
;
692 struct alg_sock
*ask
= alg_sk(sk
);
693 struct aead_ctx
*ctx
= ask
->private;
696 sock_poll_wait(file
, sk_sleep(sk
), wait
);
700 mask
|= POLLIN
| POLLRDNORM
;
702 if (aead_writable(sk
))
703 mask
|= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
708 static struct proto_ops algif_aead_ops
= {
711 .connect
= sock_no_connect
,
712 .socketpair
= sock_no_socketpair
,
713 .getname
= sock_no_getname
,
714 .ioctl
= sock_no_ioctl
,
715 .listen
= sock_no_listen
,
716 .shutdown
= sock_no_shutdown
,
717 .getsockopt
= sock_no_getsockopt
,
718 .mmap
= sock_no_mmap
,
719 .bind
= sock_no_bind
,
720 .accept
= sock_no_accept
,
721 .setsockopt
= sock_no_setsockopt
,
723 .release
= af_alg_release
,
724 .sendmsg
= aead_sendmsg
,
725 .sendpage
= aead_sendpage
,
726 .recvmsg
= aead_recvmsg
,
730 static int aead_check_key(struct socket
*sock
)
734 struct alg_sock
*pask
;
735 struct aead_tfm
*tfm
;
736 struct sock
*sk
= sock
->sk
;
737 struct alg_sock
*ask
= alg_sk(sk
);
744 pask
= alg_sk(ask
->parent
);
748 lock_sock_nested(psk
, SINGLE_DEPTH_NESTING
);
768 static int aead_sendmsg_nokey(struct socket
*sock
, struct msghdr
*msg
,
773 err
= aead_check_key(sock
);
777 return aead_sendmsg(sock
, msg
, size
);
780 static ssize_t
aead_sendpage_nokey(struct socket
*sock
, struct page
*page
,
781 int offset
, size_t size
, int flags
)
785 err
= aead_check_key(sock
);
789 return aead_sendpage(sock
, page
, offset
, size
, flags
);
792 static int aead_recvmsg_nokey(struct socket
*sock
, struct msghdr
*msg
,
793 size_t ignored
, int flags
)
797 err
= aead_check_key(sock
);
801 return aead_recvmsg(sock
, msg
, ignored
, flags
);
804 static struct proto_ops algif_aead_ops_nokey
= {
807 .connect
= sock_no_connect
,
808 .socketpair
= sock_no_socketpair
,
809 .getname
= sock_no_getname
,
810 .ioctl
= sock_no_ioctl
,
811 .listen
= sock_no_listen
,
812 .shutdown
= sock_no_shutdown
,
813 .getsockopt
= sock_no_getsockopt
,
814 .mmap
= sock_no_mmap
,
815 .bind
= sock_no_bind
,
816 .accept
= sock_no_accept
,
817 .setsockopt
= sock_no_setsockopt
,
819 .release
= af_alg_release
,
820 .sendmsg
= aead_sendmsg_nokey
,
821 .sendpage
= aead_sendpage_nokey
,
822 .recvmsg
= aead_recvmsg_nokey
,
826 static void *aead_bind(const char *name
, u32 type
, u32 mask
)
828 struct aead_tfm
*tfm
;
829 struct crypto_aead
*aead
;
831 tfm
= kzalloc(sizeof(*tfm
), GFP_KERNEL
);
833 return ERR_PTR(-ENOMEM
);
835 aead
= crypto_alloc_aead(name
, type
, mask
);
838 return ERR_CAST(aead
);
846 static void aead_release(void *private)
848 struct aead_tfm
*tfm
= private;
850 crypto_free_aead(tfm
->aead
);
854 static int aead_setauthsize(void *private, unsigned int authsize
)
856 struct aead_tfm
*tfm
= private;
858 return crypto_aead_setauthsize(tfm
->aead
, authsize
);
861 static int aead_setkey(void *private, const u8
*key
, unsigned int keylen
)
863 struct aead_tfm
*tfm
= private;
866 err
= crypto_aead_setkey(tfm
->aead
, key
, keylen
);
872 static void aead_sock_destruct(struct sock
*sk
)
874 struct alg_sock
*ask
= alg_sk(sk
);
875 struct aead_ctx
*ctx
= ask
->private;
876 unsigned int ivlen
= crypto_aead_ivsize(
877 crypto_aead_reqtfm(&ctx
->aead_req
));
879 WARN_ON(atomic_read(&sk
->sk_refcnt
) != 0);
881 sock_kzfree_s(sk
, ctx
->iv
, ivlen
);
882 sock_kfree_s(sk
, ctx
, ctx
->len
);
883 af_alg_release_parent(sk
);
886 static int aead_accept_parent_nokey(void *private, struct sock
*sk
)
888 struct aead_ctx
*ctx
;
889 struct alg_sock
*ask
= alg_sk(sk
);
890 struct aead_tfm
*tfm
= private;
891 struct crypto_aead
*aead
= tfm
->aead
;
892 unsigned int len
= sizeof(*ctx
) + crypto_aead_reqsize(aead
);
893 unsigned int ivlen
= crypto_aead_ivsize(aead
);
895 ctx
= sock_kmalloc(sk
, len
, GFP_KERNEL
);
900 ctx
->iv
= sock_kmalloc(sk
, ivlen
, GFP_KERNEL
);
902 sock_kfree_s(sk
, ctx
, len
);
905 memset(ctx
->iv
, 0, ivlen
);
913 ctx
->aead_assoclen
= 0;
914 af_alg_init_completion(&ctx
->completion
);
915 sg_init_table(ctx
->tsgl
.sg
, ALG_MAX_PAGES
);
916 INIT_LIST_HEAD(&ctx
->list
);
920 aead_request_set_tfm(&ctx
->aead_req
, aead
);
921 aead_request_set_callback(&ctx
->aead_req
, CRYPTO_TFM_REQ_MAY_BACKLOG
,
922 af_alg_complete
, &ctx
->completion
);
924 sk
->sk_destruct
= aead_sock_destruct
;
929 static int aead_accept_parent(void *private, struct sock
*sk
)
931 struct aead_tfm
*tfm
= private;
936 return aead_accept_parent_nokey(private, sk
);
939 static const struct af_alg_type algif_type_aead
= {
941 .release
= aead_release
,
942 .setkey
= aead_setkey
,
943 .setauthsize
= aead_setauthsize
,
944 .accept
= aead_accept_parent
,
945 .accept_nokey
= aead_accept_parent_nokey
,
946 .ops
= &algif_aead_ops
,
947 .ops_nokey
= &algif_aead_ops_nokey
,
952 static int __init
algif_aead_init(void)
954 return af_alg_register_type(&algif_type_aead
);
957 static void __exit
algif_aead_exit(void)
959 int err
= af_alg_unregister_type(&algif_type_aead
);
963 module_init(algif_aead_init
);
964 module_exit(algif_aead_exit
);
965 MODULE_LICENSE("GPL");
966 MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
967 MODULE_DESCRIPTION("AEAD kernel crypto API user space interface");