/* * Copyright (C) 2009-2011 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include #include /* for getopt() */ #include #include "buffalo-lib.h" #define ERR(fmt, args...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## args ); \ } while (0) static char *progname; static char *ifname; static char *ofname; static char *crypt_key = "Buffalo"; static char *magic = "start"; static int longstate; static unsigned char seed = 'O'; static char *product; static char *version; static int do_decrypt; void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -d decrypt instead of encrypt\n" " -i read input from the file \n" " -o write output to the file \n" " -l use longstate {en,de}cryption method\n" " -k use for encryption (default: Buffalo)\n" " -m set magic to \n" " -p set product name to \n" " -v set version to \n" " -h show this screen\n" ); exit(status); } static int decrypt_file(void) { struct enc_param ep; ssize_t src_len; unsigned char *buf = NULL; int err; int ret = -1; src_len = get_file_size(ifname); if (src_len < 0) { ERR("unable to get size of '%s'", ifname); goto out; } buf = malloc(src_len); if (buf == NULL) { ERR("no memory for the buffer"); goto out; } err = read_file_to_buf(ifname, buf, src_len); if (err) { ERR("unable to read from file '%s'", ifname); goto out; } memset(&ep, '\0', sizeof(ep)); ep.key = (unsigned char *) crypt_key; err = decrypt_buf(&ep, buf, src_len); if (err) { ERR("unable to decrypt '%s'", ifname); goto out; } printf("Magic\t\t: '%s'\n", ep.magic); printf("Seed\t\t: 0x%02x\n", ep.seed); printf("Product\t\t: '%s'\n", ep.product); printf("Version\t\t: '%s'\n", ep.version); printf("Data len\t: %u\n", ep.datalen); printf("Checksum\t: 0x%08x\n", ep.csum); err = write_buf_to_file(ofname, buf, ep.datalen); if (err) { ERR("unable to write to file '%s'", ofname); goto out; } ret = 0; out: free(buf); return ret; } static int encrypt_file(void) { struct enc_param ep; ssize_t src_len; unsigned char *buf; uint32_t hdrlen; ssize_t totlen = 0; int err; int ret = -1; src_len = get_file_size(ifname); if (src_len < 0) { ERR("unable to get size of '%s'", ifname); goto out; } totlen = enc_compute_buf_len(product, version, src_len); hdrlen = enc_compute_header_len(product, version); buf = malloc(totlen); if (buf == NULL) { ERR("no memory for the buffer"); goto out; } err = read_file_to_buf(ifname, &buf[hdrlen], src_len); if (err) { ERR("unable to read from file '%s'", ofname); goto free_buf; } memset(&ep, '\0', sizeof(ep)); ep.key = (unsigned char *) crypt_key; ep.seed = seed; ep.longstate = longstate; ep.csum = buffalo_csum(src_len, &buf[hdrlen], src_len); ep.datalen = src_len; strcpy((char *) ep.magic, magic); strcpy((char *) ep.product, product); strcpy((char *) ep.version, version); err = encrypt_buf(&ep, buf, &buf[hdrlen]); if (err) { ERR("invalid input file"); goto free_buf; } err = write_buf_to_file(ofname, buf, totlen); if (err) { ERR("unable to write to file '%s'", ofname); goto free_buf; } ret = 0; free_buf: free(buf); out: return ret; } static int check_params(void) { int ret = -1; if (ifname == NULL) { ERR("no input file specified"); goto out; } if (ofname == NULL) { ERR("no output file specified"); goto out; } if (crypt_key == NULL) { ERR("no key specified"); goto out; } else if (strlen(crypt_key) > BCRYPT_MAX_KEYLEN) { ERR("key '%s' is too long", crypt_key); goto out; } if (strlen(magic) != (ENC_MAGIC_LEN - 1)) { ERR("length of magic must be %d", ENC_MAGIC_LEN - 1); goto out; } if (!do_decrypt) { if (product == NULL) { ERR("no product specified"); goto out; } if (version == NULL) { ERR("no version specified"); goto out; } if (strlen(product) > (ENC_PRODUCT_LEN - 1)) { ERR("product name '%s' is too long", product); goto out; } if (strlen(version) > (ENC_VERSION_LEN - 1)) { ERR("version '%s' is too long", version); goto out; } } ret = 0; out: return ret; } int main(int argc, char *argv[]) { int res = EXIT_FAILURE; int err; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "adi:m:o:hp:v:k:r:s:"); if (c == -1) break; switch (c) { case 'd': do_decrypt = 1; break; case 'i': ifname = optarg; break; case 'l': longstate = 1; break; case 'm': magic = optarg; break; case 'o': ofname = optarg; break; case 'p': product = optarg; break; case 'v': version = optarg; break; case 'k': crypt_key = optarg; break; case 's': seed = strtoul(optarg, NULL, 16); break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } err = check_params(); if (err) goto out; if (do_decrypt) err = decrypt_file(); else err = encrypt_file(); if (err) goto out; res = EXIT_SUCCESS; out: return res; }