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