]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/random/live_entropy_sources.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 /*
56  * The live_lock protects the consistency of the "struct les_head sources"
57  */
58 static struct sx les_lock; /* need a sleepable lock */
59
60 void
61 live_entropy_source_register(struct random_hardware_source *rsource)
62 {
63         struct live_entropy_sources *les;
64
65         KASSERT(rsource != NULL, ("invalid input to %s", __func__));
66
67         les = malloc(sizeof(struct live_entropy_sources), M_ENTROPY, M_WAITOK);
68         les->rsource = rsource;
69
70         sx_xlock(&les_lock);
71         LIST_INSERT_HEAD(&sources, les, entries);
72         sx_xunlock(&les_lock);
73 }
74
75 void
76 live_entropy_source_deregister(struct random_hardware_source *rsource)
77 {
78         struct live_entropy_sources *les = NULL;
79
80         KASSERT(rsource != NULL, ("invalid input to %s", __func__));
81
82         sx_xlock(&les_lock);
83         LIST_FOREACH(les, &sources, entries)
84                 if (les->rsource == rsource) {
85                         LIST_REMOVE(les, entries);
86                         break;
87                 }
88         sx_xunlock(&les_lock);
89         if (les != NULL)
90                 free(les, M_ENTROPY);
91 }
92
93 static int
94 live_entropy_source_handler(SYSCTL_HANDLER_ARGS)
95 {
96         struct live_entropy_sources *les;
97         int error, count;
98
99         count = error = 0;
100
101         sx_slock(&les_lock);
102
103         if (LIST_EMPTY(&sources))
104                 error = SYSCTL_OUT(req, "", 0);
105         else {
106                 LIST_FOREACH(les, &sources, entries) {
107
108                         error = SYSCTL_OUT(req, ",", count++ ? 1 : 0);
109                         if (error)
110                                 break;
111
112                         error = SYSCTL_OUT(req, les->rsource->ident, strlen(les->rsource->ident));
113                         if (error)
114                                 break;
115                 }
116         }
117
118         sx_sunlock(&les_lock);
119
120         return (error);
121 }
122
123 static void
124 live_entropy_sources_init(void *unused)
125 {
126
127         SYSCTL_PROC(_kern_random, OID_AUTO, live_entropy_sources,
128             CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
129             NULL, 0, live_entropy_source_handler, "",
130             "List of Active Live Entropy Sources");
131
132         sx_init(&les_lock, "live_entropy_sources");
133 }
134
135 /*
136  * Run through all "live" sources reading entropy for the given
137  * number of rounds, which should be a multiple of the number
138  * of entropy accumulation pools in use; 2 for Yarrow and 32
139  * for Fortuna.
140  *
141  * BEWARE!!!
142  * This function runs inside the RNG thread! Don't do anything silly!
143  * Remember that we are NOT holding harvest_mtx on entry!
144  */
145 void
146 live_entropy_sources_feed(int rounds, event_proc_f entropy_processor)
147 {
148         static struct harvest event;
149         static uint8_t buf[HARVESTSIZE];
150         struct live_entropy_sources *les;
151         int i, n;
152
153         sx_slock(&les_lock);
154
155         /*
156          * Walk over all of live entropy sources, and feed their output
157          * to the system-wide RNG.
158          */
159         LIST_FOREACH(les, &sources, entries) {
160
161                 for (i = 0; i < rounds; i++) {
162                         /*
163                          * This should be quick, since it's a live entropy
164                          * source.
165                          */
166                         /* FIXME: Whine loudly if this didn't work. */
167                         n = les->rsource->read(buf, sizeof(buf));
168                         n = MIN(n, HARVESTSIZE);
169
170                         event.somecounter = get_cyclecount();
171                         event.size = n;
172                         event.bits = (n*8)/2;
173                         event.source = les->rsource->source;
174                         memcpy(event.entropy, buf, n);
175
176                         /* Do the actual entropy insertion */
177                         entropy_processor(&event);
178                 }
179
180         }
181
182         sx_sunlock(&les_lock);
183 }
184
185 static void
186 live_entropy_sources_deinit(void *unused)
187 {
188
189         sx_destroy(&les_lock);
190 }
191
192 SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
193     live_entropy_sources_init, NULL);
194 SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
195     live_entropy_sources_deinit, NULL);