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