From 9e821d21b1a6462b6d6fad288599e76eaa273603 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 14 Oct 2017 12:15:35 +0200 Subject: Simplify makefile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- .gitignore | 3 +- Makefile | 149 +++++---------- common.c | 526 +++++++++++++++++++++++++++++++++++++++++++++++++++ common.h | 48 +++++ config.mk | 15 ++ keccak-224sum.c | 11 ++ keccak-256sum.c | 11 ++ keccak-384sum.c | 11 ++ keccak-512sum.c | 11 ++ keccaksum.c | 10 + rawshake256sum.c | 11 ++ rawshake512sum.c | 11 ++ sha3-224sum.c | 11 ++ sha3-256sum.c | 11 ++ sha3-384sum.c | 11 ++ sha3-512sum.c | 11 ++ shake256sum.c | 11 ++ shake512sum.c | 11 ++ src/common.c | 526 --------------------------------------------------- src/common.h | 48 ----- src/keccak-224sum.c | 11 -- src/keccak-256sum.c | 11 -- src/keccak-384sum.c | 11 -- src/keccak-512sum.c | 11 -- src/keccaksum.c | 10 - src/rawshake256sum.c | 11 -- src/rawshake512sum.c | 11 -- src/sha3-224sum.c | 11 -- src/sha3-256sum.c | 11 -- src/sha3-384sum.c | 11 -- src/sha3-512sum.c | 11 -- src/shake256sum.c | 11 -- src/shake512sum.c | 11 -- 33 files changed, 776 insertions(+), 823 deletions(-) create mode 100644 common.c create mode 100644 common.h create mode 100644 config.mk create mode 100644 keccak-224sum.c create mode 100644 keccak-256sum.c create mode 100644 keccak-384sum.c create mode 100644 keccak-512sum.c create mode 100644 keccaksum.c create mode 100644 rawshake256sum.c create mode 100644 rawshake512sum.c create mode 100644 sha3-224sum.c create mode 100644 sha3-256sum.c create mode 100644 sha3-384sum.c create mode 100644 sha3-512sum.c create mode 100644 shake256sum.c create mode 100644 shake512sum.c delete mode 100644 src/common.c delete mode 100644 src/common.h delete mode 100644 src/keccak-224sum.c delete mode 100644 src/keccak-256sum.c delete mode 100644 src/keccak-384sum.c delete mode 100644 src/keccak-512sum.c delete mode 100644 src/keccaksum.c delete mode 100644 src/rawshake256sum.c delete mode 100644 src/rawshake512sum.c delete mode 100644 src/sha3-224sum.c delete mode 100644 src/sha3-256sum.c delete mode 100644 src/sha3-384sum.c delete mode 100644 src/sha3-512sum.c delete mode 100644 src/shake256sum.c delete mode 100644 src/shake512sum.c diff --git a/.gitignore b/.gitignore index 46c1b9f..575cf5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -obj/ -bin/ *~ *\#* *.o @@ -10,3 +8,4 @@ bin/ *.gch *.1 !/xsum.1 +/*sum diff --git a/Makefile b/Makefile index 5590bd0..007ad42 100644 --- a/Makefile +++ b/Makefile @@ -1,36 +1,26 @@ .NONPOSIX: -PREFIX = /usr/local -BINDIR = $(PREFIX)/bin -DATADIR = $(PREFIX)/share -DOCDIR = $(DATADIR)/doc -MANDIR = $(DATADIR)/man -INFODIR = $(DATADIR)/info -LICENSEDIR = $(DATADIR)/licenses - -PKGNAME = sha3sum - -WARN = -Wall -Wextra -pedantic -Wdouble-promotion -Wformat=2 -Winit-self -Wmissing-include-dirs \ - -Wtrampolines -Wfloat-equal -Wshadow -Wmissing-prototypes -Wmissing-declarations \ - -Wredundant-decls -Wnested-externs -Winline -Wno-variadic-macros -Wswitch-default \ - -Wpadded -Wsync-nand -Wunsafe-loop-optimizations -Wcast-align -Wstrict-overflow \ - -Wdeclaration-after-statement -Wundef -Wbad-function-cast -Wcast-qual -Wlogical-op \ - -Wstrict-prototypes -Wold-style-definition -Wpacked -Wvector-operation-performance \ - -Wunsuffixed-float-constants -Wsuggest-attribute=const -Wsuggest-attribute=noreturn \ - -Wsuggest-attribute=pure -Wsuggest-attribute=format -Wnormalized=nfkc - -LDOPTIMISE = -COPTIMISE = -O3 - -FLAGS = $(WARN) -std=gnu99 - - -KECCAK_CMDS = keccak-224sum keccak-256sum keccak-384sum keccak-512sum keccaksum -SHA3_CMDS = sha3-224sum sha3-256sum sha3-384sum sha3-512sum -RAWSHAKE_CMDS = rawshake256sum rawshake512sum -SHAKE_CMDS = shake256sum shake512sum - -CMDS = $(KECCAK_CMDS) $(SHA3_CMDS) $(RAWSHAKE_CMDS) $(SHAKE_CMDS) +CONFIGFILE = config.mk +include $(CONFIGFILE) + + +BIN =\ + keccaksum\ + keccak-224sum\ + keccak-256sum\ + keccak-384sum\ + keccak-512sum\ + sha3-224sum\ + sha3-256sum\ + sha3-384sum\ + sha3-512sum\ + rawshake256sum\ + rawshake512sum\ + shake256sum\ + shake512sum + +MAN1 = $(BIN:=.1) +HDR = common.h keccak-224sum = Keccak-224 keccak-256sum = Keccak-256 @@ -47,86 +37,35 @@ shake256sum = SHAKE256 shake512sum = SHAKE512 -MAN1 =\ - keccaksum.1\ - keccak-224sum.1\ - keccak-256sum.1\ - keccak-384sum.1\ - keccak-512sum.1\ - sha3-224sum.1\ - sha3-256sum.1\ - sha3-384sum.1\ - sha3-512sum.1\ - rawshake256sum.1\ - rawshake512sum.1\ - shake256sum.1\ - shake512sum.1 +all: $(BIN) $(MAN1) +%: %.o common.o + $(CC) -o $@ $^ $(LDFLAGS) - -.PHONY: all -all: command $(MAN1) - - -.PHONY: command -command: $(foreach C,$(CMDS),bin/$(C)) - -bin/%: obj/%.o obj/common.o - @mkdir -p bin - $(CC) $(FLAGS) $(LDOPTIMISE) -o $@ $^ $(LDFLAGS) -lkeccak -largparser - -obj/%.o: src/%.c src/*.h - @mkdir -p obj - $(CC) $(FLAGS) $(COPTIMISE) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) - +%.o: %.c $(HDR) + $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) %.1: xsum.1 - u=$$(printf '%s\n' $* | tr a-z A-Z); sed -e 's/xsum/$*/g' -e 's/XSUM/'"$$u"'/g' -e 's/Xsum/$($*)/g' < xsum.1 > $@ - + u=$$(printf '%s\n' $* | tr a-z A-Z); \ + sed -e 's/xsum/$*/g' -e 's/XSUM/'"$$u"'/g' -e 's/Xsum/$($*)/g' < xsum.1 > $@ -.PHONY: install -install: install-command install-license install-man +install: + mkdir -p -- "$(DESTDIR)$(PREFIX)/bin" + mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man1" + mkdir -p -- "$(DESTDIR)$(PREFIX)/share/licenses/sha3sum" + cp -- $(BIN) "$(DESTDIR)$(PREFIX)/bin/" + cp -- $(MAN1) "$(DESTDIR)$(MANPREFIX)/man1/" + cp -- LICENSE "$(DESTDIR)$(PREFIX)/share/licenses/sha3sum/" -.PHONY: install-command -install-command: install-keccak install-sha3 install-rawshake install-shake - -.PHONY: install-keccak -install-keccak: $(foreach C,$(KECCAK_CMDS),install-$(C)) - -.PHONY: install-sha3 -install-sha3: $(foreach C,$(SHA3_CMDS),install-$(C)) - -.PHONY: install-rawshake -install-rawshake: $(foreach C,$(RAWSHAKE_CMDS),install-$(C)) - -.PHONY: install-shake -install-shake: $(foreach C,$(SHAKE_CMDS),install-$(C)) - -.PHONY: install-%sum -install-%sum: bin/%sum - install -dm755 -- "$(DESTDIR)$(BINDIR)" - install -m755 -- $< "$(DESTDIR)$(BINDIR)/$*sum" - -.PHONY: install-license -install-license: - install -dm755 -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" - install -m644 -- LICENSE "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/LICENSE" - -.PHONY: install-man -install-man: $(MAN1) - mkdir -p -- "$(DESTDIR)$(MANDIR)/man1" - cp -- $(MAN1) "$(DESTDIR)$(MANDIR)/man1/" - - - -.PHONY: uninstall uninstall: - -rm -- $(foreach C,$(CMDS),"$(DESTDIR)$(BINDIR)/$(C)") - -rm -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/LICENSE" - -rmdir -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" - -cd -- "$(DESTDIR)$(MANDIR)/man1" && rm -- $(MAN1) + -cd -- "$(DESTDIR)$(PREFIX)/bin" && rm -- $(BIN) + -cd -- "$(DESTDIR)$(MANPREFIX)/man1" && rm -- $(MAN1) + -rm -- "$(DESTDIR)$(PREFIX)/share/licenses/sha3sum/LICENSE" + -rmdir -- "$(DESTDIR)$(PREFIX)/share/licenses/sha3sum" - -.PHONY: clean clean: - -rm -r -- bin obj $(MAN1) + -rm -r -- $(MAN1) $(BIN) + +.SUFFIXES: + +.PHONY: all install uninstall clean diff --git a/common.c b/common.c new file mode 100644 index 0000000..580ca72 --- /dev/null +++ b/common.c @@ -0,0 +1,526 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#ifndef STDIN_PATH +# ifndef DEVDIR +# define DEVDIR "/dev" +# endif +# define STDIN_PATH DEVDIR"/stdin" +#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]) + + + +/** + * Storage for binary hash + */ +static char *restrict hashsum = NULL; + +/** + * Storage for hexadecimal hash + */ +static char *restrict hexsum = NULL; + +/** + * Storage for binary version of expected checksum + */ +#define correct_binary hexsum + +/** + * Whether a mismatch has been found or if a file was missing + */ +static int bad_found = 0; + +/** + * `argv[0]` from `main` + */ +static char *execname; + + + +/** + * Calculate a Keccak-family hashsum of a file, + * the content of the file is assumed non-sensitive + * + * @param fd The file descriptor of the file to hash + * @param state The hashing state, should not be initialised (memory leak otherwise) + * @param spec Specifications for the hashing algorithm + * @param suffix The data suffix, see `libkeccak_digest` + * @param hash Output array for the hashsum, have an allocation size of + * at least `(spec->output / 8) * sizeof(char)`, may be `NULL` + * @return Zero on success, -1 on error + */ +static int +generalised_sum_fd_hex(int fd, libkeccak_state_t *restrict state, + const libkeccak_spec_t *restrict spec, + const char *restrict suffix, char *restrict hash) +{ + ssize_t got; + struct stat attr; + size_t blksize = 4096, r_ptr = 0, w_ptr = 0; + char *restrict chunk; + char even = 1, buf = 0, c; + + if (libkeccak_state_initialise(state, spec) < 0) + return -1; + + if (fstat(fd, &attr) == 0) + if (attr.st_blksize > 0) + blksize = (size_t)(attr.st_blksize); + + chunk = alloca(blksize); + + for (;;) { + got = read(fd, chunk, blksize); + if (got < 0) return -1; + if (!got) break; + while (r_ptr < (size_t)got) { + if (c = chunk[r_ptr++], c <= ' ') + continue; + buf = (buf << 4) | ((c & 15) + (c > '9' ? 9 : 0)); + if ((even ^= 1)) + chunk[w_ptr++] = buf; + } + if (libkeccak_fast_update(state, chunk, w_ptr) < 0) + return -1; + } + + return libkeccak_fast_digest(state, NULL, 0, 0, suffix, hash); +} + + +/** + * 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; +} + + +/** + * Calculate the checksum of a file and store it in the global variable `hashsum` + * + * @param filename The file to hash + * @param spec Hashing parameters + * @param squeezes The number of squeezes to perform + * @param suffix The message suffix + * @param hex Whether to use hexadecimal input rather than binary + * @return Zero on success, an appropriate exit value on error + */ +static int +hash(const char *restrict filename, const libkeccak_spec_t *restrict spec, + long squeezes, const char *restrict suffix, int hex) +{ + libkeccak_state_t state; + size_t length; + int r, fd; + + length = (size_t)((spec->output + 7) / 8); + + if (!hashsum && (hashsum = malloc(length * sizeof(char)), !hashsum)) + return perror(execname), 2; + + if (!hexsum && (hexsum = malloc((length * 2 + 1) * sizeof(char)), !hexsum)) + return perror(execname), 2; + + if (fd = open(strcmp(filename, "-") ? filename : STDIN_PATH, O_RDONLY), fd < 0) + return r = (errno != ENOENT), perror(execname), r + 1; + + if ((hex == 0 ? libkeccak_generalised_sum_fd : generalised_sum_fd_hex) + (fd, &state, spec, suffix, squeezes > 1 ? NULL : hashsum)) + return perror(execname), close(fd), libkeccak_state_fast_destroy(&state), 2; + close(fd); + + if (squeezes > 2) libkeccak_fast_squeeze(&state, squeezes - 2); + if (squeezes > 1) libkeccak_squeeze(&state, hashsum); + libkeccak_state_fast_destroy(&state); + + return 0; +} + + +/** + * Check that file has a reported checksum, `bad_found` will be + * updated if the file is missing or incorrect + * + * @param spec Hashing parameters + * @param squeezes The number of squeezes to perform + * @param suffix The message suffix + * @param hex Whether to use hexadecimal input rather than binary + * @param filename The file to check + * @param correct_hash The expected checksum (any form of hexadecimal) + * @return Zero on success, an appropriate exit value on error + */ +static int +check(const libkeccak_spec_t *restrict spec, long squeezes, const char *restrict suffix, + int hex, const char *restrict filename, const char *restrict correct_hash) +{ + size_t length = (size_t)((spec->output + 7) / 8); + int r; + + if (access(filename, F_OK)) { + bad_found = 1; + printf("%s: %s\n", filename, "Missing"); + return 0; + } + + if ((r = hash(filename, spec, squeezes, suffix, hex))) + return r; + + libkeccak_unhex(correct_binary, correct_hash); + if ((r = memcmp(correct_binary, hashsum, length))) + bad_found = 1; + printf("%s: %s\n", filename, !r ? "OK" : "Fail"); + + return 0; +} + + +/** + * Check checksums from a file + * + * @param filename The file to hash + * @param spec Hashing parameters + * @param squeezes The number of squeezes to perform + * @param suffix The message suffix + * @param representation (unused) + * @param hex Whether to use hexadecimal input rather than binary + * @return Zero on success, an appropriate exit value on error + */ +static int +check_checksums(const char *restrict filename, const libkeccak_spec_t *restrict spec, + long squeezes, const char *restrict suffix, int representation, int hex) +{ + struct stat attr; + size_t blksize = 4096; + size_t size = 4096; + size_t ptr = 0; + ssize_t got; + char *buf = NULL; + char *new; + int fd = -1, rc = 2, stage, r; + size_t hash_start = 0, hash_end = 0; + size_t file_start = 0, file_end = 0; + char *hash; + char *file; + size_t hash_n; + char c; + + if (fd = open(strcmp(filename, "-") ? filename : STDIN_PATH, O_RDONLY), fd < 0) + goto pfail; + + if (fstat(fd, &attr) == 0) { + if (attr.st_blksize > 0) blksize = (size_t)(attr.st_blksize); + if (attr.st_size > 0) size = (size_t)(attr.st_size); + } + + size = size > blksize ? size : blksize; + if (buf = malloc(size), buf == NULL) + goto pfail; + + for (;;) { + if (ptr + blksize < size) { + if (new = realloc(buf, size <<= 1), new == NULL) + goto pfail; + buf = new; + } + + got = read(fd, buf + ptr, blksize); + if (got < 0) goto pfail; + else if (got == 0) break; + else ptr += (size_t)got; + } + if (ptr == size) { + if (new = realloc(buf, size + 1), new == NULL) + goto pfail; + buf = new; + } + size = ptr; + close(fd), fd = -1; + buf[size++] = '\n'; + + for (ptr = 0, stage = 0; ptr < size; ptr++) { + c = buf[ptr]; + if (stage == 0) { + if (('0' <= c) && (c <= '9')); + else if (('a' <= c) && (c <= 'f')); + else if (('A' <= c) && (c <= 'F')); + else if ((c == ' ') || (c == '\t')) { + hash_end = ptr, stage++; + } else if ((c == '\n') || (c == '\f') || (c == '\r')) { + hash_end = ptr, stage = 3; + } else { + rc = USER_ERROR("file is malformated"); + goto fail; + } + } else if (stage == 1) { + if ((c == '\n') || (c == '\f') || (c == '\r')) + stage = 3; + else if ((c != ' ') && (c != '\t')) + file_start = ptr, stage++; + } else if (stage == 2) { + if ((c == '\n') || (c == '\f') || (c == '\r')) + file_end = ptr, stage++; + } + + if (stage == 3) { + if ((hash_start == hash_end) != (file_start == file_end)) { + rc = USER_ERROR("file is malformated"); + goto fail; + } + if (hash_start != hash_end) { + hash = buf + hash_start; + file = buf + file_start; + hash_n = hash_end - hash_start; + buf[hash_end] = '\0'; + buf[file_end] = '\0'; + if (hash_n % 2) { + rc = USER_ERROR("file is malformated"); + goto fail; + } + if (hash_n / 2 != (size_t)((spec->output + 7) / 8)) { + rc = USER_ERROR("algorithm parameter mismatch"); + goto fail; + } + if ((r = check(spec, squeezes, suffix, hex, file, hash))) { + rc = r; + goto fail; + } + } + stage = 0; + hash_start = hash_end = file_start = file_end = ptr + 1; + } + } + + if (stage) { + rc = USER_ERROR("file is malformated"); + goto fail; + } + + free(buf); + return 0; + +pfail: + perror(execname); +fail: + free(buf); + if (fd >= 0) + close(fd); + return rc; + + (void) representation; +} + + +/** + * Print the checksum of a file + * + * @param filename The file to hash + * @param spec Hashing parameters + * @param squeezes The number of squeezes to perform + * @param suffix The message suffix + * @param representation Either of `REPRESENTATION_BINARY`, `REPRESENTATION_UPPER_CASE` + * and `REPRESENTATION_LOWER_CASE` + * @param hex Whether to use hexadecimal input rather than binary + * @return Zero on success, an appropriate exit value on error + */ +static int +print_checksum(const char *restrict filename, const libkeccak_spec_t *restrict spec, + long squeezes, const char *restrict suffix, int representation, int hex) +{ + size_t length = (size_t)((spec->output + 7) / 8); + int r; + size_t ptr = 0; + ssize_t wrote; + + if ((r = hash(filename, spec, squeezes, suffix, hex))) + return r; + + if (representation == REPRESENTATION_UPPER_CASE) { + libkeccak_behex_upper(hexsum, hashsum, length); + printf("%s %s\n", hexsum, filename); + } else if (representation == REPRESENTATION_LOWER_CASE) { + libkeccak_behex_lower(hexsum, hashsum, length); + printf("%s %s\n", hexsum, filename); + } else { + fflush(stdout); + while (length - ptr) { + wrote = write(STDOUT_FILENO, hashsum, length - ptr); + if (wrote <= 0) + return perror(execname), 2; + ptr += (size_t)wrote; + } + } + + return 0; +} + + +/** + * Cleanup allocations + */ +static inline void +cleanup(void) +{ + free(hashsum), hashsum = NULL; + free(hexsum), hexsum = NULL; +} + + +/** + * Parse the command line and calculate the hashes of the selected files + * + * @param argc The first argument from `main` + * @param argv The second argument from `main` + * @param gspec The default algorithm parameters + * @param suffix Message suffix + * @return An appropriate exit value + */ +int +run(int argc, char *argv[], libkeccak_generalised_spec_t *restrict gspec, const char *restrict suffix) +{ + int r, verbose = 0, presentation = REPRESENTATION_UPPER_CASE, hex = 0, check = 0; + long squeezes = 1; + size_t i; + libkeccak_spec_t spec; + int (*fun)(const char *restrict filename, const libkeccak_spec_t *restrict spec, + long squeezes, const char *restrict suffix, int representation, int hex); + + execname = *argv; + + 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("COUNT", "Select squeeze count", "-Z", "--squeezes"); + ADD(NULL, "Use upper-case output", "-u", "--upper", "--uppercase", "--upper-case"); + ADD(NULL, "Use lower-case output", "-l", "--lower", "--lowercase", "--lower-case"); + ADD(NULL, "Use binary output", "-b", "--binary"); + ADD(NULL, "Use hexadecimal input", "-x", "--hex", "--hex-input"); + ADD(NULL, "Check checksums", "-c", "--check"); + ADD(NULL, "Be verbose", "-v", "--verbose"); + /* --check has been added because the sha1sum, sha256sum &c have it, + * but I ignore the other crap, mostly because not all implemention + * have them and binary vs text mode is stupid. */ + + 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("-Z")) squeezes = atol(LAST("-Z")); + if (args_opts_used("-u")) presentation = REPRESENTATION_UPPER_CASE; + if (args_opts_used("-l")) presentation = REPRESENTATION_LOWER_CASE; + if (args_opts_used("-b")) presentation = REPRESENTATION_BINARY; + if (args_opts_used("-x")) hex = 1; + if (args_opts_used("-c")) check = 1; + if (args_opts_used("-v")) verbose = 1; + + fun = check ? check_checksums : print_checksum; + + if ((r = make_spec(gspec, &spec))) + goto done; + + if (squeezes <= 0) { + r = USER_ERROR("the squeeze count most be positive"); + goto done; + } + + if (verbose) { + fprintf(stderr, "rate: %li\n", gspec->bitrate); + fprintf(stderr, "capacity: %li\n", gspec->capacity); + fprintf(stderr, "output size: %li\n", gspec->output); + fprintf(stderr, "state size: %li\n", gspec->state_size); + fprintf(stderr, "word size: %li\n", gspec->word_size); + fprintf(stderr, "squeezes: %li\n", squeezes); + fprintf(stderr, "suffix: %s\n", suffix ? suffix : ""); + } + + if (args_files_count == 0) { + r = fun("-", &spec, squeezes, suffix, presentation, hex); + } else { + for (i = 0; i < (size_t)args_files_count; i++) + if ((r = fun(args_files[i], &spec, squeezes, suffix, presentation, hex))) + break; + } + +done: + args_dispose(); + cleanup(); + return r ? r : bad_found; +} + diff --git a/common.h b/common.h new file mode 100644 index 0000000..e3182dc --- /dev/null +++ b/common.h @@ -0,0 +1,48 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#define libkeccak_spec_keccak libkeccak_spec_sha3 +#define LIBKECCAK_KECCAK_SUFFIX "" + + +/** + * Wrapper for `run` that also initialises the command line parser + * + * @param algo The name of the hashing algorithm, must be a string literal + * @param prog The name of program, must be a string literal + * @param suffix The message suffix + */ +#define RUN(algo, prog, suffix)\ + (args_init(algo " checksum calculator",\ + prog " [options...] [--] [files...]", NULL,\ + NULL, 1, 0, args_standard_abbreviations),\ + run(argc, argv, &spec, suffix)) + + +/** + * Print the checksum in binary + */ +#define REPRESENTATION_BINARY 0 + +/** + * Print the checksum in upper case hexadecimal + */ +#define REPRESENTATION_UPPER_CASE 1 + +/** + * Print the checksum in lower case hexadecimal + */ +#define REPRESENTATION_LOWER_CASE 2 + + +/** + * Parse the command line and calculate the hashes of the selected files + * + * @param argc The first argument from `main` + * @param argv The second argument from `main` + * @param gspec The default algorithm parameters + * @param suffix Message suffix + * @return An appropriate exit value + */ +int run(int argc, char *argv[], libkeccak_generalised_spec_t *restrict gspec, const char *restrict suffix); diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..e581aee --- /dev/null +++ b/config.mk @@ -0,0 +1,15 @@ +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +WARN = -pedantic -Wdouble-promotion -Wformat=2 -Winit-self -Wmissing-include-dirs \ + -Wtrampolines -Wfloat-equal -Wshadow -Wmissing-prototypes -Wmissing-declarations \ + -Wredundant-decls -Wnested-externs -Winline -Wno-variadic-macros -Wswitch-default \ + -Wpadded -Wsync-nand -Wunsafe-loop-optimizations -Wcast-align -Wstrict-overflow \ + -Wdeclaration-after-statement -Wundef -Wbad-function-cast -Wcast-qual -Wlogical-op \ + -Wstrict-prototypes -Wold-style-definition -Wpacked -Wvector-operation-performance \ + -Wunsuffixed-float-constants -Wsuggest-attribute=const -Wsuggest-attribute=noreturn \ + -Wsuggest-attribute=pure -Wsuggest-attribute=format -Wnormalized=nfkc + +CFLAGS = -std=c99 -Wall -Wextra $(WARN) -O3 +CPPFLAGS = +LDFLAGS = -s -lkeccak -largparser diff --git a/keccak-224sum.c b/keccak-224sum.c new file mode 100644 index 0000000..f7d3095 --- /dev/null +++ b/keccak-224sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_keccak((libkeccak_spec_t *)&spec, 224); + return RUN("Keccak", "keccak-224sum", LIBKECCAK_KECCAK_SUFFIX); +} diff --git a/keccak-256sum.c b/keccak-256sum.c new file mode 100644 index 0000000..f4f78ac --- /dev/null +++ b/keccak-256sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_keccak((libkeccak_spec_t *)&spec, 256); + return RUN("Keccak", "keccak-256sum", LIBKECCAK_KECCAK_SUFFIX); +} diff --git a/keccak-384sum.c b/keccak-384sum.c new file mode 100644 index 0000000..3a6e3a0 --- /dev/null +++ b/keccak-384sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_keccak((libkeccak_spec_t *)&spec, 384); + return RUN("Keccak", "keccak-384sum", LIBKECCAK_KECCAK_SUFFIX); +} diff --git a/keccak-512sum.c b/keccak-512sum.c new file mode 100644 index 0000000..6ba1041 --- /dev/null +++ b/keccak-512sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_keccak((libkeccak_spec_t *)&spec, 512); + return RUN("Keccak", "keccak-512sum", LIBKECCAK_KECCAK_SUFFIX); +} diff --git a/keccaksum.c b/keccaksum.c new file mode 100644 index 0000000..8fc10a8 --- /dev/null +++ b/keccaksum.c @@ -0,0 +1,10 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + return RUN("Keccak", "keccaksum", LIBKECCAK_KECCAK_SUFFIX); +} diff --git a/rawshake256sum.c b/rawshake256sum.c new file mode 100644 index 0000000..6d6e19a --- /dev/null +++ b/rawshake256sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_rawshake((libkeccak_spec_t *)&spec, 256, 256); + return RUN("RawSHAKE", "rawshake256sum", LIBKECCAK_RAWSHAKE_SUFFIX); +} diff --git a/rawshake512sum.c b/rawshake512sum.c new file mode 100644 index 0000000..be1d8ac --- /dev/null +++ b/rawshake512sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_rawshake((libkeccak_spec_t *)&spec, 512, 512); + return RUN("RawSHAKE", "rawshake512sum", LIBKECCAK_RAWSHAKE_SUFFIX); +} diff --git a/sha3-224sum.c b/sha3-224sum.c new file mode 100644 index 0000000..15fac82 --- /dev/null +++ b/sha3-224sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_sha3((libkeccak_spec_t *)&spec, 224); + return RUN("SHA-3", "sha3-224sum", LIBKECCAK_SHA3_SUFFIX); +} diff --git a/sha3-256sum.c b/sha3-256sum.c new file mode 100644 index 0000000..2273785 --- /dev/null +++ b/sha3-256sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_sha3((libkeccak_spec_t *)&spec, 256); + return RUN("SHA-3", "sha3-256sum", LIBKECCAK_SHA3_SUFFIX); +} diff --git a/sha3-384sum.c b/sha3-384sum.c new file mode 100644 index 0000000..2c18df7 --- /dev/null +++ b/sha3-384sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_sha3((libkeccak_spec_t *)&spec, 384); + return RUN("SHA-3", "sha3-384sum", LIBKECCAK_SHA3_SUFFIX); +} diff --git a/sha3-512sum.c b/sha3-512sum.c new file mode 100644 index 0000000..a5b40e3 --- /dev/null +++ b/sha3-512sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_sha3((libkeccak_spec_t *)&spec, 512); + return RUN("SHA-3", "sha3-512sum", LIBKECCAK_SHA3_SUFFIX); +} diff --git a/shake256sum.c b/shake256sum.c new file mode 100644 index 0000000..7ab6cc6 --- /dev/null +++ b/shake256sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_shake((libkeccak_spec_t *)&spec, 256, 256); + return RUN("SHAKE", "shake256sum", LIBKECCAK_SHAKE_SUFFIX); +} diff --git a/shake512sum.c b/shake512sum.c new file mode 100644 index 0000000..3e24ddb --- /dev/null +++ b/shake512sum.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +main(int argc, char *argv[]) +{ + libkeccak_generalised_spec_t spec; + libkeccak_generalised_spec_initialise(&spec); + libkeccak_spec_shake((libkeccak_spec_t *)&spec, 512, 512); + return RUN("SHAKE", "shake512sum", LIBKECCAK_SHAKE_SUFFIX); +} diff --git a/src/common.c b/src/common.c deleted file mode 100644 index 580ca72..0000000 --- a/src/common.c +++ /dev/null @@ -1,526 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -#ifndef STDIN_PATH -# ifndef DEVDIR -# define DEVDIR "/dev" -# endif -# define STDIN_PATH DEVDIR"/stdin" -#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]) - - - -/** - * Storage for binary hash - */ -static char *restrict hashsum = NULL; - -/** - * Storage for hexadecimal hash - */ -static char *restrict hexsum = NULL; - -/** - * Storage for binary version of expected checksum - */ -#define correct_binary hexsum - -/** - * Whether a mismatch has been found or if a file was missing - */ -static int bad_found = 0; - -/** - * `argv[0]` from `main` - */ -static char *execname; - - - -/** - * Calculate a Keccak-family hashsum of a file, - * the content of the file is assumed non-sensitive - * - * @param fd The file descriptor of the file to hash - * @param state The hashing state, should not be initialised (memory leak otherwise) - * @param spec Specifications for the hashing algorithm - * @param suffix The data suffix, see `libkeccak_digest` - * @param hash Output array for the hashsum, have an allocation size of - * at least `(spec->output / 8) * sizeof(char)`, may be `NULL` - * @return Zero on success, -1 on error - */ -static int -generalised_sum_fd_hex(int fd, libkeccak_state_t *restrict state, - const libkeccak_spec_t *restrict spec, - const char *restrict suffix, char *restrict hash) -{ - ssize_t got; - struct stat attr; - size_t blksize = 4096, r_ptr = 0, w_ptr = 0; - char *restrict chunk; - char even = 1, buf = 0, c; - - if (libkeccak_state_initialise(state, spec) < 0) - return -1; - - if (fstat(fd, &attr) == 0) - if (attr.st_blksize > 0) - blksize = (size_t)(attr.st_blksize); - - chunk = alloca(blksize); - - for (;;) { - got = read(fd, chunk, blksize); - if (got < 0) return -1; - if (!got) break; - while (r_ptr < (size_t)got) { - if (c = chunk[r_ptr++], c <= ' ') - continue; - buf = (buf << 4) | ((c & 15) + (c > '9' ? 9 : 0)); - if ((even ^= 1)) - chunk[w_ptr++] = buf; - } - if (libkeccak_fast_update(state, chunk, w_ptr) < 0) - return -1; - } - - return libkeccak_fast_digest(state, NULL, 0, 0, suffix, hash); -} - - -/** - * 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; -} - - -/** - * Calculate the checksum of a file and store it in the global variable `hashsum` - * - * @param filename The file to hash - * @param spec Hashing parameters - * @param squeezes The number of squeezes to perform - * @param suffix The message suffix - * @param hex Whether to use hexadecimal input rather than binary - * @return Zero on success, an appropriate exit value on error - */ -static int -hash(const char *restrict filename, const libkeccak_spec_t *restrict spec, - long squeezes, const char *restrict suffix, int hex) -{ - libkeccak_state_t state; - size_t length; - int r, fd; - - length = (size_t)((spec->output + 7) / 8); - - if (!hashsum && (hashsum = malloc(length * sizeof(char)), !hashsum)) - return perror(execname), 2; - - if (!hexsum && (hexsum = malloc((length * 2 + 1) * sizeof(char)), !hexsum)) - return perror(execname), 2; - - if (fd = open(strcmp(filename, "-") ? filename : STDIN_PATH, O_RDONLY), fd < 0) - return r = (errno != ENOENT), perror(execname), r + 1; - - if ((hex == 0 ? libkeccak_generalised_sum_fd : generalised_sum_fd_hex) - (fd, &state, spec, suffix, squeezes > 1 ? NULL : hashsum)) - return perror(execname), close(fd), libkeccak_state_fast_destroy(&state), 2; - close(fd); - - if (squeezes > 2) libkeccak_fast_squeeze(&state, squeezes - 2); - if (squeezes > 1) libkeccak_squeeze(&state, hashsum); - libkeccak_state_fast_destroy(&state); - - return 0; -} - - -/** - * Check that file has a reported checksum, `bad_found` will be - * updated if the file is missing or incorrect - * - * @param spec Hashing parameters - * @param squeezes The number of squeezes to perform - * @param suffix The message suffix - * @param hex Whether to use hexadecimal input rather than binary - * @param filename The file to check - * @param correct_hash The expected checksum (any form of hexadecimal) - * @return Zero on success, an appropriate exit value on error - */ -static int -check(const libkeccak_spec_t *restrict spec, long squeezes, const char *restrict suffix, - int hex, const char *restrict filename, const char *restrict correct_hash) -{ - size_t length = (size_t)((spec->output + 7) / 8); - int r; - - if (access(filename, F_OK)) { - bad_found = 1; - printf("%s: %s\n", filename, "Missing"); - return 0; - } - - if ((r = hash(filename, spec, squeezes, suffix, hex))) - return r; - - libkeccak_unhex(correct_binary, correct_hash); - if ((r = memcmp(correct_binary, hashsum, length))) - bad_found = 1; - printf("%s: %s\n", filename, !r ? "OK" : "Fail"); - - return 0; -} - - -/** - * Check checksums from a file - * - * @param filename The file to hash - * @param spec Hashing parameters - * @param squeezes The number of squeezes to perform - * @param suffix The message suffix - * @param representation (unused) - * @param hex Whether to use hexadecimal input rather than binary - * @return Zero on success, an appropriate exit value on error - */ -static int -check_checksums(const char *restrict filename, const libkeccak_spec_t *restrict spec, - long squeezes, const char *restrict suffix, int representation, int hex) -{ - struct stat attr; - size_t blksize = 4096; - size_t size = 4096; - size_t ptr = 0; - ssize_t got; - char *buf = NULL; - char *new; - int fd = -1, rc = 2, stage, r; - size_t hash_start = 0, hash_end = 0; - size_t file_start = 0, file_end = 0; - char *hash; - char *file; - size_t hash_n; - char c; - - if (fd = open(strcmp(filename, "-") ? filename : STDIN_PATH, O_RDONLY), fd < 0) - goto pfail; - - if (fstat(fd, &attr) == 0) { - if (attr.st_blksize > 0) blksize = (size_t)(attr.st_blksize); - if (attr.st_size > 0) size = (size_t)(attr.st_size); - } - - size = size > blksize ? size : blksize; - if (buf = malloc(size), buf == NULL) - goto pfail; - - for (;;) { - if (ptr + blksize < size) { - if (new = realloc(buf, size <<= 1), new == NULL) - goto pfail; - buf = new; - } - - got = read(fd, buf + ptr, blksize); - if (got < 0) goto pfail; - else if (got == 0) break; - else ptr += (size_t)got; - } - if (ptr == size) { - if (new = realloc(buf, size + 1), new == NULL) - goto pfail; - buf = new; - } - size = ptr; - close(fd), fd = -1; - buf[size++] = '\n'; - - for (ptr = 0, stage = 0; ptr < size; ptr++) { - c = buf[ptr]; - if (stage == 0) { - if (('0' <= c) && (c <= '9')); - else if (('a' <= c) && (c <= 'f')); - else if (('A' <= c) && (c <= 'F')); - else if ((c == ' ') || (c == '\t')) { - hash_end = ptr, stage++; - } else if ((c == '\n') || (c == '\f') || (c == '\r')) { - hash_end = ptr, stage = 3; - } else { - rc = USER_ERROR("file is malformated"); - goto fail; - } - } else if (stage == 1) { - if ((c == '\n') || (c == '\f') || (c == '\r')) - stage = 3; - else if ((c != ' ') && (c != '\t')) - file_start = ptr, stage++; - } else if (stage == 2) { - if ((c == '\n') || (c == '\f') || (c == '\r')) - file_end = ptr, stage++; - } - - if (stage == 3) { - if ((hash_start == hash_end) != (file_start == file_end)) { - rc = USER_ERROR("file is malformated"); - goto fail; - } - if (hash_start != hash_end) { - hash = buf + hash_start; - file = buf + file_start; - hash_n = hash_end - hash_start; - buf[hash_end] = '\0'; - buf[file_end] = '\0'; - if (hash_n % 2) { - rc = USER_ERROR("file is malformated"); - goto fail; - } - if (hash_n / 2 != (size_t)((spec->output + 7) / 8)) { - rc = USER_ERROR("algorithm parameter mismatch"); - goto fail; - } - if ((r = check(spec, squeezes, suffix, hex, file, hash))) { - rc = r; - goto fail; - } - } - stage = 0; - hash_start = hash_end = file_start = file_end = ptr + 1; - } - } - - if (stage) { - rc = USER_ERROR("file is malformated"); - goto fail; - } - - free(buf); - return 0; - -pfail: - perror(execname); -fail: - free(buf); - if (fd >= 0) - close(fd); - return rc; - - (void) representation; -} - - -/** - * Print the checksum of a file - * - * @param filename The file to hash - * @param spec Hashing parameters - * @param squeezes The number of squeezes to perform - * @param suffix The message suffix - * @param representation Either of `REPRESENTATION_BINARY`, `REPRESENTATION_UPPER_CASE` - * and `REPRESENTATION_LOWER_CASE` - * @param hex Whether to use hexadecimal input rather than binary - * @return Zero on success, an appropriate exit value on error - */ -static int -print_checksum(const char *restrict filename, const libkeccak_spec_t *restrict spec, - long squeezes, const char *restrict suffix, int representation, int hex) -{ - size_t length = (size_t)((spec->output + 7) / 8); - int r; - size_t ptr = 0; - ssize_t wrote; - - if ((r = hash(filename, spec, squeezes, suffix, hex))) - return r; - - if (representation == REPRESENTATION_UPPER_CASE) { - libkeccak_behex_upper(hexsum, hashsum, length); - printf("%s %s\n", hexsum, filename); - } else if (representation == REPRESENTATION_LOWER_CASE) { - libkeccak_behex_lower(hexsum, hashsum, length); - printf("%s %s\n", hexsum, filename); - } else { - fflush(stdout); - while (length - ptr) { - wrote = write(STDOUT_FILENO, hashsum, length - ptr); - if (wrote <= 0) - return perror(execname), 2; - ptr += (size_t)wrote; - } - } - - return 0; -} - - -/** - * Cleanup allocations - */ -static inline void -cleanup(void) -{ - free(hashsum), hashsum = NULL; - free(hexsum), hexsum = NULL; -} - - -/** - * Parse the command line and calculate the hashes of the selected files - * - * @param argc The first argument from `main` - * @param argv The second argument from `main` - * @param gspec The default algorithm parameters - * @param suffix Message suffix - * @return An appropriate exit value - */ -int -run(int argc, char *argv[], libkeccak_generalised_spec_t *restrict gspec, const char *restrict suffix) -{ - int r, verbose = 0, presentation = REPRESENTATION_UPPER_CASE, hex = 0, check = 0; - long squeezes = 1; - size_t i; - libkeccak_spec_t spec; - int (*fun)(const char *restrict filename, const libkeccak_spec_t *restrict spec, - long squeezes, const char *restrict suffix, int representation, int hex); - - execname = *argv; - - 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("COUNT", "Select squeeze count", "-Z", "--squeezes"); - ADD(NULL, "Use upper-case output", "-u", "--upper", "--uppercase", "--upper-case"); - ADD(NULL, "Use lower-case output", "-l", "--lower", "--lowercase", "--lower-case"); - ADD(NULL, "Use binary output", "-b", "--binary"); - ADD(NULL, "Use hexadecimal input", "-x", "--hex", "--hex-input"); - ADD(NULL, "Check checksums", "-c", "--check"); - ADD(NULL, "Be verbose", "-v", "--verbose"); - /* --check has been added because the sha1sum, sha256sum &c have it, - * but I ignore the other crap, mostly because not all implemention - * have them and binary vs text mode is stupid. */ - - 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("-Z")) squeezes = atol(LAST("-Z")); - if (args_opts_used("-u")) presentation = REPRESENTATION_UPPER_CASE; - if (args_opts_used("-l")) presentation = REPRESENTATION_LOWER_CASE; - if (args_opts_used("-b")) presentation = REPRESENTATION_BINARY; - if (args_opts_used("-x")) hex = 1; - if (args_opts_used("-c")) check = 1; - if (args_opts_used("-v")) verbose = 1; - - fun = check ? check_checksums : print_checksum; - - if ((r = make_spec(gspec, &spec))) - goto done; - - if (squeezes <= 0) { - r = USER_ERROR("the squeeze count most be positive"); - goto done; - } - - if (verbose) { - fprintf(stderr, "rate: %li\n", gspec->bitrate); - fprintf(stderr, "capacity: %li\n", gspec->capacity); - fprintf(stderr, "output size: %li\n", gspec->output); - fprintf(stderr, "state size: %li\n", gspec->state_size); - fprintf(stderr, "word size: %li\n", gspec->word_size); - fprintf(stderr, "squeezes: %li\n", squeezes); - fprintf(stderr, "suffix: %s\n", suffix ? suffix : ""); - } - - if (args_files_count == 0) { - r = fun("-", &spec, squeezes, suffix, presentation, hex); - } else { - for (i = 0; i < (size_t)args_files_count; i++) - if ((r = fun(args_files[i], &spec, squeezes, suffix, presentation, hex))) - break; - } - -done: - args_dispose(); - cleanup(); - return r ? r : bad_found; -} - diff --git a/src/common.h b/src/common.h deleted file mode 100644 index e3182dc..0000000 --- a/src/common.h +++ /dev/null @@ -1,48 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#define libkeccak_spec_keccak libkeccak_spec_sha3 -#define LIBKECCAK_KECCAK_SUFFIX "" - - -/** - * Wrapper for `run` that also initialises the command line parser - * - * @param algo The name of the hashing algorithm, must be a string literal - * @param prog The name of program, must be a string literal - * @param suffix The message suffix - */ -#define RUN(algo, prog, suffix)\ - (args_init(algo " checksum calculator",\ - prog " [options...] [--] [files...]", NULL,\ - NULL, 1, 0, args_standard_abbreviations),\ - run(argc, argv, &spec, suffix)) - - -/** - * Print the checksum in binary - */ -#define REPRESENTATION_BINARY 0 - -/** - * Print the checksum in upper case hexadecimal - */ -#define REPRESENTATION_UPPER_CASE 1 - -/** - * Print the checksum in lower case hexadecimal - */ -#define REPRESENTATION_LOWER_CASE 2 - - -/** - * Parse the command line and calculate the hashes of the selected files - * - * @param argc The first argument from `main` - * @param argv The second argument from `main` - * @param gspec The default algorithm parameters - * @param suffix Message suffix - * @return An appropriate exit value - */ -int run(int argc, char *argv[], libkeccak_generalised_spec_t *restrict gspec, const char *restrict suffix); diff --git a/src/keccak-224sum.c b/src/keccak-224sum.c deleted file mode 100644 index f7d3095..0000000 --- a/src/keccak-224sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_keccak((libkeccak_spec_t *)&spec, 224); - return RUN("Keccak", "keccak-224sum", LIBKECCAK_KECCAK_SUFFIX); -} diff --git a/src/keccak-256sum.c b/src/keccak-256sum.c deleted file mode 100644 index f4f78ac..0000000 --- a/src/keccak-256sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_keccak((libkeccak_spec_t *)&spec, 256); - return RUN("Keccak", "keccak-256sum", LIBKECCAK_KECCAK_SUFFIX); -} diff --git a/src/keccak-384sum.c b/src/keccak-384sum.c deleted file mode 100644 index 3a6e3a0..0000000 --- a/src/keccak-384sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_keccak((libkeccak_spec_t *)&spec, 384); - return RUN("Keccak", "keccak-384sum", LIBKECCAK_KECCAK_SUFFIX); -} diff --git a/src/keccak-512sum.c b/src/keccak-512sum.c deleted file mode 100644 index 6ba1041..0000000 --- a/src/keccak-512sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_keccak((libkeccak_spec_t *)&spec, 512); - return RUN("Keccak", "keccak-512sum", LIBKECCAK_KECCAK_SUFFIX); -} diff --git a/src/keccaksum.c b/src/keccaksum.c deleted file mode 100644 index 8fc10a8..0000000 --- a/src/keccaksum.c +++ /dev/null @@ -1,10 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - return RUN("Keccak", "keccaksum", LIBKECCAK_KECCAK_SUFFIX); -} diff --git a/src/rawshake256sum.c b/src/rawshake256sum.c deleted file mode 100644 index 6d6e19a..0000000 --- a/src/rawshake256sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_rawshake((libkeccak_spec_t *)&spec, 256, 256); - return RUN("RawSHAKE", "rawshake256sum", LIBKECCAK_RAWSHAKE_SUFFIX); -} diff --git a/src/rawshake512sum.c b/src/rawshake512sum.c deleted file mode 100644 index be1d8ac..0000000 --- a/src/rawshake512sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_rawshake((libkeccak_spec_t *)&spec, 512, 512); - return RUN("RawSHAKE", "rawshake512sum", LIBKECCAK_RAWSHAKE_SUFFIX); -} diff --git a/src/sha3-224sum.c b/src/sha3-224sum.c deleted file mode 100644 index 15fac82..0000000 --- a/src/sha3-224sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_sha3((libkeccak_spec_t *)&spec, 224); - return RUN("SHA-3", "sha3-224sum", LIBKECCAK_SHA3_SUFFIX); -} diff --git a/src/sha3-256sum.c b/src/sha3-256sum.c deleted file mode 100644 index 2273785..0000000 --- a/src/sha3-256sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_sha3((libkeccak_spec_t *)&spec, 256); - return RUN("SHA-3", "sha3-256sum", LIBKECCAK_SHA3_SUFFIX); -} diff --git a/src/sha3-384sum.c b/src/sha3-384sum.c deleted file mode 100644 index 2c18df7..0000000 --- a/src/sha3-384sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_sha3((libkeccak_spec_t *)&spec, 384); - return RUN("SHA-3", "sha3-384sum", LIBKECCAK_SHA3_SUFFIX); -} diff --git a/src/sha3-512sum.c b/src/sha3-512sum.c deleted file mode 100644 index a5b40e3..0000000 --- a/src/sha3-512sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_sha3((libkeccak_spec_t *)&spec, 512); - return RUN("SHA-3", "sha3-512sum", LIBKECCAK_SHA3_SUFFIX); -} diff --git a/src/shake256sum.c b/src/shake256sum.c deleted file mode 100644 index 7ab6cc6..0000000 --- a/src/shake256sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_shake((libkeccak_spec_t *)&spec, 256, 256); - return RUN("SHAKE", "shake256sum", LIBKECCAK_SHAKE_SUFFIX); -} diff --git a/src/shake512sum.c b/src/shake512sum.c deleted file mode 100644 index 3e24ddb..0000000 --- a/src/shake512sum.c +++ /dev/null @@ -1,11 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -int -main(int argc, char *argv[]) -{ - libkeccak_generalised_spec_t spec; - libkeccak_generalised_spec_initialise(&spec); - libkeccak_spec_shake((libkeccak_spec_t *)&spec, 512, 512); - return RUN("SHAKE", "shake512sum", LIBKECCAK_SHAKE_SUFFIX); -} -- cgit v1.2.3-70-g09d2