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