Hi tech@, Ping?
attila <[email protected]> writes: > Hi tech@, > > I've written a driver for the Araneus Alea II USB TRNG: > http://www.araneus.fi/products/alea2/en/ > > It produces 100kbit/sec of entropy, which my driver stuffs into > add_true_randomness(). A small thing, but maybe valuable in > situations that do a lot of crypto. I mainly did it to get my head > around more of the codebase, and I happened to have one lying around, > so... According to the docs the interface has not changed between the > Alea I and the Alea II so this driver should work for both, but I only > have a II. I'm interested in writing drivers for other TRNGs if > anyone else finds it useful. > > Tested under i386 and amd64. > > I'm sure I've made many mistakes. Comments and feedback most welcome. > > Pax, -A > > diff -Nurp src.orig/sys/arch/amd64/conf/GENERIC > src/sys/arch/amd64/conf/GENERIC > --- src.orig/sys/arch/amd64/conf/GENERIC Thu Apr 2 08:24:02 2015 > +++ src/sys/arch/amd64/conf/GENERIC Thu Apr 9 16:02:27 2015 > @@ -271,6 +271,7 @@ uvideo* at uhub? # USB Video > video* at uvideo? > udl* at uhub? # DisplayLink USB displays > wsdisplay* at udl? > +ualea* at uhub? # Araneus Alea II USB TRNG > > puc* at pci? # PCI "universal" communication device > com* at cardbus? > diff -Nurp src.orig/sys/arch/i386/conf/GENERIC src/sys/arch/i386/conf/GENERIC > --- src.orig/sys/arch/i386/conf/GENERIC Thu Apr 2 08:24:02 2015 > +++ src/sys/arch/i386/conf/GENERIC Thu Apr 9 16:02:01 2015 > @@ -325,6 +325,7 @@ uvideo* at uhub? # USB video > video* at uvideo? > udl* at uhub? # DisplayLink USB displays > wsdisplay* at udl? > +ualea* at uhub? # Araneus Alea II USB TRNG > > puc* at pci? # PCI "universal" communication device > com* at cardbus? > diff -Nurp src.orig/sys/arch/macppc/conf/GENERIC > src/sys/arch/macppc/conf/GENERIC > --- src.orig/sys/arch/macppc/conf/GENERIC Thu Apr 2 08:24:02 2015 > +++ src/sys/arch/macppc/conf/GENERIC Thu Apr 9 16:02:43 2015 > @@ -292,6 +292,7 @@ utrh* at uhidev? # USBRH sensor > utwitch* at uhidev? # YUREX BBU sensor > uow* at uhub? # Maxim/Dallas DS2490 1-Wire adapter > onewire* at uow? > +ualea* at uhub? # Araneus Alea II USB TRNG > > # USB Video > uvideo* at uhub? > diff -Nurp src.orig/sys/arch/sparc64/conf/GENERIC > src/sys/arch/sparc64/conf/GENERIC > --- src.orig/sys/arch/sparc64/conf/GENERIC Tue Mar 24 06:00:39 2015 > +++ src/sys/arch/sparc64/conf/GENERIC Thu Apr 9 16:02:58 2015 > @@ -245,6 +245,7 @@ ugold* at uhidev? # gold TEMPer sensor > utwitch* at uhidev? # UYUREX BBU sensor > uow* at uhub? # Maxim/Dallas DS2490 1-Wire adapter > onewire* at uow? > +ualea* at uhub? # Araneus Alea II USB TRNG > > # USB Video > uvideo* at uhub? > diff -Nurp src.orig/sys/arch/zaurus/conf/GENERIC > src/sys/arch/zaurus/conf/GENERIC > --- src.orig/sys/arch/zaurus/conf/GENERIC Sat Jan 3 15:24:19 2015 > +++ src/sys/arch/zaurus/conf/GENERIC Thu Apr 9 16:03:25 2015 > @@ -135,6 +135,7 @@ umbg* at uhub? # Meinberg > Funkuhren USB5131 > uow* at uhub? # Maxim/Dallas DS2490 1-Wire adapter > onewire* at uow? > utwitch* at uhidev? # YUREX BBU sensor > +ualea* at uhub? # Araneus Alea II USB TRNG > > scsibus* at scsi? > sd* at scsibus? # SCSI disk drives > diff -Nurp src.orig/sys/dev/usb/files.usb src/sys/dev/usb/files.usb > --- src.orig/sys/dev/usb/files.usb Thu Apr 2 08:24:02 2015 > +++ src/sys/dev/usb/files.usb Thu Apr 9 16:04:38 2015 > @@ -195,6 +195,11 @@ device utwitch: hid > attach utwitch at uhidbus > file dev/usb/utwitch.c utwitch > > +# Araneus Alea II TRNG > +device ualea > +attach ualea at uhub > +file dev/usb/ualea.c ualea > + > # Ethernet adapters > # ADMtek AN986 Pegasus > device aue: ether, ifnet, mii, ifmedia > diff -Nurp src.orig/sys/dev/usb/ualea.c src/sys/dev/usb/ualea.c > --- src.orig/sys/dev/usb/ualea.c Wed Dec 31 18:00:00 1969 > +++ src/sys/dev/usb/ualea.c Fri Apr 10 15:46:30 2015 > @@ -0,0 +1,265 @@ > +/* -*- mode:c; tab-width:8; indent-tabs-mode:t; c-basic-offset:8 -*- */ > +/* > + * Copyright (C) 2015 by attila <[email protected]> > + * > + * Permission to use, copy, modify, and/or distribute this software > + * for any purpose with or without fee is hereby granted, provided > + * that the above copyright notice and this permission notice appear > + * in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL > + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED > + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE > + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR > + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS > + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, > + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN > + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +/* > + * Alea II TRNG. Produces 100kbit/sec of entropy by black magic > + * > + * Product information in English can be found here: > + * http://www.araneus.fi/products/alea2/en/ > + * > + * I only have an Alea II to play with but the documentation says > + * that the Alea I is the same, so they should also work. > + * > + * I cribbed liberally from both the uow and umbg drivers, both of > + * which are similar to this situation in different ways. > + */ > + > +#include <sys/param.h> > +#include <sys/systm.h> > +#include <sys/device.h> > +#include <sys/kernel.h> > +#include <sys/time.h> > +#include <sys/timeout.h> > + > +#include <dev/usb/usb.h> > +#include <dev/usb/usbdevs.h> > +#include <dev/usb/usbdi.h> > +#include <dev/usb/usbdi_util.h> > + > +#include <dev/rndvar.h> > + > +#define ALEA_IFACE 0 > +#define ALEA_MSECS 10 > +#define ALEA_READ_TOUT 1100 > +#define ALEA_BUFSIZ ((1024/8)*100) /* 100 kbits */ > +/*#define ALEA_DEBUG 1*/ /* comment out */ > + > +#define OURNAME(x) x->sc_dev.dv_xname > + > +struct ualea_softc { > + struct device sc_dev; > + struct usbd_device *sc_udev; > + struct usbd_interface *sc_iface; > + struct usbd_pipe *sc_ibulk; > + struct timeout sc_tout; > + struct usb_task sc_task; > +#ifdef ALEA_DEBUG > + struct timespec sc_tattach; > + u_int32_t sc_nbits; > +#endif > +}; > + > +int ualea_match(struct device *, void *, void *); > +void ualea_attach(struct device *, struct device *, void *); > +int ualea_detach(struct device *, int); > +void ualea_task(void *); > +void ualea_intr(void *); > + > +struct cfdriver ualea_cd = { > + NULL, "ualea", DV_DULL > +}; > + > +const struct cfattach ualea_ca = { > + sizeof(struct ualea_softc), > + ualea_match, > + ualea_attach, > + ualea_detach > +}; > + > +static const struct usb_devno ualea_devs[] = { > + { USB_VENDOR_ARANEUS, USB_PRODUCT_ARANEUS_ALEA } > +}; > + > +int > +ualea_match(struct device *parent, void *match, void *aux) > +{ > + struct usb_attach_arg *uaa = aux; > + > + if (uaa->iface != NULL) > + return (UMATCH_NONE); > +#ifdef ALEA_DEBUG > + if (uaa->vendor == USB_VENDOR_ARANEUS) > + printf("ualea: vendor 0x%x (%d) (ARANEUS) product 0x%x (%d)\n", > + uaa->vendor, uaa->vendor, uaa->product, uaa->product); > +#endif > + return ((usb_lookup(ualea_devs, uaa->vendor, uaa->product) != NULL) ? > + UMATCH_VENDOR_PRODUCT : UMATCH_NONE); > +} > + > +void > +ualea_attach(struct device *parent, struct device *self, void *aux) > +{ > + struct ualea_softc *sc = (struct ualea_softc *)self; > + struct usb_attach_arg *uaa = aux; > + usb_interface_descriptor_t *id; > + usb_endpoint_descriptor_t *ed; > + int ep_ibulk = -1; > + usbd_status error; > + int i; > + > + sc->sc_udev = uaa->device; > + error = usbd_set_config_index(sc->sc_udev, 0, 1); > + if (error != 0) { > + printf("%s: failed to set config: %s\n", > + OURNAME(sc), usbd_errstr(error)); > + } > + error = usbd_device2interface_handle( > + sc->sc_udev, ALEA_IFACE, &sc->sc_iface); > + if (error != 0) { > + printf("%s: failed to get iface %d: %s\n", > + OURNAME(sc), ALEA_IFACE, usbd_errstr(error)); > + return; > + } > + /* Get endpoint (there can be only one) */ > + id = usbd_get_interface_descriptor(sc->sc_iface); > + for (i = 0; i < id->bNumEndpoints; i++) { > + ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); > + if (ed == NULL) { > + printf("%s: failed to get endpoint %d descriptor\n", > + OURNAME(sc), i); > + return; > + } > + > +#ifdef ALEA_DEBUG > + printf("%s: iface#%d endpoint#%d type %d\n", > + OURNAME(sc), i, UE_GET_DIR(ed->bEndpointAddress), > + UE_GET_XFERTYPE(ed->bmAttributes)); > +#endif /* ALEA_DEBUG */ > + > + if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && > + UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK && > + ep_ibulk == -1) { > + ep_ibulk = ed->bEndpointAddress; > +#ifdef ALEA_DEBUG > + printf("%s: chosing ibulk endpoint#%d\n", > + OURNAME(sc), ep_ibulk); > +#else > + break; > +#endif /* ALEA_DEBUG */ > + } > + } > + if (ep_ibulk == -1) { > + printf("%s: missing ibulk endpoint - cannot initialize\n", > + OURNAME(sc)); > + return; > + } > + /* Open pipe */ > + error = usbd_open_pipe(sc->sc_iface, ep_ibulk, USBD_EXCLUSIVE_USE, > + &sc->sc_ibulk); > + if (error) { > + printf("%s: failed to open bulk-in pipe: %s\n", > + OURNAME(sc), usbd_errstr(error)); > + return; > + } > + /* Get our task going */ > + usb_init_task(&sc->sc_task, ualea_task, sc, USB_TASK_TYPE_GENERIC); > + timeout_set(&sc->sc_tout, ualea_intr, sc); > + timeout_add_msec(&sc->sc_tout, ALEA_MSECS); > +#ifdef ALEA_DEBUG > + nanotime(&sc->sc_tattach); > + sc->sc_nbits = 0; > +#endif /* ALEA_DEBUG */ > +} > + > +int > +ualea_detach(struct device *self, int flags) > +{ > + struct ualea_softc *sc = (struct ualea_softc *)self; > + > + if (timeout_initialized(&sc->sc_tout)) > + timeout_del(&sc->sc_tout); > + if (sc->sc_ibulk != NULL) { > + usbd_abort_pipe(sc->sc_ibulk); > + usbd_close_pipe(sc->sc_ibulk); > + sc->sc_ibulk = NULL; > + } > + > + return 0; > +} > + > +void > +ualea_task(void *arg) > +{ > + struct ualea_softc *sc = (struct ualea_softc *)arg; > + usbd_status error; > + u_int32_t n, i; > + int *buf; > + struct usbd_xfer *xfer; > +#ifdef ALEA_DEBUG > + u_int32_t kbps, dt, nbits; > + struct timespec now; > +#endif /* ALEA_DEBUG */ > + > + xfer = usbd_alloc_xfer(sc->sc_udev); > + if (xfer == NULL) { > + printf("%s: could not alloc xfer\n", OURNAME(sc)); > + goto bail; > + } > + /* Is there any chance this buffer is not at least int-aligned? */ > + buf = usbd_alloc_buffer(xfer, ALEA_BUFSIZ); > + usbd_setup_xfer(xfer, sc->sc_ibulk, NULL, (void *)buf, > + ALEA_BUFSIZ, USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS, > + ALEA_READ_TOUT, NULL); > + error = usbd_transfer(xfer); > + if (error) { > + printf("%s: xfer failed: %s\n", OURNAME(sc), > + usbd_errstr(error)); > + goto bail; > + } > + usbd_get_xfer_status(xfer, NULL, NULL, &n, NULL); > + if (n < sizeof(int)) { > + printf("%s: xfer too short (%u bytes) - dropping\n", > + OURNAME(sc), n); > + goto bail; > + } > +#ifdef ALEA_DEBUG > + else if (n != ALEA_BUFSIZ) > + printf("%s: short read got %u bytes (exp. %u)\n", OURNAME(sc), > + n, ALEA_BUFSIZ); > +#endif /* ALEA_DEBUG */ > + n /= sizeof(int); > + /* > + * A random(|ness) koan: > + * children chug entropy like thirsty rhinos > + * surfing at the mall > + * privacy died in their hands > + */ > + for (i = 0; i < n; i++) > + add_true_randomness(buf[i]); > +#ifdef ALEA_DEBUG > + nanotime(&now); > + dt = now.tv_sec - sc->sc_tattach.tv_sec; > + nbits = n * sizeof(int) * 8; > + sc->sc_nbits += nbits; > + kbps = dt ? ((sc->sc_nbits / 1024) / dt) : 0; > + printf("%s: added %d bits: %dkbit/sec\n", OURNAME(sc), nbits, kbps); > +#endif /* ALEA_DEBUG */ > +bail: > + if (xfer) > + usbd_free_xfer(xfer); > + timeout_add_msec(&sc->sc_tout, ALEA_MSECS); > +} > + > +void > +ualea_intr(void *arg) > +{ > + struct ualea_softc *sc = arg; > + > + usb_add_task(sc->sc_udev, &sc->sc_task); > +} -- [email protected] | http://trac.haqistan.net/~attila keyid E6CC1EDB | 4D91 1B98 A210 1D71 2A0E AC29 9677 D0A6 E6CC 1EDB
