Back to home page

LXR

 
 

    


0001 /*
0002  * af_alg: User-space algorithm interface
0003  *
0004  * This file provides the user-space API for algorithms.
0005  *
0006  * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
0007  *
0008  * This program is free software; you can redistribute it and/or modify it
0009  * under the terms of the GNU General Public License as published by the Free
0010  * Software Foundation; either version 2 of the License, or (at your option)
0011  * any later version.
0012  *
0013  */
0014 
0015 #include <linux/atomic.h>
0016 #include <crypto/if_alg.h>
0017 #include <linux/crypto.h>
0018 #include <linux/init.h>
0019 #include <linux/kernel.h>
0020 #include <linux/list.h>
0021 #include <linux/module.h>
0022 #include <linux/net.h>
0023 #include <linux/rwsem.h>
0024 #include <linux/security.h>
0025 
0026 struct alg_type_list {
0027     const struct af_alg_type *type;
0028     struct list_head list;
0029 };
0030 
0031 static atomic_long_t alg_memory_allocated;
0032 
0033 static struct proto alg_proto = {
0034     .name           = "ALG",
0035     .owner          = THIS_MODULE,
0036     .memory_allocated   = &alg_memory_allocated,
0037     .obj_size       = sizeof(struct alg_sock),
0038 };
0039 
0040 static LIST_HEAD(alg_types);
0041 static DECLARE_RWSEM(alg_types_sem);
0042 
0043 static const struct af_alg_type *alg_get_type(const char *name)
0044 {
0045     const struct af_alg_type *type = ERR_PTR(-ENOENT);
0046     struct alg_type_list *node;
0047 
0048     down_read(&alg_types_sem);
0049     list_for_each_entry(node, &alg_types, list) {
0050         if (strcmp(node->type->name, name))
0051             continue;
0052 
0053         if (try_module_get(node->type->owner))
0054             type = node->type;
0055         break;
0056     }
0057     up_read(&alg_types_sem);
0058 
0059     return type;
0060 }
0061 
0062 int af_alg_register_type(const struct af_alg_type *type)
0063 {
0064     struct alg_type_list *node;
0065     int err = -EEXIST;
0066 
0067     down_write(&alg_types_sem);
0068     list_for_each_entry(node, &alg_types, list) {
0069         if (!strcmp(node->type->name, type->name))
0070             goto unlock;
0071     }
0072 
0073     node = kmalloc(sizeof(*node), GFP_KERNEL);
0074     err = -ENOMEM;
0075     if (!node)
0076         goto unlock;
0077 
0078     type->ops->owner = THIS_MODULE;
0079     if (type->ops_nokey)
0080         type->ops_nokey->owner = THIS_MODULE;
0081     node->type = type;
0082     list_add(&node->list, &alg_types);
0083     err = 0;
0084 
0085 unlock:
0086     up_write(&alg_types_sem);
0087 
0088     return err;
0089 }
0090 EXPORT_SYMBOL_GPL(af_alg_register_type);
0091 
0092 int af_alg_unregister_type(const struct af_alg_type *type)
0093 {
0094     struct alg_type_list *node;
0095     int err = -ENOENT;
0096 
0097     down_write(&alg_types_sem);
0098     list_for_each_entry(node, &alg_types, list) {
0099         if (strcmp(node->type->name, type->name))
0100             continue;
0101 
0102         list_del(&node->list);
0103         kfree(node);
0104         err = 0;
0105         break;
0106     }
0107     up_write(&alg_types_sem);
0108 
0109     return err;
0110 }
0111 EXPORT_SYMBOL_GPL(af_alg_unregister_type);
0112 
0113 static void alg_do_release(const struct af_alg_type *type, void *private)
0114 {
0115     if (!type)
0116         return;
0117 
0118     type->release(private);
0119     module_put(type->owner);
0120 }
0121 
0122 int af_alg_release(struct socket *sock)
0123 {
0124     if (sock->sk)
0125         sock_put(sock->sk);
0126     return 0;
0127 }
0128 EXPORT_SYMBOL_GPL(af_alg_release);
0129 
0130 void af_alg_release_parent(struct sock *sk)
0131 {
0132     struct alg_sock *ask = alg_sk(sk);
0133     unsigned int nokey = ask->nokey_refcnt;
0134     bool last = nokey && !ask->refcnt;
0135 
0136     sk = ask->parent;
0137     ask = alg_sk(sk);
0138 
0139     lock_sock(sk);
0140     ask->nokey_refcnt -= nokey;
0141     if (!last)
0142         last = !--ask->refcnt;
0143     release_sock(sk);
0144 
0145     if (last)
0146         sock_put(sk);
0147 }
0148 EXPORT_SYMBOL_GPL(af_alg_release_parent);
0149 
0150 static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
0151 {
0152     const u32 forbidden = CRYPTO_ALG_INTERNAL;
0153     struct sock *sk = sock->sk;
0154     struct alg_sock *ask = alg_sk(sk);
0155     struct sockaddr_alg *sa = (void *)uaddr;
0156     const struct af_alg_type *type;
0157     void *private;
0158     int err;
0159 
0160     if (sock->state == SS_CONNECTED)
0161         return -EINVAL;
0162 
0163     if (addr_len != sizeof(*sa))
0164         return -EINVAL;
0165 
0166     sa->salg_type[sizeof(sa->salg_type) - 1] = 0;
0167     sa->salg_name[sizeof(sa->salg_name) - 1] = 0;
0168 
0169     type = alg_get_type(sa->salg_type);
0170     if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) {
0171         request_module("algif-%s", sa->salg_type);
0172         type = alg_get_type(sa->salg_type);
0173     }
0174 
0175     if (IS_ERR(type))
0176         return PTR_ERR(type);
0177 
0178     private = type->bind(sa->salg_name,
0179                  sa->salg_feat & ~forbidden,
0180                  sa->salg_mask & ~forbidden);
0181     if (IS_ERR(private)) {
0182         module_put(type->owner);
0183         return PTR_ERR(private);
0184     }
0185 
0186     err = -EBUSY;
0187     lock_sock(sk);
0188     if (ask->refcnt | ask->nokey_refcnt)
0189         goto unlock;
0190 
0191     swap(ask->type, type);
0192     swap(ask->private, private);
0193 
0194     err = 0;
0195 
0196 unlock:
0197     release_sock(sk);
0198 
0199     alg_do_release(type, private);
0200 
0201     return err;
0202 }
0203 
0204 static int alg_setkey(struct sock *sk, char __user *ukey,
0205               unsigned int keylen)
0206 {
0207     struct alg_sock *ask = alg_sk(sk);
0208     const struct af_alg_type *type = ask->type;
0209     u8 *key;
0210     int err;
0211 
0212     key = sock_kmalloc(sk, keylen, GFP_KERNEL);
0213     if (!key)
0214         return -ENOMEM;
0215 
0216     err = -EFAULT;
0217     if (copy_from_user(key, ukey, keylen))
0218         goto out;
0219 
0220     err = type->setkey(ask->private, key, keylen);
0221 
0222 out:
0223     sock_kzfree_s(sk, key, keylen);
0224 
0225     return err;
0226 }
0227 
0228 static int alg_setsockopt(struct socket *sock, int level, int optname,
0229               char __user *optval, unsigned int optlen)
0230 {
0231     struct sock *sk = sock->sk;
0232     struct alg_sock *ask = alg_sk(sk);
0233     const struct af_alg_type *type;
0234     int err = -EBUSY;
0235 
0236     lock_sock(sk);
0237     if (ask->refcnt)
0238         goto unlock;
0239 
0240     type = ask->type;
0241 
0242     err = -ENOPROTOOPT;
0243     if (level != SOL_ALG || !type)
0244         goto unlock;
0245 
0246     switch (optname) {
0247     case ALG_SET_KEY:
0248         if (sock->state == SS_CONNECTED)
0249             goto unlock;
0250         if (!type->setkey)
0251             goto unlock;
0252 
0253         err = alg_setkey(sk, optval, optlen);
0254         break;
0255     case ALG_SET_AEAD_AUTHSIZE:
0256         if (sock->state == SS_CONNECTED)
0257             goto unlock;
0258         if (!type->setauthsize)
0259             goto unlock;
0260         err = type->setauthsize(ask->private, optlen);
0261     }
0262 
0263 unlock:
0264     release_sock(sk);
0265 
0266     return err;
0267 }
0268 
0269 int af_alg_accept(struct sock *sk, struct socket *newsock)
0270 {
0271     struct alg_sock *ask = alg_sk(sk);
0272     const struct af_alg_type *type;
0273     struct sock *sk2;
0274     unsigned int nokey;
0275     int err;
0276 
0277     lock_sock(sk);
0278     type = ask->type;
0279 
0280     err = -EINVAL;
0281     if (!type)
0282         goto unlock;
0283 
0284     sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto, 0);
0285     err = -ENOMEM;
0286     if (!sk2)
0287         goto unlock;
0288 
0289     sock_init_data(newsock, sk2);
0290     sock_graft(sk2, newsock);
0291     security_sk_clone(sk, sk2);
0292 
0293     err = type->accept(ask->private, sk2);
0294 
0295     nokey = err == -ENOKEY;
0296     if (nokey && type->accept_nokey)
0297         err = type->accept_nokey(ask->private, sk2);
0298 
0299     if (err)
0300         goto unlock;
0301 
0302     sk2->sk_family = PF_ALG;
0303 
0304     if (nokey || !ask->refcnt++)
0305         sock_hold(sk);
0306     ask->nokey_refcnt += nokey;
0307     alg_sk(sk2)->parent = sk;
0308     alg_sk(sk2)->type = type;
0309     alg_sk(sk2)->nokey_refcnt = nokey;
0310 
0311     newsock->ops = type->ops;
0312     newsock->state = SS_CONNECTED;
0313 
0314     if (nokey)
0315         newsock->ops = type->ops_nokey;
0316 
0317     err = 0;
0318 
0319 unlock:
0320     release_sock(sk);
0321 
0322     return err;
0323 }
0324 EXPORT_SYMBOL_GPL(af_alg_accept);
0325 
0326 static int alg_accept(struct socket *sock, struct socket *newsock, int flags)
0327 {
0328     return af_alg_accept(sock->sk, newsock);
0329 }
0330 
0331 static const struct proto_ops alg_proto_ops = {
0332     .family     =   PF_ALG,
0333     .owner      =   THIS_MODULE,
0334 
0335     .connect    =   sock_no_connect,
0336     .socketpair =   sock_no_socketpair,
0337     .getname    =   sock_no_getname,
0338     .ioctl      =   sock_no_ioctl,
0339     .listen     =   sock_no_listen,
0340     .shutdown   =   sock_no_shutdown,
0341     .getsockopt =   sock_no_getsockopt,
0342     .mmap       =   sock_no_mmap,
0343     .sendpage   =   sock_no_sendpage,
0344     .sendmsg    =   sock_no_sendmsg,
0345     .recvmsg    =   sock_no_recvmsg,
0346     .poll       =   sock_no_poll,
0347 
0348     .bind       =   alg_bind,
0349     .release    =   af_alg_release,
0350     .setsockopt =   alg_setsockopt,
0351     .accept     =   alg_accept,
0352 };
0353 
0354 static void alg_sock_destruct(struct sock *sk)
0355 {
0356     struct alg_sock *ask = alg_sk(sk);
0357 
0358     alg_do_release(ask->type, ask->private);
0359 }
0360 
0361 static int alg_create(struct net *net, struct socket *sock, int protocol,
0362               int kern)
0363 {
0364     struct sock *sk;
0365     int err;
0366 
0367     if (sock->type != SOCK_SEQPACKET)
0368         return -ESOCKTNOSUPPORT;
0369     if (protocol != 0)
0370         return -EPROTONOSUPPORT;
0371 
0372     err = -ENOMEM;
0373     sk = sk_alloc(net, PF_ALG, GFP_KERNEL, &alg_proto, kern);
0374     if (!sk)
0375         goto out;
0376 
0377     sock->ops = &alg_proto_ops;
0378     sock_init_data(sock, sk);
0379 
0380     sk->sk_family = PF_ALG;
0381     sk->sk_destruct = alg_sock_destruct;
0382 
0383     return 0;
0384 out:
0385     return err;
0386 }
0387 
0388 static const struct net_proto_family alg_family = {
0389     .family =   PF_ALG,
0390     .create =   alg_create,
0391     .owner  =   THIS_MODULE,
0392 };
0393 
0394 int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len)
0395 {
0396     size_t off;
0397     ssize_t n;
0398     int npages, i;
0399 
0400     n = iov_iter_get_pages(iter, sgl->pages, len, ALG_MAX_PAGES, &off);
0401     if (n < 0)
0402         return n;
0403 
0404     npages = (off + n + PAGE_SIZE - 1) >> PAGE_SHIFT;
0405     if (WARN_ON(npages == 0))
0406         return -EINVAL;
0407     /* Add one extra for linking */
0408     sg_init_table(sgl->sg, npages + 1);
0409 
0410     for (i = 0, len = n; i < npages; i++) {
0411         int plen = min_t(int, len, PAGE_SIZE - off);
0412 
0413         sg_set_page(sgl->sg + i, sgl->pages[i], plen, off);
0414 
0415         off = 0;
0416         len -= plen;
0417     }
0418     sg_mark_end(sgl->sg + npages - 1);
0419     sgl->npages = npages;
0420 
0421     return n;
0422 }
0423 EXPORT_SYMBOL_GPL(af_alg_make_sg);
0424 
0425 void af_alg_link_sg(struct af_alg_sgl *sgl_prev, struct af_alg_sgl *sgl_new)
0426 {
0427     sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1);
0428     sg_chain(sgl_prev->sg, sgl_prev->npages + 1, sgl_new->sg);
0429 }
0430 EXPORT_SYMBOL_GPL(af_alg_link_sg);
0431 
0432 void af_alg_free_sg(struct af_alg_sgl *sgl)
0433 {
0434     int i;
0435 
0436     for (i = 0; i < sgl->npages; i++)
0437         put_page(sgl->pages[i]);
0438 }
0439 EXPORT_SYMBOL_GPL(af_alg_free_sg);
0440 
0441 int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
0442 {
0443     struct cmsghdr *cmsg;
0444 
0445     for_each_cmsghdr(cmsg, msg) {
0446         if (!CMSG_OK(msg, cmsg))
0447             return -EINVAL;
0448         if (cmsg->cmsg_level != SOL_ALG)
0449             continue;
0450 
0451         switch (cmsg->cmsg_type) {
0452         case ALG_SET_IV:
0453             if (cmsg->cmsg_len < CMSG_LEN(sizeof(*con->iv)))
0454                 return -EINVAL;
0455             con->iv = (void *)CMSG_DATA(cmsg);
0456             if (cmsg->cmsg_len < CMSG_LEN(con->iv->ivlen +
0457                               sizeof(*con->iv)))
0458                 return -EINVAL;
0459             break;
0460 
0461         case ALG_SET_OP:
0462             if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
0463                 return -EINVAL;
0464             con->op = *(u32 *)CMSG_DATA(cmsg);
0465             break;
0466 
0467         case ALG_SET_AEAD_ASSOCLEN:
0468             if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
0469                 return -EINVAL;
0470             con->aead_assoclen = *(u32 *)CMSG_DATA(cmsg);
0471             break;
0472 
0473         default:
0474             return -EINVAL;
0475         }
0476     }
0477 
0478     return 0;
0479 }
0480 EXPORT_SYMBOL_GPL(af_alg_cmsg_send);
0481 
0482 int af_alg_wait_for_completion(int err, struct af_alg_completion *completion)
0483 {
0484     switch (err) {
0485     case -EINPROGRESS:
0486     case -EBUSY:
0487         wait_for_completion(&completion->completion);
0488         reinit_completion(&completion->completion);
0489         err = completion->err;
0490         break;
0491     };
0492 
0493     return err;
0494 }
0495 EXPORT_SYMBOL_GPL(af_alg_wait_for_completion);
0496 
0497 void af_alg_complete(struct crypto_async_request *req, int err)
0498 {
0499     struct af_alg_completion *completion = req->data;
0500 
0501     if (err == -EINPROGRESS)
0502         return;
0503 
0504     completion->err = err;
0505     complete(&completion->completion);
0506 }
0507 EXPORT_SYMBOL_GPL(af_alg_complete);
0508 
0509 static int __init af_alg_init(void)
0510 {
0511     int err = proto_register(&alg_proto, 0);
0512 
0513     if (err)
0514         goto out;
0515 
0516     err = sock_register(&alg_family);
0517     if (err != 0)
0518         goto out_unregister_proto;
0519 
0520 out:
0521     return err;
0522 
0523 out_unregister_proto:
0524     proto_unregister(&alg_proto);
0525     goto out;
0526 }
0527 
0528 static void __exit af_alg_exit(void)
0529 {
0530     sock_unregister(PF_ALG);
0531     proto_unregister(&alg_proto);
0532 }
0533 
0534 module_init(af_alg_init);
0535 module_exit(af_alg_exit);
0536 MODULE_LICENSE("GPL");
0537 MODULE_ALIAS_NETPROTO(AF_ALG);