linux/crypto/rng.c
<<
>>
Prefs
   1/*
   2 * Cryptographic API.
   3 *
   4 * RNG operations.
   5 *
   6 * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com>
   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 <asm/atomic.h>
  16#include <crypto/internal/rng.h>
  17#include <linux/err.h>
  18#include <linux/module.h>
  19#include <linux/mutex.h>
  20#include <linux/random.h>
  21#include <linux/seq_file.h>
  22#include <linux/slab.h>
  23#include <linux/string.h>
  24
  25static DEFINE_MUTEX(crypto_default_rng_lock);
  26struct crypto_rng *crypto_default_rng;
  27EXPORT_SYMBOL_GPL(crypto_default_rng);
  28static int crypto_default_rng_refcnt;
  29
  30static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
  31{
  32        u8 *buf = NULL;
  33        int err;
  34
  35        if (!seed && slen) {
  36                buf = kmalloc(slen, GFP_KERNEL);
  37                if (!buf)
  38                        return -ENOMEM;
  39
  40                get_random_bytes(buf, slen);
  41                seed = buf;
  42        }
  43
  44        err = crypto_rng_alg(tfm)->rng_reset(tfm, seed, slen);
  45
  46        kfree(buf);
  47        return err;
  48}
  49
  50static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
  51{
  52        struct rng_alg *alg = &tfm->__crt_alg->cra_rng;
  53        struct rng_tfm *ops = &tfm->crt_rng;
  54
  55        ops->rng_gen_random = alg->rng_make_random;
  56        ops->rng_reset = rngapi_reset;
  57
  58        return 0;
  59}
  60
  61static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
  62        __attribute__ ((unused));
  63static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
  64{
  65        seq_printf(m, "type         : rng\n");
  66        seq_printf(m, "seedsize     : %u\n", alg->cra_rng.seedsize);
  67}
  68
  69static unsigned int crypto_rng_ctxsize(struct crypto_alg *alg, u32 type,
  70                                       u32 mask)
  71{
  72        return alg->cra_ctxsize;
  73}
  74
  75const struct crypto_type crypto_rng_type = {
  76        .ctxsize = crypto_rng_ctxsize,
  77        .init = crypto_init_rng_ops,
  78#ifdef CONFIG_PROC_FS
  79        .show = crypto_rng_show,
  80#endif
  81};
  82EXPORT_SYMBOL_GPL(crypto_rng_type);
  83
  84int crypto_get_default_rng(void)
  85{
  86        struct crypto_rng *rng;
  87        int err;
  88
  89        mutex_lock(&crypto_default_rng_lock);
  90        if (!crypto_default_rng) {
  91                rng = crypto_alloc_rng("stdrng", 0, 0);
  92                err = PTR_ERR(rng);
  93                if (IS_ERR(rng))
  94                        goto unlock;
  95
  96                err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
  97                if (err) {
  98                        crypto_free_rng(rng);
  99                        goto unlock;
 100                }
 101
 102                crypto_default_rng = rng;
 103        }
 104
 105        crypto_default_rng_refcnt++;
 106        err = 0;
 107
 108unlock:
 109        mutex_unlock(&crypto_default_rng_lock);
 110
 111        return err;
 112}
 113EXPORT_SYMBOL_GPL(crypto_get_default_rng);
 114
 115void crypto_put_default_rng(void)
 116{
 117        mutex_lock(&crypto_default_rng_lock);
 118        if (!--crypto_default_rng_refcnt) {
 119                crypto_free_rng(crypto_default_rng);
 120                crypto_default_rng = NULL;
 121        }
 122        mutex_unlock(&crypto_default_rng_lock);
 123}
 124EXPORT_SYMBOL_GPL(crypto_put_default_rng);
 125
 126MODULE_LICENSE("GPL");
 127MODULE_DESCRIPTION("Random Number Generator");
 128