/* * trng_extractor.c * ---------------- * This program extracts raw data from the avalanche_entropy, rosc_entropy, * and csprng cores. * * Author: Paul Selkirk * Copyright (c) 2015, NORDUnet A/S All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the NORDUnet nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "tc_eim.h" #include "cryptech_memory_map.h" char *usage = "%s [-a|r|c] [-n #] [-o file]\n\ \n\ -a avalanche entropy\n\ -r rosc entropy\n\ -c csprng (default data source)\n\ -n number of 4-byte samples (scale with K, M, or G suffix)\n\ -o output file (defaults to stdout)\n\ "; int debug = 0; /* for dump() */ // Check availability of avalanche entropy core by reading core name and version. uint32_t avalanche_check(void) { uint8_t name0[4] = "extn"; uint8_t name1[4] = "oise"; uint8_t version[4] = "0.10"; printf("Reading name and version words from avalanche_entropy core.\n"); return tc_expected(ENTROPY1_ADDR_NAME0, name0, 4) || tc_expected(ENTROPY1_ADDR_NAME1, name1, 4) || tc_expected(ENTROPY1_ADDR_VERSION, version, 4); } // check availability of rosc core by reading the core name and version. uint32_t rosc_check(void) { uint8_t name0[4] = "rosc"; uint8_t name1[4] = " ent"; uint8_t version[4] = "0.10"; printf("Reading name and version words from rosc_entropy core.\n"); return tc_expected(ENTROPY2_ADDR_NAME0, name0, 4) || tc_expected(ENTROPY2_ADDR_NAME1, name1, 4) || tc_expected(ENTROPY2_ADDR_VERSION, version, 4); } // Check availability of trng by reading core name and version. uint32_t trng_check(void) { // uint8_t name0[4] = "extn"; // uint8_t name1[4] = "oise"; // uint8_t version[4] = "0.10"; // // if (!quiet) // printf("TC2: Reading name and version words from avalanche_entropy core.\n"); // // return // tc_expected(ENTROPY1_ADDR_NAME0, name0, 4) || // tc_expected(ENTROPY1_ADDR_NAME1, name1, 4) || // tc_expected(ENTROPY1_ADDR_VERSION, version, 4); return (uint32_t) 0; } /* extract one data sample */ static int extract(off_t status_addr, off_t data_addr, uint32_t *data) { if (tc_wait(status_addr, ENTROPY1_STATUS_VALID, NULL) != 0) { fprintf(stderr, "tc_wait failed\n"); return 1; } if (tc_read(data_addr, (uint8_t *)data, 4) != 0) { fprintf(stderr, "tc_read failed\n"); return 1; } return 0; } /* main */ int main(int argc, char *argv[]) { int i, opt; unsigned long num_words = 1; char *endptr; off_t status_addr = CSPRNG_ADDR_STATUS; off_t data_addr = CSPRNG_ADDR_RANDOM; FILE *output = stdout; uint32_t data; /* parse command line */ while ((opt = getopt(argc, argv, "h?arcn:o:")) != -1) { switch (opt) { case 'h': case '?': printf(usage, argv[0]); return EXIT_SUCCESS; case 'a': status_addr = ENTROPY1_ADDR_STATUS; data_addr = ENTROPY1_ADDR_ENTROPY; break; case 'r': status_addr = ENTROPY2_ADDR_STATUS; data_addr = ENTROPY2_ADDR_ENTROPY; break; case 'c': status_addr = CSPRNG_ADDR_STATUS; data_addr = CSPRNG_ADDR_RANDOM; break; case 'n': num_words = strtoul(optarg, &endptr, 10); switch (toupper(*endptr)) { case '\0': break; case 'K': num_words *= 1000; break; case 'M': num_words *= 1000000; break; case 'G': num_words *= 1000000000; break; default: fprintf(stderr, "unsupported -n suffix %s\n", endptr); return EXIT_FAILURE; } break; case 'o': output = fopen(optarg, "wb+"); if (output == NULL) { fprintf(stderr, "error opening output file %s: ", optarg); perror(""); return EXIT_FAILURE; } break; default: errout: fprintf(stderr, usage, argv[0]); return EXIT_FAILURE; } } if (optind < argc) { fprintf(stderr, "%s: invalid argument%s --", argv[0], argc - optind > 1 ? "s" : ""); do { fprintf(stderr, " %s", argv[optind]); ++optind; } while (optind < argc); fprintf(stderr, "\n"); goto errout; } /* get the data */ for (i = 0; i < num_words; ++i) { if (extract(status_addr, data_addr, &data) != 0) return EXIT_FAILURE; if (fwrite(&data, sizeof(data), 1, output) != 1) { perror("fwrite"); fclose(output); return EXIT_FAILURE; } } fclose(output); return EXIT_SUCCESS; }