1/* 2 * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 as published 6 * by the Free Software Foundation. 7 * 8 */ 9 10#include <stdio.h> 11#include <stdlib.h> 12#include <stdint.h> 13#include <string.h> 14#include <libgen.h> 15#include <getopt.h> /* for getopt() */ 16#include <stdarg.h> 17 18#include "buffalo-lib.h" 19 20#define ERR(fmt, args...) do { \ 21 fflush(0); \ 22 fprintf(stderr, "[%s] *** error: " fmt "\n", \ 23 progname, ## args ); \ 24} while (0) 25 26static char *progname; 27static char *ifname; 28static char *ofname; 29static char *crypt_key = "Buffalo"; 30static char *magic = "start"; 31static int longstate; 32static unsigned char seed = 'O'; 33 34static char *product; 35static char *version; 36static int do_decrypt; 37static int offset; 38 39void usage(int status) 40{ 41 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 42 43 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); 44 fprintf(stream, 45"\n" 46"Options:\n" 47" -d decrypt instead of encrypt\n" 48" -i <file> read input from the file <file>\n" 49" -o <file> write output to the file <file>\n" 50" -l use longstate {en,de}cryption method\n" 51" -k <key> use <key> for encryption (default: Buffalo)\n" 52" -m <magic> set magic to <magic>\n" 53" -p <product> set product name to <product>\n" 54" -v <version> set version to <version>\n" 55" -h show this screen\n" 56" -O Offset of encrypted data in file (decryption)\n" 57 ); 58 59 exit(status); 60} 61 62static int decrypt_file(void) 63{ 64 struct enc_param ep; 65 ssize_t src_len; 66 unsigned char *buf = NULL; 67 int err; 68 int ret = -1; 69 70 src_len = get_file_size(ifname); 71 if (src_len < 0) { 72 ERR("unable to get size of '%s'", ifname); 73 goto out; 74 } 75 76 buf = malloc(src_len); 77 if (buf == NULL) { 78 ERR("no memory for the buffer"); 79 goto out; 80 } 81 82 err = read_file_to_buf(ifname, buf, src_len); 83 if (err) { 84 ERR("unable to read from file '%s'", ifname); 85 goto out; 86 } 87 88 memset(&ep, '\0', sizeof(ep)); 89 ep.key = (unsigned char *) crypt_key; 90 ep.longstate = longstate; 91 92 err = decrypt_buf(&ep, buf + offset, src_len - offset); 93 if (err) { 94 ERR("unable to decrypt '%s'", ifname); 95 goto out; 96 } 97 98 printf("Magic\t\t: '%s'\n", ep.magic); 99 printf("Seed\t\t: 0x%02x\n", ep.seed); 100 printf("Product\t\t: '%s'\n", ep.product); 101 printf("Version\t\t: '%s'\n", ep.version); 102 printf("Data len\t: %u\n", ep.datalen); 103 printf("Checksum\t: 0x%08x\n", ep.csum); 104 105 err = write_buf_to_file(ofname, buf + offset, ep.datalen); 106 if (err) { 107 ERR("unable to write to file '%s'", ofname); 108 goto out; 109 } 110 111 ret = 0; 112 113out: 114 free(buf); 115 return ret; 116} 117 118static int encrypt_file(void) 119{ 120 struct enc_param ep; 121 ssize_t src_len; 122 unsigned char *buf; 123 uint32_t hdrlen; 124 ssize_t totlen = 0; 125 int err; 126 int ret = -1; 127 128 src_len = get_file_size(ifname); 129 if (src_len < 0) { 130 ERR("unable to get size of '%s'", ifname); 131 goto out; 132 } 133 134 totlen = enc_compute_buf_len(product, version, src_len); 135 hdrlen = enc_compute_header_len(product, version); 136 137 buf = malloc(totlen); 138 if (buf == NULL) { 139 ERR("no memory for the buffer"); 140 goto out; 141 } 142 143 err = read_file_to_buf(ifname, &buf[hdrlen], src_len); 144 if (err) { 145 ERR("unable to read from file '%s'", ofname); 146 goto free_buf; 147 } 148 149 memset(&ep, '\0', sizeof(ep)); 150 ep.key = (unsigned char *) crypt_key; 151 ep.seed = seed; 152 ep.longstate = longstate; 153 ep.csum = buffalo_csum(src_len, &buf[hdrlen], src_len); 154 ep.datalen = src_len; 155 strcpy((char *) ep.magic, magic); 156 strcpy((char *) ep.product, product); 157 strcpy((char *) ep.version, version); 158 159 err = encrypt_buf(&ep, buf, &buf[hdrlen]); 160 if (err) { 161 ERR("invalid input file"); 162 goto free_buf; 163 } 164 165 err = write_buf_to_file(ofname, buf, totlen); 166 if (err) { 167 ERR("unable to write to file '%s'", ofname); 168 goto free_buf; 169 } 170 171 ret = 0; 172 173free_buf: 174 free(buf); 175out: 176 return ret; 177} 178 179static int check_params(void) 180{ 181 int ret = -1; 182 183 if (ifname == NULL) { 184 ERR("no input file specified"); 185 goto out; 186 } 187 188 if (ofname == NULL) { 189 ERR("no output file specified"); 190 goto out; 191 } 192 193 if (crypt_key == NULL) { 194 ERR("no key specified"); 195 goto out; 196 } else if (strlen(crypt_key) > BCRYPT_MAX_KEYLEN) { 197 ERR("key '%s' is too long", crypt_key); 198 goto out; 199 } 200 201 if (strlen(magic) != (ENC_MAGIC_LEN - 1)) { 202 ERR("length of magic must be %d", ENC_MAGIC_LEN - 1); 203 goto out; 204 } 205 206 if (!do_decrypt) { 207 if (product == NULL) { 208 ERR("no product specified"); 209 goto out; 210 } 211 212 if (version == NULL) { 213 ERR("no version specified"); 214 goto out; 215 } 216 217 if (strlen(product) > (ENC_PRODUCT_LEN - 1)) { 218 ERR("product name '%s' is too long", product); 219 goto out; 220 } 221 222 if (strlen(version) > (ENC_VERSION_LEN - 1)) { 223 ERR("version '%s' is too long", version); 224 goto out; 225 } 226 } 227 228 ret = 0; 229 230out: 231 return ret; 232} 233 234int main(int argc, char *argv[]) 235{ 236 int res = EXIT_FAILURE; 237 int err; 238 239 progname = basename(argv[0]); 240 241 while ( 1 ) { 242 int c; 243 244 c = getopt(argc, argv, "adi:m:o:hlp:v:k:O:r:s:"); 245 if (c == -1) 246 break; 247 248 switch (c) { 249 case 'd': 250 do_decrypt = 1; 251 break; 252 case 'i': 253 ifname = optarg; 254 break; 255 case 'l': 256 longstate = 1; 257 break; 258 case 'm': 259 magic = optarg; 260 break; 261 case 'o': 262 ofname = optarg; 263 break; 264 case 'p': 265 product = optarg; 266 break; 267 case 'v': 268 version = optarg; 269 break; 270 case 'k': 271 crypt_key = optarg; 272 break; 273 case 's': 274 seed = strtoul(optarg, NULL, 16); 275 break; 276 case 'O': 277 offset = strtoul(optarg, NULL, 0); 278 break; 279 case 'h': 280 usage(EXIT_SUCCESS); 281 break; 282 default: 283 usage(EXIT_FAILURE); 284 break; 285 } 286 } 287 288 err = check_params(); 289 if (err) 290 goto out; 291 292 if (do_decrypt) 293 err = decrypt_file(); 294 else 295 err = encrypt_file(); 296 297 if (err) 298 goto out; 299 300 res = EXIT_SUCCESS; 301 302out: 303 return res; 304} 305