brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · 9d8804e Raw
222 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Cryptographic API.4 *5 * RNG operations.6 *7 * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com>8 * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>9 */10 11#include <crypto/internal/rng.h>12#include <linux/atomic.h>13#include <linux/cryptouser.h>14#include <linux/err.h>15#include <linux/kernel.h>16#include <linux/module.h>17#include <linux/mutex.h>18#include <linux/random.h>19#include <linux/seq_file.h>20#include <linux/slab.h>21#include <linux/string.h>22#include <net/netlink.h>23 24#include "internal.h"25 26static DEFINE_MUTEX(crypto_default_rng_lock);27struct crypto_rng *crypto_default_rng;28EXPORT_SYMBOL_GPL(crypto_default_rng);29static int crypto_default_rng_refcnt;30 31int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)32{33	u8 *buf = NULL;34	int err;35 36	if (!seed && slen) {37		buf = kmalloc(slen, GFP_KERNEL);38		if (!buf)39			return -ENOMEM;40 41		err = get_random_bytes_wait(buf, slen);42		if (err)43			goto out;44		seed = buf;45	}46 47	err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);48out:49	kfree_sensitive(buf);50	return err;51}52EXPORT_SYMBOL_GPL(crypto_rng_reset);53 54static int crypto_rng_init_tfm(struct crypto_tfm *tfm)55{56	return 0;57}58 59static unsigned int seedsize(struct crypto_alg *alg)60{61	struct rng_alg *ralg = container_of(alg, struct rng_alg, base);62 63	return ralg->seedsize;64}65 66static int __maybe_unused crypto_rng_report(67	struct sk_buff *skb, struct crypto_alg *alg)68{69	struct crypto_report_rng rrng;70 71	memset(&rrng, 0, sizeof(rrng));72 73	strscpy(rrng.type, "rng", sizeof(rrng.type));74 75	rrng.seedsize = seedsize(alg);76 77	return nla_put(skb, CRYPTOCFGA_REPORT_RNG, sizeof(rrng), &rrng);78}79 80static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)81	__maybe_unused;82static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)83{84	seq_printf(m, "type         : rng\n");85	seq_printf(m, "seedsize     : %u\n", seedsize(alg));86}87 88static const struct crypto_type crypto_rng_type = {89	.extsize = crypto_alg_extsize,90	.init_tfm = crypto_rng_init_tfm,91#ifdef CONFIG_PROC_FS92	.show = crypto_rng_show,93#endif94#if IS_ENABLED(CONFIG_CRYPTO_USER)95	.report = crypto_rng_report,96#endif97	.maskclear = ~CRYPTO_ALG_TYPE_MASK,98	.maskset = CRYPTO_ALG_TYPE_MASK,99	.type = CRYPTO_ALG_TYPE_RNG,100	.tfmsize = offsetof(struct crypto_rng, base),101};102 103struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)104{105	return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask);106}107EXPORT_SYMBOL_GPL(crypto_alloc_rng);108 109int crypto_get_default_rng(void)110{111	struct crypto_rng *rng;112	int err;113 114	mutex_lock(&crypto_default_rng_lock);115	if (!crypto_default_rng) {116		rng = crypto_alloc_rng("stdrng", 0, 0);117		err = PTR_ERR(rng);118		if (IS_ERR(rng))119			goto unlock;120 121		err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));122		if (err) {123			crypto_free_rng(rng);124			goto unlock;125		}126 127		crypto_default_rng = rng;128	}129 130	crypto_default_rng_refcnt++;131	err = 0;132 133unlock:134	mutex_unlock(&crypto_default_rng_lock);135 136	return err;137}138EXPORT_SYMBOL_GPL(crypto_get_default_rng);139 140void crypto_put_default_rng(void)141{142	mutex_lock(&crypto_default_rng_lock);143	crypto_default_rng_refcnt--;144	mutex_unlock(&crypto_default_rng_lock);145}146EXPORT_SYMBOL_GPL(crypto_put_default_rng);147 148#if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)149int crypto_del_default_rng(void)150{151	int err = -EBUSY;152 153	mutex_lock(&crypto_default_rng_lock);154	if (crypto_default_rng_refcnt)155		goto out;156 157	crypto_free_rng(crypto_default_rng);158	crypto_default_rng = NULL;159 160	err = 0;161 162out:163	mutex_unlock(&crypto_default_rng_lock);164 165	return err;166}167EXPORT_SYMBOL_GPL(crypto_del_default_rng);168#endif169 170int crypto_register_rng(struct rng_alg *alg)171{172	struct crypto_alg *base = &alg->base;173 174	if (alg->seedsize > PAGE_SIZE / 8)175		return -EINVAL;176 177	base->cra_type = &crypto_rng_type;178	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;179	base->cra_flags |= CRYPTO_ALG_TYPE_RNG;180 181	return crypto_register_alg(base);182}183EXPORT_SYMBOL_GPL(crypto_register_rng);184 185void crypto_unregister_rng(struct rng_alg *alg)186{187	crypto_unregister_alg(&alg->base);188}189EXPORT_SYMBOL_GPL(crypto_unregister_rng);190 191int crypto_register_rngs(struct rng_alg *algs, int count)192{193	int i, ret;194 195	for (i = 0; i < count; i++) {196		ret = crypto_register_rng(algs + i);197		if (ret)198			goto err;199	}200 201	return 0;202 203err:204	for (--i; i >= 0; --i)205		crypto_unregister_rng(algs + i);206 207	return ret;208}209EXPORT_SYMBOL_GPL(crypto_register_rngs);210 211void crypto_unregister_rngs(struct rng_alg *algs, int count)212{213	int i;214 215	for (i = count - 1; i >= 0; --i)216		crypto_unregister_rng(algs + i);217}218EXPORT_SYMBOL_GPL(crypto_unregister_rngs);219 220MODULE_LICENSE("GPL");221MODULE_DESCRIPTION("Random Number Generator");222