#include #include #include #include #include #include "util.h" #include "none.h" #include "sha2.h" #include "scrypt.h" /* Options */ #define OPT(flag, opt, name, desc) \ { name "\0" desc, flag, NULL, opt } #define OPT_OPT(opt) ((opt).val) #define OPT_LEN(opt) ((int)strlen((opt).name)) #define OPT_NAME(opt) ((opt).name) #define OPT_DESC(opt) (&(opt).name[OPT_LEN(opt)]) /* Crypto functions */ typedef enum { NONE, SHA256, SCRYPT, } crypt_t; /* Options */ static struct option long_options[] = { OPT( 0, 'e', "encrypt", "Encrypt data" ), OPT( 0, 'd', "decrypt", "Decrypt data" ), OPT( 0, 't', "test", "Run self tests" ), OPT( 1, 'f', "function", "Specify crypto function" ), OPT( 1, 'i', "input", "Input file" ), OPT( 1, 'o', "output", "Output file" ), OPT( 0, 'q', "quiet", "Decrease verbosity" ), OPT( 0, 'v', "verbose", "Increase verbosity" ), OPT( 0, 'h', "help", "Print usage information" ), { }, }; static struct { const char *name; const char *desc; } crypt_info[] = { [NONE ] { "none", "No-op encryption/decryption" }, [SHA256] { "sha256", "SHA-256 hash function" }, [SCRYPT] { "scrypt", "Memory intensive hash function" }, }; /* Settings */ static int opt_decrypt; static int opt_encrypt; static crypt_t opt_crypt; static char *opt_instr; static char *opt_outstr; static FILE *opt_input; static FILE *opt_output; static int opt_level; static int opt_test; /* Helpers */ static const char *crypt_name(crypt_t id) { if (id < 0 || id >= N_ELEM(crypt_info)) error("invalid crypt id %d", id); return crypt_info[id].name; } static crypt_t crypt_id(const char *name) { for (int i = 0; i < N_ELEM(crypt_info); i++) if (!strcmp(name, crypt_info[i].name)) return (crypt_t)i; error("invalid crypt function %s", name); return NONE; } static void usage(const char *name) { printf("Usage:\n"); printf(" %s [OPTION...]\n", name); printf("\n"); printf("Options:\n"); for (int i = 0; long_options[i].name; i++) printf(" -%c, --%-10s %s\n", long_options[i].val, long_options[i].name, long_options[i].name + 1 + strlen(long_options[i].name)); printf("\n"); printf("Crypto functions:\n"); for (int i = 0; i < N_ELEM(crypt_info); i++) printf(" %-16s %s\n", crypt_info[i].name, crypt_info[i].desc); } static void parse(int argc, char **argv) { while (1) { int c = getopt_long(argc, argv, "edf:i:o:qvth", long_options, NULL); if (c == -1) break; switch (c) { case 'e': opt_encrypt = 1; break; case 'd': opt_decrypt = 1; break; case 't': opt_test = 1; break; case 'f': opt_crypt = crypt_id(optarg); break; case 'i': opt_input = fopen(optarg, "rb"); opt_instr = optarg; break; case 'o': opt_output = fopen(optarg, "wb+"); opt_outstr = optarg; break; case 'q': opt_level--; break; case 'v': opt_level++; break; case 'h': usage(argv[0]); exit(0); case '?': exit(1); default: exit(2); } } } void run(crypt_t id, FILE *in, FILE *out) { uint8_t dec[512], enc[512]; uint8_t sum[512]; int len; switch (id) { case NONE: while ((len = fread(&dec, 1, 512, in)) > 0) { //debug("<< [%s]:%d", dec, len); none_enc(dec, enc, len); //debug(">> [%s]:%d", enc, len); fwrite(enc, 1, len, out); } break; case SHA256: break; case SCRYPT: while ((len = fread(&dec, 1, 512, in)) > 0) { scrypt_hash(dec, sum); } break; } } /* Test */ static void test(crypt_t id) { if (!opt_test) return; switch (id) { case NONE: none_test(); break; case SHA256: sha256_test(); break; case SCRYPT: scrypt_test(); break; } } /* Main */ int main(int argc, char **argv) { /* Parse arguments */ opt_instr = "stdin"; opt_outstr = "stdout"; opt_input = stdin; opt_output = stdout; parse(argc, argv); loglevel = opt_level; /* Debug output */ debug("encrypt: %s", opt_encrypt ? "true" : "false"); debug("decrypt: %s", opt_decrypt ? "true" : "false"); debug("crypto: %s", crypt_name(opt_crypt)); debug("loglevel: %d", opt_level); debug("input: %s", opt_instr); debug("output: %s", opt_outstr); /* Run tests */ test(opt_crypt); /* Main loop */ run(opt_crypt, opt_input, opt_output); return 0; };