crypto: rng - Mark crypto_rng_reset seed as const
[linux-2.6-block.git] / crypto / rng.c
CommitLineData
17f0f4a4
NH
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
60063497 15#include <linux/atomic.h>
17f0f4a4
NH
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>
5a0e3ad6 22#include <linux/slab.h>
17f0f4a4 23#include <linux/string.h>
792608e9
SK
24#include <linux/cryptouser.h>
25#include <net/netlink.h>
17f0f4a4 26
d0e83059
HX
27#include "internal.h"
28
17f0f4a4
NH
29static DEFINE_MUTEX(crypto_default_rng_lock);
30struct crypto_rng *crypto_default_rng;
31EXPORT_SYMBOL_GPL(crypto_default_rng);
32static int crypto_default_rng_refcnt;
33
d0e83059
HX
34static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm)
35{
36 return container_of(tfm, struct crypto_rng, base);
37}
38
ff030b09
HX
39static int generate(struct crypto_rng *tfm, const u8 *src, unsigned int slen,
40 u8 *dst, unsigned int dlen)
41{
42 return crypto_rng_alg(tfm)->rng_make_random(tfm, dst, dlen);
43}
44
3c5d8fa9
HX
45static int rngapi_reset(struct crypto_rng *tfm, const u8 *seed,
46 unsigned int slen)
47{
48 u8 *buf = NULL;
49 u8 *src = (u8 *)seed;
50 int err;
51
52 if (slen) {
53 buf = kmalloc(slen, GFP_KERNEL);
54 if (!buf)
55 return -ENOMEM;
56
57 memcpy(buf, seed, slen);
58 src = buf;
59 }
60
61 err = crypto_rng_alg(tfm)->rng_reset(tfm, src, slen);
62
63 kzfree(buf);
64 return err;
65}
66
67int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
17f0f4a4
NH
68{
69 u8 *buf = NULL;
70 int err;
71
72 if (!seed && slen) {
73 buf = kmalloc(slen, GFP_KERNEL);
74 if (!buf)
75 return -ENOMEM;
76
77 get_random_bytes(buf, slen);
78 seed = buf;
79 }
80
3c5d8fa9 81 err = tfm->seed(tfm, seed, slen);
17f0f4a4
NH
82
83 kfree(buf);
84 return err;
85}
3c5d8fa9 86EXPORT_SYMBOL_GPL(crypto_rng_reset);
17f0f4a4 87
d0e83059 88static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
17f0f4a4 89{
d0e83059 90 struct crypto_rng *rng = __crypto_rng_cast(tfm);
17f0f4a4 91
ff030b09 92 rng->generate = generate;
d0e83059 93 rng->seed = rngapi_reset;
17f0f4a4
NH
94
95 return 0;
96}
97
3acc8473 98#ifdef CONFIG_NET
792608e9
SK
99static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
100{
101 struct crypto_report_rng rrng;
102
9a5467bf 103 strncpy(rrng.type, "rng", sizeof(rrng.type));
792608e9
SK
104
105 rrng.seedsize = alg->cra_rng.seedsize;
106
6662df33
DM
107 if (nla_put(skb, CRYPTOCFGA_REPORT_RNG,
108 sizeof(struct crypto_report_rng), &rrng))
109 goto nla_put_failure;
792608e9
SK
110 return 0;
111
112nla_put_failure:
113 return -EMSGSIZE;
114}
3acc8473
HX
115#else
116static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
117{
118 return -ENOSYS;
119}
120#endif
792608e9 121
17f0f4a4
NH
122static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
123 __attribute__ ((unused));
124static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
125{
126 seq_printf(m, "type : rng\n");
127 seq_printf(m, "seedsize : %u\n", alg->cra_rng.seedsize);
128}
129
17f0f4a4 130const struct crypto_type crypto_rng_type = {
d0e83059
HX
131 .extsize = crypto_alg_extsize,
132 .init_tfm = crypto_rng_init_tfm,
17f0f4a4
NH
133#ifdef CONFIG_PROC_FS
134 .show = crypto_rng_show,
135#endif
792608e9 136 .report = crypto_rng_report,
d0e83059
HX
137 .maskclear = ~CRYPTO_ALG_TYPE_MASK,
138 .maskset = CRYPTO_ALG_TYPE_MASK,
139 .type = CRYPTO_ALG_TYPE_RNG,
140 .tfmsize = offsetof(struct crypto_rng, base),
17f0f4a4
NH
141};
142EXPORT_SYMBOL_GPL(crypto_rng_type);
143
d0e83059
HX
144struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)
145{
146 return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask);
147}
148EXPORT_SYMBOL_GPL(crypto_alloc_rng);
149
17f0f4a4
NH
150int crypto_get_default_rng(void)
151{
152 struct crypto_rng *rng;
153 int err;
154
155 mutex_lock(&crypto_default_rng_lock);
156 if (!crypto_default_rng) {
157 rng = crypto_alloc_rng("stdrng", 0, 0);
158 err = PTR_ERR(rng);
159 if (IS_ERR(rng))
160 goto unlock;
161
162 err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
163 if (err) {
164 crypto_free_rng(rng);
165 goto unlock;
166 }
167
168 crypto_default_rng = rng;
169 }
170
171 crypto_default_rng_refcnt++;
172 err = 0;
173
174unlock:
175 mutex_unlock(&crypto_default_rng_lock);
176
177 return err;
178}
179EXPORT_SYMBOL_GPL(crypto_get_default_rng);
180
181void crypto_put_default_rng(void)
182{
183 mutex_lock(&crypto_default_rng_lock);
184 if (!--crypto_default_rng_refcnt) {
185 crypto_free_rng(crypto_default_rng);
186 crypto_default_rng = NULL;
187 }
188 mutex_unlock(&crypto_default_rng_lock);
189}
190EXPORT_SYMBOL_GPL(crypto_put_default_rng);
191
192MODULE_LICENSE("GPL");
a8ccc393 193MODULE_DESCRIPTION("Random Number Generator");