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