diff options
Diffstat (limited to 'c/sha3sum.c')
-rw-r--r-- | c/sha3sum.c | 760 |
1 files changed, 0 insertions, 760 deletions
diff --git a/c/sha3sum.c b/c/sha3sum.c deleted file mode 100644 index 8b32755..0000000 --- a/c/sha3sum.c +++ /dev/null @@ -1,760 +0,0 @@ -/** - * sha3sum – SHA-3 (Keccak) checksum calculator - * - * Copyright © 2013, 2014 Mattias Andrée (maandree@member.fsf.org) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#include <stdio.h> -#include <alloca.h> -#include <sys/stat.h> - -#include "sha3.h" - - -#define false 0 -#define true 1 -#define null 0 - -#define SET void** - -#define HEXADECA "0123456789ABCDEF" - - -/** - * Prints a number of bytes to stdout - * - * @param BYTES:char* The bytes to print - * @param N:long The number of bytes - */ -#define putchars(BYTES, N) fwrite(BYTES, 1, N, stdout) - - -/** - * Creates a new set - * - * @return The set - */ -SET set_new() -{ - long i; - void** rc = (void**)malloc(sizeof(void*) << 4); - for (i = 0; i < 16; i++) - *(rc + i) = 0; - return rc; -} - - -/** - * Frees a set - * - * @param set The set - */ -void set_free(SET restrict_ set) -{ - if (*(set + 0)) set_free((void**)*(set + 0)); - if (*(set + 1)) set_free((void**)*(set + 1)); - if (*(set + 2)) set_free((void**)*(set + 2)); - if (*(set + 3)) set_free((void**)*(set + 3)); - if (*(set + 4)) set_free((void**)*(set + 4)); - if (*(set + 5)) set_free((void**)*(set + 5)); - if (*(set + 6)) set_free((void**)*(set + 6)); - if (*(set + 7)) set_free((void**)*(set + 7)); - if (*(set + 8)) set_free((void**)*(set + 8)); - if (*(set + 9)) set_free((void**)*(set + 9)); - if (*(set + 10)) set_free((void**)*(set + 10)); - if (*(set + 11)) set_free((void**)*(set + 11)); - if (*(set + 12)) set_free((void**)*(set + 12)); - if (*(set + 13)) set_free((void**)*(set + 13)); - if (*(set + 14)) set_free((void**)*(set + 14)); - if (*(set + 15)) set_free((void**)*(set + 15)); - free(set); -} - - -/** - * Adds an item to a set - * - * @param set The set - * @param item The item - * @param n The length of the item - */ -void set_add(SET restrict_ set, char* restrict_ item, long n) -{ - long i, j; - void** at = set; - for (i = 0; i < n; i++) - { - long a = (long)((*(item + i)) & 15), b = (long)((*(item + i) >> 4) & 15); - if (*(at + a)) - at = (void**)*(at + a); - else - { - at = (void**)(*(at + a) = (void*)malloc(sizeof(void*) << 4)); - for (j = 0; j < 16; j++) - *(at + j) = 0; - } - if (*(at + b)) - at = (void**)*(at + b); - else - { - at = (void**)(*(at + b) = (void*)malloc(sizeof(void*) << 4)); - for (j = 0; j < 16; j++) - *(at + j) = 0; - } - } -} - - -/** - * Checks if a set contains an item - * - * @param set The set - * @param item The item - * @param n The length of the item - * @return Whether the set contains the item - */ -long set_contains(SET restrict_ set, byte* restrict_ item, long n) -{ - long i; - void** at = set; - for (i = 0; i < n; i++) - { - long a = (long)((*(item + i)) & 15), b = (long)((*(item + i) >> 4) & 15); - if (*(at + a)) - at = (void**)*(at + a); - else - return false; - if (*(at + b)) - at = (void**)*(at + b); - else - return false; - } - return true; -} - - -/** - * String equality comparator - * - * @param a First comparand - * @param b Second comparand - * @return Whether the comparands are equal - */ -long eq(char* restrict_ a, char* restrict_ b) -{ - while (*a) - if (*a++ != *b++) - return false; - return !*b; -} - - -/** - * Convert a string to an integer - * - * @param str String representation - * @return Native representation - */ -long parseInt(char* restrict_ str) -{ - long rc = 0; - while (*str) - rc = rc * 10 - (*str++ & 15); - return -rc; -} - - -/** - * This is the main entry point of the program - * - * @param argc Command line argument count - * @param argv Command line arguments - * @return Exit value, zero on and only on successful execution - */ -int main(int argc, char** argv) -{ - char* out_alloc; - byte* stdin_alloc; - - long _o, o, _s, s, _r, r, _c, c, _w, w, _i, i, _j, j; - long _O, O, _S, S, _R, R, _C, C, _W, W, _I, I, _J, J; - long binary = false, hex = false, dashed = false; - long multi = 0, fptr = 0, bn; - - char** files = (char**)alloca((argc + 2) * sizeof(char*)); - char** linger = files + argc; - char* linger0 = (char*)alloca(sizeof(char) << 13); - - long a = 0, an = argc - 1; - char** args = argv + 1; - char* cmd = *argv; - - - _O = _S = _R = _C = _W = _I = _J = false; - O = S = R = C = W = I = J = 0; - o = s = r = c = w = i = j = 0; - - *linger = 0; - - - s = -1; - for (i = 0; *(cmd + i); i++) - if (*(cmd + i) == '/') - s = i; - if (s >= 0) - cmd += s + 1; - - _o = 512; /* --outputsize */ - if ((cmd[0] == 's') && (cmd[1] == 'h') && (cmd[2] == 'a') && (cmd[3] == '3') && (cmd[4] == '-')) - if ((cmd[5] != 0) && (cmd[6] != 0) && (cmd[7] != 0)) - if ((cmd[8] == 's') && (cmd[9] == 'u') && (cmd[10] == 'm') && (cmd[11] == 0)) - { - if ((cmd[5] == '2') && (cmd[6] == '2') && (cmd[7] == '4')) - _o = 224; - else if ((cmd[5] == '2') && (cmd[6] == '5') && (cmd[7] == '6')) - _o = 256; - else if ((cmd[5] == '3') && (cmd[6] == '8') && (cmd[7] == '4')) - _o = 384; - else if ((cmd[5] == '5') && (cmd[6] == '1') && (cmd[7] == '2')) - _o = 512; - } - _s = 1600; /* --statesize */ - _c = _s - (_o << 1); /* --capacity */ - _r = _s - _c; /* --bitrate */ - _w = _s / 25; /* --wordsize */ - _i = 1; /* --iterations */ - _j = 1; /* --squeezes */ - - - for (; a <= an; a++) - { - char* arg = a == an ? null : *(args + a); - if (*linger) - { - if (eq(*linger, "-h") || eq(*linger, "--help")) - { - printf("\n"); - printf("SHA-3/Keccak checksum calculator\n"); - printf("\n"); - printf("USAGE: sha3sum [option...] < file\n"); - printf(" sha3sum [option...] file...\n"); - printf("\n"); - printf("\n"); - printf("OPTIONS:\n"); - printf(" -r BITRATE\n"); - printf(" --bitrate The bitrate to use for checksum. (default: %li)\n", _r); - printf(" \n"); - printf(" -c CAPACITY\n"); - printf(" --capacity The capacity to use for checksum. (default: %li)\n", _c); - printf(" \n"); - printf(" -w WORDSIZE\n"); - printf(" --wordsize The word size to use for checksum. (default: %li)\n", _w); - printf(" \n"); - printf(" -o OUTPUTSIZE\n"); - printf(" --outputsize The output size to use for checksum. (default: %li)\n", _o); - printf(" \n"); - printf(" -s STATESIZE\n"); - printf(" --statesize The state size to use for ckecksum. (default: %li)\n", _s); - printf(" \n"); - printf(" -i ITERATIONS\n"); - printf(" --iterations The number of hash iterations to run. (default: %li)\n", _i); - printf(" \n"); - printf(" -j SQUEEZES\n"); - printf(" --squeezes The number of hash squeezes to run. (default: %li)\n", _j); - printf(" \n"); - printf(" -x\n"); - printf(" --hex Read the input in hexadecimal, rather than binary.\n"); - printf(" \n"); - printf(" -b\n"); - printf(" --binary Print the checksum in binary, rather than hexadecimal.\n"); - printf(" \n"); - printf(" -m\n"); - printf(" --multi Print the checksum at all iterations.\n"); - printf("\n"); - printf("\n"); - printf("COPYRIGHT:\n"); - printf("\n"); - printf("Copyright © 2013, 2014 Mattias Andrée (maandree@member.fsf.org)\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"); - printf("\n"); - fflush(stdout); - fflush(stderr); - return 0; - } - else - { - if (*(linger + 1) == null) - { - *(linger + 1) = arg; - arg = null; - } - if (eq(*linger, "-r") || eq(*linger, "--bitrate")) - _R = 1 | (R = parseInt(linger[1])); - else if (eq(*linger, "-c") || eq(*linger, "--capacity")) - _C = 1 | (C = parseInt(linger[1])); - else if (eq(*linger, "-w") || eq(*linger, "--wordsize")) - _W = 1 | (W = parseInt(linger[1])); - else if (eq(*linger, "-o") || eq(*linger, "--outputsize")) - _O = 1 | (O = parseInt(linger[1])); - else if (eq(*linger, "-s") || eq(*linger, "--statesize")) - _S = 1 | (S = parseInt(linger[1])); - else if (eq(*linger, "-i") || eq(*linger, "--iterations")) - _I = 1 | (I = parseInt(linger[1])); - else if (eq(*linger, "-j") || eq(*linger, "--squeezes")) - _J = 1 | (J = parseInt(linger[1])); - else - { - fprintf(stderr, "%s: unrecognised option: %s\n", cmd, *linger); - fflush(stdout); - fflush(stderr); - return 1; - } - } - *linger = null; - if (arg == null) - continue; - } - if (arg == null) - continue; - if (dashed) - files[fptr++] = ((arg[0] == '-') && (arg[1] == 0)) ? null : arg; - else if ((arg[0] == '-') && (arg[1] == '-') && (arg[2] == 0)) - dashed = true; - else if ((arg[0] == '-') && (arg[1] == 0)) - files[fptr++] = null; - else if ((arg[0] == '-') && (arg[1] == '-') && arg[2]) - { - long idx = -1, j; - for (j = 0; *(arg + j); j++) - if (*(arg + j) == '=') - { - idx = j; - break; - } - if (idx >= 0) - { - linger[0] = linger0; - linger[1] = arg + idx + 1; - for (j = 0; j < idx; j++) - *(*linger + j) = *(arg + j); - } - else - if (eq(arg, "--binary")) - binary = true; - else if (eq(arg, "--multi")) - multi++; - else if (eq(arg, "--hex")) - hex = true; - else - { - linger[0] = arg; - linger[1] = null; - } - } - else if ((arg[0] == '-') && arg[1]) - { - arg++; - if (*arg == 'b') - { - binary = true; - arg++; - } - else if (*arg == 'm') - { - multi++; - arg++; - } - else if (*arg == 'x') - { - hex = true; - arg++; - } - else - { - { - char* _ = linger0; - *_++ = '-'; *_++ = *arg; *_ = 0; - linger[0] = _ - 2; - } - { - long _ = 0; - while (*(arg + _)) - _++; - linger[1] = _ == 1 ? null : arg + 1; - } - } - } - else - files[fptr++] = arg; - } - - - i = _I ? I : _i; - j = _J ? J : _j; - - #define ERR(text) fprintf(stderr, "%s: " text "\n", cmd); fflush(stdout); fflush(stderr) - - if (_S) - { - s = S; - if ((s <= 0) || (s > 1600) || (s % 25)) - { - ERR("the state size must be a positive multiple of 25 and is limited to 1600."); - return 6; - } - } - - if (_W) - { - w = W; - if ((w <= 0) || (w > 64)) - { - ERR("the word size must be positive and is limited to 64."); - return 6; - } - if (_S && (s != w * 25)) - { - ERR("the state size must be 25 times of the word size."); - return 6; - } - else if (_S == null) - _S = 1 | (S = w * 25); - } - - if (_C) - { - c = C; - if ((c <= 0) || (c & 7)) - { - ERR("the capacity must be a positive multiple of 8."); - return 6; - } - } - - if (_R) - { - r = R; - if ((r <= 0) || (r & 7)) - { - ERR("the bitrate must be a positive multiple of 8."); - return 6; - } - } - - if (_O) - { - o = O; - if (o <= 0) - { - ERR("the output size must be positive."); - return 6; - } - } - - if ((_R | _C | _O) == null) /* s? */ - { - s = _S ? s : _s; - c = -((r = (o = (((s << 5) / 100 + 7) >> 3) << 3) << 1) - s); - o = o < 8 ? 8 : o; - } - else if ((_R | _C) == null) /* !o s? */ - { - r = _r; - c = _c; - s = _S ? s : (r + c); - } - else if (_R == null) /* !c o? s? */ - { - r = (s = _S ? s : _s) - c; - o = _O ? o : (c == 8 ? 8 : (c << 1)); - } - else if (_C == null) /* !r o? s? */ - { - c = (s = _S ? s : _s) - r; - o = _O ? o : (c == 8 ? 8 : (c << 1)); - } - else /* !r !c o? s? */ - { - s = _S ? s : (r + c); - o = _O ? o : (c == 8 ? 8 : (c << 1)); - } - - - fprintf(stderr, "Bitrate: %li\n", r); - fprintf(stderr, "Capacity: %li\n", c); - fprintf(stderr, "Word size: %li\n", w); - fprintf(stderr, "State size: %li\n", s); - fprintf(stderr, "Output Size: %li\n", o); - fprintf(stderr, "Iterations: %li\n", i); - fprintf(stderr, "Squeezes: %li\n", j); - - - if (r > s) - { - ERR("the bitrate must not be higher than the state size."); - return 6; - } - if (c > s) - { - ERR("the capacity must not be higher than the state size."); - return 6; - } - if (r + c != s) - { - ERR("the sum of the bitrate and the capacity must equal the state size."); - return 6; - } - - - if (fptr == 0) - files[fptr++] = null; - if (i < 1) - { - ERR("sorry, I will only do at least one hash iteration!"); - return 3; - } - if (j < 1) - { - ERR("sorry, I will only do at least one squeeze iteration!"); - return 3; - } - - #undef ERR - - bn = (o + 7) >> 3; - out_alloc = (char*)alloca(bn * 2 * sizeof(char) + bn * sizeof(byte)); - stdin_alloc = (byte*)(out_alloc + bn * 2); - { - byte* stdin; - char* filename; - char* fn; - long f, fail, _; - struct stat attr; - - char* out = binary ? null : out_alloc; - - fail = false; - stdin = null; - - for (f = 0; f < fptr; f++) - { - FILE* file; - long blksize; - byte* chunk; - byte* bs; - - filename = *(files + f); - fn = filename ? filename : "/dev/stdin"; - file = fopen(fn, "r"); - if (file == null) - { - fprintf(stderr, "%s: cannot read file: %s\n", cmd, filename); - fail = true; - continue; - } - - if ((filename != null) || (stdin == null)) - { - sha3_initialise(r, c, o); - blksize = stat(*(argv + f), &attr) ? 0 : attr.st_blksize; - if (blksize <= 0) - blksize = 4096; - chunk = (byte*)alloca(blksize * sizeof(byte)); - for (;;) - { - long read = fread(chunk, 1, blksize, file); - if (read <= 0) - break; - if (hex == false) - sha3_update(chunk, read); - else - { - int n = read >> 1; - for (_ = 0; _ < n; _++) - { - byte a = *(chunk + (_ << 1)), b = *(chunk + ((_ << 1) | 1)); - a = (a & 15) + (a <= '9' ? 0 : 9); - b = (b & 15) + (b <= '9' ? 0 : 9); - *(chunk + _) = (a << 4) | b; - } - sha3_update(chunk, n); - } - } - bs = sha3_digest(null, 0, 0, SHA3_SUFFIX, j == 1); - if (j > 2) - sha3_fastSqueeze(j - 2); - if (j > 1) - bs = sha3_squeeze(); - sha3_dispose(); - - if (filename == null) - { - stdin = stdin_alloc; - for (_ = 0; _ < bn; _++) - *(stdin_alloc + _) = *(bs + _); - } - } - else - bs = stdin; - - if (multi == 0) - { - for (_ = 1; _ < i; _++) - { - byte* _bs = bs; - sha3_initialise(r, c, o); - bs = sha3_digest(bs, bn, 0, SHA3_SUFFIX, j == 1); - if (j > 2) - sha3_fastSqueeze(j - 2); - if (j > 1) - bs = sha3_squeeze(); - free(_bs); - sha3_dispose(); - } - if (binary) - putchars((char*)bs, bn); - else - { - long b, outptr = 0; - for (b = 0; b < bn; b++) - { - byte v = bs[b]; - *(out + outptr++) = HEXADECA[(v >> 4) & 15]; - *(out + outptr++) = HEXADECA[v & 15]; - } - out[outptr] = '\0'; - printf("%s %s\n", out, filename ? filename : "-"); - } - } - else if (multi == 1) - { - long b; - if (binary) - putchars((char*)bs, bn); - else - { - for (b = 0; b < bn; b++) - { - byte v = bs[b]; - out[b * 2 ] = HEXADECA[(v >> 4) & 15]; - out[b * 2 + 1] = HEXADECA[v & 15]; - } - out[b*2] = '\0'; - printf("%s %s\n", out, filename ? filename : "-"); - } - for (_ = 1; _ < i; _++) - { - byte* _bs = bs; - sha3_initialise(r, c, o); - bs = sha3_digest(bs, bn, 0, SHA3_SUFFIX, j == 1); - if (j > 2) - sha3_fastSqueeze(j - 2); - if (j > 1) - bs = sha3_squeeze(); - free(_bs); - sha3_dispose(); - if (binary) - putchars((char*)bs, bn); - else - { - for (b = 0; b < bn; b++) - { - byte v = bs[b]; - out[b * 2 ] = HEXADECA[(v >> 4) & 15]; - out[b * 2 + 1] = HEXADECA[v & 15]; - } - out[b*2] = '\0'; - printf("%s\n", out); - } - } - } - else - { - long b; - char loophere; - char* loop = null; - SET got = set_new(); - for (_ = 0; _ < i; _++) - { - if (_ > 0) - { - byte* _bs = bs; - sha3_initialise(r, c, o); - bs = sha3_digest(bs, bn, 0, SHA3_SUFFIX, j == 1); - if (j > 2) - sha3_fastSqueeze(j - 2); - if (j > 1) - bs = sha3_squeeze(); - free(_bs); - sha3_dispose(); - } - for (b = 0; b < bn; b++) - { - byte v = bs[b]; - out[b * 2 ] = HEXADECA[(v >> 4) & 15]; - out[b * 2 + 1] = HEXADECA[v & 15]; - } - if (loop == null) - { - if (set_contains(got, bs, bn)) - { - loop = (char*)malloc(bn * 2 * sizeof(char)); - for (b = 0; b < bn * 2; b++) - *(loop + b) = *(out + b); - } - else - set_add(got, out, bn); - } - loophere = loop && eq(loop, out); - if (loophere) - printf("\033[31m"); - putchars(out, bn * 2); - if (loophere) - printf("\033[00m"); - fflush(stdout); - } - if (loop) - { - fprintf(stderr, "\033[01;31mLoop found\033[00m\n"); - free(loop); - } - set_free(got); - } - if (bs != null) - free(bs); - fclose(file); - } - - fflush(stdout); - fflush(stderr); - if (fail) - return 5; - } - - return 0; -} - |