linux/crypto/af_alg.c
<<
>>
Prefs
   1/*
   2 * af_alg: User-space algorithm interface
   3 *
   4 * This file provides the user-space API for algorithms.
   5 *
   6 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License as published by the Free
  10 * Software Foundation; either version 2 of the License, or (at your option)
  11 * any later version.
  12 *
  13 */
  14
  15#include <linux/atomic.h>
  16#include <crypto/if_alg.h>
  17#include <linux/crypto.h>
  18#include <linux/init.h>
  19#include <linux/kernel.h>
  20#include <linux/list.h>
  21#include <linux/module.h>
  22#include <linux/net.h>
  23#include <linux/rwsem.h>
  24#include <linux/security.h>
  25
  26struct alg_type_list {
  27        const struct af_alg_type *type;
  28        struct list_head list;
  29};
  30
  31static atomic_long_t alg_memory_allocated;
  32
  33static struct proto alg_proto = {
  34        .name                   = "ALG",
  35        .owner                  = THIS_MODULE,
  36        .memory_allocated       = &alg_memory_allocated,
  37        .obj_size               = sizeof(struct alg_sock),
  38};
  39
  40static LIST_HEAD(alg_types);
  41static DECLARE_RWSEM(alg_types_sem);
  42
  43static const struct af_alg_type *alg_get_type(const char *name)
  44{
  45        const struct af_alg_type *type = ERR_PTR(-ENOENT);
  46        struct alg_type_list *node;
  47
  48        down_read(&alg_types_sem);
  49        list_for_each_entry(node, &alg_types, list) {
  50                if (strcmp(node->type->name, name))
  51                        continue;
  52
  53                if (try_module_get(node->type->owner))
  54                        type = node->type;
  55                break;
  56        }
  57        up_read(&alg_types_sem);
  58
  59        return type;
  60}
  61
  62int af_alg_register_type(const struct af_alg_type *type)
  63{
  64        struct alg_type_list *node;
  65        int err = -EEXIST;
  66
  67        down_write(&alg_types_sem);
  68        list_for_each_entry(node, &alg_types, list) {
  69                if (!strcmp(node->type->name, type->name))
  70                        goto unlock;
  71        }
  72
  73        node = kmalloc(sizeof(*node), GFP_KERNEL);
  74        err = -ENOMEM;
  75        if (!node)
  76                goto unlock;
  77
  78        type->ops->owner = THIS_MODULE;
  79        if (type->ops_nokey)
  80                type->ops_nokey->owner = THIS_MODULE;
  81        node->type = type;
  82        list_add(&node->list, &alg_types);
  83        err = 0;
  84
  85unlock:
  86        up_write(&alg_types_sem);
  87
  88        return err;
  89}
  90EXPORT_SYMBOL_GPL(af_alg_register_type);
  91
  92int af_alg_unregister_type(const struct af_alg_type *type)
  93{
  94        struct alg_type_list *node;
  95        int err = -ENOENT;
  96
  97        down_write(&alg_types_sem);
  98        list_for_each_entry(node, &alg_types, list) {
  99                if (strcmp(node->type->name, type->name))
 100                        continue;
 101
 102                list_del(&node->list);
 103                kfree(node);
 104                err = 0;
 105                break;
 106        }
 107        up_write(&alg_types_sem);
 108
 109        return err;
 110}
 111EXPORT_SYMBOL_GPL(af_alg_unregister_type);
 112
 113static void alg_do_release(const struct af_alg_type *type, void *private)
 114{
 115        if (!type)
 116                return;
 117
 118        type->release(private);
 119        module_put(type->owner);
 120}
 121
 122int af_alg_release(struct socket *sock)
 123{
 124        if (sock->sk)
 125                sock_put(sock->sk);
 126        return 0;
 127}
 128EXPORT_SYMBOL_GPL(af_alg_release);
 129
 130void af_alg_release_parent(struct sock *sk)
 131{
 132        struct alg_sock *ask = alg_sk(sk);
 133        unsigned int nokey = ask->nokey_refcnt;
 134        bool last = nokey && !ask->refcnt;
 135
 136        sk = ask->parent;
 137        ask = alg_sk(sk);
 138
 139        lock_sock(sk);
 140        ask->nokey_refcnt -= nokey;
 141        if (!last)
 142                last = !--ask->refcnt;
 143        release_sock(sk);
 144
 145        if (last)
 146                sock_put(sk);
 147}
 148EXPORT_SYMBOL_GPL(af_alg_release_parent);
 149
 150static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 151{
 152        const u32 forbidden = CRYPTO_ALG_INTERNAL;
 153        struct sock *sk = sock->sk;
 154        struct alg_sock *ask = alg_sk(sk);
 155        struct sockaddr_alg *sa = (void *)uaddr;
 156        const struct af_alg_type *type;
 157        void *private;
 158        int err;
 159
 160        if (sock->state == SS_CONNECTED)
 161                return -EINVAL;
 162
 163        if (addr_len != sizeof(*sa))
 164                return -EINVAL;
 165
 166        sa->salg_type[sizeof(sa->salg_type) - 1] = 0;
 167        sa->salg_name[sizeof(sa->salg_name) - 1] = 0;
 168
 169        type = alg_get_type(sa->salg_type);
 170        if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) {
 171                request_module("algif-%s", sa->salg_type);
 172                type = alg_get_type(sa->salg_type);
 173        }
 174
 175        if (IS_ERR(type))
 176                return PTR_ERR(type);
 177
 178        private = type->bind(sa->salg_name,
 179                             sa->salg_feat & ~forbidden,
 180                             sa->salg_mask & ~forbidden);
 181        if (IS_ERR(private)) {
 182                module_put(type->owner);
 183                return PTR_ERR(private);
 184        }
 185
 186        err = -EBUSY;
 187        lock_sock(sk);
 188        if (ask->refcnt | ask->nokey_refcnt)
 189                goto unlock;
 190
 191        swap(ask->type, type);
 192        swap(ask->private, private);
 193
 194        err = 0;
 195
 196unlock:
 197        release_sock(sk);
 198
 199        alg_do_release(type, private);
 200
 201        return err;
 202}
 203
 204static int alg_setkey(struct sock *sk, char __user *ukey,
 205                      unsigned int keylen)
 206{
 207        struct alg_sock *ask = alg_sk(sk);
 208        const struct af_alg_type *type = ask->type;
 209        u8 *key;
 210        int err;
 211
 212        key = sock_kmalloc(sk, keylen, GFP_KERNEL);
 213        if (!key)
 214                return -ENOMEM;
 215
 216        err = -EFAULT;
 217        if (copy_from_user(key, ukey, keylen))
 218                goto out;
 219
 220        err = type->setkey(ask->private, key, keylen);
 221
 222out:
 223        sock_kzfree_s(sk, key, keylen);
 224
 225        return err;
 226}
 227
 228static int alg_setsockopt(struct socket *sock, int level, int optname,
 229                          char __user *optval, unsigned int optlen)
 230{
 231        struct sock *sk = sock->sk;
 232        struct alg_sock *ask = alg_sk(sk);
 233        const struct af_alg_type *type;
 234        int err = -EBUSY;
 235
 236        lock_sock(sk);
 237        if (ask->refcnt)
 238                goto unlock;
 239
 240        type = ask->type;
 241
 242        err = -ENOPROTOOPT;
 243        if (level != SOL_ALG || !type)
 244                goto unlock;
 245
 246        switch (optname) {
 247        case ALG_SET_KEY:
 248                if (sock->state == SS_CONNECTED)
 249                        goto unlock;
 250                if (!type->setkey)
 251                        goto unlock;
 252
 253                err = alg_setkey(sk, optval, optlen);
 254                break;
 255        case ALG_SET_AEAD_AUTHSIZE:
 256                if (sock->state == SS_CONNECTED)
 257                        goto unlock;
 258                if (!type->setauthsize)
 259                        goto unlock;
 260                err = type->setauthsize(ask->private, optlen);
 261        }
 262
 263unlock:
 264        release_sock(sk);
 265
 266        return err;
 267}
 268
 269int af_alg_accept(struct sock *sk, struct socket *newsock)
 270{
 271        struct alg_sock *ask = alg_sk(sk);
 272        const struct af_alg_type *type;
 273        struct sock *sk2;
 274        unsigned int nokey;
 275        int err;
 276
 277        lock_sock(sk);
 278        type = ask->type;
 279
 280        err = -EINVAL;
 281        if (!type)
 282                goto unlock;
 283
 284        sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto, 0);
 285        err = -ENOMEM;
 286        if (!sk2)
 287                goto unlock;
 288
 289        sock_init_data(newsock, sk2);
 290        sock_graft(sk2, newsock);
 291        security_sk_clone(sk, sk2);
 292
 293        err = type->accept(ask->private, sk2);
 294
 295        nokey = err == -ENOKEY;
 296        if (nokey && type->accept_nokey)
 297                err = type->accept_nokey(ask->private, sk2);
 298
 299        if (err)
 300                goto unlock;
 301
 302        sk2->sk_family = PF_ALG;
 303
 304        if (nokey || !ask->refcnt++)
 305                sock_hold(sk);
 306        ask->nokey_refcnt += nokey;
 307        alg_sk(sk2)->parent = sk;
 308        alg_sk(sk2)->type = type;
 309        alg_sk(sk2)->nokey_refcnt = nokey;
 310
 311        newsock->ops = type->ops;
 312        newsock->state = SS_CONNECTED;
 313
 314        if (nokey)
 315                newsock->ops = type->ops_nokey;
 316
 317        err = 0;
 318
 319unlock:
 320        release_sock(sk);
 321
 322        return err;
 323}
 324EXPORT_SYMBOL_GPL(af_alg_accept);
 325
 326static int alg_accept(struct socket *sock, struct socket *newsock, int flags)
 327{
 328        return af_alg_accept(sock->sk, newsock);
 329}
 330
 331static const struct proto_ops alg_proto_ops = {
 332        .family         =       PF_ALG,
 333        .owner          =       THIS_MODULE,
 334
 335        .connect        =       sock_no_connect,
 336        .socketpair     =       sock_no_socketpair,
 337        .getname        =       sock_no_getname,
 338        .ioctl          =       sock_no_ioctl,
 339        .listen         =       sock_no_listen,
 340        .shutdown       =       sock_no_shutdown,
 341        .getsockopt     =       sock_no_getsockopt,
 342        .mmap           =       sock_no_mmap,
 343        .sendpage       =       sock_no_sendpage,
 344        .sendmsg        =       sock_no_sendmsg,
 345        .recvmsg        =       sock_no_recvmsg,
 346        .poll           =       sock_no_poll,
 347
 348        .bind           =       alg_bind,
 349        .release        =       af_alg_release,
 350        .setsockopt     =       alg_setsockopt,
 351        .accept         =       alg_accept,
 352};
 353
 354static void alg_sock_destruct(struct sock *sk)
 355{
 356        struct alg_sock *ask = alg_sk(sk);
 357
 358        alg_do_release(ask->type, ask->private);
 359}
 360
 361static int alg_create(struct net *net, struct socket *sock, int protocol,
 362                      int kern)
 363{
 364        struct sock *sk;
 365        int err;
 366
 367        if (sock->type != SOCK_SEQPACKET)
 368                return -ESOCKTNOSUPPORT;
 369        if (protocol != 0)
 370                return -EPROTONOSUPPORT;
 371
 372        err = -ENOMEM;
 373        sk = sk_alloc(net, PF_ALG, GFP_KERNEL, &alg_proto, kern);
 374        if (!sk)
 375                goto out;
 376
 377        sock->ops = &alg_proto_ops;
 378        sock_init_data(sock, sk);
 379
 380        sk->sk_family = PF_ALG;
 381        sk->sk_destruct = alg_sock_destruct;
 382
 383        return 0;
 384out:
 385        return err;
 386}
 387
 388static const struct net_proto_family alg_family = {
 389        .family =       PF_ALG,
 390        .create =       alg_create,
 391        .owner  =       THIS_MODULE,
 392};
 393
 394int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len)
 395{
 396        size_t off;
 397        ssize_t n;
 398        int npages, i;
 399
 400        n = iov_iter_get_pages(iter, sgl->pages, len, ALG_MAX_PAGES, &off);
 401        if (n < 0)
 402                return n;
 403
 404        npages = (off + n + PAGE_SIZE - 1) >> PAGE_SHIFT;
 405        if (WARN_ON(npages == 0))
 406                return -EINVAL;
 407        /* Add one extra for linking */
 408        sg_init_table(sgl->sg, npages + 1);
 409
 410        for (i = 0, len = n; i < npages; i++) {
 411                int plen = min_t(int, len, PAGE_SIZE - off);
 412
 413                sg_set_page(sgl->sg + i, sgl->pages[i], plen, off);
 414
 415                off = 0;
 416                len -= plen;
 417        }
 418        sg_mark_end(sgl->sg + npages - 1);
 419        sgl->npages = npages;
 420
 421        return n;
 422}
 423EXPORT_SYMBOL_GPL(af_alg_make_sg);
 424
 425void af_alg_link_sg(struct af_alg_sgl *sgl_prev, struct af_alg_sgl *sgl_new)
 426{
 427        sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1);
 428        sg_chain(sgl_prev->sg, sgl_prev->npages + 1, sgl_new->sg);
 429}
 430EXPORT_SYMBOL_GPL(af_alg_link_sg);
 431
 432void af_alg_free_sg(struct af_alg_sgl *sgl)
 433{
 434        int i;
 435
 436        for (i = 0; i < sgl->npages; i++)
 437                put_page(sgl->pages[i]);
 438}
 439EXPORT_SYMBOL_GPL(af_alg_free_sg);
 440
 441int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
 442{
 443        struct cmsghdr *cmsg;
 444
 445        for_each_cmsghdr(cmsg, msg) {
 446                if (!CMSG_OK(msg, cmsg))
 447                        return -EINVAL;
 448                if (cmsg->cmsg_level != SOL_ALG)
 449                        continue;
 450
 451                switch (cmsg->cmsg_type) {
 452                case ALG_SET_IV:
 453                        if (cmsg->cmsg_len < CMSG_LEN(sizeof(*con->iv)))
 454                                return -EINVAL;
 455                        con->iv = (void *)CMSG_DATA(cmsg);
 456                        if (cmsg->cmsg_len < CMSG_LEN(con->iv->ivlen +
 457                                                      sizeof(*con->iv)))
 458                                return -EINVAL;
 459                        break;
 460
 461                case ALG_SET_OP:
 462                        if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
 463                                return -EINVAL;
 464                        con->op = *(u32 *)CMSG_DATA(cmsg);
 465                        break;
 466
 467                case ALG_SET_AEAD_ASSOCLEN:
 468                        if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
 469                                return -EINVAL;
 470                        con->aead_assoclen = *(u32 *)CMSG_DATA(cmsg);
 471                        break;
 472
 473                default:
 474                        return -EINVAL;
 475                }
 476        }
 477
 478        return 0;
 479}
 480EXPORT_SYMBOL_GPL(af_alg_cmsg_send);
 481
 482int af_alg_wait_for_completion(int err, struct af_alg_completion *completion)
 483{
 484        switch (err) {
 485        case -EINPROGRESS:
 486        case -EBUSY:
 487                wait_for_completion(&completion->completion);
 488                reinit_completion(&completion->completion);
 489                err = completion->err;
 490                break;
 491        };
 492
 493        return err;
 494}
 495EXPORT_SYMBOL_GPL(af_alg_wait_for_completion);
 496
 497void af_alg_complete(struct crypto_async_request *req, int err)
 498{
 499        struct af_alg_completion *completion = req->data;
 500
 501        if (err == -EINPROGRESS)
 502                return;
 503
 504        completion->err = err;
 505        complete(&completion->completion);
 506}
 507EXPORT_SYMBOL_GPL(af_alg_complete);
 508
 509static int __init af_alg_init(void)
 510{
 511        int err = proto_register(&alg_proto, 0);
 512
 513        if (err)
 514                goto out;
 515
 516        err = sock_register(&alg_family);
 517        if (err != 0)
 518                goto out_unregister_proto;
 519
 520out:
 521        return err;
 522
 523out_unregister_proto:
 524        proto_unregister(&alg_proto);
 525        goto out;
 526}
 527
 528static void __exit af_alg_exit(void)
 529{
 530        sock_unregister(PF_ALG);
 531        proto_unregister(&alg_proto);
 532}
 533
 534module_init(af_alg_init);
 535module_exit(af_alg_exit);
 536MODULE_LICENSE("GPL");
 537MODULE_ALIAS_NETPROTO(AF_ALG);
 538