Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Cryptographic API.
0004  *
0005  * RNG operations.
0006  *
0007  * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com>
0008  * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
0009  */
0010 
0011 #include <linux/atomic.h>
0012 #include <crypto/internal/rng.h>
0013 #include <linux/err.h>
0014 #include <linux/module.h>
0015 #include <linux/mutex.h>
0016 #include <linux/random.h>
0017 #include <linux/seq_file.h>
0018 #include <linux/slab.h>
0019 #include <linux/string.h>
0020 #include <linux/cryptouser.h>
0021 #include <linux/compiler.h>
0022 #include <net/netlink.h>
0023 
0024 #include "internal.h"
0025 
0026 static DEFINE_MUTEX(crypto_default_rng_lock);
0027 struct crypto_rng *crypto_default_rng;
0028 EXPORT_SYMBOL_GPL(crypto_default_rng);
0029 static int crypto_default_rng_refcnt;
0030 
0031 int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
0032 {
0033     struct crypto_alg *alg = tfm->base.__crt_alg;
0034     u8 *buf = NULL;
0035     int err;
0036 
0037     if (!seed && slen) {
0038         buf = kmalloc(slen, GFP_KERNEL);
0039         if (!buf)
0040             return -ENOMEM;
0041 
0042         err = get_random_bytes_wait(buf, slen);
0043         if (err)
0044             goto out;
0045         seed = buf;
0046     }
0047 
0048     crypto_stats_get(alg);
0049     err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
0050     crypto_stats_rng_seed(alg, err);
0051 out:
0052     kfree_sensitive(buf);
0053     return err;
0054 }
0055 EXPORT_SYMBOL_GPL(crypto_rng_reset);
0056 
0057 static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
0058 {
0059     return 0;
0060 }
0061 
0062 static unsigned int seedsize(struct crypto_alg *alg)
0063 {
0064     struct rng_alg *ralg = container_of(alg, struct rng_alg, base);
0065 
0066     return ralg->seedsize;
0067 }
0068 
0069 #ifdef CONFIG_NET
0070 static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
0071 {
0072     struct crypto_report_rng rrng;
0073 
0074     memset(&rrng, 0, sizeof(rrng));
0075 
0076     strscpy(rrng.type, "rng", sizeof(rrng.type));
0077 
0078     rrng.seedsize = seedsize(alg);
0079 
0080     return nla_put(skb, CRYPTOCFGA_REPORT_RNG, sizeof(rrng), &rrng);
0081 }
0082 #else
0083 static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
0084 {
0085     return -ENOSYS;
0086 }
0087 #endif
0088 
0089 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
0090     __maybe_unused;
0091 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
0092 {
0093     seq_printf(m, "type         : rng\n");
0094     seq_printf(m, "seedsize     : %u\n", seedsize(alg));
0095 }
0096 
0097 static const struct crypto_type crypto_rng_type = {
0098     .extsize = crypto_alg_extsize,
0099     .init_tfm = crypto_rng_init_tfm,
0100 #ifdef CONFIG_PROC_FS
0101     .show = crypto_rng_show,
0102 #endif
0103     .report = crypto_rng_report,
0104     .maskclear = ~CRYPTO_ALG_TYPE_MASK,
0105     .maskset = CRYPTO_ALG_TYPE_MASK,
0106     .type = CRYPTO_ALG_TYPE_RNG,
0107     .tfmsize = offsetof(struct crypto_rng, base),
0108 };
0109 
0110 struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)
0111 {
0112     return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask);
0113 }
0114 EXPORT_SYMBOL_GPL(crypto_alloc_rng);
0115 
0116 int crypto_get_default_rng(void)
0117 {
0118     struct crypto_rng *rng;
0119     int err;
0120 
0121     mutex_lock(&crypto_default_rng_lock);
0122     if (!crypto_default_rng) {
0123         rng = crypto_alloc_rng("stdrng", 0, 0);
0124         err = PTR_ERR(rng);
0125         if (IS_ERR(rng))
0126             goto unlock;
0127 
0128         err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
0129         if (err) {
0130             crypto_free_rng(rng);
0131             goto unlock;
0132         }
0133 
0134         crypto_default_rng = rng;
0135     }
0136 
0137     crypto_default_rng_refcnt++;
0138     err = 0;
0139 
0140 unlock:
0141     mutex_unlock(&crypto_default_rng_lock);
0142 
0143     return err;
0144 }
0145 EXPORT_SYMBOL_GPL(crypto_get_default_rng);
0146 
0147 void crypto_put_default_rng(void)
0148 {
0149     mutex_lock(&crypto_default_rng_lock);
0150     crypto_default_rng_refcnt--;
0151     mutex_unlock(&crypto_default_rng_lock);
0152 }
0153 EXPORT_SYMBOL_GPL(crypto_put_default_rng);
0154 
0155 #if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)
0156 int crypto_del_default_rng(void)
0157 {
0158     int err = -EBUSY;
0159 
0160     mutex_lock(&crypto_default_rng_lock);
0161     if (crypto_default_rng_refcnt)
0162         goto out;
0163 
0164     crypto_free_rng(crypto_default_rng);
0165     crypto_default_rng = NULL;
0166 
0167     err = 0;
0168 
0169 out:
0170     mutex_unlock(&crypto_default_rng_lock);
0171 
0172     return err;
0173 }
0174 EXPORT_SYMBOL_GPL(crypto_del_default_rng);
0175 #endif
0176 
0177 int crypto_register_rng(struct rng_alg *alg)
0178 {
0179     struct crypto_alg *base = &alg->base;
0180 
0181     if (alg->seedsize > PAGE_SIZE / 8)
0182         return -EINVAL;
0183 
0184     base->cra_type = &crypto_rng_type;
0185     base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
0186     base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
0187 
0188     return crypto_register_alg(base);
0189 }
0190 EXPORT_SYMBOL_GPL(crypto_register_rng);
0191 
0192 void crypto_unregister_rng(struct rng_alg *alg)
0193 {
0194     crypto_unregister_alg(&alg->base);
0195 }
0196 EXPORT_SYMBOL_GPL(crypto_unregister_rng);
0197 
0198 int crypto_register_rngs(struct rng_alg *algs, int count)
0199 {
0200     int i, ret;
0201 
0202     for (i = 0; i < count; i++) {
0203         ret = crypto_register_rng(algs + i);
0204         if (ret)
0205             goto err;
0206     }
0207 
0208     return 0;
0209 
0210 err:
0211     for (--i; i >= 0; --i)
0212         crypto_unregister_rng(algs + i);
0213 
0214     return ret;
0215 }
0216 EXPORT_SYMBOL_GPL(crypto_register_rngs);
0217 
0218 void crypto_unregister_rngs(struct rng_alg *algs, int count)
0219 {
0220     int i;
0221 
0222     for (i = count - 1; i >= 0; --i)
0223         crypto_unregister_rng(algs + i);
0224 }
0225 EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
0226 
0227 MODULE_LICENSE("GPL");
0228 MODULE_DESCRIPTION("Random Number Generator");