linux/crypto/api.c
<<
>>
Prefs
   1/*
   2 * Scatterlist Cryptographic API.
   3 *
   4 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
   5 * Copyright (c) 2002 David S. Miller (davem@redhat.com)
   6 * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
   7 *
   8 * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
   9 * and Nettle, by Niels M\xF6ller.
  10 *
  11 * This program is free software; you can redistribute it and/or modify it
  12 * under the terms of the GNU General Public License as published by the Free
  13 * Software Foundation; either version 2 of the License, or (at your option) 
  14 * any later version.
  15 *
  16 */
  17
  18#include <linux/err.h>
  19#include <linux/errno.h>
  20#include <linux/kernel.h>
  21#include <linux/kmod.h>
  22#include <linux/module.h>
  23#include <linux/param.h>
  24#include <linux/sched.h>
  25#include <linux/slab.h>
  26#include <linux/string.h>
  27#include "internal.h"
  28
  29LIST_HEAD(crypto_alg_list);
  30EXPORT_SYMBOL_GPL(crypto_alg_list);
  31DECLARE_RWSEM(crypto_alg_sem);
  32EXPORT_SYMBOL_GPL(crypto_alg_sem);
  33
  34BLOCKING_NOTIFIER_HEAD(crypto_chain);
  35EXPORT_SYMBOL_GPL(crypto_chain);
  36
  37static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg)
  38{
  39        atomic_inc(&alg->cra_refcnt);
  40        return alg;
  41}
  42
  43struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
  44{
  45        return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL;
  46}
  47EXPORT_SYMBOL_GPL(crypto_mod_get);
  48
  49void crypto_mod_put(struct crypto_alg *alg)
  50{
  51        crypto_alg_put(alg);
  52        module_put(alg->cra_module);
  53}
  54EXPORT_SYMBOL_GPL(crypto_mod_put);
  55
  56struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask)
  57{
  58        struct crypto_alg *q, *alg = NULL;
  59        int best = -2;
  60
  61        list_for_each_entry(q, &crypto_alg_list, cra_list) {
  62                int exact, fuzzy;
  63
  64                if (crypto_is_moribund(q))
  65                        continue;
  66
  67                if ((q->cra_flags ^ type) & mask)
  68                        continue;
  69
  70                if (crypto_is_larval(q) &&
  71                    ((struct crypto_larval *)q)->mask != mask)
  72                        continue;
  73
  74                exact = !strcmp(q->cra_driver_name, name);
  75                fuzzy = !strcmp(q->cra_name, name);
  76                if (!exact && !(fuzzy && q->cra_priority > best))
  77                        continue;
  78
  79                if (unlikely(!crypto_mod_get(q)))
  80                        continue;
  81
  82                best = q->cra_priority;
  83                if (alg)
  84                        crypto_mod_put(alg);
  85                alg = q;
  86
  87                if (exact)
  88                        break;
  89        }
  90
  91        return alg;
  92}
  93EXPORT_SYMBOL_GPL(__crypto_alg_lookup);
  94
  95static void crypto_larval_destroy(struct crypto_alg *alg)
  96{
  97        struct crypto_larval *larval = (void *)alg;
  98
  99        BUG_ON(!crypto_is_larval(alg));
 100        if (larval->adult)
 101                crypto_mod_put(larval->adult);
 102        kfree(larval);
 103}
 104
 105static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type,
 106                                              u32 mask)
 107{
 108        struct crypto_alg *alg;
 109        struct crypto_larval *larval;
 110
 111        larval = kzalloc(sizeof(*larval), GFP_KERNEL);
 112        if (!larval)
 113                return ERR_PTR(-ENOMEM);
 114
 115        larval->mask = mask;
 116        larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type;
 117        larval->alg.cra_priority = -1;
 118        larval->alg.cra_destroy = crypto_larval_destroy;
 119
 120        atomic_set(&larval->alg.cra_refcnt, 2);
 121        strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME);
 122        init_completion(&larval->completion);
 123
 124        down_write(&crypto_alg_sem);
 125        alg = __crypto_alg_lookup(name, type, mask);
 126        if (!alg) {
 127                alg = &larval->alg;
 128                list_add(&alg->cra_list, &crypto_alg_list);
 129        }
 130        up_write(&crypto_alg_sem);
 131
 132        if (alg != &larval->alg)
 133                kfree(larval);
 134
 135        return alg;
 136}
 137
 138static void crypto_larval_kill(struct crypto_alg *alg)
 139{
 140        struct crypto_larval *larval = (void *)alg;
 141
 142        down_write(&crypto_alg_sem);
 143        list_del(&alg->cra_list);
 144        up_write(&crypto_alg_sem);
 145        complete(&larval->completion);
 146        crypto_alg_put(alg);
 147}
 148
 149static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
 150{
 151        struct crypto_larval *larval = (void *)alg;
 152
 153        wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ);
 154        alg = larval->adult;
 155        if (alg) {
 156                if (!crypto_mod_get(alg))
 157                        alg = ERR_PTR(-EAGAIN);
 158        } else
 159                alg = ERR_PTR(-ENOENT);
 160        crypto_mod_put(&larval->alg);
 161
 162        return alg;
 163}
 164
 165static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
 166                                            u32 mask)
 167{
 168        struct crypto_alg *alg;
 169
 170        down_read(&crypto_alg_sem);
 171        alg = __crypto_alg_lookup(name, type, mask);
 172        up_read(&crypto_alg_sem);
 173
 174        return alg;
 175}
 176
 177struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
 178{
 179        struct crypto_alg *alg;
 180        struct crypto_alg *larval;
 181        int ok;
 182
 183        if (!name)
 184                return ERR_PTR(-ENOENT);
 185
 186        mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
 187        type &= mask;
 188
 189        alg = try_then_request_module(crypto_alg_lookup(name, type, mask),
 190                                      name);
 191        if (alg)
 192                return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
 193
 194        larval = crypto_larval_alloc(name, type, mask);
 195        if (IS_ERR(larval) || !crypto_is_larval(larval))
 196                return larval;
 197
 198        ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval);
 199        if (ok == NOTIFY_DONE) {
 200                request_module("cryptomgr");
 201                ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval);
 202        }
 203
 204        if (ok == NOTIFY_STOP)
 205                alg = crypto_larval_wait(larval);
 206        else {
 207                crypto_mod_put(larval);
 208                alg = ERR_PTR(-ENOENT);
 209        }
 210        crypto_larval_kill(larval);
 211        return alg;
 212}
 213EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
 214
 215static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
 216{
 217        tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK;
 218        flags &= ~CRYPTO_TFM_REQ_MASK;
 219        
 220        switch (crypto_tfm_alg_type(tfm)) {
 221        case CRYPTO_ALG_TYPE_CIPHER:
 222                return crypto_init_cipher_flags(tfm, flags);
 223                
 224        case CRYPTO_ALG_TYPE_DIGEST:
 225                return crypto_init_digest_flags(tfm, flags);
 226                
 227        case CRYPTO_ALG_TYPE_COMPRESS:
 228                return crypto_init_compress_flags(tfm, flags);
 229        }
 230        
 231        return 0;
 232}
 233
 234static int crypto_init_ops(struct crypto_tfm *tfm)
 235{
 236        const struct crypto_type *type = tfm->__crt_alg->cra_type;
 237
 238        if (type)
 239                return type->init(tfm);
 240
 241        switch (crypto_tfm_alg_type(tfm)) {
 242        case CRYPTO_ALG_TYPE_CIPHER:
 243                return crypto_init_cipher_ops(tfm);
 244                
 245        case CRYPTO_ALG_TYPE_DIGEST:
 246                return crypto_init_digest_ops(tfm);
 247                
 248        case CRYPTO_ALG_TYPE_COMPRESS:
 249                return crypto_init_compress_ops(tfm);
 250        
 251        default:
 252                break;
 253        }
 254        
 255        BUG();
 256        return -EINVAL;
 257}
 258
 259static void crypto_exit_ops(struct crypto_tfm *tfm)
 260{
 261        const struct crypto_type *type = tfm->__crt_alg->cra_type;
 262
 263        if (type) {
 264                if (type->exit)
 265                        type->exit(tfm);
 266                return;
 267        }
 268
 269        switch (crypto_tfm_alg_type(tfm)) {
 270        case CRYPTO_ALG_TYPE_CIPHER:
 271                crypto_exit_cipher_ops(tfm);
 272                break;
 273                
 274        case CRYPTO_ALG_TYPE_DIGEST:
 275                crypto_exit_digest_ops(tfm);
 276                break;
 277                
 278        case CRYPTO_ALG_TYPE_COMPRESS:
 279                crypto_exit_compress_ops(tfm);
 280                break;
 281        
 282        default:
 283                BUG();
 284                
 285        }
 286}
 287
 288static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags)
 289{
 290        const struct crypto_type *type = alg->cra_type;
 291        unsigned int len;
 292
 293        len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
 294        if (type)
 295                return len + type->ctxsize(alg);
 296
 297        switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
 298        default:
 299                BUG();
 300
 301        case CRYPTO_ALG_TYPE_CIPHER:
 302                len += crypto_cipher_ctxsize(alg, flags);
 303                break;
 304                
 305        case CRYPTO_ALG_TYPE_DIGEST:
 306                len += crypto_digest_ctxsize(alg, flags);
 307                break;
 308                
 309        case CRYPTO_ALG_TYPE_COMPRESS:
 310                len += crypto_compress_ctxsize(alg, flags);
 311                break;
 312        }
 313
 314        return len;
 315}
 316
 317void crypto_shoot_alg(struct crypto_alg *alg)
 318{
 319        down_write(&crypto_alg_sem);
 320        alg->cra_flags |= CRYPTO_ALG_DYING;
 321        up_write(&crypto_alg_sem);
 322}
 323EXPORT_SYMBOL_GPL(crypto_shoot_alg);
 324
 325struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags)
 326{
 327        struct crypto_tfm *tfm = NULL;
 328        unsigned int tfm_size;
 329        int err = -ENOMEM;
 330
 331        tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags);
 332        tfm = kzalloc(tfm_size, GFP_KERNEL);
 333        if (tfm == NULL)
 334                goto out_err;
 335
 336        tfm->__crt_alg = alg;
 337
 338        err = crypto_init_flags(tfm, flags);
 339        if (err)
 340                goto out_free_tfm;
 341                
 342        err = crypto_init_ops(tfm);
 343        if (err)
 344                goto out_free_tfm;
 345
 346        if (alg->cra_init && (err = alg->cra_init(tfm))) {
 347                if (err == -EAGAIN)
 348                        crypto_shoot_alg(alg);
 349                goto cra_init_failed;
 350        }
 351
 352        goto out;
 353
 354cra_init_failed:
 355        crypto_exit_ops(tfm);
 356out_free_tfm:
 357        kfree(tfm);
 358out_err:
 359        tfm = ERR_PTR(err);
 360out:
 361        return tfm;
 362}
 363EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
 364
 365struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
 366{
 367        struct crypto_tfm *tfm = NULL;
 368        int err;
 369
 370        do {
 371                struct crypto_alg *alg;
 372
 373                alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC);
 374                err = PTR_ERR(alg);
 375                if (IS_ERR(alg))
 376                        continue;
 377
 378                tfm = __crypto_alloc_tfm(alg, flags);
 379                err = 0;
 380                if (IS_ERR(tfm)) {
 381                        crypto_mod_put(alg);
 382                        err = PTR_ERR(tfm);
 383                        tfm = NULL;
 384                }
 385        } while (err == -EAGAIN && !signal_pending(current));
 386
 387        return tfm;
 388}
 389
 390/*
 391 *      crypto_alloc_base - Locate algorithm and allocate transform
 392 *      @alg_name: Name of algorithm
 393 *      @type: Type of algorithm
 394 *      @mask: Mask for type comparison
 395 *
 396 *      crypto_alloc_base() will first attempt to locate an already loaded
 397 *      algorithm.  If that fails and the kernel supports dynamically loadable
 398 *      modules, it will then attempt to load a module of the same name or
 399 *      alias.  If that fails it will send a query to any loaded crypto manager
 400 *      to construct an algorithm on the fly.  A refcount is grabbed on the
 401 *      algorithm which is then associated with the new transform.
 402 *
 403 *      The returned transform is of a non-determinate type.  Most people
 404 *      should use one of the more specific allocation functions such as
 405 *      crypto_alloc_blkcipher.
 406 *
 407 *      In case of error the return value is an error pointer.
 408 */
 409struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
 410{
 411        struct crypto_tfm *tfm;
 412        int err;
 413
 414        for (;;) {
 415                struct crypto_alg *alg;
 416
 417                alg = crypto_alg_mod_lookup(alg_name, type, mask);
 418                if (IS_ERR(alg)) {
 419                        err = PTR_ERR(alg);
 420                        goto err;
 421                }
 422
 423                tfm = __crypto_alloc_tfm(alg, 0);
 424                if (!IS_ERR(tfm))
 425                        return tfm;
 426
 427                crypto_mod_put(alg);
 428                err = PTR_ERR(tfm);
 429
 430err:
 431                if (err != -EAGAIN)
 432                        break;
 433                if (signal_pending(current)) {
 434                        err = -EINTR;
 435                        break;
 436                }
 437        }
 438
 439        return ERR_PTR(err);
 440}
 441EXPORT_SYMBOL_GPL(crypto_alloc_base);
 442 
 443/*
 444 *      crypto_free_tfm - Free crypto transform
 445 *      @tfm: Transform to free
 446 *
 447 *      crypto_free_tfm() frees up the transform and any associated resources,
 448 *      then drops the refcount on the associated algorithm.
 449 */
 450void crypto_free_tfm(struct crypto_tfm *tfm)
 451{
 452        struct crypto_alg *alg;
 453        int size;
 454
 455        if (unlikely(!tfm))
 456                return;
 457
 458        alg = tfm->__crt_alg;
 459        size = sizeof(*tfm) + alg->cra_ctxsize;
 460
 461        if (alg->cra_exit)
 462                alg->cra_exit(tfm);
 463        crypto_exit_ops(tfm);
 464        crypto_mod_put(alg);
 465        memset(tfm, 0, size);
 466        kfree(tfm);
 467}
 468
 469int crypto_alg_available(const char *name, u32 flags)
 470{
 471        int ret = 0;
 472        struct crypto_alg *alg = crypto_alg_mod_lookup(name, 0,
 473                                                       CRYPTO_ALG_ASYNC);
 474        
 475        if (!IS_ERR(alg)) {
 476                crypto_mod_put(alg);
 477                ret = 1;
 478        }
 479        
 480        return ret;
 481}
 482
 483EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
 484EXPORT_SYMBOL_GPL(crypto_free_tfm);
 485EXPORT_SYMBOL_GPL(crypto_alg_available);
 486
 487int crypto_has_alg(const char *name, u32 type, u32 mask)
 488{
 489        int ret = 0;
 490        struct crypto_alg *alg = crypto_alg_mod_lookup(name, type, mask);
 491        
 492        if (!IS_ERR(alg)) {
 493                crypto_mod_put(alg);
 494                ret = 1;
 495        }
 496        
 497        return ret;
 498}
 499EXPORT_SYMBOL_GPL(crypto_has_alg);
 500
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.