diff options
| author | Mattias Andrée <m@maandree.se> | 2026-02-22 14:14:28 +0100 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-02-22 14:14:28 +0100 |
| commit | f4a40c25b29c3b4db904ef66667d129b38b279d3 (patch) | |
| tree | 6ab6bb7c5757d267045940f81d21f7465ce05e4f | |
| parent | Update e-mail and urls (diff) | |
| download | autopasswd-f4a40c25b29c3b4db904ef66667d129b38b279d3.tar.gz autopasswd-f4a40c25b29c3b4db904ef66667d129b38b279d3.tar.bz2 autopasswd-f4a40c25b29c3b4db904ef66667d129b38b279d3.tar.xz | |
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to '')
| -rw-r--r-- | COPYING | 1 | ||||
| -rw-r--r-- | DEPENDENCIES | 2 | ||||
| -rw-r--r-- | Makefile | 57 | ||||
| -rw-r--r-- | README | 25 | ||||
| -rw-r--r-- | config.mk | 15 | ||||
| -rw-r--r-- | src/autopasswd.c | 660 |
6 files changed, 372 insertions, 388 deletions
@@ -14,4 +14,3 @@ 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/>. - diff --git a/DEPENDENCIES b/DEPENDENCIES index 56dda49..efa80a8 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -5,7 +5,6 @@ RUNTIME DEPENDENCIES: libkeccak https://codeberg.org/maandree/libkeccak libc - BUILD DEPENDENCIES: libpassphrase https://codeberg.org/maandree/libpassphrase @@ -15,4 +14,3 @@ BUILD DEPENDENCIES: gcc make coreutils - @@ -3,61 +3,32 @@ # notice and this notice are preserved. This file is offered as-is, # without any warranty. -PREFIX = /usr -BIN = /bin -BINDIR = $(PREFIX)$(BIN) -DATA = /share -DATADIR = $(PREFIX)$(DATA) -LICENSEDIR = $(DATADIR)/licenses +CONFIGFILE = config.mk +include $(CONFIGFILE) -PKGNAME = autopasswd -COMMAND = autopasswd - -OPTIMISE = -O3 - -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 \ - -Wsync-nand -Wunsafe-loop-optimizations -Wcast-align -Wstrict-overflow -Wundef \ - -Wbad-function-cast -Wcast-qual -Wpacked -Wlogical-op -Wstrict-prototypes -Wconversion \ - -Wold-style-definition -Wvector-operation-performance -Wunsuffixed-float-constants \ - -Wsuggest-attribute=const -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure \ - -Wsuggest-attribute=format -Wnormalized=nfkc -Wdeclaration-after-statement - -F_OPTS = -ftree-vrp -fstrict-aliasing -fipa-pure-const -fstack-usage -fstrict-overflow \ - -funsafe-loop-optimizations -fno-builtin - -FLAGS = $(OPTIMISE) -std=gnu99 $(F_OPTS) $(WARN) - - -.PHONY: all all: bin/autopasswd bin/autopasswd: obj/autopasswd.o @mkdir -p bin - $(CC) $(FLAGS) -lpassphrase -largparser -lkeccak -o $@ $^ $(LDFLAGS) + $(CC) -o $@ obj/autopasswd.o $(LDFLAGS) obj/%.o: src/%.c @mkdir -p obj - $(CC) $(FLAGS) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) - + $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) -.PHONY: install install: bin/autopasswd - install -dm755 -- "$(DESTDIR)$(BINDIR)" - install -m755 bin/autopasswd -- "$(DESTDIR)$(BINDIR)/$(COMMAND)" - install -dm755 -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" - install -m644 COPYING LICENSE -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" - + mkdir -p -- "$(DESTDIR)$(BINDIR)" + mkdir -p -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" + cp -- bin/autopasswd "$(DESTDIR)$(BINDIR)/$(COMMAND)" + cp -- COPYING LICENSE "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/" -.PHONY: uninstall uninstall: - -rm -- "$(DESTDIR)$(BINDIR)/$(COMMAND)" - -rm -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/COPYING" - -rm -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/LICENSE" + -rm -f -- "$(DESTDIR)$(BINDIR)/$(COMMAND)" + -rm -f -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/COPYING" + -rm -f -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/LICENSE" -rmdir -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" - -.PHONY: clean clean: - -rm -r bin obj + -rm -rf -- bin obj + +.PHONY: all install uninstall clean @@ -1,26 +1,25 @@ -autopasswd is command line program that deterministically +autopasswd is a command line program that deterministically generates a strong password based on your master password -and the service name your that ask it to generate a password -for. autopasswd will print the entered password with black +and the service name that asks it to generate a password. +autopasswd will print the generated password in black on black text so that it cannot be read visually. You can also choose to make the output readable by a program. To -make sure that you did not mistype your master passphrase +make sure that you did not mistype your master passphrase, a short Keccak hash of it will be echoed. autopasswd uses Keccak with fully configurable parameters to generate a password and performs 300000 sponge squeezes -by default. This number can be configured like the other -Keccak parameter, but you can also specify a bump level -that modifies it. A bump level is a number to you increase +by default. This number can be configured like other +Keccak parameters, but you can also specify a bump level +that modifies it. A bump level is a number you increase when you need to change your password for a service. I recommend that you use correctpony to generate your master passphrase. -autopasswd use libpassphrase to read your passphrase from -the terminal. This is library that can be personalised at +autopasswd uses libpassphrase to read your passphrase from +the terminal. This is a library that can be personalised at compile time and ensures that the passphrase is not stored -in memory in any other place that its return value. This -passphrase is wipe by autopasswd from memory as soon as -possible it autopasswd makes its best to ensure that the +in memory in any other place than its return value. This +passphrase is wiped by autopasswd from memory as soon as +possible. autopasswd does its best to ensure that the program cannot crash before it is wiped. - diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..856eeca --- /dev/null +++ b/config.mk @@ -0,0 +1,15 @@ +PREFIX = /usr +BIN = /bin +BINDIR = $(PREFIX)$(BIN) +DATA = /share +DATADIR = $(PREFIX)$(DATA) +LICENSEDIR = $(DATADIR)/licenses + +PKGNAME = autopasswd +COMMAND = autopasswd + +CC = c99 + +CPPFLAGS = +CFLAGS = +LDFLAGS = -lpassphrase -largparser -lkeccak diff --git a/src/autopasswd.c b/src/autopasswd.c index f03fa49..bf8ac76 100644 --- a/src/autopasswd.c +++ b/src/autopasswd.c @@ -1,5 +1,5 @@ /** - * autopasswd – Reproducable password generator + * autopasswd – Reproducible password generator * * Copyright © 2014 Mattias Andrée (m@maandree.se) * @@ -53,7 +53,7 @@ #define DEFAULT_SQUEEZES 300000 /** - * The number of addition squeezes to perform per bump level + * The number of additional squeezes to perform per bump level */ #define BUMP_LEVEL_MULTIPLIER 5000 @@ -88,26 +88,28 @@ -#define USER_ERROR(string) \ - (fprintf(stderr, "%s: %s.\n", execname, string), 1) +#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 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]) +#define LAST(arg)\ + (args_opts_get(arg)[args_opts_get_count(arg) - 1]) -#define t(expr) if ((r = (expr))) goto fail +#define t(expr)\ + do { if ((r = (expr))) goto fail; } while (0) -#define xfree(s) (free(s), s = NULL) +#define xfree(s)\ + (free(s), s = NULL) /** * `argv[0]` from `main` */ -static char* execname; +static char *execname; @@ -118,57 +120,58 @@ static char* execname; * @param spec See `libkeccak_degeneralise_spec` * @return Zero on success, an appropriate exit value on error */ -static int make_spec(libkeccak_generalised_spec_t* gspec, libkeccak_spec_t* spec) +static int +make_spec(libkeccak_generalised_spec_t *gspec, libkeccak_spec_t *spec) { - int r; + 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"); - } + if ((r = libkeccak_degeneralise_spec(gspec, spec))) { + 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"); - } + if ((r = libkeccak_spec_check(spec))) { + 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; + + return 0; } /** * Parse the command line arguments * - * @param argc The number of command line argumnets - * @param argv Command line argumnets + * @param argc The number of command line arguments + * @param argv Command line arguments * @param gspec Output parameter for the algorithm parameters, must already be initialised * @param squeezes Output parameter for the number of squeezes to perform, must already have default value * @param bump_level Output parameter for the bump level, must already be zero @@ -177,88 +180,88 @@ static int make_spec(libkeccak_generalised_spec_t* gspec, libkeccak_spec_t* spec * @return Zero on success, an appropriate exit value on error, however -1 if * the program should exit with value zero */ -static int parse_cmdline(int argc, char* argv[], libkeccak_generalised_spec_t* gspec, - long* squeezes, long* bump_level, int* clear_mode, int* verbose) +static int +parse_cmdline(int argc, char *argv[], libkeccak_generalised_spec_t *gspec, + long *squeezes, long *bump_level, int *clear_mode, int *verbose) { - args_init("Reproducable password generator", "autopasswd [options...]", - NULL, NULL, 1, 0, args_standard_abbreviations); - - ADD(NULL, "Display option summary", "-h", "-?", "--help"); - ADD(NULL, "Display copyright information", "+c", "--copyright", "--copying"); - ADD(NULL, "Display warranty disclaimer", "+w", "--warranty"); - ADD(NULL, "Display extra information", "-v", "--verbose"); - ADD(NULL, "Do not hide the output, but rather make it ease to pass into another program\n" - "Use twice to suppress terminal line break", "-c", "--clear-mode"); - ADD("LEVEL", "Select bump level, can contain + or - to perform accumulated adjustment", - "-b", "--bump-level"); - ADD("RATE", "Select rate parameter for Keccak sponge", "-R", "--bitrate", "--rate"); - ADD("CAPACITY", "Select capacity parameter for Keccak sponge", "-C", "--capacity"); - ADD("SIZE", "Select output parameter for Keccak sponge", "-N", "-O", "--output-size", "--output"); - ADD("SIZE", "Select state size parameter for Keccak sponge", "-S", "-B", "--state-size", "--state"); - ADD("SIZE", "Select word size parameter for Keccak sponge", "-W", "--word-size", "--word"); - ADD("COUNT", "Select the number squeezes performed on the Keccak sponge at bump level zero", - "-Z", "--squeezes"); - - args_parse(argc, argv); - - if (args_opts_used("-h")) return args_help(0), args_dispose(), -1; - if (args_opts_used("+c")) - { - printf("autopasswd – Reproducable password generator\n"); - printf("\n"); - printf("Copyright © 2014 Mattias Andrée (m@maandree.se)\n"); - printf("\n"); - printf("This program is free software: you can redistribute it and/or modify\n"); - printf("it under the terms of the GNU Affero General Public License as published by\n"); - printf("the Free Software Foundation, either version 3 of the License, or\n"); - printf("(at your option) any later version.\n"); - printf("\n"); - printf("This program is distributed in the hope that it will be useful,\n"); - printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); - printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); - printf("GNU Affero General Public License for more details.\n"); - printf("\n"); - printf("You should have received a copy of the GNU Affero General Public License\n"); - printf("along with this program. If not, see <http://www.gnu.org/licenses/>.\n"); - args_dispose(); - return -1; - } - if (args_opts_used("+w")) - { - printf("This program is distributed in the hope that it will be useful,\n"); - printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); - printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); - printf("GNU Affero General Public License for more details.\n"); - args_dispose(); - return -1; - } - - 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("-v")) *verbose = 1; - if (args_opts_used("-c")) *clear_mode = (int)args_opts_get_count("-c"); - if (args_opts_used("-b")) - { - size_t i, n = (size_t)args_opts_get_count("-b"); - char** arr = args_opts_get("-b"); - char* arg; - for (i = 0; i < n; i++) - if ((arg = arr[i])) - switch (*arg) - { - case 0: break; - case '+': *bump_level += atol(arg + 1); break; - case '-': *bump_level -= atol(arg + 1); break; - default: *bump_level = atol(arg); break; - } - } - - args_dispose(); - return 0; + args_init("Reproducible password generator", "autopasswd [options...]", + NULL, NULL, 1, 0, args_standard_abbreviations); + + ADD(NULL, "Display option summary", "-h", "-?", "--help"); + ADD(NULL, "Display copyright information", "+c", "--copyright", "--copying"); + ADD(NULL, "Display warranty disclaimer", "+w", "--warranty"); + ADD(NULL, "Display extra information", "-v", "--verbose"); + ADD(NULL, "Do not hide the output, but rather make it ease to pass into another program\n" + "Use twice to suppress terminal line break", "-c", "--clear-mode"); + ADD("LEVEL", "Select bump level, can contain + or - to perform accumulated adjustment", + "-b", "--bump-level"); + ADD("RATE", "Select rate parameter for Keccak sponge", "-R", "--bitrate", "--rate"); + ADD("CAPACITY", "Select capacity parameter for Keccak sponge", "-C", "--capacity"); + ADD("SIZE", "Select output parameter for Keccak sponge", "-N", "-O", "--output-size", "--output"); + ADD("SIZE", "Select state size parameter for Keccak sponge", "-S", "-B", "--state-size", "--state"); + ADD("SIZE", "Select word size parameter for Keccak sponge", "-W", "--word-size", "--word"); + ADD("COUNT", "Select the number squeezes performed on the Keccak sponge at bump level zero", + "-Z", "--squeezes"); + + args_parse(argc, argv); + + if (args_opts_used("-h")) + return args_help(0), args_dispose(), -1; + if (args_opts_used("+c")) { + printf("autopasswd – Reproducible password generator\n"); + printf("\n"); + printf("Copyright © 2014 Mattias Andrée (m@maandree.se)\n"); + printf("\n"); + printf("This program is free software: you can redistribute it and/or modify\n"); + printf("it under the terms of the GNU Affero General Public License as published by\n"); + printf("the Free Software Foundation, either version 3 of the License, or\n"); + printf("(at your option) any later version.\n"); + printf("\n"); + printf("This program is distributed in the hope that it will be useful,\n"); + printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); + printf("GNU Affero General Public License for more details.\n"); + printf("\n"); + printf("You should have received a copy of the GNU Affero General Public License\n"); + printf("along with this program. If not, see <http://www.gnu.org/licenses/>.\n"); + args_dispose(); + return -1; + } + if (args_opts_used("+w")) { + printf("This program is distributed in the hope that it will be useful,\n"); + printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); + printf("GNU Affero General Public License for more details.\n"); + args_dispose(); + return -1; + } + + 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("-v")) *verbose = 1; + if (args_opts_used("-c")) *clear_mode = (int)args_opts_get_count("-c"); + if (args_opts_used("-b")) { + size_t i, n = (size_t)args_opts_get_count("-b"); + char **arr = args_opts_get("-b"); + char *arg; + for (i = 0; i < n; i++) { + if ((arg = arr[i])) { + switch (*arg) { + case 0: break; + case '+': *bump_level += atol(arg + 1); break; + case '-': *bump_level -= atol(arg + 1); break; + default: *bump_level = atol(arg); break; + } + } + } + } + + args_dispose(); + return 0; } @@ -270,40 +273,42 @@ static int parse_cmdline(int argc, char* argv[], libkeccak_generalised_spec_t* g * @param passphrase The master passphrase * @return Zero on success, an appropriate exit value on error */ -static int hash_master_passphrase(const char* passphrase) +static int +hash_master_passphrase(const char *passphrase) { #define SQUEEZES MASTER_PASSPHRASE_KECCAK_SQUEEZES - libkeccak_spec_t spec; - libkeccak_state_t state; - char hashsum[MASTER_PASSPHRASE_KECCAK_OUTPUT / 8]; - char hexsum[MASTER_PASSPHRASE_KECCAK_OUTPUT / 4 + 1]; - - spec.bitrate = MASTER_PASSPHRASE_KECCAK_RATE; - spec.capacity = MASTER_PASSPHRASE_KECCAK_CAPACITY; - spec.output = MASTER_PASSPHRASE_KECCAK_OUTPUT; - - if (libkeccak_spec_check(&spec) || (SQUEEZES <= 0)) - return USER_ERROR("bad master passhprase hashing parameters, " - "please recompile autopasswd with with proper " - "values on MASTER_PASSPHRASE_KECCAK_RATE, " - "MASTER_PASSPHRASE_KECCAK_CAPACITY, " - "MASTER_PASSPHRASE_KECCAK_OUTPUT and " - "MASTER_PASSPHRASE_KECCAK_SQUEEZES"); - - if (libkeccak_state_initialise(&state, &spec)) - return perror(execname), 2; - - if (libkeccak_digest(&state, passphrase, strlen(passphrase), 0, NULL, SQUEEZES == 1 ? hashsum : NULL)) - return perror(execname), libkeccak_state_destroy(&state), 2; - if (SQUEEZES > 2) libkeccak_fast_squeeze(&state, SQUEEZES - 2); - if (SQUEEZES > 1) libkeccak_squeeze(&state, hashsum); - - libkeccak_state_destroy(&state); - - libkeccak_behex_lower(hexsum, hashsum, sizeof(hashsum) / sizeof(char)); - fprintf(stderr, "%s: master passphrase hash: %s\n", execname, hexsum); - - return 0; + libkeccak_spec_t spec; + libkeccak_state_t state; + char hashsum[MASTER_PASSPHRASE_KECCAK_OUTPUT / 8]; + char hexsum[MASTER_PASSPHRASE_KECCAK_OUTPUT / 4 + 1]; + + spec.bitrate = MASTER_PASSPHRASE_KECCAK_RATE; + spec.capacity = MASTER_PASSPHRASE_KECCAK_CAPACITY; + spec.output = MASTER_PASSPHRASE_KECCAK_OUTPUT; + + if (libkeccak_spec_check(&spec) || (SQUEEZES <= 0)) { + return USER_ERROR("bad master passphrase hashing parameters, " + "please recompile autopasswd with proper " + "values on MASTER_PASSPHRASE_KECCAK_RATE, " + "MASTER_PASSPHRASE_KECCAK_CAPACITY, " + "MASTER_PASSPHRASE_KECCAK_OUTPUT and " + "MASTER_PASSPHRASE_KECCAK_SQUEEZES"); + } + + if (libkeccak_state_initialise(&state, &spec)) + return perror(execname), 2; + + if (libkeccak_digest(&state, passphrase, strlen(passphrase), 0, NULL, SQUEEZES == 1 ? hashsum : NULL)) + return perror(execname), libkeccak_state_destroy(&state), 2; + if (SQUEEZES > 2) libkeccak_fast_squeeze(&state, SQUEEZES - 2); + if (SQUEEZES > 1) libkeccak_squeeze(&state, hashsum); + + libkeccak_state_destroy(&state); + + libkeccak_behex_lower(hexsum, hashsum, sizeof(hashsum) / sizeof(char)); + fprintf(stderr, "%s: master passphrase hash: %s\n", execname, hexsum); + + return 0; #undef SQUEEZES } @@ -314,41 +319,39 @@ static int hash_master_passphrase(const char* passphrase) * @param site Output parameter for the site * @return Zero on success, an appropriate exit value on error */ -static int get_site(char** site) +static int +get_site(char **site) { - size_t size = 64; - size_t ptr = 0; - char* buf = malloc(size * sizeof(char)); - if (buf == NULL) - return perror(execname), 2; - - fprintf(stderr, "%s", SITE_PROMPT_STRING); - fflush(stderr); - - for (;;) - { - int c = getchar(); - if (ptr == size) - { - char* new = realloc(buf, (size <<= 1) * sizeof(char)); - if (new == NULL) - return perror(execname), free(buf), 2; + size_t size = 64; + size_t ptr = 0; + char *buf = malloc(size * sizeof(char)); + if (!buf) + return perror(execname), 2; + + fprintf(stderr, "%s", SITE_PROMPT_STRING); + fflush(stderr); + + for (;;) { + int c = getchar(); + if (ptr == size) { + char *new = realloc(buf, (size <<= 1) * sizeof(char)); + if (!new) + return perror(execname), free(buf), 2; + } + if ((c < 0) || (c == '\n')) + break; + buf[ptr++] = (char)c; } - if ((c < 0) || (c == '\n')) - break; - buf[ptr++] = (char)c; - } - - if (ptr == size) - { - char* new = realloc(buf, (size += 1) * sizeof(char)); - if (new == NULL) - return perror(execname), free(buf), 2; - } - buf[ptr] = '\0'; - - *site = buf; - return 0; + + if (ptr == size) { + char *new = realloc(buf, (size += 1) * sizeof(char)); + if (!new) + return perror(execname), free(buf), 2; + } + buf[ptr] = '\0'; + + *site = buf; + return 0; } @@ -358,16 +361,17 @@ static int get_site(char** site) * @param passphrase Output parameter for the passphrase * @return Zero on success, an appropriate exit value on error */ -static int get_master_passphrase(char** passphrase) +static int +get_master_passphrase(char **passphrase) { - passphrase_disable_echo(); - fprintf(stderr, "%s", PASSPHRASE_PROMPT_STRING); - fflush(stderr); - *passphrase = passphrase_read(); - if (*passphrase == NULL) - perror(execname); - passphrase_reenable_echo(); - return *passphrase ? 0 : 2; + passphrase_disable_echo(); + fprintf(stderr, "%s", PASSPHRASE_PROMPT_STRING); + fflush(stderr); + *passphrase = passphrase_read(); + if (!*passphrase) + perror(execname); + passphrase_reenable_echo(); + return *passphrase ? 0 : 2; } @@ -381,33 +385,34 @@ static int get_master_passphrase(char** passphrase) * @param hash Output paramter for the raw password * @return Zero on success, an appropriate exit value on error */ -static int calculate_raw_password(const libkeccak_spec_t* spec, long squeezes, - const char* passphrase, const char* site, char** hash) +static int +calculate_raw_password(const libkeccak_spec_t *spec, long squeezes, + const char *passphrase, const char *site, char **hash) { - libkeccak_state_t state; - char* hashsum = NULL; - - if (libkeccak_state_initialise(&state, spec)) - return perror(execname), 2; - - if (hashsum = malloc((size_t)(spec->output / 8) * sizeof(char)), hashsum == NULL) - goto fail; - - if (libkeccak_update(&state, passphrase, strlen(passphrase))) - goto fail; - if (libkeccak_digest(&state, site, strlen(site), 0, NULL, squeezes == 1 ? hashsum : NULL)) - goto fail; - if (squeezes > 2) libkeccak_fast_squeeze(&state, squeezes - 2); - if (squeezes > 1) libkeccak_squeeze(&state, hashsum); - - libkeccak_state_destroy(&state); - *hash = hashsum; - return 0; - fail: - perror(execname); - free(hashsum); - libkeccak_state_destroy(&state); - return 2; + libkeccak_state_t state; + char *hashsum = NULL; + + if (libkeccak_state_initialise(&state, spec)) + return perror(execname), 2; + + if (hashsum = malloc((size_t)(spec->output / 8) * sizeof(char)), !hashsum) + goto fail; + + if (libkeccak_update(&state, passphrase, strlen(passphrase))) + goto fail; + if (libkeccak_digest(&state, site, strlen(site), 0, NULL, squeezes == 1 ? hashsum : NULL)) + goto fail; + if (squeezes > 2) libkeccak_fast_squeeze(&state, squeezes - 2); + if (squeezes > 1) libkeccak_squeeze(&state, hashsum); + + libkeccak_state_destroy(&state); + *hash = hashsum; + return 0; +fail: + perror(execname); + free(hashsum); + libkeccak_state_destroy(&state); + return 2; } @@ -419,111 +424,108 @@ static int calculate_raw_password(const libkeccak_spec_t* spec, long squeezes, * @param base64 Output parameter for the base64-encoded password * @return Zero on success, an appropriate exit value on error */ -static int encode_base64(const char* raw, size_t length, char** base64) +static int +encode_base64(const char *raw, size_t length, char **base64) { - size_t ptr, ptr64, out_length = ((length + 2) / 3) * 4 + 2; - char* buf = malloc(out_length * sizeof(char)); - - if (*base64 = buf, buf == NULL) - return perror(execname), 2; - - for (ptr = ptr64 = 0; ptr < length; ptr64 += 4) - { - uint8_t a = (uint8_t)(ptr < length ? raw[ptr++] : 0); - uint8_t b = (uint8_t)(ptr < length ? raw[ptr++] : 0); - uint8_t c = (uint8_t)(ptr < length ? raw[ptr++] : 0); - - uint32_t abc = ((uint32_t)a << 16) | ((uint32_t)b << 8) | ((uint32_t)c << 0); - - buf[ptr64 | 0] = BASE64[(abc >> (3 * 6)) & 63]; - buf[ptr64 | 1] = BASE64[(abc >> (2 * 6)) & 63]; - buf[ptr64 | 2] = BASE64[(abc >> (1 * 6)) & 63]; - buf[ptr64 | 3] = BASE64[(abc >> (0 * 6)) & 63]; - } - if (length % 3 == 1) buf[ptr64++] = BASE64[64]; - if (length % 3 == 2) buf[ptr64++] = BASE64[65]; - buf[ptr64++] = '\0'; - - return 0; + size_t ptr, ptr64, out_length = ((length + 2) / 3) * 4 + 2; + char *buf = malloc(out_length * sizeof(char)); + + if (*base64 = buf, !buf) + return perror(execname), 2; + + for (ptr = ptr64 = 0; ptr < length; ptr64 += 4) { + uint8_t a = (uint8_t)(ptr < length ? raw[ptr++] : 0); + uint8_t b = (uint8_t)(ptr < length ? raw[ptr++] : 0); + uint8_t c = (uint8_t)(ptr < length ? raw[ptr++] : 0); + + uint32_t abc = ((uint32_t)a << 16) | ((uint32_t)b << 8) | ((uint32_t)c << 0); + + buf[ptr64 | 0] = BASE64[(abc >> (3 * 6)) & 63]; + buf[ptr64 | 1] = BASE64[(abc >> (2 * 6)) & 63]; + buf[ptr64 | 2] = BASE64[(abc >> (1 * 6)) & 63]; + buf[ptr64 | 3] = BASE64[(abc >> (0 * 6)) & 63]; + } + if (length % 3 == 1) buf[ptr64++] = BASE64[64]; + if (length % 3 == 2) buf[ptr64++] = BASE64[65]; + buf[ptr64++] = '\0'; + + return 0; } /** * Here we go! * - * @param argc The number of command line argumnets - * @param argv Command line argumnets + * @param argc The number of command line arguments + * @param argv Command line arguments * @return Zero on success, 1 on user error, 2 on system error */ -int main(int argc, char* argv[]) +int +main(int argc, char *argv[]) { - int r, verbose = 0, clear_mode = 0; - libkeccak_generalised_spec_t gspec; - libkeccak_spec_t spec; - long squeezes = DEFAULT_SQUEEZES, bump_level = 0; - char* site = NULL; - char* passphrase = NULL; - char* raw_password = NULL; - char* base64 = NULL; - - libkeccak_generalised_spec_initialise(&gspec); - execname = *argv; - - t (parse_cmdline(argc, argv, &gspec, &squeezes, &bump_level, &clear_mode, &verbose)); - t (make_spec(&gspec, &spec)); - if (squeezes <= 0) - { - r = USER_ERROR("the squeeze count most be positive"); - goto fail; - } - - squeezes += bump_level * BUMP_LEVEL_MULTIPLIER; - - if (verbose) - { - fprintf(stderr, "bump level: %li\n", bump_level); - 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 after bump level: %li\n", squeezes); - fprintf(stderr, "squeezes before bump level: %li\n", - squeezes - bump_level * BUMP_LEVEL_MULTIPLIER); - } - - t (get_site(&site)); - t (get_master_passphrase(&passphrase)); - t (hash_master_passphrase(passphrase)); - - t (calculate_raw_password(&spec, squeezes, passphrase, site, &raw_password)); - passphrase_wipe(passphrase, strlen(passphrase)); - xfree(passphrase); - xfree(site); - - t (encode_base64(raw_password, (size_t)(spec.output / 8), &base64)); - xfree(raw_password); - - if (verbose) - { - fprintf(stderr, "password length before base64: %li\n", spec.output / 8); - fprintf(stderr, "password length after base64: %li\n", strlen(base64)); - } - - if (clear_mode > 1) printf("%s", base64); - else if (clear_mode) printf("%s\n", base64); - else printf("\033[00m>\033[08;30;40m%s\033[00m<\n", base64); - - free(base64); - return 0; - - fail: - if (passphrase) - passphrase_wipe(passphrase, strlen(passphrase)); - free(passphrase); - free(site); - free(raw_password); - free(base64); - return r < 0 ? 0 : r; -} + int r, verbose = 0, clear_mode = 0; + libkeccak_generalised_spec_t gspec; + libkeccak_spec_t spec; + long squeezes = DEFAULT_SQUEEZES, bump_level = 0; + char *site = NULL; + char *passphrase = NULL; + char *raw_password = NULL; + char *base64 = NULL; + + libkeccak_generalised_spec_initialise(&gspec); + execname = *argv; + + t (parse_cmdline(argc, argv, &gspec, &squeezes, &bump_level, &clear_mode, &verbose)); + t (make_spec(&gspec, &spec)); + if (squeezes <= 0) { + r = USER_ERROR("the squeeze count most be positive"); + goto fail; + } + + squeezes += bump_level * BUMP_LEVEL_MULTIPLIER; + if (verbose) { + fprintf(stderr, "bump level: %li\n", bump_level); + 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 after bump level: %li\n", squeezes); + fprintf(stderr, "squeezes before bump level: %li\n", + squeezes - bump_level * BUMP_LEVEL_MULTIPLIER); + } + + t (get_site(&site)); + t (get_master_passphrase(&passphrase)); + t (hash_master_passphrase(passphrase)); + + t (calculate_raw_password(&spec, squeezes, passphrase, site, &raw_password)); + passphrase_wipe(passphrase, strlen(passphrase)); + xfree(passphrase); + xfree(site); + + t (encode_base64(raw_password, (size_t)(spec.output / 8), &base64)); + xfree(raw_password); + + if (verbose) { + fprintf(stderr, "password length before base64: %li\n", spec.output / 8); + fprintf(stderr, "password length after base64: %li\n", strlen(base64)); + } + + if (clear_mode > 1) printf("%s", base64); + else if (clear_mode) printf("%s\n", base64); + else printf("\033[00m>\033[08;30;40m%s\033[00m<\n", base64); + + free(base64); + return 0; + +fail: + if (passphrase) + passphrase_wipe(passphrase, strlen(passphrase)); + free(passphrase); + free(site); + free(raw_password); + free(base64); + return r < 0 ? 0 : r; +} |
