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 *, size_t); 88 static bool random_other_seeded(void); 89 static void random_other_process_event(struct harvest_event *); 90 91 /* 92 * RANDOM_OTHER_NPOOLS is used when reading hardware random 93 * number sources to ensure that each pool gets one read sample 94 * per loop iteration. Fortuna has 32 (0-31). 95 */ 96 #define RANDOM_OTHER_NPOOLS 1 97 98 #ifdef RANDOM_LOADABLE 99 static 100 #endif 101 const struct random_algorithm random_alg_context = { 102 .ra_ident = "other", 103 .ra_pre_read = random_other_pre_read, 104 .ra_read = random_other_read, 105 .ra_seeded = random_other_seeded, 106 .ra_event_processor = random_other_process_event, 107 .ra_poolcount = RANDOM_OTHER_NPOOLS, 108 }; 109 110 /* Use a mutex to protect your reseed variables? */ 111 static mtx_t other_mtx; 112 113 /* 114 * Do algorithm-specific initialisation here. 115 */ 116 static void 117 random_other_init_alg(void *unused __unused) 118 { 119 120 #ifdef RANDOM_LOADABLE 121 p_random_alg_context = &random_alg_context; 122 #endif 123 124 RANDOM_RESEED_INIT_LOCK(); 125 } 126 SYSINIT(random_alg, SI_SUB_RANDOM, SI_ORDER_SECOND, random_other_init_alg, 127 NULL); 128 129 /* 130 * void random_other_pre_read(void) 131 * 132 * Do any pre-read preparation you need to. This will be called 133 * before >=1 calls to random_other_read() corresponding to one 134 * read(2). 135 * 136 * This routine will be called periodically while the generator is 137 * still blocked and a read is being attempted, giving you an 138 * opportunity to unblock. 139 */ 140 static void 141 random_other_pre_read(void) 142 { 143 144 RANDOM_RESEED_LOCK(); 145 /* 146 * Do pre-read housekeeping work here! 147 * You may use this as a chance to unblock the generator. 148 */ 149 RANDOM_RESEED_UNLOCK(); 150 } 151 152 /* 153 * void random_other_read(uint8_t *buf, size_t count) 154 * 155 * Generate <count> bytes of output into <*buf>. 156 * You may NOT use the fact that <count> will be a multiple of 157 * RANDOM_BLOCKSIZE for optimization purposes. 158 * 159 * This function will always be called with your generator 160 * unblocked and ready. If you are not ready to generate 161 * output here, then feel free to KASSERT() or panic(). 162 */ 163 static void 164 random_other_read(uint8_t *buf, size_t count) 165 { 166 167 RANDOM_RESEED_LOCK(); 168 /* 169 * Do random-number generation work here! 170 */ 171 RANDOM_RESEED_UNLOCK(); 172 } 173 174 /* 175 * bool random_other_seeded(void) 176 * 177 * Return true if your generator is ready to generate 178 * output, and false otherwise. 179 */ 180 static bool 181 random_other_seeded(void) 182 { 183 bool seeded = false; 184 185 /* 186 * Find out if your generator is seeded here! 187 */ 188 return (seeded); 189 } 190 191 /* 192 * void random_other_process_event(struct harvest_event *event) 193 * 194 * Process one stochastic event <*event> into your entropy 195 * processor. 196 * 197 * The structure of the event may change, so it is easier to 198 * just grab the whole thing into your accumulation system. 199 * You may pick-and-choose bits, but please don't complain 200 * when/if these change. 201 */ 202 static void 203 random_other_process_event(struct harvest_event *event) 204 { 205 206 RANDOM_RESEED_LOCK(); 207 /* 208 * Do entropy accumulation work here! 209 * You may use this as a chance to unblock the generator. 210 */ 211 RANDOM_RESEED_UNLOCK(); 212 } 213