Branch data Line data Source code
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 <linux/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 : : #include <linux/cryptouser.h>
25 : : #include <net/netlink.h>
26 : :
27 : : static DEFINE_MUTEX(crypto_default_rng_lock);
28 : : struct crypto_rng *crypto_default_rng;
29 : : EXPORT_SYMBOL_GPL(crypto_default_rng);
30 : : static int crypto_default_rng_refcnt;
31 : :
32 : 0 : static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
33 : : {
34 : : u8 *buf = NULL;
35 : : int err;
36 : :
37 [ # # ]: 0 : if (!seed && slen) {
38 : : buf = kmalloc(slen, GFP_KERNEL);
39 [ # # ]: 0 : if (!buf)
40 : : return -ENOMEM;
41 : :
42 : 0 : get_random_bytes(buf, slen);
43 : : seed = buf;
44 : : }
45 : :
46 : 0 : err = crypto_rng_alg(tfm)->rng_reset(tfm, seed, slen);
47 : :
48 : 0 : kfree(buf);
49 : 0 : return err;
50 : : }
51 : :
52 : 0 : static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
53 : : {
54 : 0 : struct rng_alg *alg = &tfm->__crt_alg->cra_rng;
55 : : struct rng_tfm *ops = &tfm->crt_rng;
56 : :
57 : 0 : ops->rng_gen_random = alg->rng_make_random;
58 : 0 : ops->rng_reset = rngapi_reset;
59 : :
60 : 0 : return 0;
61 : : }
62 : :
63 : : #ifdef CONFIG_NET
64 : 0 : static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
65 : : {
66 : : struct crypto_report_rng rrng;
67 : :
68 : 0 : strncpy(rrng.type, "rng", sizeof(rrng.type));
69 : :
70 : 0 : rrng.seedsize = alg->cra_rng.seedsize;
71 : :
72 [ # # ]: 0 : if (nla_put(skb, CRYPTOCFGA_REPORT_RNG,
73 : : sizeof(struct crypto_report_rng), &rrng))
74 : : goto nla_put_failure;
75 : : return 0;
76 : :
77 : : nla_put_failure:
78 : 0 : return -EMSGSIZE;
79 : : }
80 : : #else
81 : : static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
82 : : {
83 : : return -ENOSYS;
84 : : }
85 : : #endif
86 : :
87 : : static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
88 : : __attribute__ ((unused));
89 : 0 : static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
90 : : {
91 : 1 : seq_printf(m, "type : rng\n");
92 : 1 : seq_printf(m, "seedsize : %u\n", alg->cra_rng.seedsize);
93 : 1 : }
94 : :
95 : 0 : static unsigned int crypto_rng_ctxsize(struct crypto_alg *alg, u32 type,
96 : : u32 mask)
97 : : {
98 : 0 : return alg->cra_ctxsize;
99 : : }
100 : :
101 : : const struct crypto_type crypto_rng_type = {
102 : : .ctxsize = crypto_rng_ctxsize,
103 : : .init = crypto_init_rng_ops,
104 : : #ifdef CONFIG_PROC_FS
105 : : .show = crypto_rng_show,
106 : : #endif
107 : : .report = crypto_rng_report,
108 : : };
109 : : EXPORT_SYMBOL_GPL(crypto_rng_type);
110 : :
111 : 0 : int crypto_get_default_rng(void)
112 : : {
113 : : struct crypto_rng *rng;
114 : : int err;
115 : :
116 : 0 : mutex_lock(&crypto_default_rng_lock);
117 [ # # ]: 0 : if (!crypto_default_rng) {
118 : : rng = crypto_alloc_rng("stdrng", 0, 0);
119 : : err = PTR_ERR(rng);
120 [ # # ]: 0 : if (IS_ERR(rng))
121 : : goto unlock;
122 : :
123 : : err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
124 [ # # ]: 0 : if (err) {
125 : : crypto_free_rng(rng);
126 : : goto unlock;
127 : : }
128 : :
129 : 0 : crypto_default_rng = rng;
130 : : }
131 : :
132 : 0 : crypto_default_rng_refcnt++;
133 : : err = 0;
134 : :
135 : : unlock:
136 : 0 : mutex_unlock(&crypto_default_rng_lock);
137 : :
138 : 0 : return err;
139 : : }
140 : : EXPORT_SYMBOL_GPL(crypto_get_default_rng);
141 : :
142 : 0 : void crypto_put_default_rng(void)
143 : : {
144 : 0 : mutex_lock(&crypto_default_rng_lock);
145 [ # # ]: 0 : if (!--crypto_default_rng_refcnt) {
146 : 0 : crypto_free_rng(crypto_default_rng);
147 : 0 : crypto_default_rng = NULL;
148 : : }
149 : 0 : mutex_unlock(&crypto_default_rng_lock);
150 : 0 : }
151 : : EXPORT_SYMBOL_GPL(crypto_put_default_rng);
152 : :
153 : : MODULE_LICENSE("GPL");
154 : : MODULE_DESCRIPTION("Random Number Generator");
|