pax_global_header00006660000000000000000000000064134147654120014521gustar00rootroot0000000000000052 comment=6cc8424aa8e67cc1e26c91bf8451d52fb5c76b49 chaosread-1.1/000077500000000000000000000000001341476541200133135ustar00rootroot00000000000000chaosread-1.1/Makefile.am000066400000000000000000000002331341476541200153450ustar00rootroot00000000000000bin_PROGRAMS=chaosread AM_CFLAGS=$(LIBUSB_CFLAGS) $(WARN_CFLAGS) chaosread_LDADD=$(LIBUSB_LIBS) chaosread_SOURCES = chaosread.c man_MANS = chaosread.1 chaosread-1.1/autogen.sh000066400000000000000000000002621341476541200153110ustar00rootroot00000000000000#! /bin/sh srcdir=`dirname $0` test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` cd $srcdir autoreconf --force -v --install || exit 1 cd $ORIGDIR || exit $? $srcdir/configure "$@" chaosread-1.1/chaosread.1000066400000000000000000000037271341476541200153370ustar00rootroot00000000000000.\" .\" Copyright © 2016 Keith Packard .\" .\" This program is free software; you can redistribute it and/or modify .\" it under the terms of the GNU General Public License as published by .\" the Free Software Foundation; either version 2 of the License, or .\" (at your option) any later version. .\" .\" This program is distributed in the hope that it will be useful, but .\" WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU .\" General Public License for more details. .\" .\" You should have received a copy of the GNU General Public License along .\" with this program; if not, write to the Free Software Foundation, Inc., .\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. .\" .\" .TH CHAOSREAD 1 "chaosread" "" .SH NAME chaosread \- read raw noise source from chaoskey .SH SYNOPSIS .B "chaosread" .SH DESCRIPTION .I chaosread reads ADC values from the noise source on the attached ChaosKey device. .SH OPTIONS .TP \-s serial | --serial serial This selects a ChaosKey by serial number instead of using the first one found. .TP \-l length | --length length Set the amount of data to read. Suffixes 'k', 'M' and 'G' are supported. The default is 1k. .TP \-i | --infinite Keep reading forever (or until the process is killed). .TP \-b | --bytes Read 16-bits little endian values and write out one byte per sample from bits 1-8 of the sample (zero-based, so shift right by one). .TP \-b | --cooked Read values from the 'cooked' endpoint, which is the source used by the kernel driver that contains trimmed and whitened data which has 8 bits of entropy per byte. .TP \-b | --raw Read from the raw RNG source endpoint, which is best for testing the hardware on the device. This is the default .TP \-b | --firmware Read from the device firmware. This can be used to verify that the firmware in the device has the expected contents. .SH USAGE .I chaosread reads noise data. .SH AUTHOR Keith Packard chaosread-1.1/chaosread.c000066400000000000000000000156051341476541200154170ustar00rootroot00000000000000/* * Copyright © 2016 Keith Packard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include #include #include #include #include #include #include #include "config.h" #define CHAOS_SIZE 64 #define CHAOS_VENDOR 0x1d50 #define CHAOS_PRODUCT 0x60c6 struct chaoskey { libusb_context *ctx; libusb_device_handle *handle; int kernel_active; }; static libusb_device_handle * chaoskey_match(libusb_device *dev, char *match_serial) { struct libusb_device_descriptor desc; int ret; int match_len; char *device_serial = NULL; libusb_device_handle *handle = NULL; ret = libusb_get_device_descriptor(dev, &desc); if (ret < 0) { fprintf(stderr, "failed to get device descriptor: %s\n", libusb_strerror(ret)); return 0; } if (desc.idVendor != CHAOS_VENDOR) return NULL; if (desc.idProduct != CHAOS_PRODUCT) return NULL; ret = libusb_open(dev, &handle); if (match_serial == NULL) return handle; if (ret < 0) { fprintf(stderr, "failed to open device: %s\n", libusb_strerror(ret)); return NULL; } match_len = strlen(match_serial); device_serial = malloc(match_len + 2); if (!device_serial) { fprintf(stderr, "malloc failed\n"); goto out; } ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *) device_serial, match_len + 1); if (ret < 0) { fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret)); goto out; } device_serial[ret] = '\0'; ret = strcmp(device_serial, match_serial); free(device_serial); if (ret) goto out; return handle; out: if (handle) libusb_close(handle); return 0; } static struct chaoskey * chaoskey_open(char *serial) { struct chaoskey *ck; int ret; ssize_t num; libusb_device **list; int d; ck = calloc(sizeof (struct chaoskey), 1); if (!ck) goto out; ret = libusb_init(&ck->ctx); if (ret ) { fprintf(stderr, "libusb_init failed: %s\n", libusb_strerror(ret)); goto out; } num = libusb_get_device_list(ck->ctx, &list); if (num < 0) { fprintf(stderr, "libusb_get_device_list failed: %s\n", libusb_strerror(num)); goto out; } for (d = 0; d < num; d++) { libusb_device_handle *handle; handle = chaoskey_match(list[d], serial); if (handle) { ck->handle = handle; break; } } libusb_free_device_list(list, 1); if (!ck->handle) { if (serial) fprintf (stderr, "No chaoskey matching %s\n", serial); else fprintf (stderr, "No chaoskey\n"); goto out; } ck->kernel_active = libusb_kernel_driver_active(ck->handle, 0); if (ck->kernel_active) { ret = libusb_detach_kernel_driver(ck->handle, 0); if (ret) goto out; } ret = libusb_claim_interface(ck->handle, 0); if (ret) goto out; return ck; out: if (ck->kernel_active) libusb_attach_kernel_driver(ck->handle, 0); if (ck->handle) libusb_close(ck->handle); if (ck->ctx) libusb_exit(ck->ctx); free(ck); return NULL; } static void chaoskey_close(struct chaoskey *ck) { libusb_release_interface(ck->handle, 0); if (ck->kernel_active) libusb_attach_kernel_driver(ck->handle, 0); libusb_close(ck->handle); libusb_exit(ck->ctx); free(ck); } #define COOKED_ENDPOINT 0x85 #define RAW_ENDPOINT 0x86 #define FLASH_ENDPOINT 0x87 static int chaoskey_read(struct chaoskey *ck, int endpoint, void *buffer, int len) { uint8_t *buf = buffer; int total = 0; while (len) { int ret; int transferred; ret = libusb_bulk_transfer(ck->handle, endpoint, buf, len, &transferred, 10000); if (ret) { if (total) return total; else { errno = EIO; return -1; } } len -= transferred; buf += transferred; total += transferred; } return total; } static const struct option options[] = { { .name = "serial", .has_arg = 1, .val = 's' }, { .name = "length", .has_arg = 1, .val = 'l' }, { .name = "infinite", .has_arg = 0, .val = 'i' }, { .name = "bytes", .has_arg = 0, .val = 'b' }, { .name = "cooked", .has_arg = 0, .val = 'c' }, { .name = "raw", .has_arg = 0, .val = 'r' }, { .name = "flash", .has_arg = 0, .val = 'f' }, { .name = "version", .has_arg = 0, .val = 'V' }, { .name = "help", .has_arg = 0, .val = '?' }, { 0, 0, 0, 0}, }; static void usage(char *program, int code) { fprintf(stderr, "usage: %s [--serial=] [--length=[kMG]] [--infinite] [--bytes] [--cooked] [--raw] [--flash] [ --version] [--help]\n", program); exit(code); } static void finish(struct chaoskey *ck, int code) { chaoskey_close(ck); exit(code); } int main (int argc, char **argv) { struct chaoskey *ck; uint16_t buf[512]; int got; int c; char *serial = NULL; char *length_string; char *length_end; unsigned long length = sizeof(buf); int this_time; int infinite = 0; int bytes = 0; int endpoint = RAW_ENDPOINT; while ((c = getopt_long(argc, argv, "s:l:ibcrfV?", options, NULL)) != -1) { switch (c) { case 's': serial = optarg; break; case 'l': length_string = optarg; length = strtoul(length_string, &length_end, 10); if (!strcasecmp(length_end, "k")) length *= 1024; else if (!strcasecmp(length_end, "m")) length *= 1024 * 1024; else if (!strcasecmp(length_end, "g")) length *= 1024 * 1024 * 1024; else if (strlen(length_end)) usage(argv[0], 1); break; case 'i': infinite = 1; break; case 'b': bytes = 1; break; case 'c': endpoint = COOKED_ENDPOINT; break; case 'r': endpoint = RAW_ENDPOINT; break; case 'f': endpoint = FLASH_ENDPOINT; break; case 'V': printf("%s %s (%s)\n", PACKAGE, VERSION, RELEASE_DATE); exit(0); case '?': usage(argv[0], 0); break; default: usage(argv[0], 1); break; } } ck = chaoskey_open(serial); if (!ck) exit(1); if (bytes) length *= 2; while (length || infinite) { this_time = sizeof(buf); if (!infinite && length < sizeof(buf)) this_time = (int) length; got = chaoskey_read(ck, endpoint, buf, this_time); if (got < 0) { perror("read"); finish(ck, 1); } if (bytes) { int i; for (i = 0; i < got / 2; i++) putchar((buf[i] >> 1 & 0xff)); } else { int i; int ret; for (i = 0; i < got; i += ret) { ret = write(1, ((char *) buf) + i, got - i); if (ret <= 0) { perror("write"); finish(ck, 1); } } } length -= got; } finish(ck, 0); } chaosread-1.1/configure.ac000066400000000000000000000025101341476541200155770ustar00rootroot00000000000000dnl dnl Copyright © 2017 Keith Packard dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License along dnl with this program; if not, write to the Free Software Foundation, Inc., dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) AC_INIT([chaosread], 1.1) AC_CONFIG_SRCDIR([chaosread.c]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) RELEASE_DATE=2019-01-07 AC_CONFIG_HEADERS(config.h) AC_DEFINE_UNQUOTED(RELEASE_DATE, "$RELEASE_DATE", [Release date]) AC_PROG_CC AC_PROG_INSTALL PKG_PROG_PKG_CONFIG WARN_CFLAGS="-Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs" AC_SUBST(WARN_CFLAGS) PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) AC_OUTPUT([ Makefile])