firmware-utils/mktplinkfw: add support for TL-WR743ND v1
[openwrt/svn-archive/archive.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
89 err = decrypt_buf(&ep, buf, src_len);
90 if (err) {
91 ERR("unable to decrypt '%s'", ifname);
92 goto out;
93 }
94
95 printf("Magic\t\t: '%s'\n", ep.magic);
96 printf("Seed\t\t: 0x%02x\n", ep.seed);
97 printf("Product\t\t: '%s'\n", ep.product);
98 printf("Version\t\t: '%s'\n", ep.version);
99 printf("Data len\t: %u\n", ep.datalen);
100 printf("Checksum\t: 0x%08x\n", ep.csum);
101
102 err = write_buf_to_file(ofname, buf, ep.datalen);
103 if (err) {
104 ERR("unable to write to file '%s'", ofname);
105 goto out;
106 }
107
108 ret = 0;
109
110 out:
111 free(buf);
112 return ret;
113 }
114
115 static int encrypt_file(void)
116 {
117 struct enc_param ep;
118 ssize_t src_len;
119 unsigned char *buf;
120 uint32_t hdrlen;
121 ssize_t totlen = 0;
122 int err;
123 int ret = -1;
124
125 src_len = get_file_size(ifname);
126 if (src_len < 0) {
127 ERR("unable to get size of '%s'", ifname);
128 goto out;
129 }
130
131 totlen = enc_compute_buf_len(product, version, src_len);
132 hdrlen = enc_compute_header_len(product, version);
133
134 buf = malloc(totlen);
135 if (buf == NULL) {
136 ERR("no memory for the buffer");
137 goto out;
138 }
139
140 err = read_file_to_buf(ifname, &buf[hdrlen], src_len);
141 if (err) {
142 ERR("unable to read from file '%s'", ofname);
143 goto free_buf;
144 }
145
146 memset(&ep, '\0', sizeof(ep));
147 ep.key = (unsigned char *) crypt_key;
148 ep.seed = seed;
149 ep.longstate = longstate;
150 ep.csum = buffalo_csum(src_len, &buf[hdrlen], src_len);
151 ep.datalen = src_len;
152 strcpy((char *) ep.magic, magic);
153 strcpy((char *) ep.product, product);
154 strcpy((char *) ep.version, version);
155
156 err = encrypt_buf(&ep, buf, &buf[hdrlen]);
157 if (err) {
158 ERR("invalid input file");
159 goto free_buf;
160 }
161
162 err = write_buf_to_file(ofname, buf, totlen);
163 if (err) {
164 ERR("unable to write to file '%s'", ofname);
165 goto free_buf;
166 }
167
168 ret = 0;
169
170 free_buf:
171 free(buf);
172 out:
173 return ret;
174 }
175
176 static int check_params(void)
177 {
178 int ret = -1;
179
180 if (ifname == NULL) {
181 ERR("no input file specified");
182 goto out;
183 }
184
185 if (ofname == NULL) {
186 ERR("no output file specified");
187 goto out;
188 }
189
190 if (crypt_key == NULL) {
191 ERR("no key specified");
192 goto out;
193 } else if (strlen(crypt_key) > BCRYPT_MAX_KEYLEN) {
194 ERR("key '%s' is too long", crypt_key);
195 goto out;
196 }
197
198 if (strlen(magic) != (ENC_MAGIC_LEN - 1)) {
199 ERR("length of magic must be %d", ENC_MAGIC_LEN - 1);
200 goto out;
201 }
202
203 if (!do_decrypt) {
204 if (product == NULL) {
205 ERR("no product specified");
206 goto out;
207 }
208
209 if (version == NULL) {
210 ERR("no version specified");
211 goto out;
212 }
213
214 if (strlen(product) > (ENC_PRODUCT_LEN - 1)) {
215 ERR("product name '%s' is too long", product);
216 goto out;
217 }
218
219 if (strlen(version) > (ENC_VERSION_LEN - 1)) {
220 ERR("version '%s' is too long", version);
221 goto out;
222 }
223 }
224
225 ret = 0;
226
227 out:
228 return ret;
229 }
230
231 int main(int argc, char *argv[])
232 {
233 int res = EXIT_FAILURE;
234 int err;
235
236 progname = basename(argv[0]);
237
238 while ( 1 ) {
239 int c;
240
241 c = getopt(argc, argv, "adi:m:o:hp:v:k:r:s:");
242 if (c == -1)
243 break;
244
245 switch (c) {
246 case 'd':
247 do_decrypt = 1;
248 break;
249 case 'i':
250 ifname = optarg;
251 break;
252 case 'l':
253 longstate = 1;
254 break;
255 case 'm':
256 magic = optarg;
257 break;
258 case 'o':
259 ofname = optarg;
260 break;
261 case 'p':
262 product = optarg;
263 break;
264 case 'v':
265 version = optarg;
266 break;
267 case 'k':
268 crypt_key = optarg;
269 break;
270 case 's':
271 seed = strtoul(optarg, NULL, 16);
272 break;
273 case 'h':
274 usage(EXIT_SUCCESS);
275 break;
276 default:
277 usage(EXIT_FAILURE);
278 break;
279 }
280 }
281
282 err = check_params();
283 if (err)
284 goto out;
285
286 if (do_decrypt)
287 err = decrypt_file();
288 else
289 err = encrypt_file();
290
291 if (err)
292 goto out;
293
294 res = EXIT_SUCCESS;
295
296 out:
297 return res;
298 }