xref: /openbsd-src/sys/dev/usb/urng.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: urng.c,v 1.9 2018/07/09 20:09:00 jasper Exp $ */
2 
3 /*
4  * Copyright (c) 2017 Jasper Lievisse Adriaanse <jasper@openbsd.org>
5  * Copyright (c) 2017 Aaron Bieber <abieber@openbsd.org>
6  * Copyright (C) 2015 Sean Levy <attila@stalphonsos.com>
7  * Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org>
8  * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22 
23 /*
24  * Universal TRNG driver for a collection of TRNG devices:
25  * - ChaosKey TRNG
26  *   http://altusmetrum.org/ChaosKey/
27  * - Alea II TRNG.  Produces 100kbit/sec of entropy by black magic
28  *   http://www.araneus.fi/products/alea2/en/
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/device.h>
34 #include <sys/time.h>
35 #include <sys/timeout.h>
36 
37 #include <dev/usb/usb.h>
38 #include <dev/usb/usbdi.h>
39 #include <dev/usb/usbdevs.h>
40 
41 #include <dev/rndvar.h>
42 
43 #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
44 
45 #ifdef URNG_DEBUG
46 #define DPRINTF(x)	printf x
47 #else
48 #define DPRINTF(x)
49 #endif
50 
51 /*
52  * Define URNG_MEASURE_RATE to periodically log rate at which we provide
53  * random data to the kernel.
54  */
55 #ifdef URNG_MEASURE_RATE
56 #define URNG_RATE_SECONDS 30
57 #endif
58 
59 struct urng_chip {
60 	int	bufsiz;
61 	int	endpoint;
62 	int	ctl_iface_idx;
63 	int	msecs;
64 	int	read_timeout;
65 };
66 
67 struct urng_softc {
68 	struct  device		 sc_dev;
69 	struct  usbd_device	*sc_udev;
70 	struct  usbd_pipe	*sc_inpipe;
71 	struct  timeout 	 sc_timeout;
72 	struct  usb_task	 sc_task;
73 	struct  usbd_xfer	*sc_xfer;
74 	struct	urng_chip	 sc_chip;
75 	int     		*sc_buf;
76 	int			 sc_product;
77 #ifdef URNG_MEASURE_RATE
78 	struct	timeval		 sc_start;
79 	struct	timeval 	 sc_cur;
80 	int			 sc_counted_bytes;
81 	u_char			 sc_first_run;
82 #endif
83 };
84 
85 int urng_match(struct device *, void *, void *);
86 void urng_attach(struct device *, struct device *, void *);
87 int urng_detach(struct device *, int);
88 void urng_task(void *);
89 void urng_timeout(void *);
90 
91 struct cfdriver urng_cd = {
92 	NULL, "urng", DV_DULL
93 };
94 
95 const struct cfattach urng_ca = {
96 	sizeof(struct urng_softc), urng_match, urng_attach, urng_detach
97 };
98 
99 struct urng_type {
100 	struct usb_devno	urng_dev;
101 	struct urng_chip	urng_chip;
102 };
103 
104 static const struct urng_type urng_devs[] = {
105 	{ { USB_VENDOR_OPENMOKO2, USB_PRODUCT_OPENMOKO2_CHAOSKEY },
106 	  {64, 5, 0, 100, 5000} },
107 	{ { USB_VENDOR_ARANEUS, USB_PRODUCT_ARANEUS_ALEA },
108 	  {128, 1, 0, 100, 5000} },
109 };
110 #define urng_lookup(v, p) ((struct urng_type *)usb_lookup(urng_devs, v, p))
111 
112 int
113 urng_match(struct device *parent, void *match, void *aux)
114 {
115 	struct usb_attach_arg *uaa = aux;
116 
117 	if (uaa->iface == NULL)
118 		return (UMATCH_NONE);
119 
120 	if (urng_lookup(uaa->vendor, uaa->product) != NULL)
121 		return (UMATCH_VENDOR_PRODUCT);
122 
123 	return (UMATCH_NONE);
124 }
125 
126 void
127 urng_attach(struct device *parent, struct device *self, void *aux)
128 {
129 	struct urng_softc *sc = (struct urng_softc *)self;
130 	struct usb_attach_arg *uaa = aux;
131 	usb_interface_descriptor_t *id;
132 	usb_endpoint_descriptor_t *ed;
133 	int ep_ibulk = -1;
134 	usbd_status error;
135 	int i, ep_addr;
136 
137 	sc->sc_udev = uaa->device;
138 	sc->sc_chip = urng_lookup(uaa->vendor, uaa->product)->urng_chip;
139 	sc->sc_product = uaa->product;
140 #ifdef URNG_MEASURE_RATE
141 	sc->sc_first_run = 1;
142 #endif
143 
144 	DPRINTF(("%s: bufsiz: %d, endpoint: %d ctl iface: %d, msecs: %d, read_timeout: %d\n",
145 		DEVNAME(sc),
146 		sc->sc_chip.bufsiz,
147 		sc->sc_chip.endpoint,
148 		sc->sc_chip.ctl_iface_idx,
149 		sc->sc_chip.msecs,
150 		sc->sc_chip.read_timeout));
151 
152 	/* Find the bulk endpoints. */
153 	id = usbd_get_interface_descriptor(uaa->iface);
154 	for (i = 0; i < id->bNumEndpoints; i++) {
155 		ed = usbd_interface2endpoint_descriptor(uaa->iface, i);
156 		if (ed == NULL) {
157 			printf("%s: failed to get endpoint %d descriptor\n",
158 			    DEVNAME(sc), i);
159 			goto fail;
160 		}
161 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
162 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
163 		    	ep_addr = UE_GET_ADDR(ed->bEndpointAddress);
164 
165 			DPRINTF(("%s: bulk endpoint %d\n",
166 			    DEVNAME(sc), ep_addr));
167 
168 			if (ep_addr == sc->sc_chip.endpoint) {
169 				ep_ibulk = ed->bEndpointAddress;
170 				break;
171 			}
172 		}
173 	}
174 
175 	if (ep_ibulk == -1) {
176 		printf("%s: missing bulk input endpoint\n", DEVNAME(sc));
177 		goto fail;
178 	}
179 
180 	/* Open the pipes. */
181 	error = usbd_open_pipe(uaa->iface, ep_ibulk, USBD_EXCLUSIVE_USE,
182 		    &sc->sc_inpipe);
183 	if (error) {
184 		printf("%s: failed to open bulk-in pipe: %s\n",
185 				DEVNAME(sc), usbd_errstr(error));
186 		goto fail;
187 	}
188 
189 	/* Allocate the transfer buffers. */
190 	sc->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
191 	if (sc->sc_xfer == NULL) {
192 		printf("%s: could not alloc xfer\n", DEVNAME(sc));
193 		goto fail;
194 	}
195 
196 	sc->sc_buf = usbd_alloc_buffer(sc->sc_xfer, sc->sc_chip.bufsiz);
197 	if (sc->sc_buf == NULL) {
198 		printf("%s: could not alloc %d-byte buffer\n", DEVNAME(sc),
199 				sc->sc_chip.bufsiz);
200 		goto fail;
201 	}
202 
203 	/* And off we go! */
204 	usb_init_task(&sc->sc_task, urng_task, sc, USB_TASK_TYPE_GENERIC);
205 	timeout_set(&sc->sc_timeout, urng_timeout, sc);
206 	usb_add_task(sc->sc_udev, &sc->sc_task);
207 
208 	return;
209 
210 fail:
211 	usbd_deactivate(sc->sc_udev);
212 }
213 
214 int
215 urng_detach(struct device *self, int flags)
216 {
217 	struct urng_softc *sc = (struct urng_softc *)self;
218 
219 	usb_rem_task(sc->sc_udev, &sc->sc_task);
220 
221 	if (timeout_initialized(&sc->sc_timeout))
222 		timeout_del(&sc->sc_timeout);
223 
224 	if (sc->sc_xfer != NULL) {
225 		usbd_free_xfer(sc->sc_xfer);
226 		sc->sc_xfer = NULL;
227 	}
228 
229 	if (sc->sc_inpipe != NULL) {
230 		usbd_close_pipe(sc->sc_inpipe);
231 		sc->sc_inpipe = NULL;
232 	}
233 
234 	return (0);
235 }
236 
237 
238 void
239 urng_task(void *arg)
240 {
241 	struct urng_softc *sc = (struct urng_softc *)arg;
242 	usbd_status error;
243 	u_int32_t len, i;
244 #ifdef URNG_MEASURE_RATE
245 	time_t elapsed;
246 	int rate;
247 #endif
248 	usbd_setup_xfer(sc->sc_xfer, sc->sc_inpipe, NULL, sc->sc_buf,
249 	    sc->sc_chip.bufsiz, USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS,
250 	    sc->sc_chip.read_timeout, NULL);
251 
252 	error = usbd_transfer(sc->sc_xfer);
253 	if (error) {
254 		printf("%s: xfer failed: %s\n", DEVNAME(sc),
255 		    usbd_errstr(error));
256 		goto bail;
257 	}
258 
259 	usbd_get_xfer_status(sc->sc_xfer, NULL, NULL, &len, NULL);
260 	if (len < sizeof(int)) {
261 		printf("%s: xfer too short (%u bytes) - dropping\n",
262 		    DEVNAME(sc), len);
263 		goto bail;
264 	}
265 
266 #ifdef URNG_MEASURE_RATE
267 	if (sc->sc_first_run) {
268 		sc->sc_counted_bytes = 0;
269 		getmicrotime(&(sc->sc_start));
270 	}
271 	sc->sc_counted_bytes += len;
272 	getmicrotime(&(sc->sc_cur));
273 	elapsed = sc->sc_cur.tv_sec - sc->sc_start.tv_sec;
274 	if (elapsed >= URNG_RATE_SECONDS) {
275 		rate = (8 * sc->sc_counted_bytes) / (elapsed * 1024);
276 		printf("%s: transfer rate = %d kb/s\n", DEVNAME(sc), rate);
277 
278 		/* set up for next measurement */
279 		sc->sc_counted_bytes = 0;
280 		getmicrotime(&(sc->sc_start));
281 	}
282 #endif
283 
284 	len /= sizeof(int);
285 	for (i = 0; i < len; i++) {
286 		enqueue_randomness(sc->sc_buf[i]);
287 	}
288 bail:
289 #ifdef URNG_MEASURE_RATE
290 	if (sc->sc_first_run) {
291 		sc->sc_first_run = 0;
292 	}
293 #endif
294 
295 	timeout_add_msec(&sc->sc_timeout, sc->sc_chip.msecs);
296 }
297 
298 void
299 urng_timeout(void *arg)
300 {
301 	struct urng_softc *sc = arg;
302 
303 	usb_add_task(sc->sc_udev, &sc->sc_task);
304 }
305