xref: /linux/crypto/rng.c (revision b2cb6011bcaf5bba08b55f20e3eea9cdd415ec9d)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
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  
26  static DEFINE_MUTEX(crypto_default_rng_lock);
27  struct crypto_rng *crypto_default_rng;
28  EXPORT_SYMBOL_GPL(crypto_default_rng);
29  static int crypto_default_rng_refcnt;
30  
31  int 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);
48  out:
49  	kfree_sensitive(buf);
50  	return err;
51  }
52  EXPORT_SYMBOL_GPL(crypto_rng_reset);
53  
54  static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
55  {
56  	return 0;
57  }
58  
59  static 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  
66  static 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  
80  static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
81  	__maybe_unused;
82  static 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  
88  static const struct crypto_type crypto_rng_type = {
89  	.extsize = crypto_alg_extsize,
90  	.init_tfm = crypto_rng_init_tfm,
91  #ifdef CONFIG_PROC_FS
92  	.show = crypto_rng_show,
93  #endif
94  #if IS_ENABLED(CONFIG_CRYPTO_USER)
95  	.report = crypto_rng_report,
96  #endif
97  	.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  
103  struct 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  }
107  EXPORT_SYMBOL_GPL(crypto_alloc_rng);
108  
109  int 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  
133  unlock:
134  	mutex_unlock(&crypto_default_rng_lock);
135  
136  	return err;
137  }
138  EXPORT_SYMBOL_GPL(crypto_get_default_rng);
139  
140  void 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  }
146  EXPORT_SYMBOL_GPL(crypto_put_default_rng);
147  
148  #if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)
149  int 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  
162  out:
163  	mutex_unlock(&crypto_default_rng_lock);
164  
165  	return err;
166  }
167  EXPORT_SYMBOL_GPL(crypto_del_default_rng);
168  #endif
169  
170  int 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  }
183  EXPORT_SYMBOL_GPL(crypto_register_rng);
184  
185  void crypto_unregister_rng(struct rng_alg *alg)
186  {
187  	crypto_unregister_alg(&alg->base);
188  }
189  EXPORT_SYMBOL_GPL(crypto_unregister_rng);
190  
191  int 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  
203  err:
204  	for (--i; i >= 0; --i)
205  		crypto_unregister_rng(algs + i);
206  
207  	return ret;
208  }
209  EXPORT_SYMBOL_GPL(crypto_register_rngs);
210  
211  void 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  }
218  EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
219  
220  MODULE_LICENSE("GPL");
221  MODULE_DESCRIPTION("Random Number Generator");
222