diff options
Diffstat (limited to 'src/krandom.c')
-rw-r--r-- | src/krandom.c | 218 |
1 files changed, 0 insertions, 218 deletions
diff --git a/src/krandom.c b/src/krandom.c deleted file mode 100644 index 54eca43..0000000 --- a/src/krandom.c +++ /dev/null @@ -1,218 +0,0 @@ -/** - * krandom – Keccak-based userspace pseudorandom number generator - * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#include <stdio.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <alloca.h> - -#include <libkeccak.h> -#include <argparser.h> - - - -#ifndef URANDOM -# ifndef DEVDIR -# define DEVDIR "/dev" -# endif -# define URANDOM DEVDIR "/urandom" -#endif - - - -#define USER_ERROR(string) \ - (fprintf(stderr, "%s: %s.\n", execname, string), 1) - -#define ADD(arg, desc, ...) \ - (arg ? args_add_option(args_new_argumented(NULL, arg, 0, __VA_ARGS__, NULL), desc) \ - : args_add_option(args_new_argumentless(NULL, 0, __VA_ARGS__, NULL), desc)) - -#define LAST(arg) \ - (args_opts_get(arg)[args_opts_get_count(arg) - 1]) - - - -/** - * `argv[0]` from `main` - */ -static char* execname; - - -/** - * Convert `libkeccak_generalised_spec_t` to `libkeccak_spec_t` and check for errors - * - * @param gspec See `libkeccak_degeneralise_spec` - * @param spec See `libkeccak_degeneralise_spec` - * @return Zero on success, an appropriate exit value on error - */ -static int make_spec(libkeccak_generalised_spec_t* restrict gspec, libkeccak_spec_t* restrict spec) -{ - int r; - -#define TEST(CASE, STR) case LIBKECCAK_GENERALISED_SPEC_ERROR_##CASE: return USER_ERROR(STR) - if (r = libkeccak_degeneralise_spec(gspec, spec), r) - switch (r) - { - TEST (STATE_NONPOSITIVE, "the state size must be positive"); - TEST (STATE_TOO_LARGE, "the state size is too large, may not exceed 1600"); - TEST (STATE_MOD_25, "the state size must be a multiple of 25"); - TEST (WORD_NONPOSITIVE, "the word size must be positive"); - TEST (WORD_TOO_LARGE, "the word size is too large, may not exceed 64"); - TEST (STATE_WORD_INCOHERENCY, "the state size must be exactly 25 times the word size"); - TEST (CAPACITY_NONPOSITIVE, "the capacity must be positive"); - TEST (CAPACITY_MOD_8, "the capacity must be a multiple of 8"); - TEST (BITRATE_NONPOSITIVE, "the rate must be positive"); - TEST (BITRATE_MOD_8, "the rate must be a multiple of 8"); - TEST (OUTPUT_NONPOSITIVE, "the output size must be positive"); - default: - return USER_ERROR("unknown error in algorithm parameters"); - } -#undef TEST - -#define TEST(CASE, STR) case LIBKECCAK_SPEC_ERROR_##CASE: return USER_ERROR(STR) - if (r = libkeccak_spec_check(spec), r) - switch (r) - { - TEST (BITRATE_NONPOSITIVE, "the rate size must be positive"); - TEST (BITRATE_MOD_8, "the rate must be a multiple of 8"); - TEST (CAPACITY_NONPOSITIVE, "the capacity must be positive"); - TEST (CAPACITY_MOD_8, "the capacity must be a multiple of 8"); - TEST (OUTPUT_NONPOSITIVE, "the output size must be positive"); - TEST (STATE_TOO_LARGE, "the state size is too large, may not exceed 1600"); - TEST (STATE_MOD_25, "the state size must be a multiple of 25"); - TEST (WORD_NON_2_POTENT, "the word size must be a power of 2"); - TEST (WORD_MOD_8, "the word size must be a multiple of 8"); - default: - return USER_ERROR("unknown error in algorithm parameters"); - } -#undef TEST - - return 0; -} - - - -/** - * Mane! - * - * @param argc The number of elements in `argv` - * @param argv Command line arguments - * @return Zero on and only on success - */ -int main(int argc, char** argv) -{ - char* restrict generated_random = NULL; - libkeccak_generalised_spec_t gspec; - libkeccak_spec_t spec; - libkeccak_state_t state; - size_t length, ptr; - ssize_t got; - int r, fd = -1, verbose = 0; - - execname = argc ? *argv : "krandom"; - - - memset(&state, 0, sizeof(libkeccak_state_t)); - libkeccak_generalised_spec_initialise(&gspec); - if (!argc) - goto skip_argv_parsing; - - args_init("Keccak-based userspace pseudorandom number generator", - "krandom [options...]", NULL, - NULL, 1, 0, args_standard_abbreviations); - - ADD(NULL, "Display option summary", "-h", "--help"); - ADD("RATE", "Select rate", "-R", "--bitrate", "--rate"); - ADD("CAPACITY", "Select capacity", "-C", "--capacity"); - ADD("SIZE", "Select output size", "-N", "-O", "--output-size", "--output"); - ADD("SIZE", "Select state size", "-S", "-B", "--state-size", "--state"); - ADD("SIZE", "Select word size", "-W", "--word-size", "--word"); - ADD(NULL, "Be verbose", "-v", "--verbose"); - - args_parse(argc, argv); - - if (args_opts_used("-h")) return args_help(0), args_dispose(), 0; - if (args_opts_used("-R")) gspec.bitrate = atol(LAST("-R")); - if (args_opts_used("-C")) gspec.capacity = atol(LAST("-C")); - if (args_opts_used("-N")) gspec.output = atol(LAST("-N")); - if (args_opts_used("-S")) gspec.state_size = atol(LAST("-S")); - if (args_opts_used("-W")) gspec.word_size = atol(LAST("-W")); - if (args_opts_used("-v")) verbose = 1; - - skip_argv_parsing: - if ((r = make_spec(&gspec, &spec))) - goto done; - - if (verbose) - { - fprintf(stderr, "%s: " "rate: %li\n", execname, gspec.bitrate); - fprintf(stderr, "%s: " "capacity: %li\n", execname, gspec.capacity); - fprintf(stderr, "%s: " "output size: %li\n", execname, gspec.output); - fprintf(stderr, "%s: " "state size: %li\n", execname, gspec.state_size); - fprintf(stderr, "%s: " "word size: %li\n", execname, gspec.word_size); - } - - libkeccak_state_initialise(&state, &spec); - - fd = open(URANDOM, O_RDONLY); - if (fd < 0) - goto fail; - for (ptr = 0, length = sizeof(state.S); ptr < length;) - { - got = read(fd, (char*)(state.S) + ptr, length - ptr); - if (got <= 0) - goto fail; - ptr += (size_t)got; - } - close(fd), fd = -1; - - length = (size_t)((spec.output + 7) / 8); - generated_random = malloc(length); - if (generated_random == NULL) - goto fail; - - for (;;) - { - libkeccak_squeeze(&state, generated_random); - got = write(STDOUT_FILENO, generated_random, length); - if (got >= 0) - continue; - if (errno == EPIPE) - break; - goto fail; - } - - - done: - if (fd >= 0) - close(fd); - if (argc) - args_dispose(); - free(generated_random); - libkeccak_state_fast_destroy(&state); - return r; - fail: - perror(execname); - r = 2; - goto done; -} - |