source: trunk/tools/firmware-utils/src/buffalo-enc.c @ 27167

Last change on this file since 27167 was 27167, checked in by juhosg, 5 years ago

tools/firmware-utils: fix buffalo csum calculation

Also print an error message if decryption fails.

  • Property svn:eol-style set to native
File size: 5.5 KB
Line 
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;
37
38void 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
60static 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
110out:
111        free(buf);
112        return ret;
113}
114
115static 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
170free_buf:
171        free(buf);
172out:
173        return ret;
174}
175
176static 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
227out:
228        return ret;
229}
230
231int 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
296out:
297        return res;
298}
Note: See TracBrowser for help on using the repository browser.