]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/random/live_entropy_sources.c
Debug run. This now works, except that the "live" sources haven't
[FreeBSD/FreeBSD.git] / sys / dev / random / live_entropy_sources.c
1 /*-
2  * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
3  * Copyright (c) 2013 Mark R V Murray
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer
11  *    in this position and unchanged.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <sys/param.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/kernel.h>
32 #include <sys/libkern.h>
33 #include <sys/lock.h>
34 #include <sys/malloc.h>
35 #include <sys/queue.h>
36 #include <sys/random.h>
37 #include <sys/selinfo.h>
38 #include <sys/sx.h>
39 #include <sys/sysctl.h>
40 #include <sys/systm.h>
41 #include <sys/unistd.h>
42
43 #include <machine/cpu.h>
44
45 #include <dev/random/randomdev.h>
46 #include <dev/random/randomdev_soft.h>
47 #include <dev/random/random_adaptors.h>
48 #include <dev/random/random_harvestq.h>
49
50 #include "live_entropy_sources.h"
51
52 LIST_HEAD(les_head, live_entropy_sources);
53 static struct les_head sources = LIST_HEAD_INITIALIZER(sources);
54
55 #define LES_THRESHOLD 10
56
57 void
58 live_entropy_source_register(struct random_hardware_source *rsource)
59 {
60         struct live_entropy_sources *les;
61
62         KASSERT(rsource != NULL, ("invalid input to %s", __func__));
63
64         les = malloc(sizeof(struct live_entropy_sources), M_ENTROPY, M_WAITOK);
65         les->rsource = rsource;
66
67         mtx_lock_spin(&harvest_mtx);
68         LIST_INSERT_HEAD(&sources, les, entries);
69         mtx_unlock_spin(&harvest_mtx);
70 }
71
72 void
73 live_entropy_source_deregister(struct random_hardware_source *rsource)
74 {
75         struct live_entropy_sources *les;
76
77         KASSERT(rsource != NULL, ("invalid input to %s", __func__));
78
79         mtx_lock_spin(&harvest_mtx);
80         LIST_FOREACH(les, &sources, entries) {
81                 if (les->rsource == rsource) {
82                         LIST_REMOVE(les, entries);
83                         free(les, M_ENTROPY);
84                         break;
85                 }
86         }
87         mtx_unlock_spin(&harvest_mtx);
88 }
89
90 static int
91 live_entropy_source_handler(SYSCTL_HANDLER_ARGS)
92 {
93         struct live_entropy_sources *les;
94         int error, count;
95
96         count = error = 0;
97
98         mtx_lock_spin(&harvest_mtx);
99
100         if (LIST_EMPTY(&sources))
101                 error = SYSCTL_OUT(req, "", 0);
102         else {
103                 LIST_FOREACH(les, &sources, entries) {
104
105                         error = SYSCTL_OUT(req, ",", count++ ? 1 : 0);
106                         if (error)
107                                 break;
108
109                         error = SYSCTL_OUT(req, les->rsource->ident, strlen(les->rsource->ident));
110                         if (error)
111                                 break;
112                 }
113         }
114
115         mtx_unlock_spin(&harvest_mtx);
116
117         return (error);
118 }
119
120 static void
121 live_entropy_sources_init(void *unused)
122 {
123
124         SYSCTL_PROC(_kern_random, OID_AUTO, live_entropy_sources,
125             CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
126             NULL, 0, live_entropy_source_handler, "",
127             "List of Active Live Entropy Sources");
128 }
129
130 /*
131  * Run through all "live" sources reading entropy for the given
132  * number of rounds, which should be a multiple of the number
133  * of entropy accumulation pools in use; 2 for Yarrow and 32
134  * for Fortuna.
135  *
136  * BEWARE!!!
137  * This function runs inside the RNG thread! Don't do anything silly!
138  * The harvest_mtx mutex is held; you may count on that.
139  */
140 void
141 live_entropy_sources_feed(int rounds, event_proc_f entropy_processor)
142 {
143         static struct harvest event;
144         static uint8_t buf[HARVESTSIZE];
145         struct live_entropy_sources *les;
146         int i, n;
147
148         /*
149          * Walk over all of live entropy sources, and feed their output
150          * to the system-wide RNG.
151          */
152         LIST_FOREACH(les, &sources, entries) {
153
154                 for (i = 0; i < rounds; i++) {
155                         /*
156                          * This should be quick, since it's a live entropy
157                          * source.
158                          */
159                         /* FIXME: Whine loudly if this didn't work. */
160                         n = les->rsource->read(buf, sizeof(buf));
161                         n = MIN(n, HARVESTSIZE);
162
163                         event.somecounter = get_cyclecount();
164                         event.size = n;
165                         event.bits = (n*8)/2;
166                         event.source = les->rsource->source;
167                         memcpy(event.entropy, buf, n);
168
169                         /* Do the actual entropy insertion */
170                         entropy_processor(&event);
171
172                 }
173
174         }
175 }
176
177 static void
178 live_entropy_sources_deinit(void *unused)
179 {
180 }
181
182 SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
183     live_entropy_sources_init, NULL);
184 SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
185     live_entropy_sources_deinit, NULL);