live_entropy_sources.c revision 259065
1130561Sobrien/*- 2218822Sdim * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com> 3218822Sdim * Copyright (c) 2013 Mark R V Murray 4130561Sobrien * All rights reserved. 5130561Sobrien * 6130561Sobrien * Redistribution and use in source and binary forms, with or without 7130561Sobrien * modification, are permitted provided that the following conditions 8130561Sobrien * are met: 9130561Sobrien * 1. Redistributions of source code must retain the above copyright 10130561Sobrien * notice, this list of conditions and the following disclaimer 11130561Sobrien * in this position and unchanged. 12130561Sobrien * 2. Redistributions in binary form must reproduce the above copyright 13130561Sobrien * notice, this list of conditions and the following disclaimer in the 14130561Sobrien * documentation and/or other materials provided with the distribution. 15130561Sobrien * 16130561Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17130561Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18130561Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19130561Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20218822Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21130561Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22130561Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23130561Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24130561Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25130561Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26130561Sobrien */ 27130561Sobrien 28130561Sobrien#include <sys/param.h> 29130561Sobrien__FBSDID("$FreeBSD: releng/10.0/sys/dev/random/live_entropy_sources.c 256381 2013-10-12 15:31:36Z markm $"); 30130561Sobrien 31130561Sobrien#include <sys/kernel.h> 32130561Sobrien#include <sys/libkern.h> 33130561Sobrien#include <sys/lock.h> 34130561Sobrien#include <sys/malloc.h> 35130561Sobrien#include <sys/queue.h> 36130561Sobrien#include <sys/random.h> 37130561Sobrien#include <sys/selinfo.h> 38130561Sobrien#include <sys/sx.h> 39130561Sobrien#include <sys/sysctl.h> 40130561Sobrien#include <sys/systm.h> 41130561Sobrien#include <sys/unistd.h> 42130561Sobrien 43130561Sobrien#include <machine/cpu.h> 44130561Sobrien 45130561Sobrien#include <dev/random/randomdev.h> 46130561Sobrien#include <dev/random/randomdev_soft.h> 47130561Sobrien#include <dev/random/random_adaptors.h> 48130561Sobrien#include <dev/random/random_harvestq.h> 49130561Sobrien 50130561Sobrien#include "live_entropy_sources.h" 51130561Sobrien 52130561SobrienLIST_HEAD(les_head, live_entropy_sources); 53130561Sobrienstatic struct les_head sources = LIST_HEAD_INITIALIZER(sources); 54130561Sobrien 55130561Sobrien/* 56130561Sobrien * The live_lock protects the consistency of the "struct les_head sources" 57130561Sobrien */ 58130561Sobrienstatic struct sx les_lock; /* need a sleepable lock */ 59130561Sobrien 60130561Sobrienvoid 61130561Sobrienlive_entropy_source_register(struct random_hardware_source *rsource) 62130561Sobrien{ 63130561Sobrien struct live_entropy_sources *les; 64130561Sobrien 65130561Sobrien KASSERT(rsource != NULL, ("invalid input to %s", __func__)); 66130561Sobrien 67130561Sobrien les = malloc(sizeof(struct live_entropy_sources), M_ENTROPY, M_WAITOK); 68130561Sobrien les->rsource = rsource; 69130561Sobrien 70130561Sobrien sx_xlock(&les_lock); 71130561Sobrien LIST_INSERT_HEAD(&sources, les, entries); 72130561Sobrien sx_xunlock(&les_lock); 73130561Sobrien} 74130561Sobrien 75130561Sobrienvoid 76130561Sobrienlive_entropy_source_deregister(struct random_hardware_source *rsource) 77130561Sobrien{ 78130561Sobrien struct live_entropy_sources *les = NULL; 79130561Sobrien 80130561Sobrien KASSERT(rsource != NULL, ("invalid input to %s", __func__)); 81130561Sobrien 82130561Sobrien sx_xlock(&les_lock); 83130561Sobrien LIST_FOREACH(les, &sources, entries) 84130561Sobrien if (les->rsource == rsource) { 85130561Sobrien LIST_REMOVE(les, entries); 86130561Sobrien break; 87130561Sobrien } 88130561Sobrien sx_xunlock(&les_lock); 89130561Sobrien if (les != NULL) 90130561Sobrien free(les, M_ENTROPY); 91130561Sobrien} 92130561Sobrien 93130561Sobrienstatic int 94130561Sobrienlive_entropy_source_handler(SYSCTL_HANDLER_ARGS) 95130561Sobrien{ 96130561Sobrien struct live_entropy_sources *les; 97130561Sobrien int error, count; 98130561Sobrien 99130561Sobrien count = error = 0; 100130561Sobrien 101130561Sobrien sx_slock(&les_lock); 102130561Sobrien 103130561Sobrien if (LIST_EMPTY(&sources)) 104130561Sobrien error = SYSCTL_OUT(req, "", 0); 105130561Sobrien else { 106130561Sobrien LIST_FOREACH(les, &sources, entries) { 107130561Sobrien 108130561Sobrien error = SYSCTL_OUT(req, ",", count++ ? 1 : 0); 109130561Sobrien if (error) 110130561Sobrien break; 111130561Sobrien 112130561Sobrien error = SYSCTL_OUT(req, les->rsource->ident, strlen(les->rsource->ident)); 113130561Sobrien if (error) 114130561Sobrien break; 115130561Sobrien } 116130561Sobrien } 117130561Sobrien 118130561Sobrien sx_sunlock(&les_lock); 119130561Sobrien 120130561Sobrien return (error); 121130561Sobrien} 122130561Sobrien 123130561Sobrienstatic void 124130561Sobrienlive_entropy_sources_init(void *unused) 125130561Sobrien{ 126130561Sobrien 127130561Sobrien SYSCTL_PROC(_kern_random, OID_AUTO, live_entropy_sources, 128130561Sobrien CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 129130561Sobrien NULL, 0, live_entropy_source_handler, "", 130130561Sobrien "List of Active Live Entropy Sources"); 131130561Sobrien 132130561Sobrien sx_init(&les_lock, "live_entropy_sources"); 133130561Sobrien} 134130561Sobrien 135130561Sobrien/* 136130561Sobrien * Run through all "live" sources reading entropy for the given 137130561Sobrien * number of rounds, which should be a multiple of the number 138130561Sobrien * of entropy accumulation pools in use; 2 for Yarrow and 32 139130561Sobrien * for Fortuna. 140130561Sobrien * 141130561Sobrien * BEWARE!!! 142130561Sobrien * This function runs inside the RNG thread! Don't do anything silly! 143130561Sobrien * Remember that we are NOT holding harvest_mtx on entry! 144130561Sobrien */ 145130561Sobrienvoid 146130561Sobrienlive_entropy_sources_feed(int rounds, event_proc_f entropy_processor) 147130561Sobrien{ 148130561Sobrien static struct harvest event; 149130561Sobrien static uint8_t buf[HARVESTSIZE]; 150130561Sobrien struct live_entropy_sources *les; 151130561Sobrien int i, n; 152130561Sobrien 153130561Sobrien sx_slock(&les_lock); 154130561Sobrien 155130561Sobrien /* 156218822Sdim * Walk over all of live entropy sources, and feed their output 157218822Sdim * to the system-wide RNG. 158218822Sdim */ 159218822Sdim LIST_FOREACH(les, &sources, entries) { 160218822Sdim 161218822Sdim for (i = 0; i < rounds; i++) { 162218822Sdim /* 163130561Sobrien * This should be quick, since it's a live entropy 164130561Sobrien * source. 165130561Sobrien */ 166130561Sobrien /* FIXME: Whine loudly if this didn't work. */ 167130561Sobrien n = les->rsource->read(buf, sizeof(buf)); 168130561Sobrien n = MIN(n, HARVESTSIZE); 169130561Sobrien 170130561Sobrien event.somecounter = get_cyclecount(); 171130561Sobrien event.size = n; 172130561Sobrien event.bits = (n*8)/2; 173130561Sobrien event.source = les->rsource->source; 174130561Sobrien memcpy(event.entropy, buf, n); 175130561Sobrien 176130561Sobrien /* Do the actual entropy insertion */ 177130561Sobrien entropy_processor(&event); 178130561Sobrien } 179130561Sobrien 180130561Sobrien } 181130561Sobrien 182130561Sobrien sx_sunlock(&les_lock); 183130561Sobrien} 184130561Sobrien 185130561Sobrienstatic void 186130561Sobrienlive_entropy_sources_deinit(void *unused) 187130561Sobrien{ 188130561Sobrien 189130561Sobrien sx_destroy(&les_lock); 190130561Sobrien} 191130561Sobrien 192130561SobrienSYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, 193130561Sobrien live_entropy_sources_init, NULL); 194130561SobrienSYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, 195130561Sobrien live_entropy_sources_deinit, NULL); 196130561Sobrien