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