Line data Source code
1 : /* $OpenBSD: uonerng.c,v 1.4 2018/07/09 20:06:12 jasper Exp $ */
2 : /*
3 : * Copyright (C) 2015 Devin Reade <gdr@gno.org>
4 : * Copyright (C) 2015 Sean Levy <attila@stalphonsos.com>
5 : * Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org>
6 : * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
7 : * Copyright (c) 1998 The NetBSD Foundation, Inc.
8 : *
9 : * Permission to use, copy, modify, and distribute this software for any
10 : * purpose with or without fee is hereby granted, provided that the above
11 : * copyright notice and this permission notice appear in all copies.
12 : *
13 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 : */
21 :
22 : /*
23 : * Moonbase Otago OneRNG TRNG. Note that the encoded vendor for this
24 : * device is OpenMoko as OpenMoko has made its device ranges available
25 : * for other open source / open hardware vendors.
26 : *
27 : * Product information can be found here:
28 : * http://onerng.info/onerng
29 : *
30 : * Based on the ualea(4), uow(4), and umodem(4) source code.
31 : */
32 :
33 : #include <sys/param.h>
34 : #include <sys/systm.h>
35 : #include <sys/device.h>
36 : #include <sys/time.h>
37 : #include <sys/timeout.h>
38 : #include <machine/bus.h>
39 :
40 : #include <dev/usb/usb.h>
41 : #include <dev/usb/usbdi.h>
42 : #include <dev/usb/usbdivar.h>
43 : #include <dev/usb/usbdi_util.h>
44 : #include <dev/usb/usbdevs.h>
45 : #include <dev/usb/usbcdc.h>
46 :
47 : #include <dev/rndvar.h>
48 :
49 : /*
50 : * The OneRNG is documented to provide ~350kbits/s of entropy at
51 : * ~7.8 bits/byte, and when used at a lower rate providing close
52 : * to 8 bits/byte.
53 : *
54 : * Although this driver is able to consume the data at the full rate,
55 : * we tune this down to 10kbit/s as the OpenBSD RNG is better off
56 : * with small amounts of input at a time so as to not saturate the
57 : * input queue and mute other sources of entropy.
58 : *
59 : * Furthermore, unlike other implementations, for us there is no benefit
60 : * to discarding the initial bytes retrieved from the OneRNG, regardless
61 : * of the quality of the data. (Empirical tests suggest that the initial
62 : * quality is fine, anyway.)
63 : */
64 : #define ONERNG_BUFSIZ 128
65 : #define ONERNG_MSECS 100
66 :
67 : #define ONERNG_TIMEOUT 1000 /* ms */
68 :
69 : /*
70 : * Define ONERNG_MEASURE_RATE to periodically log rate at which we provide
71 : * random data to the kernel.
72 : */
73 : #ifdef ONERNG_MEASURE_RATE
74 : #define ONERNG_RATE_SECONDS 30
75 : #endif
76 :
77 : /* OneRNG operational modes */
78 : #define ONERNG_OP_ENABLE "cmdO\n" /* start emitting data */
79 : #define ONERNG_OP_DISABLE "cmdo\n" /* stop emitting data */
80 : #define ONERNG_OP_FLUSH_ENTROPY "cmdw\n"
81 :
82 : /* permits extracting the firmware in order to check the crypto signature */
83 : #define ONERNG_OP_EXTRACT_FIRMWARE "cmdX\n"
84 :
85 : /*
86 : * Noise sources include an avalache circuit and an RF circuit.
87 : * There is also a whitener to provide a uniform distribution.
88 : * Different combinations are possible.
89 : */
90 : #define ONERNG_AVALANCHE_WHITENER "cmd0\n" /* device default */
91 : #define ONERNG_AVALANCHE "cmd1\n"
92 : #define ONERNG_AVALANCHE_RF_WHITENER "cmd2\n"
93 : #define ONERNG_AVALANCHE_RF "cmd3\n"
94 : #define ONERNG_SILENT "cmd4\n" /* none; necessary for cmdX */
95 : #define ONERNG_SILENT2 "cmd5\n"
96 : #define ONERNG_RF_WHITENER "cmd6\n"
97 : #define ONERNG_RF "cmd7\n"
98 :
99 :
100 : #define ONERNG_IFACE_CTRL_INDEX 0
101 : #define ONERNG_IFACE_DATA_INDEX 1
102 :
103 : #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
104 :
105 : struct uonerng_softc {
106 : struct device sc_dev;
107 : struct usbd_device *sc_udev;
108 :
109 : int sc_ctl_iface_no; /* control */
110 : struct usbd_interface *sc_data_iface; /* data */
111 :
112 : struct usbd_pipe *sc_inpipe;
113 : struct usbd_pipe *sc_outpipe;
114 :
115 : struct timeout sc_timeout;
116 : struct usb_task sc_task;
117 : struct usbd_xfer *sc_xfer;
118 : int *sc_buf;
119 : #ifdef ONERNG_MEASURE_RATE
120 : struct timeval sc_start;
121 : struct timeval sc_cur;
122 : int sc_counted_bytes;
123 : #endif
124 : u_char sc_dtr; /* current DTR state */
125 : u_char sc_rts; /* current RTS state */
126 : u_char sc_first_run;
127 : };
128 :
129 : int uonerng_match(struct device *, void *, void *);
130 : void uonerng_attach(struct device *, struct device *, void *);
131 : int uonerng_detach(struct device *, int);
132 : void uonerng_task(void *);
133 : void uonerng_timeout(void *);
134 : int uonerng_enable(struct uonerng_softc *sc);
135 : void uonerng_cleanup(struct uonerng_softc *sc);
136 : usbd_status uonerng_set_line_state(struct uonerng_softc *sc);
137 : usbd_status uonerng_rts(struct uonerng_softc *sc, int onoff);
138 :
139 : struct cfdriver uonerng_cd = {
140 : NULL, "uonerng", DV_DULL
141 : };
142 :
143 : const struct cfattach uonerng_ca = {
144 : sizeof(struct uonerng_softc), uonerng_match, uonerng_attach, uonerng_detach
145 : };
146 :
147 : int
148 0 : uonerng_match(struct device *parent, void *match, void *aux)
149 : {
150 0 : struct usb_attach_arg *uaa = aux;
151 :
152 0 : if (uaa->iface == NULL)
153 0 : return UMATCH_NONE;
154 :
155 0 : if (uaa->vendor != USB_VENDOR_OPENMOKO2 ||
156 0 : uaa->product != USB_PRODUCT_OPENMOKO2_ONERNG)
157 0 : return UMATCH_NONE;
158 :
159 0 : return UMATCH_VENDOR_PRODUCT;
160 0 : }
161 :
162 : void
163 0 : uonerng_attach(struct device *parent, struct device *self, void *aux)
164 : {
165 0 : struct uonerng_softc *sc = (struct uonerng_softc *)self;
166 0 : struct usb_attach_arg *uaa = aux;
167 0 : struct usbd_interface *iface = uaa->iface;
168 : usb_interface_descriptor_t *id;
169 : usb_endpoint_descriptor_t *ed;
170 : int ep_ibulk = -1, ep_obulk = -1;
171 : usbd_status err;
172 : int i;
173 :
174 0 : sc->sc_udev = uaa->device;
175 0 : sc->sc_dtr = -1;
176 0 : sc->sc_rts = -1;
177 0 : sc->sc_first_run = 1;
178 :
179 0 : usb_init_task(&sc->sc_task, uonerng_task, sc, USB_TASK_TYPE_GENERIC);
180 :
181 : /* locate the control interface number and the data interface */
182 0 : err = usbd_device2interface_handle(sc->sc_udev,
183 : ONERNG_IFACE_CTRL_INDEX, &iface);
184 0 : if (err || iface == NULL) {
185 0 : printf("%s: failed to locate control interface, err=%s\n",
186 0 : DEVNAME(sc), usbd_errstr(err));
187 0 : goto fail;
188 : }
189 0 : id = usbd_get_interface_descriptor(iface);
190 0 : if (id != NULL &&
191 0 : id->bInterfaceClass == UICLASS_CDC &&
192 0 : id->bInterfaceSubClass == UISUBCLASS_ABSTRACT_CONTROL_MODEL &&
193 0 : id->bInterfaceProtocol == UIPROTO_CDC_AT) {
194 0 : sc->sc_ctl_iface_no = id->bInterfaceNumber;
195 : } else {
196 0 : printf("%s: control interface number not found\n",
197 0 : DEVNAME(sc));
198 0 : goto fail;
199 : }
200 :
201 0 : err = usbd_device2interface_handle(sc->sc_udev,
202 0 : ONERNG_IFACE_DATA_INDEX, &sc->sc_data_iface);
203 0 : if (err || sc->sc_data_iface == NULL) {
204 0 : printf("%s: failed to locate data interface, err=%s\n",
205 0 : DEVNAME(sc), usbd_errstr(err));
206 0 : goto fail;
207 : }
208 :
209 : /* Find the bulk endpoints */
210 0 : id = usbd_get_interface_descriptor(sc->sc_data_iface);
211 0 : if (id == NULL ||
212 0 : id->bInterfaceClass != UICLASS_CDC_DATA ||
213 0 : id->bInterfaceSubClass != UISUBCLASS_DATA) {
214 0 : printf("%s: no data interface descriptor\n", DEVNAME(sc));
215 0 : goto fail;
216 : }
217 0 : for (i = 0; i < id->bNumEndpoints; i++) {
218 0 : ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i);
219 0 : if (ed == NULL) {
220 0 : printf("%s: no endpoint descriptor for %d\n",
221 0 : DEVNAME(sc), i);
222 0 : goto fail;
223 : }
224 0 : if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
225 0 : UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
226 : ep_ibulk = ed->bEndpointAddress;
227 0 : } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
228 0 : UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
229 : ep_obulk = ed->bEndpointAddress;
230 0 : }
231 : }
232 :
233 0 : if (ep_ibulk == -1) {
234 0 : printf("%s: Could not find data bulk in\n", DEVNAME(sc));
235 0 : goto fail;
236 : }
237 0 : if (ep_obulk == -1) {
238 0 : printf("%s: Could not find data bulk out\n", DEVNAME(sc));
239 0 : goto fail;
240 : }
241 :
242 : /* Open pipes */
243 0 : err = usbd_open_pipe(sc->sc_data_iface, ep_ibulk,
244 0 : USBD_EXCLUSIVE_USE, &sc->sc_inpipe);
245 0 : if (err) {
246 0 : printf("%s: failed to open bulk-in pipe: %s\n",
247 0 : DEVNAME(sc), usbd_errstr(err));
248 0 : goto fail;
249 : }
250 0 : err = usbd_open_pipe(sc->sc_data_iface, ep_obulk,
251 0 : USBD_EXCLUSIVE_USE, &sc->sc_outpipe);
252 0 : if (err) {
253 0 : printf("%s: failed to open bulk-out pipe: %s\n",
254 0 : DEVNAME(sc), usbd_errstr(err));
255 0 : goto fail;
256 : }
257 :
258 : /* Allocate xfer/buffer for bulk transfers */
259 0 : sc->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
260 0 : if (sc->sc_xfer == NULL) {
261 0 : printf("%s: could not alloc xfer\n", DEVNAME(sc));
262 0 : goto fail;
263 : }
264 0 : sc->sc_buf = usbd_alloc_buffer(sc->sc_xfer, ONERNG_BUFSIZ);
265 0 : if (sc->sc_buf == NULL) {
266 0 : printf("%s: could not alloc %d-byte buffer\n", DEVNAME(sc),
267 : ONERNG_BUFSIZ);
268 0 : goto fail;
269 : }
270 :
271 0 : if (uonerng_enable(sc) != 0) {
272 : goto fail;
273 : }
274 :
275 0 : timeout_set(&sc->sc_timeout, uonerng_timeout, sc);
276 :
277 : /* get the initial random data as early as possible */
278 0 : uonerng_task(sc);
279 :
280 0 : usb_add_task(sc->sc_udev, &sc->sc_task);
281 0 : return;
282 :
283 : fail:
284 0 : usbd_deactivate(sc->sc_udev);
285 0 : uonerng_cleanup(sc);
286 0 : }
287 :
288 : int
289 0 : uonerng_enable(struct uonerng_softc *sc)
290 : {
291 : int err;
292 :
293 0 : if ((err = uonerng_rts(sc, 0))) {
294 0 : printf("%s: failed to clear RTS: %s\n", DEVNAME(sc),
295 0 : usbd_errstr(err));
296 0 : return (1);
297 : }
298 :
299 0 : usbd_setup_xfer(sc->sc_xfer, sc->sc_outpipe, sc,
300 : ONERNG_AVALANCHE_WHITENER, sizeof(ONERNG_AVALANCHE_WHITENER),
301 : USBD_SYNCHRONOUS, ONERNG_TIMEOUT, NULL);
302 0 : if ((err = usbd_transfer(sc->sc_xfer))) {
303 0 : printf("%s: failed to set operating mode: %s\n",
304 0 : DEVNAME(sc), usbd_errstr(err));
305 0 : return (1);
306 : }
307 :
308 0 : usbd_setup_xfer(sc->sc_xfer, sc->sc_outpipe, sc,
309 : ONERNG_OP_ENABLE, sizeof(ONERNG_OP_ENABLE),
310 : USBD_SYNCHRONOUS, ONERNG_TIMEOUT, NULL);
311 0 : if ((err = usbd_transfer(sc->sc_xfer))) {
312 0 : printf("%s: failed to enable device: %s\n",
313 0 : DEVNAME(sc), usbd_errstr(err));
314 0 : return (1);
315 : }
316 :
317 0 : return (0);
318 0 : }
319 :
320 : int
321 0 : uonerng_detach(struct device *self, int flags)
322 : {
323 0 : struct uonerng_softc *sc = (struct uonerng_softc *)self;
324 :
325 0 : usb_rem_task(sc->sc_udev, &sc->sc_task);
326 0 : if (timeout_initialized(&sc->sc_timeout)) {
327 0 : timeout_del(&sc->sc_timeout);
328 0 : }
329 0 : uonerng_cleanup(sc);
330 0 : return (0);
331 : }
332 :
333 : void
334 0 : uonerng_cleanup(struct uonerng_softc *sc)
335 : {
336 0 : if (sc->sc_inpipe != NULL) {
337 0 : usbd_close_pipe(sc->sc_inpipe);
338 0 : sc->sc_inpipe = NULL;
339 0 : }
340 0 : if (sc->sc_outpipe != NULL) {
341 0 : usbd_close_pipe(sc->sc_outpipe);
342 0 : sc->sc_outpipe = NULL;
343 0 : }
344 :
345 : /* usbd_free_xfer will also free the buffer if necessary */
346 0 : if (sc->sc_xfer != NULL) {
347 0 : usbd_free_xfer(sc->sc_xfer);
348 0 : sc->sc_xfer = NULL;
349 0 : }
350 0 : }
351 :
352 : usbd_status
353 0 : uonerng_rts(struct uonerng_softc *sc, int onoff)
354 : {
355 0 : if (sc->sc_rts == onoff)
356 0 : return USBD_NORMAL_COMPLETION;
357 0 : sc->sc_rts = onoff;
358 :
359 0 : return uonerng_set_line_state(sc);
360 0 : }
361 :
362 : usbd_status
363 0 : uonerng_set_line_state(struct uonerng_softc *sc)
364 : {
365 0 : usb_device_request_t req;
366 : int ls;
367 :
368 0 : ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
369 0 : (sc->sc_rts ? UCDC_LINE_RTS : 0);
370 0 : req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
371 0 : req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
372 0 : USETW(req.wValue, ls);
373 0 : USETW(req.wIndex, sc->sc_ctl_iface_no);
374 0 : USETW(req.wLength, 0);
375 :
376 0 : return usbd_do_request(sc->sc_udev, &req, 0);
377 0 : }
378 :
379 : void
380 0 : uonerng_task(void *arg)
381 : {
382 0 : struct uonerng_softc *sc = (struct uonerng_softc *) arg;
383 : usbd_status error;
384 0 : u_int32_t len, int_count, i;
385 : #ifdef ONERNG_MEASURE_RATE
386 : time_t elapsed;
387 : int rate;
388 : #endif
389 :
390 0 : usbd_setup_xfer(sc->sc_xfer, sc->sc_inpipe, NULL, sc->sc_buf,
391 : ONERNG_BUFSIZ,
392 : USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS | USBD_NO_COPY,
393 : ONERNG_TIMEOUT, NULL);
394 0 : error = usbd_transfer(sc->sc_xfer);
395 0 : if (error) {
396 0 : printf("%s: xfer failed: %s\n", DEVNAME(sc),
397 0 : usbd_errstr(error));
398 0 : goto bail;
399 : }
400 0 : usbd_get_xfer_status(sc->sc_xfer, NULL, NULL, &len, NULL);
401 0 : if (len < sizeof(int)) {
402 0 : printf("%s: xfer too short (%u bytes) - dropping\n",
403 0 : DEVNAME(sc), len);
404 0 : goto bail;
405 : }
406 :
407 : #ifdef ONERNG_MEASURE_RATE
408 : if (sc->sc_first_run) {
409 : sc->sc_counted_bytes = 0;
410 : getmicrotime(&(sc->sc_start));
411 : }
412 : sc->sc_counted_bytes += len;
413 : getmicrotime(&(sc->sc_cur));
414 : elapsed = sc->sc_cur.tv_sec - sc->sc_start.tv_sec;
415 : if (elapsed >= ONERNG_RATE_SECONDS) {
416 : rate = (8 * sc->sc_counted_bytes) / (elapsed * 1024);
417 : printf("%s: transfer rate = %d kb/s\n", DEVNAME(sc), rate);
418 :
419 : /* set up for next measurement */
420 : sc->sc_counted_bytes = 0;
421 : getmicrotime(&(sc->sc_start));
422 : }
423 : #endif
424 :
425 0 : int_count = len / sizeof(int);
426 0 : for (i = 0; i < int_count; i++) {
427 0 : enqueue_randomness(sc->sc_buf[i]);
428 : }
429 : bail:
430 :
431 0 : if (sc->sc_first_run) {
432 0 : sc->sc_first_run = 0;
433 0 : } else {
434 0 : timeout_add_msec(&sc->sc_timeout, ONERNG_MSECS);
435 : }
436 0 : }
437 :
438 : void
439 0 : uonerng_timeout(void *arg)
440 : {
441 0 : struct uonerng_softc *sc = arg;
442 :
443 0 : usb_add_task(sc->sc_udev, &sc->sc_task);
444 0 : }
|