xref: /linux/drivers/char/hw_random/core.c (revision 4c020b032b8a15966e1207b71144ffbb75697e29)
1 /*
2         Added support for the AMD Geode LX RNG
3 	(c) Copyright 2004-2005 Advanced Micro Devices, Inc.
4 
5 	derived from
6 
7  	Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
8 	(c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
9 
10  	derived from
11 
12         Hardware driver for the AMD 768 Random Number Generator (RNG)
13         (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
14 
15  	derived from
16 
17 	Hardware driver for Intel i810 Random Number Generator (RNG)
18 	Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
19 	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
20 
21 	Added generic RNG API
22 	Copyright 2006 Michael Buesch <m@bues.ch>
23 	Copyright 2005 (c) MontaVista Software, Inc.
24 
25 	Please read Documentation/hw_random.txt for details on use.
26 
27 	----------------------------------------------------------
28 	This software may be used and distributed according to the terms
29         of the GNU General Public License, incorporated herein by reference.
30 
31  */
32 
33 
34 #include <linux/device.h>
35 #include <linux/hw_random.h>
36 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/fs.h>
39 #include <linux/sched.h>
40 #include <linux/miscdevice.h>
41 #include <linux/delay.h>
42 #include <linux/slab.h>
43 #include <asm/uaccess.h>
44 
45 
46 #define RNG_MODULE_NAME		"hw_random"
47 #define PFX			RNG_MODULE_NAME ": "
48 #define RNG_MISCDEV_MINOR	183 /* official */
49 
50 
51 static struct hwrng *current_rng;
52 static LIST_HEAD(rng_list);
53 static DEFINE_MUTEX(rng_mutex);
54 static int data_avail;
55 static u8 *rng_buffer;
56 
57 static size_t rng_buffer_size(void)
58 {
59 	return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
60 }
61 
62 static inline int hwrng_init(struct hwrng *rng)
63 {
64 	if (!rng->init)
65 		return 0;
66 	return rng->init(rng);
67 }
68 
69 static inline void hwrng_cleanup(struct hwrng *rng)
70 {
71 	if (rng && rng->cleanup)
72 		rng->cleanup(rng);
73 }
74 
75 static int rng_dev_open(struct inode *inode, struct file *filp)
76 {
77 	/* enforce read-only access to this chrdev */
78 	if ((filp->f_mode & FMODE_READ) == 0)
79 		return -EINVAL;
80 	if (filp->f_mode & FMODE_WRITE)
81 		return -EINVAL;
82 	return 0;
83 }
84 
85 static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
86 			int wait) {
87 	int present;
88 
89 	if (rng->read)
90 		return rng->read(rng, (void *)buffer, size, wait);
91 
92 	if (rng->data_present)
93 		present = rng->data_present(rng, wait);
94 	else
95 		present = 1;
96 
97 	if (present)
98 		return rng->data_read(rng, (u32 *)buffer);
99 
100 	return 0;
101 }
102 
103 static ssize_t rng_dev_read(struct file *filp, char __user *buf,
104 			    size_t size, loff_t *offp)
105 {
106 	ssize_t ret = 0;
107 	int err = 0;
108 	int bytes_read, len;
109 
110 	while (size) {
111 		if (mutex_lock_interruptible(&rng_mutex)) {
112 			err = -ERESTARTSYS;
113 			goto out;
114 		}
115 
116 		if (!current_rng) {
117 			err = -ENODEV;
118 			goto out_unlock;
119 		}
120 
121 		if (!data_avail) {
122 			bytes_read = rng_get_data(current_rng, rng_buffer,
123 				rng_buffer_size(),
124 				!(filp->f_flags & O_NONBLOCK));
125 			if (bytes_read < 0) {
126 				err = bytes_read;
127 				goto out_unlock;
128 			}
129 			data_avail = bytes_read;
130 		}
131 
132 		if (!data_avail) {
133 			if (filp->f_flags & O_NONBLOCK) {
134 				err = -EAGAIN;
135 				goto out_unlock;
136 			}
137 		} else {
138 			len = data_avail;
139 			if (len > size)
140 				len = size;
141 
142 			data_avail -= len;
143 
144 			if (copy_to_user(buf + ret, rng_buffer + data_avail,
145 								len)) {
146 				err = -EFAULT;
147 				goto out_unlock;
148 			}
149 
150 			size -= len;
151 			ret += len;
152 		}
153 
154 		mutex_unlock(&rng_mutex);
155 
156 		if (need_resched())
157 			schedule_timeout_interruptible(1);
158 
159 		if (signal_pending(current)) {
160 			err = -ERESTARTSYS;
161 			goto out;
162 		}
163 	}
164 out:
165 	return ret ? : err;
166 out_unlock:
167 	mutex_unlock(&rng_mutex);
168 	goto out;
169 }
170 
171 
172 static const struct file_operations rng_chrdev_ops = {
173 	.owner		= THIS_MODULE,
174 	.open		= rng_dev_open,
175 	.read		= rng_dev_read,
176 	.llseek		= noop_llseek,
177 };
178 
179 static struct miscdevice rng_miscdev = {
180 	.minor		= RNG_MISCDEV_MINOR,
181 	.name		= RNG_MODULE_NAME,
182 	.nodename	= "hwrng",
183 	.fops		= &rng_chrdev_ops,
184 };
185 
186 
187 static ssize_t hwrng_attr_current_store(struct device *dev,
188 					struct device_attribute *attr,
189 					const char *buf, size_t len)
190 {
191 	int err;
192 	struct hwrng *rng;
193 
194 	err = mutex_lock_interruptible(&rng_mutex);
195 	if (err)
196 		return -ERESTARTSYS;
197 	err = -ENODEV;
198 	list_for_each_entry(rng, &rng_list, list) {
199 		if (strcmp(rng->name, buf) == 0) {
200 			if (rng == current_rng) {
201 				err = 0;
202 				break;
203 			}
204 			err = hwrng_init(rng);
205 			if (err)
206 				break;
207 			hwrng_cleanup(current_rng);
208 			current_rng = rng;
209 			err = 0;
210 			break;
211 		}
212 	}
213 	mutex_unlock(&rng_mutex);
214 
215 	return err ? : len;
216 }
217 
218 static ssize_t hwrng_attr_current_show(struct device *dev,
219 				       struct device_attribute *attr,
220 				       char *buf)
221 {
222 	int err;
223 	ssize_t ret;
224 	const char *name = "none";
225 
226 	err = mutex_lock_interruptible(&rng_mutex);
227 	if (err)
228 		return -ERESTARTSYS;
229 	if (current_rng)
230 		name = current_rng->name;
231 	ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
232 	mutex_unlock(&rng_mutex);
233 
234 	return ret;
235 }
236 
237 static ssize_t hwrng_attr_available_show(struct device *dev,
238 					 struct device_attribute *attr,
239 					 char *buf)
240 {
241 	int err;
242 	ssize_t ret = 0;
243 	struct hwrng *rng;
244 
245 	err = mutex_lock_interruptible(&rng_mutex);
246 	if (err)
247 		return -ERESTARTSYS;
248 	buf[0] = '\0';
249 	list_for_each_entry(rng, &rng_list, list) {
250 		strncat(buf, rng->name, PAGE_SIZE - ret - 1);
251 		ret += strlen(rng->name);
252 		strncat(buf, " ", PAGE_SIZE - ret - 1);
253 		ret++;
254 	}
255 	strncat(buf, "\n", PAGE_SIZE - ret - 1);
256 	ret++;
257 	mutex_unlock(&rng_mutex);
258 
259 	return ret;
260 }
261 
262 static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
263 		   hwrng_attr_current_show,
264 		   hwrng_attr_current_store);
265 static DEVICE_ATTR(rng_available, S_IRUGO,
266 		   hwrng_attr_available_show,
267 		   NULL);
268 
269 
270 static void unregister_miscdev(void)
271 {
272 	device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
273 	device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
274 	misc_deregister(&rng_miscdev);
275 }
276 
277 static int register_miscdev(void)
278 {
279 	int err;
280 
281 	err = misc_register(&rng_miscdev);
282 	if (err)
283 		goto out;
284 	err = device_create_file(rng_miscdev.this_device,
285 				 &dev_attr_rng_current);
286 	if (err)
287 		goto err_misc_dereg;
288 	err = device_create_file(rng_miscdev.this_device,
289 				 &dev_attr_rng_available);
290 	if (err)
291 		goto err_remove_current;
292 out:
293 	return err;
294 
295 err_remove_current:
296 	device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
297 err_misc_dereg:
298 	misc_deregister(&rng_miscdev);
299 	goto out;
300 }
301 
302 int hwrng_register(struct hwrng *rng)
303 {
304 	int must_register_misc;
305 	int err = -EINVAL;
306 	struct hwrng *old_rng, *tmp;
307 
308 	if (rng->name == NULL ||
309 	    (rng->data_read == NULL && rng->read == NULL))
310 		goto out;
311 
312 	mutex_lock(&rng_mutex);
313 
314 	/* kmalloc makes this safe for virt_to_page() in virtio_rng.c */
315 	err = -ENOMEM;
316 	if (!rng_buffer) {
317 		rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL);
318 		if (!rng_buffer)
319 			goto out_unlock;
320 	}
321 
322 	/* Must not register two RNGs with the same name. */
323 	err = -EEXIST;
324 	list_for_each_entry(tmp, &rng_list, list) {
325 		if (strcmp(tmp->name, rng->name) == 0)
326 			goto out_unlock;
327 	}
328 
329 	must_register_misc = (current_rng == NULL);
330 	old_rng = current_rng;
331 	if (!old_rng) {
332 		err = hwrng_init(rng);
333 		if (err)
334 			goto out_unlock;
335 		current_rng = rng;
336 	}
337 	err = 0;
338 	if (must_register_misc) {
339 		err = register_miscdev();
340 		if (err) {
341 			if (!old_rng) {
342 				hwrng_cleanup(rng);
343 				current_rng = NULL;
344 			}
345 			goto out_unlock;
346 		}
347 	}
348 	INIT_LIST_HEAD(&rng->list);
349 	list_add_tail(&rng->list, &rng_list);
350 out_unlock:
351 	mutex_unlock(&rng_mutex);
352 out:
353 	return err;
354 }
355 EXPORT_SYMBOL_GPL(hwrng_register);
356 
357 void hwrng_unregister(struct hwrng *rng)
358 {
359 	int err;
360 
361 	mutex_lock(&rng_mutex);
362 
363 	list_del(&rng->list);
364 	if (current_rng == rng) {
365 		hwrng_cleanup(rng);
366 		if (list_empty(&rng_list)) {
367 			current_rng = NULL;
368 		} else {
369 			current_rng = list_entry(rng_list.prev, struct hwrng, list);
370 			err = hwrng_init(current_rng);
371 			if (err)
372 				current_rng = NULL;
373 		}
374 	}
375 	if (list_empty(&rng_list))
376 		unregister_miscdev();
377 
378 	mutex_unlock(&rng_mutex);
379 }
380 EXPORT_SYMBOL_GPL(hwrng_unregister);
381 
382 static void __exit hwrng_exit(void)
383 {
384 	mutex_lock(&rng_mutex);
385 	BUG_ON(current_rng);
386 	kfree(rng_buffer);
387 	mutex_unlock(&rng_mutex);
388 }
389 
390 module_exit(hwrng_exit);
391 
392 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
393 MODULE_LICENSE("GPL");
394