Branch data Line data Source code
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 <linux/atomic.h>
12 : : #include <crypto/internal/rng.h>
13 : : #include <linux/err.h>
14 : : #include <linux/module.h>
15 : : #include <linux/mutex.h>
16 : : #include <linux/random.h>
17 : : #include <linux/seq_file.h>
18 : : #include <linux/slab.h>
19 : : #include <linux/string.h>
20 : : #include <linux/cryptouser.h>
21 : : #include <linux/compiler.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 : 0 : int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
32 : : {
33 : 0 : struct crypto_alg *alg = tfm->base.__crt_alg;
34 : : u8 *buf = NULL;
35 : : int err;
36 : :
37 : : crypto_stats_get(alg);
38 [ # # ]: 0 : if (!seed && slen) {
39 : : buf = kmalloc(slen, GFP_KERNEL);
40 [ # # ]: 0 : if (!buf) {
41 : 0 : crypto_alg_put(alg);
42 : 0 : return -ENOMEM;
43 : : }
44 : :
45 : 0 : err = get_random_bytes_wait(buf, slen);
46 [ # # ]: 0 : if (err) {
47 : 0 : crypto_alg_put(alg);
48 : 0 : goto out;
49 : : }
50 : : seed = buf;
51 : : }
52 : :
53 : 0 : err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
54 : : crypto_stats_rng_seed(alg, err);
55 : : out:
56 : 0 : kzfree(buf);
57 : 0 : return err;
58 : : }
59 : : EXPORT_SYMBOL_GPL(crypto_rng_reset);
60 : :
61 : 0 : static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
62 : : {
63 : 0 : return 0;
64 : : }
65 : :
66 : : static unsigned int seedsize(struct crypto_alg *alg)
67 : : {
68 : : struct rng_alg *ralg = container_of(alg, struct rng_alg, base);
69 : :
70 : 0 : return ralg->seedsize;
71 : : }
72 : :
73 : : #ifdef CONFIG_NET
74 : 0 : static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
75 : : {
76 : : struct crypto_report_rng rrng;
77 : :
78 : 0 : memset(&rrng, 0, sizeof(rrng));
79 : :
80 : 0 : strscpy(rrng.type, "rng", sizeof(rrng.type));
81 : :
82 : 0 : rrng.seedsize = seedsize(alg);
83 : :
84 : 0 : return nla_put(skb, CRYPTOCFGA_REPORT_RNG, sizeof(rrng), &rrng);
85 : : }
86 : : #else
87 : : static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
88 : : {
89 : : return -ENOSYS;
90 : : }
91 : : #endif
92 : :
93 : : static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
94 : : __maybe_unused;
95 : 0 : static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
96 : : {
97 : 0 : seq_printf(m, "type : rng\n");
98 : 0 : seq_printf(m, "seedsize : %u\n", seedsize(alg));
99 : 0 : }
100 : :
101 : : static const struct crypto_type crypto_rng_type = {
102 : : .extsize = crypto_alg_extsize,
103 : : .init_tfm = crypto_rng_init_tfm,
104 : : #ifdef CONFIG_PROC_FS
105 : : .show = crypto_rng_show,
106 : : #endif
107 : : .report = crypto_rng_report,
108 : : .maskclear = ~CRYPTO_ALG_TYPE_MASK,
109 : : .maskset = CRYPTO_ALG_TYPE_MASK,
110 : : .type = CRYPTO_ALG_TYPE_RNG,
111 : : .tfmsize = offsetof(struct crypto_rng, base),
112 : : };
113 : :
114 : 0 : struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)
115 : : {
116 : 0 : return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask);
117 : : }
118 : : EXPORT_SYMBOL_GPL(crypto_alloc_rng);
119 : :
120 : 0 : int crypto_get_default_rng(void)
121 : : {
122 : : struct crypto_rng *rng;
123 : : int err;
124 : :
125 : 0 : mutex_lock(&crypto_default_rng_lock);
126 [ # # ]: 0 : if (!crypto_default_rng) {
127 : : rng = crypto_alloc_rng("stdrng", 0, 0);
128 : : err = PTR_ERR(rng);
129 [ # # ]: 0 : if (IS_ERR(rng))
130 : : goto unlock;
131 : :
132 : 0 : err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
133 [ # # ]: 0 : if (err) {
134 : : crypto_free_rng(rng);
135 : : goto unlock;
136 : : }
137 : :
138 : 0 : crypto_default_rng = rng;
139 : : }
140 : :
141 : 0 : crypto_default_rng_refcnt++;
142 : : err = 0;
143 : :
144 : : unlock:
145 : 0 : mutex_unlock(&crypto_default_rng_lock);
146 : :
147 : 0 : return err;
148 : : }
149 : : EXPORT_SYMBOL_GPL(crypto_get_default_rng);
150 : :
151 : 0 : void crypto_put_default_rng(void)
152 : : {
153 : 0 : mutex_lock(&crypto_default_rng_lock);
154 : 0 : crypto_default_rng_refcnt--;
155 : 0 : mutex_unlock(&crypto_default_rng_lock);
156 : 0 : }
157 : : EXPORT_SYMBOL_GPL(crypto_put_default_rng);
158 : :
159 : : #if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)
160 : 0 : int crypto_del_default_rng(void)
161 : : {
162 : : int err = -EBUSY;
163 : :
164 : 0 : mutex_lock(&crypto_default_rng_lock);
165 [ # # ]: 0 : if (crypto_default_rng_refcnt)
166 : : goto out;
167 : :
168 : 0 : crypto_free_rng(crypto_default_rng);
169 : 0 : crypto_default_rng = NULL;
170 : :
171 : : err = 0;
172 : :
173 : : out:
174 : 0 : mutex_unlock(&crypto_default_rng_lock);
175 : :
176 : 0 : return err;
177 : : }
178 : : EXPORT_SYMBOL_GPL(crypto_del_default_rng);
179 : : #endif
180 : :
181 : 0 : int crypto_register_rng(struct rng_alg *alg)
182 : : {
183 : 0 : struct crypto_alg *base = &alg->base;
184 : :
185 [ # # ]: 0 : if (alg->seedsize > PAGE_SIZE / 8)
186 : : return -EINVAL;
187 : :
188 : 0 : base->cra_type = &crypto_rng_type;
189 : 0 : base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
190 : 0 : base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
191 : :
192 : 0 : return crypto_register_alg(base);
193 : : }
194 : : EXPORT_SYMBOL_GPL(crypto_register_rng);
195 : :
196 : 0 : void crypto_unregister_rng(struct rng_alg *alg)
197 : : {
198 : 0 : crypto_unregister_alg(&alg->base);
199 : 0 : }
200 : : EXPORT_SYMBOL_GPL(crypto_unregister_rng);
201 : :
202 : 0 : int crypto_register_rngs(struct rng_alg *algs, int count)
203 : : {
204 : : int i, ret;
205 : :
206 [ # # ]: 0 : for (i = 0; i < count; i++) {
207 : 0 : ret = crypto_register_rng(algs + i);
208 [ # # ]: 0 : if (ret)
209 : : goto err;
210 : : }
211 : :
212 : : return 0;
213 : :
214 : : err:
215 [ # # ]: 0 : for (--i; i >= 0; --i)
216 : 0 : crypto_unregister_rng(algs + i);
217 : :
218 : 0 : return ret;
219 : : }
220 : : EXPORT_SYMBOL_GPL(crypto_register_rngs);
221 : :
222 : 0 : void crypto_unregister_rngs(struct rng_alg *algs, int count)
223 : : {
224 : : int i;
225 : :
226 [ # # ]: 0 : for (i = count - 1; i >= 0; --i)
227 : 0 : crypto_unregister_rng(algs + i);
228 : 0 : }
229 : : EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
230 : :
231 : : MODULE_LICENSE("GPL");
232 : : MODULE_DESCRIPTION("Random Number Generator");
|