diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-07-11 15:50:46 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-07-11 15:50:46 +0000 |
commit | 14c7f45cdae826f88dc539c8c38dd95caf305731 (patch) | |
tree | 832da054b7cfb2dc6fd63339af736625f31d21aa /utils/zenutils/source/zen_crypt/main.cpp | |
parent | 7c84ede3781c27db73403bd6302f320c76a58c8c (diff) | |
download | rockbox-14c7f45cdae826f88dc539c8c38dd95caf305731.tar.gz rockbox-14c7f45cdae826f88dc539c8c38dd95caf305731.zip |
Add zook's ZenUtils to SVN
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18010 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/zenutils/source/zen_crypt/main.cpp')
-rwxr-xr-x | utils/zenutils/source/zen_crypt/main.cpp | 687 |
1 files changed, 687 insertions, 0 deletions
diff --git a/utils/zenutils/source/zen_crypt/main.cpp b/utils/zenutils/source/zen_crypt/main.cpp new file mode 100755 index 0000000000..8301cbbea5 --- /dev/null +++ b/utils/zenutils/source/zen_crypt/main.cpp | |||
@@ -0,0 +1,687 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include <iostream> | ||
20 | #include <getpot/getpot.hpp> | ||
21 | #include <cenc.h> | ||
22 | #include <crypt.h> | ||
23 | #include <file.h> | ||
24 | #include <firmware.h> | ||
25 | #include <utils.h> | ||
26 | |||
27 | |||
28 | namespace { | ||
29 | enum command_t | ||
30 | { | ||
31 | cmd_none = 0, | ||
32 | cmd_sign, | ||
33 | cmd_verify, | ||
34 | cmd_encrypt, | ||
35 | cmd_decrypt | ||
36 | }; | ||
37 | |||
38 | enum mode_t | ||
39 | { | ||
40 | mode_none = 0, | ||
41 | mode_cenc, | ||
42 | mode_fresc, | ||
43 | mode_tl | ||
44 | }; | ||
45 | |||
46 | struct player_info_t | ||
47 | { | ||
48 | const char* name; | ||
49 | const char* null_key; // HMAC-SHA1 key | ||
50 | const char* fresc_key; // BlowFish key | ||
51 | const char* tl_key; // BlowFish key | ||
52 | bool big_endian; | ||
53 | }; | ||
54 | }; //namespace | ||
55 | |||
56 | |||
57 | static const char VERSION[] = "0.1"; | ||
58 | |||
59 | static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN."; | ||
60 | static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP."; | ||
61 | |||
62 | static const char fresc_key[] = "Copyright (C) CTL. -" | ||
63 | " zN0MAD iz v~p0wderful!"; | ||
64 | |||
65 | static const char tl_zvm_key[] = "1sN0TM3D az u~may th1nk*" | ||
66 | "Creative Zen Vision:M"; | ||
67 | static const char tl_zvw_key[] = "1sN0TM3D az u~may th1nk*" | ||
68 | "Creative ZEN Vision W"; | ||
69 | static const char tl_zm_key[] = "1sN0TM3D az u~may th1nk*" | ||
70 | "Creative Zen Micro"; | ||
71 | static const char tl_zmp_key[] = "1sN0TM3D az u~may th1nk*" | ||
72 | "Creative Zen MicroPhoto"; | ||
73 | static const char tl_zs_key[] = "1sN0TM3D az u~may th1nk*" | ||
74 | "Creative Zen Sleek"; | ||
75 | static const char tl_zsp_key[] = "1sN0TM3D az u~may th1nk*" | ||
76 | "Creative Zen Sleek Photo"; | ||
77 | static const char tl_zt_key[] = "1sN0TM3D az u~may th1nk*" | ||
78 | "Creative Zen Touch"; | ||
79 | static const char tl_zx_key[] = "1sN0TM3D az u~may th1nk*" | ||
80 | "NOMAD Jukebox Zen Xtra"; | ||
81 | |||
82 | player_info_t players[] = { | ||
83 | {"Vision:M", null_key_v2, fresc_key, tl_zvm_key, false}, | ||
84 | {"Vision W", null_key_v2, fresc_key, tl_zvw_key, false}, | ||
85 | {"Micro", null_key_v1, fresc_key, tl_zm_key, true}, | ||
86 | {"MicroPhoto", null_key_v1, fresc_key, tl_zmp_key, true}, | ||
87 | {"Sleek", null_key_v1, fresc_key, tl_zs_key, true}, | ||
88 | {"SleekPhoto", null_key_v1, fresc_key, tl_zsp_key, true}, | ||
89 | {"Touch", null_key_v1, fresc_key, tl_zt_key, true}, | ||
90 | {"Xtra", null_key_v1, fresc_key, tl_zx_key, true}, | ||
91 | {NULL, NULL, NULL, NULL, false} | ||
92 | }; | ||
93 | |||
94 | |||
95 | player_info_t* find_player_info(std::string player) | ||
96 | { | ||
97 | for (int i = 0; players[i].name != NULL; i++) | ||
98 | { | ||
99 | if (!stricmp(players[i].name, player.c_str())) | ||
100 | { | ||
101 | return &players[i]; | ||
102 | } | ||
103 | } | ||
104 | return NULL; | ||
105 | } | ||
106 | |||
107 | void print_version() | ||
108 | { | ||
109 | std::cout | ||
110 | << "zen_crypt - A utility for encrypting, decrypting or signing" | ||
111 | " Creative firmwares." << std::endl | ||
112 | << "Version " << VERSION << std::endl | ||
113 | << "Copyright (c) 2007 Rasmus Ry" << std::endl; | ||
114 | } | ||
115 | |||
116 | void print_help() | ||
117 | { | ||
118 | print_version(); | ||
119 | std::cout << std::endl | ||
120 | << "Usage: zen_crypt [command] [options]" << std::endl | ||
121 | << std::endl | ||
122 | << " Commands:" << std::endl | ||
123 | << " -h,--help" << std::endl | ||
124 | << " prints this message." << std::endl | ||
125 | << " -s,--sign" << std::endl | ||
126 | << " signs a given input file." << std::endl | ||
127 | << " -v,--verify" << std::endl | ||
128 | << " verifies a signed input file." << std::endl | ||
129 | << " -e,--encrypt" << std::endl | ||
130 | << " encrypts a given input file." << std::endl | ||
131 | << " -d,--decrypt" << std::endl | ||
132 | << " decrypts a given input file." << std::endl | ||
133 | << std::endl | ||
134 | << " Options:" << std::endl | ||
135 | << " -V,--verbose" << std::endl | ||
136 | << " prints verbose messages." << std::endl | ||
137 | << " -b,--big-endian" << std::endl | ||
138 | << " specifies that the input is big-endian, default is" | ||
139 | " little-endian." << std::endl | ||
140 | << " -i,--input [file]" << std::endl | ||
141 | << " specifies the input file." << std::endl | ||
142 | << " -o,--output [file]" << std::endl | ||
143 | << " specifies the output file." << std::endl | ||
144 | << " -m,--mode [CENC|FRESC|TL]" << std::endl | ||
145 | << " specifies which algorithm to use." << std::endl | ||
146 | << " -k,--key [player|key]" << std::endl | ||
147 | << " specifies which key to use." << std::endl | ||
148 | << std::endl | ||
149 | ; | ||
150 | std::cout << " Players:" << std::endl; | ||
151 | for (int i = 0; players[i].name != NULL; i++) | ||
152 | { | ||
153 | std::cout << " " << players[i].name; | ||
154 | if (!i) | ||
155 | std::cout << " (default)"; | ||
156 | std::cout << std::endl; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | size_t find_null_signature(shared::bytes& data) | ||
161 | { | ||
162 | size_t index = data.size(); | ||
163 | if (index < (20 + 8 + 7)) | ||
164 | return 0; | ||
165 | index -= 20 + 8; | ||
166 | for (int i = 0; i < 7; i++) | ||
167 | { | ||
168 | if (*(dword*)&data[index-i] == 'NULL' || | ||
169 | *(dword*)&data[index-i] == 'LLUN') | ||
170 | { | ||
171 | return index-i; | ||
172 | } | ||
173 | } | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | |||
178 | bool sign(shared::bytes& data, player_info_t* pi, const std::string& file, | ||
179 | bool verbose) | ||
180 | { | ||
181 | if (verbose) | ||
182 | std::cout << "[*] Checking for the presence of an existing" | ||
183 | " NULL signature..." << std::endl; | ||
184 | size_t index = find_null_signature(data); | ||
185 | if (index) | ||
186 | { | ||
187 | if (verbose) | ||
188 | std::cout << "[*] Found NULL signature at: " | ||
189 | << std::hex << index << std::endl; | ||
190 | |||
191 | if (verbose) | ||
192 | std::cout << "[*] Computing digest..." << std::endl; | ||
193 | |||
194 | shared::bytes digest(20); | ||
195 | if (!zen::hmac_sha1_calc((const byte*)pi->null_key, | ||
196 | strlen(pi->null_key)+1, &data[0], index, | ||
197 | &digest[0], NULL)) | ||
198 | { | ||
199 | std::cerr << "Failed to compute digest." << std::endl; | ||
200 | return false; | ||
201 | } | ||
202 | |||
203 | if (verbose) | ||
204 | std::cout << "[*] Writing file data..." << std::endl; | ||
205 | |||
206 | if (!shared::write_file(file, data, true)) | ||
207 | { | ||
208 | std::cerr << "Failed to write file data." << std::endl; | ||
209 | return false; | ||
210 | } | ||
211 | |||
212 | if (verbose) | ||
213 | std::cout << "[*] Writing digest data..." << std::endl; | ||
214 | |||
215 | if (!shared::write_file(file, digest, false, index+8)) | ||
216 | { | ||
217 | std::cerr << "Failed to write digest data." << std::endl; | ||
218 | return false; | ||
219 | } | ||
220 | } | ||
221 | else | ||
222 | { | ||
223 | if (verbose) | ||
224 | std::cout << "[*] Computing digest..." << std::endl; | ||
225 | |||
226 | shared::bytes signature(20+8); | ||
227 | if (!zen::hmac_sha1_calc((const byte*)pi->null_key, | ||
228 | strlen(pi->null_key)+1, &data[0], data.size(), | ||
229 | &signature[8], NULL)) | ||
230 | { | ||
231 | std::cerr << "Failed to compute digest." << std::endl; | ||
232 | return false; | ||
233 | } | ||
234 | |||
235 | |||
236 | zen::firmware_header_t header = {'NULL', 20}; | ||
237 | if (pi->big_endian) | ||
238 | { | ||
239 | header.tag = shared::swap(header.tag); | ||
240 | header.size = shared::swap(header.size); | ||
241 | } | ||
242 | memcpy(&signature[0], &header, sizeof(zen::firmware_header_t)); | ||
243 | |||
244 | if (verbose) | ||
245 | std::cout << "[*] Writing file data..." << std::endl; | ||
246 | |||
247 | if (!shared::write_file(file, data, true)) | ||
248 | { | ||
249 | std::cerr << "Failed to write file data." << std::endl; | ||
250 | return false; | ||
251 | } | ||
252 | |||
253 | if (verbose) | ||
254 | std::cout << "[*] Writing signature data..." << std::endl; | ||
255 | |||
256 | if (!shared::write_file(file, signature, false, data.size())) | ||
257 | { | ||
258 | std::cerr << "Failed to write signature data." << std::endl; | ||
259 | return false; | ||
260 | } | ||
261 | |||
262 | if (verbose) | ||
263 | std::cout << "[*] Ensuring that the file length is" | ||
264 | " 32-bit aligned..." << std::endl; | ||
265 | |||
266 | int length = data.size() + signature.size(); | ||
267 | int align = length % 4; | ||
268 | if (align) | ||
269 | { | ||
270 | shared::bytes padding(4 - align, 0); | ||
271 | if (!shared::write_file(file, padding, false, length)) | ||
272 | { | ||
273 | std::cerr << "Failed to write padding data." << std::endl; | ||
274 | return false; | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | |||
279 | return true; | ||
280 | } | ||
281 | |||
282 | bool verify(shared::bytes& data, player_info_t* pi, bool verbose) | ||
283 | { | ||
284 | if (verbose) | ||
285 | std::cout << "[*] Checking for the presence of an existing" | ||
286 | " NULL signature..." << std::endl; | ||
287 | size_t index = find_null_signature(data); | ||
288 | if (!index) | ||
289 | { | ||
290 | std::cerr << "No NULL signature present in the input file." | ||
291 | << std::endl; | ||
292 | return false; | ||
293 | } | ||
294 | if (verbose) | ||
295 | std::cout << "[*] Found NULL signature at: " | ||
296 | << std::hex << index << std::endl; | ||
297 | |||
298 | if (verbose) | ||
299 | std::cout << "[*] Computing digest..." << std::endl; | ||
300 | |||
301 | byte digest[20]; | ||
302 | if (!zen::hmac_sha1_calc((const byte*)pi->null_key, strlen(pi->null_key)+1, | ||
303 | &data[0], index, digest, NULL)) | ||
304 | { | ||
305 | std::cerr << "Failed to compute digest." << std::endl; | ||
306 | return false; | ||
307 | } | ||
308 | |||
309 | if (verbose) | ||
310 | std::cout << "[*] Verifying NULL signature digest..." << std::endl; | ||
311 | |||
312 | if (memcmp(&digest[0], &data[index+8], 20)) | ||
313 | { | ||
314 | std::cerr << "The NULL signature contains an incorrect digest." | ||
315 | << std::endl; | ||
316 | return false; | ||
317 | } | ||
318 | |||
319 | return true; | ||
320 | } | ||
321 | |||
322 | bool encrypt(shared::bytes& data, int mode, player_info_t* pi, | ||
323 | const std::string& file, bool verbose) | ||
324 | { | ||
325 | if (mode == mode_cenc) | ||
326 | { | ||
327 | if (verbose) | ||
328 | std::cout << "[*] Encoding input file..." << std::endl; | ||
329 | |||
330 | shared::bytes outbuf(data.size() * 2); | ||
331 | int len = zen::cenc_encode(&data[0], data.size(), &outbuf[0], outbuf.size()); | ||
332 | if (!len) | ||
333 | { | ||
334 | std::cerr << "Failed to encode the input file." << std::endl; | ||
335 | return false; | ||
336 | } | ||
337 | |||
338 | if (verbose) | ||
339 | std::cout << "[*] Writing decoded length to file..." << std::endl; | ||
340 | |||
341 | shared::bytes length(sizeof(dword)); | ||
342 | *(dword*)&length[0] = pi->big_endian ? shared::swap(data.size()) : data.size(); | ||
343 | if (!shared::write_file(file, length, true)) | ||
344 | { | ||
345 | std::cerr << "Failed to write the file data." << std::endl; | ||
346 | return false; | ||
347 | } | ||
348 | |||
349 | if (verbose) | ||
350 | std::cout << "[*] Writing file data..." << std::endl; | ||
351 | |||
352 | if (!shared::write_file(file, outbuf, sizeof(dword), len)) | ||
353 | { | ||
354 | std::cerr << "Failed to write the file data." << std::endl; | ||
355 | return false; | ||
356 | } | ||
357 | } | ||
358 | else if (mode == mode_fresc) | ||
359 | { | ||
360 | std::cerr << "FRESC mode is not supported." << std::endl; | ||
361 | return false; | ||
362 | } | ||
363 | else if (mode == mode_tl) | ||
364 | { | ||
365 | if (verbose) | ||
366 | std::cout << "[*] Encoding input file..." << std::endl; | ||
367 | |||
368 | shared::bytes outbuf(data.size() * 2); | ||
369 | *(dword*)&outbuf[0] = pi->big_endian ? shared::swap(data.size()) : data.size(); | ||
370 | int len = zen::cenc_encode(&data[0], data.size(), | ||
371 | &outbuf[sizeof(dword)], | ||
372 | outbuf.size()-sizeof(dword)); | ||
373 | if (!len) | ||
374 | { | ||
375 | std::cerr << "Failed to encode the input file." << std::endl; | ||
376 | return false; | ||
377 | } | ||
378 | len += sizeof(dword); | ||
379 | |||
380 | int align = len % 8; | ||
381 | align = align ? (8 - align) : 0; | ||
382 | len += align; | ||
383 | |||
384 | if (verbose) | ||
385 | std::cout << "[*] Encrypting encoded data..." << std::endl; | ||
386 | |||
387 | dword iv[2] = {0, shared::swap(len)}; | ||
388 | if (!zen::bf_cbc_encrypt((const byte*)pi->tl_key, strlen(pi->tl_key)+1, | ||
389 | &outbuf[0], len, (const byte*)iv)) | ||
390 | { | ||
391 | std::cerr << "Failed to decrypt the input file." << std::endl; | ||
392 | return false; | ||
393 | } | ||
394 | |||
395 | if (verbose) | ||
396 | std::cout << "[*] Writing file data..." << std::endl; | ||
397 | |||
398 | if (!shared::write_file(file, outbuf, true, 0, len)) | ||
399 | { | ||
400 | std::cerr << "Failed to save the output file." << std::endl; | ||
401 | return false; | ||
402 | } | ||
403 | } | ||
404 | else | ||
405 | { | ||
406 | std::cerr << "Invalid mode specified." << std::endl; | ||
407 | return false; | ||
408 | } | ||
409 | |||
410 | return true; | ||
411 | } | ||
412 | |||
413 | bool decrypt(shared::bytes& data, int mode, player_info_t* pi, | ||
414 | const std::string& file, bool verbose) | ||
415 | { | ||
416 | if (mode == mode_cenc) | ||
417 | { | ||
418 | dword length = *(dword*)&data[0]; | ||
419 | length = pi->big_endian ? shared::swap(length) : length; | ||
420 | |||
421 | if (verbose) | ||
422 | std::cout << "[*] Decoding input file..." << std::endl; | ||
423 | |||
424 | shared::bytes outbuf(length); | ||
425 | if (!zen::cenc_decode(&data[sizeof(dword)], data.size()-sizeof(dword), | ||
426 | &outbuf[0], length)) | ||
427 | { | ||
428 | std::cerr << "Failed to decode the input file." << std::endl; | ||
429 | return false; | ||
430 | } | ||
431 | |||
432 | if (verbose) | ||
433 | std::cout << "[*] Writing file data..." << std::endl; | ||
434 | |||
435 | if (!shared::write_file(file, outbuf, true)) | ||
436 | { | ||
437 | std::cerr << "Failed to write the file data." << std::endl; | ||
438 | return false; | ||
439 | } | ||
440 | } | ||
441 | else if (mode == mode_fresc) | ||
442 | { | ||
443 | if (verbose) | ||
444 | std::cout << "[*] Decrypting input file..." << std::endl; | ||
445 | |||
446 | dword iv[2] = {shared::swap(data.size()), 0}; | ||
447 | if (!zen::bf_cbc_decrypt((const byte*)pi->fresc_key, | ||
448 | strlen(pi->fresc_key)+1, &data[0], | ||
449 | data.size(), (const byte*)iv)) | ||
450 | { | ||
451 | std::cerr << "Failed to decrypt the input file." << std::endl; | ||
452 | return false; | ||
453 | } | ||
454 | |||
455 | if (verbose) | ||
456 | std::cout << "[*] Writing file data..." << std::endl; | ||
457 | |||
458 | if (!shared::write_file(file, data, true)) | ||
459 | { | ||
460 | std::cerr << "Failed to save the output file." << std::endl; | ||
461 | return false; | ||
462 | } | ||
463 | } | ||
464 | else if (mode == mode_tl) | ||
465 | { | ||
466 | if (verbose) | ||
467 | std::cout << "[*] Decrypting input file..." << std::endl; | ||
468 | |||
469 | dword iv[2] = {0, shared::swap(data.size())}; | ||
470 | if (!zen::bf_cbc_decrypt((const byte*)pi->tl_key, strlen(pi->tl_key)+1, | ||
471 | &data[0], data.size(), (const byte*)iv)) | ||
472 | { | ||
473 | std::cerr << "Failed to decrypt the input file." << std::endl; | ||
474 | return false; | ||
475 | } | ||
476 | |||
477 | dword length = *(dword*)&data[0]; | ||
478 | length = pi->big_endian ? shared::swap(length) : length; | ||
479 | if (length > (data.size() * 3)) | ||
480 | { | ||
481 | std::cerr << "Decrypted length is unexpectedly large: " | ||
482 | << std::hex << length | ||
483 | << " Check the endian and key settings." << std::endl; | ||
484 | return false; | ||
485 | } | ||
486 | |||
487 | if (verbose) | ||
488 | std::cout << "[*] Decoding decrypted data..." << std::endl; | ||
489 | |||
490 | shared::bytes outbuf(length); | ||
491 | if (!zen::cenc_decode(&data[sizeof(dword)], data.size()-sizeof(dword), | ||
492 | &outbuf[0], length)) | ||
493 | { | ||
494 | std::cerr << "Failed to decode the input file." << std::endl; | ||
495 | return false; | ||
496 | } | ||
497 | |||
498 | if (verbose) | ||
499 | std::cout << "[*] Writing file data..." << std::endl; | ||
500 | |||
501 | if (!shared::write_file(file, outbuf, true)) | ||
502 | { | ||
503 | std::cerr << "Failed to save the output file." << std::endl; | ||
504 | return false; | ||
505 | } | ||
506 | } | ||
507 | else | ||
508 | { | ||
509 | std::cerr << "Invalid mode specified." << std::endl; | ||
510 | return false; | ||
511 | } | ||
512 | |||
513 | return true; | ||
514 | } | ||
515 | |||
516 | int process_arguments(int argc, char*argv[]) | ||
517 | { | ||
518 | //-------------------------------------------------------------------- | ||
519 | // Parse input variables. | ||
520 | //-------------------------------------------------------------------- | ||
521 | |||
522 | GetPot cl(argc, argv); | ||
523 | if (cl.size() == 1 || cl.search(2, "-h", "--help")) | ||
524 | { | ||
525 | print_help(); | ||
526 | return 1; | ||
527 | } | ||
528 | |||
529 | int command = cmd_none; | ||
530 | if (cl.search(2, "-s", "--sign")) | ||
531 | command = cmd_sign; | ||
532 | else if (cl.search(2, "-v", "--verify")) | ||
533 | command = cmd_verify; | ||
534 | else if (cl.search(2, "-e", "--encrypt")) | ||
535 | command = cmd_encrypt; | ||
536 | else if (cl.search(2, "-d", "--decrypt")) | ||
537 | command = cmd_decrypt; | ||
538 | |||
539 | if (command == cmd_none) | ||
540 | { | ||
541 | std::cerr << "No command specified." << std::endl; | ||
542 | return 2; | ||
543 | } | ||
544 | |||
545 | int mode = mode_none; | ||
546 | if (command == cmd_encrypt || command == cmd_decrypt) | ||
547 | { | ||
548 | if (!cl.search(2, "-m", "--mode")) | ||
549 | { | ||
550 | std::cerr << "The specified command requires that" | ||
551 | " a mode is specified." | ||
552 | << std::endl; | ||
553 | return 3; | ||
554 | } | ||
555 | std::string name = cl.next(""); | ||
556 | if (!name.empty()) | ||
557 | { | ||
558 | if (!stricmp(name.c_str(), "CENC")) | ||
559 | mode = mode_cenc; | ||
560 | else if (!stricmp(name.c_str(), "FRESC")) | ||
561 | mode = mode_fresc; | ||
562 | else if (!stricmp(name.c_str(), "TL")) | ||
563 | mode = mode_tl; | ||
564 | } | ||
565 | if (mode == mode_none) | ||
566 | { | ||
567 | std::cerr << "Invalid mode specified." << std::endl; | ||
568 | return 4; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | bool verbose = false; | ||
573 | if (cl.search(2, "-V", "--verbose")) | ||
574 | verbose = true; | ||
575 | |||
576 | bool big_endian = false; | ||
577 | if (cl.search(2, "-b", "--big-endian")) | ||
578 | big_endian = true; | ||
579 | |||
580 | std::string infile; | ||
581 | if (cl.search(2, "-i", "--input")) | ||
582 | infile = cl.next(""); | ||
583 | if (infile.empty()) | ||
584 | { | ||
585 | std::cerr << "An input file must be specified." << std::endl; | ||
586 | return 5; | ||
587 | } | ||
588 | |||
589 | std::string outfile = infile; | ||
590 | if (cl.search(2, "-o", "--output")) | ||
591 | outfile = cl.next(outfile.c_str()); | ||
592 | |||
593 | player_info_t* pi = &players[0]; | ||
594 | std::string key; | ||
595 | if (cl.search(2, "-k", "--key")) | ||
596 | key = cl.next(""); | ||
597 | if (!key.empty()) | ||
598 | { | ||
599 | player_info_t* pitmp = find_player_info(key); | ||
600 | if (pitmp != NULL) | ||
601 | pi = pitmp; | ||
602 | else | ||
603 | { | ||
604 | static player_info_t player = { | ||
605 | NULL, key.c_str(), key.c_str(), key.c_str(), false | ||
606 | }; | ||
607 | pi = &player; | ||
608 | } | ||
609 | } | ||
610 | if (big_endian) | ||
611 | pi->big_endian = big_endian; | ||
612 | |||
613 | |||
614 | //-------------------------------------------------------------------- | ||
615 | // Read the input file. | ||
616 | //-------------------------------------------------------------------- | ||
617 | |||
618 | if (verbose) | ||
619 | std::cout << "[*] Reading input file..." << std::endl; | ||
620 | |||
621 | shared::bytes buffer; | ||
622 | if (!shared::read_file(infile, buffer)) | ||
623 | { | ||
624 | std::cerr << "Failed to read the input file." << std::endl; | ||
625 | return 6; | ||
626 | } | ||
627 | |||
628 | |||
629 | //-------------------------------------------------------------------- | ||
630 | // Process the input file. | ||
631 | //-------------------------------------------------------------------- | ||
632 | |||
633 | switch (command) | ||
634 | { | ||
635 | case cmd_sign: | ||
636 | if (verbose) | ||
637 | std::cout << "[*] Signing input file..." << std::endl; | ||
638 | if (!sign(buffer, pi, outfile, verbose)) | ||
639 | return 7; | ||
640 | std::cout << "Successfully signed the input file." << std::endl; | ||
641 | break; | ||
642 | case cmd_verify: | ||
643 | if (verbose) | ||
644 | std::cout << "[*] Verifying signature on input file..." | ||
645 | << std::endl; | ||
646 | if (!verify(buffer, pi, verbose)) | ||
647 | return 8; | ||
648 | std::cout << "Successfully verified the input file signature." | ||
649 | << std::endl; | ||
650 | break; | ||
651 | case cmd_encrypt: | ||
652 | if (verbose) | ||
653 | std::cout << "[*] Encrypting input file..." << std::endl; | ||
654 | if (!encrypt(buffer, mode, pi, outfile, verbose)) | ||
655 | return 9; | ||
656 | std::cout << "Successfully encrypted the input file." << std::endl; | ||
657 | break; | ||
658 | case cmd_decrypt: | ||
659 | if (verbose) | ||
660 | std::cout << "[*] Decrypting input file..." << std::endl; | ||
661 | if (!decrypt(buffer, mode, pi, outfile, verbose)) | ||
662 | return 10; | ||
663 | std::cout << "Successfully decrypted the input file." << std::endl; | ||
664 | break; | ||
665 | }; | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | int main(int argc, char* argv[]) | ||
671 | { | ||
672 | try | ||
673 | { | ||
674 | return process_arguments(argc, argv); | ||
675 | } | ||
676 | catch (const std::exception& xcpt) | ||
677 | { | ||
678 | std::cerr << "Exception caught: " << xcpt.what() << std::endl; | ||
679 | return -1; | ||
680 | } | ||
681 | catch (...) | ||
682 | { | ||
683 | std::cerr << "Unknown exception caught." << std::endl; | ||
684 | return -2; | ||
685 | } | ||
686 | return -3; | ||
687 | } | ||