1 /*- 2 * Copyright (c) 2015 Mark R V Murray 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/malloc.h> 35 #include <sys/random.h> 36 #include <sys/sysctl.h> 37 38 #if defined(RANDOM_LOADABLE) 39 #include <sys/lock.h> 40 #include <sys/sx.h> 41 #endif 42 43 #include <dev/random/randomdev.h> 44 45 /* Set up the sysctl root node for the entropy device */ 46 SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Cryptographically Secure Random Number Generator"); 47 48 MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures"); 49 50 struct sources_head source_list = LIST_HEAD_INITIALIZER(source_list); 51 52 #if defined(RANDOM_LOADABLE) 53 struct random_algorithm *p_random_alg_context = NULL; 54 #else /* !defined(RANDOM_LOADABLE) */ 55 struct random_algorithm *p_random_alg_context = &random_alg_context; 56 #endif /* defined(RANDOM_LOADABLE) */ 57 58 #if defined(RANDOM_LOADABLE) 59 60 struct random_readers { 61 int (*read_random_uio)(struct uio *, bool); 62 u_int (*read_random)(void *, u_int); 63 } random_reader_context = { 64 (int (*)(struct uio *, bool))nullop, 65 (u_int (*)(void *, u_int))nullop, 66 }; 67 68 struct sx randomdev_config_lock; 69 70 static void 71 random_infra_sysinit(void *dummy __unused) 72 { 73 74 RANDOM_CONFIG_INIT_LOCK(); 75 } 76 SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_FIRST, random_infra_sysinit, NULL); 77 78 void 79 random_infra_init(int (*p_random_read_uio)(struct uio *, bool), u_int (*p_random_read)(void *, u_int)) 80 { 81 82 RANDOM_CONFIG_X_LOCK(); 83 random_reader_context.read_random_uio = p_random_read_uio; 84 random_reader_context.read_random = p_random_read; 85 RANDOM_CONFIG_X_UNLOCK(); 86 } 87 88 void 89 random_infra_uninit(void) 90 { 91 92 RANDOM_CONFIG_X_LOCK(); 93 random_reader_context.read_random_uio = (int (*)(struct uio *, bool))nullop; 94 random_reader_context.read_random = (u_int (*)(void *, u_int))nullop; 95 RANDOM_CONFIG_X_UNLOCK(); 96 } 97 98 static void 99 random_infra_sysuninit(void *dummy __unused) 100 { 101 102 RANDOM_CONFIG_DEINIT_LOCK(); 103 } 104 SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_FIRST, random_infra_sysuninit, NULL); 105 106 int 107 read_random_uio(struct uio *uio, bool nonblock) 108 { 109 int retval; 110 111 RANDOM_CONFIG_S_LOCK(); 112 retval = random_reader_context.read_random_uio(uio, nonblock); 113 RANDOM_CONFIG_S_UNLOCK(); 114 return (retval); 115 } 116 117 u_int 118 read_random(void *buf, u_int len) 119 { 120 u_int retval; 121 122 RANDOM_CONFIG_S_LOCK(); 123 retval = random_reader_context.read_random(buf, len); 124 RANDOM_CONFIG_S_UNLOCK(); 125 return (retval); 126 } 127 128 #endif /* defined(RANDOM_LOADABLE) */ 129