/* See LICENSE file for copyright and license details. */ #include "common.h" const char *argv0 = "bsum"; static int lenght_by_command_name = 0; static int flag_check = 0; static int flag_binary = 0; static int flag_lower = 0; static int flag_upper = 0; static int flag_hex = 0; static int flag_zero = 0; static int length; static void *salt = NULL; static void usage(void) { fprintf(stderr, "usage: %s%s [-c | -B | -L | -U] [-S salt] [-xz] [file] ...", argv0, lenght_by_command_name ? "" : " [-l bits]"); exit(2); } static void get_lenght_by_command_name(const char *command) { const char *p; p = strrchr(command, '/'); p = p ? &p[1] : command; if (strstr(p, "b224sum")) lenght_by_command_name = 224; else if (strstr(p, "b256sum")) lenght_by_command_name = 256; else if (strstr(p, "b384sum")) lenght_by_command_name = 384; else if (strstr(p, "b512sum")) lenght_by_command_name = 512; } static int hash_fd_blake(int fd, const char *fname, int decode_hex, unsigned char hash[], void *state, void *salt, void (*init_func)(void *state, void *salt), size_t (*update_func)(void *state, const void *msg, size_t n), size_t (*get_buf_size_func)(size_t bytes, size_t bits, const char *suffix), void (*digest_func)(void *state, void *msg, size_t bytes, size_t bits, const char *suffix, unsigned char out[])) { char *buf = NULL; size_t size = 0; size_t len = 0; size_t off = 0; size_t req; ssize_t r; int ok; init_func(state, salt); for (;;) { if (len == size) buf = erealloc(buf, size += 8 << 10); r = read(fd, &buf[len], size - len); if (r <= 0) { if (!r) break; if (errno == EINTR) continue; fprintf(stderr, "%s: %s: %s\n", argv0, fname, strerror(errno)); free(buf); return -1; } len += (size_t)r; if (!decode_hex) { off += update_func(state, &buf[off], len - off); if (off == len) off = 0; } } if (off) memmove(&buf[0], &buf[off], len -= off); if (decode_hex) { len = libblake_decode_hex(buf, len, buf, &ok); if (!ok) { fprintf(stderr, "%s: %s: %s\n", argv0, fname, "invalid hexadecimal input"); free(buf); return -1; } } req = get_buf_size_func(len, 0, NULL); if (req > size) buf = erealloc(buf, size); libblake_blake224_digest(state, buf, len, 0, NULL, hash); free(buf); return 0; } static int hash_fd_blake224(int fd, const char *fname, int decode_hex, unsigned char hash[], void *salt) { struct libblake_blake224_state state; return hash_fd_blake(fd, fname, decode_hex, hash, &state, salt, (void (*)(void *, void *))&libblake_blake224_init2, (size_t (*)(void *, const void *, size_t))&libblake_blake224_update, &libblake_blake224_digest_get_required_input_size, (void (*)(void *, void *, size_t, size_t, const char *, unsigned char[]))&libblake_blake224_digest); } static int hash_fd_blake256(int fd, const char *fname, int decode_hex, unsigned char hash[], void *salt) { struct libblake_blake256_state state; return hash_fd_blake(fd, fname, decode_hex, hash, &state, salt, (void (*)(void *, void *))&libblake_blake256_init2, (size_t (*)(void *, const void *, size_t))&libblake_blake256_update, &libblake_blake256_digest_get_required_input_size, (void (*)(void *, void *, size_t, size_t, const char *, unsigned char[]))&libblake_blake256_digest); } static int hash_fd_blake384(int fd, const char *fname, int decode_hex, unsigned char hash[], void *salt) { struct libblake_blake384_state state; return hash_fd_blake(fd, fname, decode_hex, hash, &state, salt, (void (*)(void *, void *))&libblake_blake384_init2, (size_t (*)(void *, const void *, size_t))&libblake_blake384_update, &libblake_blake384_digest_get_required_input_size, (void (*)(void *, void *, size_t, size_t, const char *, unsigned char[]))&libblake_blake384_digest); } static int hash_fd_blake512(int fd, const char *fname, int decode_hex, unsigned char hash[], void *salt) { struct libblake_blake512_state state; return hash_fd_blake(fd, fname, decode_hex, hash, &state, salt, (void (*)(void *, void *))&libblake_blake512_init2, (size_t (*)(void *, const void *, size_t))&libblake_blake512_update, &libblake_blake512_digest_get_required_input_size, (void (*)(void *, void *, size_t, size_t, const char *, unsigned char[]))&libblake_blake512_digest); } int hash_fd(int fd, const char *fname, int decode_hex, unsigned char hash[]) { int ret; if (length == 224) ret = hash_fd_blake224(fd, fname, decode_hex, hash, salt); else if (length == 256) ret = hash_fd_blake256(fd, fname, decode_hex, hash, salt); else if (length == 384) ret = hash_fd_blake384(fd, fname, decode_hex, hash, salt); else if (length == 512) ret = hash_fd_blake512(fd, fname, decode_hex, hash, salt); else abort(); return ret; } int main(int argc, char *argv[]) { const char *salt_str = NULL; uint_least8_t salt_buf[32]; int status = 0; int output_case; char newline; if (argv[0]) get_lenght_by_command_name(argv[0]); length = lenght_by_command_name; ARGBEGIN { case 'c': flag_check = 1; break; case 'B': flag_binary = 1; break; case 'L': flag_lower = 1; flag_upper = 0; break; case 'U': flag_upper = 1; flag_lower = 0; break; case 'S': if (salt_str) usage(); salt_str = ARG(); break; case 'x': flag_hex = 1; break; case 'z': flag_zero = 1; break; case 'l': if (length) usage(); length = atoi(ARG()); if (length != 224 && length != 256 && length != 384 && length != 512) { fprintf(stderr, "%s: valid arguments for -l are 224 (default), 256, 384, and 512\n", argv0); return 2; } break; default: usage(); } ARGEND; if (flag_check + flag_binary + flag_lower + flag_upper > 1) usage(); if (!length) length = 224; if (salt_str) { parse_salt(salt_buf, salt_str, length <= 256 ? 16 : 32); salt = salt_buf; } newline = flag_zero ? '\0' : '\n'; if (flag_check) { if (!argc) { status |= -check_and_print("-", (size_t)length, flag_hex, newline); } else { for (; *argv; argv++) status |= -check_and_print(*argv, (size_t)length, flag_hex, newline); } } else { output_case = flag_binary ? -1 : flag_upper; if (!argc) { status |= -hash_and_print("-", (size_t)length, flag_hex, newline, output_case); } else { for (; *argv; argv++) status |= -hash_and_print(*argv, (size_t)length, flag_hex, newline, output_case); } } if (fflush(stdout) || ferror(stdout) || fclose(stdout)) { fprintf(stderr, "%s: %s\n", argv0, strerror(errno)); return 2; } return status; }