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 /*- 29 * This is a skeleton for folks who wish to build a loadable module 30 * containing an alternative entropy-processing algorithm for random(4). 31 * 32 * The functions below should be completed with the appropriate code, 33 * and the nearby yarrow.c and fortuna.c may be consulted for examples 34 * of working code. 35 * 36 * The author is willing to provide reasonable help to those wishing to 37 * write such a module for themselves. Please use the markm@ FreeBSD 38 * email address, and ensure that you are developing this on a suitably 39 * supported branch (This is currently 11-CURRENT, and will be no 40 * older than 11-STABLE in the future). 41 */ 42 43 #include <sys/cdefs.h> 44 __FBSDID("$FreeBSD$"); 45 46 #include <sys/param.h> 47 #include <sys/kernel.h> 48 #include <sys/lock.h> 49 #include <sys/malloc.h> 50 #include <sys/mutex.h> 51 #include <sys/random.h> 52 #include <sys/sysctl.h> 53 #include <sys/systm.h> 54 55 #include <machine/cpu.h> 56 57 #include <crypto/rijndael/rijndael-api-fst.h> 58 #include <crypto/sha2/sha2.h> 59 60 #include <dev/random/hash.h> 61 #include <dev/random/randomdev.h> 62 #include <dev/random/random_harvestq.h> 63 #include <dev/random/uint128.h> 64 #include <dev/random/other_algorithm.h> 65 66 static void random_other_pre_read(void); 67 static void random_other_read(uint8_t *, u_int); 68 static bool random_other_seeded(void); 69 static void random_other_process_event(struct harvest_event *); 70 static void random_other_init_alg(void *); 71 static void random_other_deinit_alg(void *); 72 73 /* 74 * RANDOM_OTHER_NPOOLS is used when reading hardware random 75 * number sources to ensure that each pool gets one read sample 76 * per loop iteration. Yarrow has 2 such pools (FAST and SLOW), 77 * and fortuna has 32 (0-31). The RNG used prior to Yarrow and 78 * ported from Linux had just 1 pool. 79 */ 80 #define RANDOM_OTHER_NPOOLS 1 81 82 struct random_algorithm random_alg_context = { 83 .ra_ident = "other", 84 .ra_init_alg = random_other_init_alg, 85 .ra_deinit_alg = random_other_deinit_alg, 86 .ra_pre_read = random_other_pre_read, 87 .ra_read = random_other_read, 88 .ra_seeded = random_other_seeded, 89 .ra_event_processor = random_other_process_event, 90 .ra_poolcount = RANDOM_OTHER_NPOOLS, 91 }; 92 93 /* Use a mutex to protect your reseed variables? */ 94 static mtx_t other_mtx; 95 96 /* 97 * void random_other_init_alg(void *unused __unused) 98 * 99 * Do algorithm-specific initialisation here. 100 */ 101 void 102 random_other_init_alg(void *unused __unused) 103 { 104 105 RANDOM_RESEED_INIT_LOCK(); 106 /* 107 * Do set-up work here! 108 */ 109 } 110 111 /* 112 * void random_other_deinit_alg(void *unused __unused) 113 * 114 * Do algorithm-specific deinitialisation here. 115 */ 116 static void 117 random_other_deinit_alg(void *unused __unused) 118 { 119 120 /* 121 * Do tear-down work here! 122 */ 123 RANDOM_RESEED_DEINIT_LOCK(); 124 } 125 126 /* 127 * void random_other_pre_read(void) 128 * 129 * Do any pre-read preparation you need to. This will be called 130 * before >=1 calls to random_other_read() corresponding to one 131 * read(2). 132 * 133 * This routine will be called periodically while the generator is 134 * still blocked and a read is being attempted, giving you an 135 * opportunity to unblock. 136 */ 137 static void 138 random_other_pre_read(void) 139 { 140 141 RANDOM_RESEED_LOCK(); 142 /* 143 * Do pre-read housekeeping work here! 144 * You may use this as a chance to unblock the generator. 145 */ 146 RANDOM_RESEED_UNLOCK(); 147 } 148 149 /* 150 * void random_other_read(uint8_t *buf, u_int count) 151 * 152 * Generate <count> bytes of output into <*buf>. 153 * You may use the fact that <count> will be a multiple of 154 * RANDOM_BLOCKSIZE for optimization purposes. 155 * 156 * This function will always be called with your generator 157 * unblocked and ready. If you are not ready to generate 158 * output here, then feel free to KASSERT() or panic(). 159 */ 160 static void 161 random_other_read(uint8_t *buf, u_int count) 162 { 163 164 RANDOM_RESEED_LOCK(); 165 /* 166 * Do random-number generation work here! 167 */ 168 RANDOM_RESEED_UNLOCK(); 169 } 170 171 /* 172 * bool random_other_seeded(void) 173 * 174 * Return true if your generator is ready to generate 175 * output, and false otherwise. 176 */ 177 static bool 178 random_other_seeded(void) 179 { 180 bool seeded = false; 181 182 /* 183 * Find out if your generator is seeded here! 184 */ 185 return (seeded); 186 } 187 188 /* 189 * void random_other_process_event(struct harvest_event *event) 190 * 191 * Process one stochastic event <*event> into your entropy 192 * processor. 193 * 194 * The structure of the event may change, so it is easier to 195 * just grab the whole thing into your accumulation system. 196 * You may pick-and-choose bits, but please don't complain 197 * when/if these change. 198 */ 199 static void 200 random_other_process_event(struct harvest_event *event) 201 { 202 203 RANDOM_RESEED_LOCK(); 204 /* 205 * Do entropy accumulation work here! 206 * You may use this as a chance to unblock the generator. 207 */ 208 RANDOM_RESEED_UNLOCK(); 209 } 210