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