blob: 54bbbf3270959d543cdbc724d7ba3f1553a5740b [file] [log] [blame]
Amaury Poulycb09e362012-11-03 02:16:01 +01001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include <stdint.h>
23#include <stdbool.h>
24#include <stdlib.h>
25#include <string.h>
26#include <getopt.h>
27#include <stdarg.h>
28#include <ctype.h>
29#include "misc.h"
30#include "elf.h"
31#include <sys/stat.h>
32#include <openssl/md5.h>
33#include "crypt.h"
34#include "fwp.h"
35#include "keysig_search.h"
36
37#ifndef MIN
38#define MIN(a,b) ((a) < (b) ? (a) : (b))
39#endif
40
41bool g_debug = false;
42static char *g_out_prefix = NULL;
43static char *g_in_file = NULL;
44bool g_force = false;
45static const char *g_model = NULL;
46static int g_model_index = -1;
47static char *g_kas = NULL;
48static char *g_key = NULL;
49static char *g_sig = NULL;
50
51enum keysig_search_method_t g_keysig_search = KEYSIG_SEARCH_NONE;
52
Amaury Poulycb09e362012-11-03 02:16:01 +010053#define let_the_force_flow(x) do { if(!g_force) return x; } while(0)
54#define continue_the_force(x) if(x) let_the_force_flow(x)
55
56#define check_field(v_exp, v_have, str_ok, str_bad) \
57 if((v_exp) != (v_have)) \
58 { cprintf(RED, str_bad); let_the_force_flow(__LINE__); } \
59 else { cprintf(RED, str_ok); }
60
61static void print_hex(void *p, int size, int unit)
62{
63 uint8_t *p8 = p;
64 uint16_t *p16 = p;
65 uint32_t *p32 = p;
66 for(int i = 0; i < size; i += unit, p8++, p16++, p32++)
67 {
68 if(i != 0 && (i % 16) == 0)
69 printf("\n");
70 if(unit == 1)
71 printf(" %02x", *p8);
72 else if(unit == 2)
73 printf(" %04x", *p16);
74 else
75 printf(" %08x", *p32);
76 }
77}
78
Amaury Pouly214f2262012-11-12 18:35:00 +010079static void usage(void);
80
Amaury Poulycb09e362012-11-03 02:16:01 +010081/* key and signature */
82struct nwz_kas_t
83{
84 char kas[NWZ_KAS_SIZE];
85};
86
87#define HAS_KAS (1 << 0)
88#define HAS_KEY (1 << 1)
89#define HAS_SIG (1 << 2)
90#define CONFIRMED (1 << 3)
91
92struct nwz_model_t
93{
94 const char *model;
95 unsigned flags;
96 struct nwz_kas_t kas;
97 char key[8];
98 char sig[8];
99};
100
101struct upg_md5_t
102{
103 uint8_t md5[16];
104}__attribute__((packed));
105
106struct upg_header_t
107{
108 char sig[8];
109 uint32_t nr_files;
Amaury Pouly214f2262012-11-12 18:35:00 +0100110 uint32_t pad; // make sure structure size is a multiple of 8
Amaury Poulycb09e362012-11-03 02:16:01 +0100111} __attribute__((packed));
112
113struct upg_entry_t
114{
115 uint32_t offset;
116 uint32_t size;
117} __attribute__((packed));
118
119struct nwz_model_t g_model_list[] =
120{
121 { "nwz-e463", HAS_KAS | HAS_KEY | HAS_SIG | CONFIRMED, {"89d813f8f966efdebd9c9e0ea98156d2"}, "eb4431eb", "4f1d9cac" },
122 { "nwz-a86x", HAS_KEY | HAS_SIG, {""}, "c824e4e2", "7c262bb0" },
123 { "nw-a82x", HAS_KEY | HAS_SIG, {""}, "4df06482", "07fa0b6e" },
124};
125
126static int digit_value(char c)
127{
128 if(c >= '0' && c <= '9') return c - '0';
129 if(c >= 'a' && c <= 'f') return c - 'a' + 10;
130 if(c >= 'A' && c <= 'F') return c - 'A' + 10;
131 return -1;
132}
133
134static char hex_digit(unsigned v)
135{
136 return (v < 10) ? v + '0' : (v < 16) ? v - 10 + 'a' : 'x';
137}
138
139static int decrypt_keysig(char keysig[NWZ_KEYSIG_SIZE])
140{
141 uint8_t src[16];
142 for(int i = 32; i < NWZ_KEYSIG_SIZE; i++)
143 keysig[i] = 0;
144 for(int index = 0; index < 16; index++)
145 {
146 int a = digit_value(keysig[index * 2]);
147 int b = digit_value(keysig[index * 2 + 1]);
148 if(a < 0 || b < 0)
149 {
150 cprintf(GREY, "Invalid KAS !\n");
151 return -1;
152 }
153 src[index] = a << 4 | b;
154 }
155 fwp_setkey("ed295076");
156 fwp_crypt(src, sizeof(src), 1);
157 memcpy(keysig + 33, src, 8);
158 memcpy(keysig + 42, src + 8, 8);
159 return 0;
160}
161
162static bool upg_notify_keysig(void *user, uint8_t key[8], uint8_t sig[8])
163{
164 memcpy(user + 33, key, 8);
165 memcpy(user + 42, sig, 8);
166 return true;
167}
168
169static int do_upg(void *buf, long size)
170{
171 struct upg_md5_t *md5 = buf;
172 cprintf(BLUE, "Preliminary\n");
173 cprintf(GREEN, " MD5: ");
174 for(int i = 0; i < 16; i++)
175 cprintf(YELLOW, "%02x", md5->md5[i]);
176 printf(" ");
177
178 uint8_t actual_md5[MD5_DIGEST_LENGTH];
179 {
180 MD5_CTX c;
181 MD5_Init(&c);
182 MD5_Update(&c, md5 + 1, size - sizeof(struct upg_header_t));
183 MD5_Final(actual_md5, &c);
184 }
185 check_field(memcmp(actual_md5, md5->md5, 16), 0, "Ok\n", "Mismatch\n");
186
187 if(g_model_index == -1 && g_keysig_search == KEYSIG_SEARCH_NONE && g_key == NULL && g_kas == NULL)
188 {
189 cprintf(GREY, "A KAS or a keysig is needed to decrypt the firmware\n");
Amaury Pouly214f2262012-11-12 18:35:00 +0100190 cprintf(GREY, "You have the following options(see help for more details):\n");
Amaury Poulycb09e362012-11-03 02:16:01 +0100191 cprintf(GREY, "- select a model with a known KAS\n");
192 cprintf(GREY, "- specify an explicit KAS or key(+optional sig)\n");
193 cprintf(GREY, "- let me try to find the keysig(slow !)\n");
194 return 1;
195 }
196
197 struct nwz_kas_t kas;
198 char keysig[NWZ_KEYSIG_SIZE];
199
200 memset(kas.kas, '?', NWZ_KAS_SIZE);
201 memset(keysig, '?', NWZ_KEYSIG_SIZE);
202 keysig[32] = keysig[41] = keysig[50] = 0;
203
204 if(g_kas)
205 {
206 if(strlen(g_kas) != NWZ_KAS_SIZE)
207 {
208 cprintf(GREY, "The specified KAS has wrong length (must be %d hex digits)\n", NWZ_KAS_SIZE);
209 return 4;
210 }
211 memcpy(keysig, g_kas, NWZ_KAS_SIZE);
212 decrypt_keysig(keysig);
213 g_kas = keysig;
214 g_key = keysig + 33;
215 g_sig = keysig + 42;
216 }
217 else if(g_key)
218 {
219 if(strlen(g_key) != 8)
220 {
221 cprintf(GREY, "The specified key has wrong length (must be 8 hex digits)\n");
222 return 4;
223 }
224 if(g_sig && strlen(g_sig) != 8)
225 {
226 cprintf(GREY, "The specified sig has wrong length (must be 8 hex digits)\n");
227 return 5;
228 }
229
230 memcpy(keysig + 33, g_key, 8);
231 if(!g_sig)
232 cprintf(GREY, "Warning: you have specified a key but no sig, I won't be able to do any checks\n");
233 else
234 memcpy(keysig + 42, g_sig, 8);
235 g_key = keysig + 33;
236 if(g_sig)
237 g_sig = keysig + 42;
238 }
239 else if(g_model_index == -1)
240 {
241 cprintf(BLUE, "keysig Search\n");
242 cprintf_field(" Method: ", "%s\n", keysig_search_desc[g_keysig_search].name);
243 bool ok = keysig_search_desc[g_keysig_search].fn((void *)(md5 + 1), &upg_notify_keysig, keysig);
244 cprintf(GREEN, " Result: ");
245 cprintf(ok ? YELLOW : RED, "%s\n", ok ? "Key found" : "No key found");
246 if(!ok)
247 return 2;
248 g_key = keysig + 33;
249 g_sig = keysig + 42;
250 }
251 else
252 {
253 if(g_model_list[g_model_index].flags & HAS_KAS)
254 g_kas = g_model_list[g_model_index].kas.kas;
255 if(g_model_list[g_model_index].flags & HAS_KEY)
256 g_key = g_model_list[g_model_index].key;
257 if(g_model_list[g_model_index].flags & HAS_SIG)
258 g_sig = g_model_list[g_model_index].sig;
259
260 if(g_kas)
261 {
262 memcpy(keysig, g_kas, NWZ_KAS_SIZE);
263 decrypt_keysig(keysig);
264 g_kas = keysig;
265 g_key = keysig + 33;
266 g_sig = keysig + 42;
267 }
268 else
269 {
270 if(g_key)
271 {
272 memcpy(keysig + 33, g_key, 8);
273 g_key = keysig + 33;
274 }
275 if(g_sig)
276 {
277 memcpy(keysig + 42, g_sig, 8);
278 g_sig = keysig + 42;
279 }
280 }
281 }
282
283 if(!g_kas)
284 {
285 g_kas = keysig;
286 fwp_setkey("ed295076");
287 if(g_key)
288 {
289 memcpy(kas.kas, g_key, 8);
290 fwp_crypt(kas.kas, 8, 0);
291 for(int i = 0; i < 8; i++)
292 {
293 g_kas[2 * i] = hex_digit((kas.kas[i] >> 4) & 0xf);
294 g_kas[2 * i + 1] = hex_digit(kas.kas[i] & 0xf);
295 }
296 }
297 if(g_sig)
298 {
299 memcpy(kas.kas + 8, g_sig, 8);
300 fwp_crypt(kas.kas + 8, 8, 0);
301 for(int i = 8; i < 16; i++)
302 {
303 g_kas[2 * i] = hex_digit((kas.kas[i] >> 4) & 0xf);
304 g_kas[2 * i + 1] = hex_digit(kas.kas[i] & 0xf);
305 }
306 }
307 }
308
309 cprintf(BLUE, "Keys\n");
310 cprintf_field(" KAS: ", "%."STR(NWZ_KAS_SIZE)"s\n", g_kas);
311 cprintf_field(" Key: ", "%s\n", g_key);
312 if(g_sig)
313 cprintf_field(" Sig: ", "%s\n", g_sig);
314
315 struct upg_header_t *hdr = (void *)(md5 + 1);
316 int ret = fwp_read(hdr, sizeof(struct upg_header_t), hdr, (void *)g_key);
317 if(ret)
318 return ret;
319
320 cprintf(BLUE, "Header\n");
321 cprintf_field(" Signature:", " ");
322 for(int i = 0; i < 8; i++)
323 cprintf(YELLOW, "%c", isprint(hdr->sig[i]) ? hdr->sig[i] : '.');
324 if(g_sig)
325 {
326 check_field(memcmp(hdr->sig, g_sig, 8), 0, " OK\n", " Mismatch\n");
327 }
328 else
329 cprintf(RED, " Can't check\n");
330 cprintf_field(" Files: ", "%d\n", hdr->nr_files);
Amaury Pouly214f2262012-11-12 18:35:00 +0100331 cprintf_field(" Pad: ", "0x%x\n", hdr->pad);
Amaury Poulycb09e362012-11-03 02:16:01 +0100332
333 cprintf(BLUE, "Files\n");
334 struct upg_entry_t *entry = (void *)(hdr + 1);
335 for(unsigned i = 0; i < hdr->nr_files; i++, entry++)
336 {
337 int ret = fwp_read(entry, sizeof(struct upg_entry_t), entry, (void *)g_key);
338 if(ret)
339 return ret;
340 cprintf(GREY, " File");
341 cprintf(RED, " %d\n", i);
342 cprintf_field(" Offset: ", "0x%x\n", entry->offset);
343 cprintf_field(" Size: ", "0x%x\n", entry->size);
344
345 if(g_out_prefix)
346 {
347 char *str = malloc(strlen(g_out_prefix) + 32);
Amaury Pouly214f2262012-11-12 18:35:00 +0100348 sprintf(str, "%s%d.bin", g_out_prefix, i);
Amaury Poulycb09e362012-11-03 02:16:01 +0100349 FILE *f = fopen(str, "wb");
350 if(f)
351 {
Amaury Pouly214f2262012-11-12 18:35:00 +0100352 // round up size, there is some padding done with random data
353 int crypt_size = ROUND_UP(entry->size, 8);
354 int ret = fwp_read(buf + entry->offset, crypt_size,
Amaury Poulycb09e362012-11-03 02:16:01 +0100355 buf + entry->offset, (void *)g_key);
356 if(ret)
357 return ret;
Amaury Pouly214f2262012-11-12 18:35:00 +0100358 // but write the *good* amount of data
Amaury Poulycb09e362012-11-03 02:16:01 +0100359 fwrite(buf + entry->offset, 1, entry->size, f);
360
361 fclose(f);
362 }
363 else
364 cprintf(GREY, "Cannot open '%s' for writing\n", str);
365 }
366 }
367
368 return 0;
369}
370
Amaury Pouly214f2262012-11-12 18:35:00 +0100371static int extract_upg(int argc, char **argv)
372{
373 if(argc == 0 || argc > 1)
374 {
375 if(argc == 0)
376 printf("You must specify a firmware file\n");
377 else
378 printf("Extra arguments after firmware file\n");
379 usage();
380 }
381
382 g_in_file = argv[0];
383 FILE *fin = fopen(g_in_file, "r");
384 if(fin == NULL)
385 {
386 perror("Cannot open boot file");
387 return 1;
388 }
389 fseek(fin, 0, SEEK_END);
390 long size = ftell(fin);
391 fseek(fin, 0, SEEK_SET);
392
393 void *buf = malloc(size);
394 if(buf == NULL)
395 {
396 perror("Cannot allocate memory");
397 return 1;
398 }
399
400 if(fread(buf, size, 1, fin) != 1)
401 {
402 perror("Cannot read file");
403 return 1;
404 }
405
406 fclose(fin);
407
408 int ret = do_upg(buf, size);
409 if(ret != 0)
410 {
411 cprintf(GREY, "Error: %d", ret);
412 if(!g_force)
413 cprintf(GREY, " (use --force to force processing)");
414 printf("\n");
415 ret = 2;
416 }
417 free(buf);
418
419 return ret;
420}
421
422static long filesize(FILE *f)
423{
424 long pos = ftell(f);
425 fseek(f, 0, SEEK_END);
426 long size = ftell(f);
427 fseek(f, pos, SEEK_SET);
428 return size;
429}
430
431static int create_upg(int argc, char **argv)
432{
433 if(argc == 0)
434 {
435 printf("You must specify a firmware filename\n");
436 usage();
437 }
438
439 if(g_model_index == -1 && (g_key == NULL || g_sig == NULL) && g_kas == NULL)
440 {
441 cprintf(GREY, "A KAS or a keysig is needed to encrypt the firmware\n");
442 cprintf(GREY, "You have the following options(see help for more details):\n");
443 cprintf(GREY, "- select a model with a known KAS\n");
444 cprintf(GREY, "- specify an explicit KAS or key+sig\n");
445 return 1;
446 }
447
448 struct nwz_kas_t kas;
449 char keysig[NWZ_KEYSIG_SIZE];
450
451 memset(kas.kas, '?', NWZ_KAS_SIZE);
452 memset(keysig, '?', NWZ_KEYSIG_SIZE);
453 keysig[32] = keysig[41] = keysig[50] = 0;
454
455 if(g_kas)
456 {
457 if(strlen(g_kas) != NWZ_KAS_SIZE)
458 {
459 cprintf(GREY, "The specified KAS has wrong length (must be %d hex digits)\n", NWZ_KAS_SIZE);
460 return 4;
461 }
462 memcpy(keysig, g_kas, NWZ_KAS_SIZE);
463 decrypt_keysig(keysig);
464 g_kas = keysig;
465 g_key = keysig + 33;
466 g_sig = keysig + 42;
467 }
468 else if(g_key)
469 {
470 if(strlen(g_key) != 8)
471 {
472 cprintf(GREY, "The specified key has wrong length (must be 8 hex digits)\n");
473 return 4;
474 }
475 if(strlen(g_sig) != 8)
476 {
477 cprintf(GREY, "The specified sig has wrong length (must be 8 hex digits)\n");
478 return 5;
479 }
480
481 memcpy(keysig + 33, g_key, 8);
482 if(!g_sig)
483 cprintf(GREY, "Warning: you have specified a key but no sig, I won't be able to do any checks\n");
484 else
485 memcpy(keysig + 42, g_sig, 8);
486 g_key = keysig + 33;
487 g_sig = keysig + 42;
488 }
489 else if(g_model_index != -1)
490 {
491 if(g_model_list[g_model_index].flags & HAS_KAS)
492 g_kas = g_model_list[g_model_index].kas.kas;
493 if(g_model_list[g_model_index].flags & HAS_KEY)
494 g_key = g_model_list[g_model_index].key;
495 if(g_model_list[g_model_index].flags & HAS_SIG)
496 g_sig = g_model_list[g_model_index].sig;
497
498 if(g_key && g_sig)
499 {
500 memcpy(keysig + 33, g_key, 8);
501 g_key = keysig + 33;
502 memcpy(keysig + 42, g_sig, 8);
503 g_sig = keysig + 42;
504 }
505 else if(g_kas)
506 {
507 memcpy(keysig, g_kas, NWZ_KAS_SIZE);
508 decrypt_keysig(keysig);
509 g_kas = keysig;
510 g_key = keysig + 33;
511 g_sig = keysig + 42;
512 }
513 else
514 {
515 printf("Target doesn't have enough information to get key and sig\n");
516 return 1;
517 }
518 }
519 else
520 {
521 printf("Kill me\n");
522 return 1;
523 }
524
525 if(!g_kas)
526 {
527 g_kas = keysig;
528 fwp_setkey("ed295076");
529 memcpy(kas.kas, g_key, 8);
530 fwp_crypt(kas.kas, 8, 0);
531 for(int i = 0; i < 8; i++)
532 {
533 g_kas[2 * i] = hex_digit((kas.kas[i] >> 4) & 0xf);
534 g_kas[2 * i + 1] = hex_digit(kas.kas[i] & 0xf);
535 }
536 memcpy(kas.kas + 8, g_sig, 8);
537 fwp_crypt(kas.kas + 8, 8, 0);
538 for(int i = 8; i < 16; i++)
539 {
540 g_kas[2 * i] = hex_digit((kas.kas[i] >> 4) & 0xf);
541 g_kas[2 * i + 1] = hex_digit(kas.kas[i] & 0xf);
542 }
543 }
544
545 cprintf(BLUE, "Keys\n");
546 cprintf_field(" KAS: ", "%."STR(NWZ_KAS_SIZE)"s\n", g_kas);
547 cprintf_field(" Key: ", "%s\n", g_key);
548 if(g_sig)
549 cprintf_field(" Sig: ", "%s\n", g_sig);
550
551 FILE *fout = fopen(argv[0], "wb");
552 if(fout == NULL)
553 {
554 printf("Cannot open output firmware file: %m\n");
555 return 1;
556 }
557
558 int nr_files = argc - 1;
559 FILE **files = malloc(nr_files * sizeof(FILE *));
560
561 for(int i = 0; i < nr_files; i++)
562 {
563 files[i] = fopen(argv[1 + i], "rb");
564 if(files[i] == NULL)
565 {
566 printf("Cannot open input file '%s': %m\n", argv[i + 1]);
567 return 1;
568 }
569 }
570
571 struct upg_md5_t md5;
572 memset(&md5, 0, sizeof(md5));
573 MD5_CTX c;
574 MD5_Init(&c);
575 // output a dummy md5 sum
576 fwrite(&md5, 1, sizeof(md5), fout);
577 // output the encrypted signature
578 struct upg_header_t hdr;
579 memcpy(hdr.sig, g_sig, 8);
580 hdr.nr_files = nr_files;
581 hdr.pad = 0;
582
583 int ret = fwp_write(&hdr, sizeof(hdr), &hdr, (void *)g_key);
584 if(ret)
585 return ret;
586 MD5_Update(&c, &hdr, sizeof(hdr));
587 fwrite(&hdr, 1, sizeof(hdr), fout);
588
589 // output file headers
590 long offset = sizeof(md5) + sizeof(hdr) + nr_files * sizeof(struct upg_entry_t);
591 for(int i = 0; i < nr_files; i++)
592 {
593 struct upg_entry_t entry;
594 entry.offset = offset;
595 entry.size = filesize(files[i]);
596 offset += ROUND_UP(entry.size, 8); // do it before encryption !!
597
598 ret = fwp_write(&entry, sizeof(entry), &entry, (void *)g_key);
599 if(ret)
600 return ret;
601 MD5_Update(&c, &entry, sizeof(entry));
602 fwrite(&entry, 1, sizeof(entry), fout);
603 }
604
605 cprintf(BLUE, "Files\n");
606 for(int i = 0; i < nr_files; i++)
607 {
608 long size = filesize(files[i]);
609 long r_size = ROUND_UP(size, 8);
610 cprintf(GREY, " File");
611 cprintf(RED, " %d\n", i);
612 cprintf_field(" Offset: ", "0x%lx\n", ftell(fout));
613 cprintf_field(" Size: ", "0x%lx\n", size);
614
615 void *buf = malloc(r_size);
616 memset(buf, 0, r_size);
617 fread(buf, 1, size, files[i]);
618 fclose(files[i]);
619
620 ret = fwp_write(buf, r_size, buf, (void *)g_key);
621 if(ret)
622 return ret;
623 MD5_Update(&c, buf, r_size);
624 fwrite(buf, 1, r_size, fout);
625
626 free(buf);
627 }
628
629 fseek(fout, 0, SEEK_SET);
630 MD5_Final(md5.md5, &c);
631 fwrite(&md5, 1, sizeof(md5), fout);
632 fclose(fout);
633
634 return 0;
635}
636
Amaury Poulycb09e362012-11-03 02:16:01 +0100637static void usage(void)
638{
639 color(OFF);
Amaury Pouly214f2262012-11-12 18:35:00 +0100640 printf("Usage: upgtool [options] firmware [files...]\n");
Amaury Poulycb09e362012-11-03 02:16:01 +0100641 printf("Options:\n");
642 printf(" -o <prefix>\t\tSet output prefix\n");
643 printf(" -f/--force\t\tForce to continue on errors\n");
644 printf(" -?/--help\t\tDisplay this message\n");
645 printf(" -d/--debug\t\tDisplay debug messages\n");
646 printf(" -c/--no-color\t\tDisable color output\n");
647 printf(" -m/--model <model>\tSelect model (or ? to list them)\n");
Amaury Pouly214f2262012-11-12 18:35:00 +0100648 printf(" -l/--search <method>\tTry to find the keysig (implies -e)\n");
Amaury Poulycb09e362012-11-03 02:16:01 +0100649 printf(" -a/--kas <kas>\tForce KAS\n");
650 printf(" -k/--key <key>\tForce key\n");
651 printf(" -s/--sig <sig>\tForce sig\n");
Amaury Pouly214f2262012-11-12 18:35:00 +0100652 printf(" -e/--extract\t\tExtract a UPG archive\n");
653 printf(" -c/--create\t\tCreate a UPG archive\n");
Amaury Poulycb09e362012-11-03 02:16:01 +0100654 printf("keysig search method:\n");
655 for(int i = KEYSIG_SEARCH_FIRST; i < KEYSIG_SEARCH_LAST; i++)
656 printf(" %s\t%s\n", keysig_search_desc[i].name, keysig_search_desc[i].comment);
657 exit(1);
658}
659
660int main(int argc, char **argv)
661{
Amaury Pouly214f2262012-11-12 18:35:00 +0100662 bool extract = false;
663 bool create = false;
664
665 if(argc <= 1)
666 usage();
667
Amaury Poulycb09e362012-11-03 02:16:01 +0100668 while(1)
669 {
670 static struct option long_options[] =
671 {
672 {"help", no_argument, 0, '?'},
673 {"debug", no_argument, 0, 'd'},
Amaury Pouly214f2262012-11-12 18:35:00 +0100674 {"no-color", no_argument, 0, 'n'},
Amaury Poulycb09e362012-11-03 02:16:01 +0100675 {"force", no_argument, 0, 'f'},
676 {"model", required_argument, 0, 'm'},
677 {"search", required_argument, 0, 'l'},
678 {"kas", required_argument, 0, 'a'},
679 {"key", required_argument, 0, 'k'},
680 {"sig", required_argument, 0, 's'},
Amaury Pouly214f2262012-11-12 18:35:00 +0100681 {"extract", no_argument, 0, 'e'},
682 {"create", no_argument, 0 ,'c'},
Amaury Poulycb09e362012-11-03 02:16:01 +0100683 {0, 0, 0, 0}
684 };
685
Amaury Pouly214f2262012-11-12 18:35:00 +0100686 int c = getopt_long(argc, argv, "?dnfo:m:l:a:k:s:ec", long_options, NULL);
Amaury Poulycb09e362012-11-03 02:16:01 +0100687 if(c == -1)
688 break;
689 switch(c)
690 {
691 case -1:
692 break;
Amaury Pouly214f2262012-11-12 18:35:00 +0100693 case 'n':
Amaury Poulycb09e362012-11-03 02:16:01 +0100694 enable_color(false);
695 break;
696 case 'd':
697 g_debug = true;
698 break;
699 case 'f':
700 g_force = true;
701 break;
702 case '?':
703 usage();
704 break;
705 case 'o':
706 g_out_prefix = optarg;
707 break;
708 case 'm':
709 g_model = optarg;
710 break;
711 case 'l':
712 g_keysig_search = KEYSIG_SEARCH_NONE;
713 for(int i = KEYSIG_SEARCH_FIRST; i < KEYSIG_SEARCH_LAST; i++)
714 if(strcmp(keysig_search_desc[i].name, optarg) == 0)
715 g_keysig_search = i;
716 if(g_keysig_search == KEYSIG_SEARCH_NONE)
717 {
718 cprintf(GREY, "Unknown keysig search method '%s'\n", optarg);
719 return 1;
720 }
Amaury Pouly214f2262012-11-12 18:35:00 +0100721 extract = true;
Amaury Poulycb09e362012-11-03 02:16:01 +0100722 break;
723 case 'a':
724 g_kas = optarg;
725 break;
726 case 'k':
727 g_key = optarg;
728 break;
729 case 's':
730 g_sig = optarg;
731 break;
Amaury Pouly214f2262012-11-12 18:35:00 +0100732 case 'e':
733 extract = true;
734 break;
735 case 'c':
736 create = true;
737 break;
Amaury Poulycb09e362012-11-03 02:16:01 +0100738 default:
739 abort();
740 }
741 }
742
743 if(g_model && strcmp(g_model, "?") == 0)
744 {
745 cprintf(BLUE, "Model list:\n");
746 for(unsigned i = 0; i < sizeof(g_model_list) / sizeof(g_model_list[0]); i++)
747 {
748 cprintf(GREEN, " %s:", g_model_list[i].model);
749 if(g_model_list[i].flags & HAS_KAS)
750 {
751 cprintf(RED, " kas=");
752 cprintf(YELLOW, "%."STR(NWZ_KAS_SIZE)"s", g_model_list[i].kas.kas);
753 }
754 if(g_model_list[i].flags & HAS_KEY)
755 {
756 cprintf(RED, " key=");
757 cprintf(YELLOW, "%.8s", g_model_list[i].key);
758 }
759 if(g_model_list[i].flags & HAS_SIG)
760 {
761 cprintf(RED, " sig=");
762 cprintf(YELLOW, "%.8s", g_model_list[i].sig);
763 }
764 if(g_model_list[i].flags & CONFIRMED)
765 cprintf(RED, " confirmed");
766 else
767 cprintf(RED, " guessed");
768 printf("\n");
769 }
770 return 1;
771 }
772
773 if(g_model)
774 {
775 for(unsigned i = 0; i < sizeof(g_model_list) / sizeof(g_model_list[0]); i++)
776 if(strcmp(g_model, g_model_list[i].model) == 0)
777 g_model_index = i;
778 if(g_model_index == -1)
779 cprintf(GREY, "Warning: unknown model %s\n", g_model);
780 }
781
Amaury Pouly214f2262012-11-12 18:35:00 +0100782 if(!create && !extract)
Amaury Poulycb09e362012-11-03 02:16:01 +0100783 {
Amaury Pouly214f2262012-11-12 18:35:00 +0100784 printf("You must specify an action (extract or create)\n");
Amaury Poulycb09e362012-11-03 02:16:01 +0100785 return 1;
786 }
787
Amaury Pouly214f2262012-11-12 18:35:00 +0100788 if(create && extract)
Amaury Poulycb09e362012-11-03 02:16:01 +0100789 {
Amaury Pouly214f2262012-11-12 18:35:00 +0100790 printf("You cannot specify both create and extract\n");
Amaury Poulycb09e362012-11-03 02:16:01 +0100791 return 1;
792 }
793
Amaury Pouly214f2262012-11-12 18:35:00 +0100794 int ret = 0;
795 if(create)
796 ret = create_upg(argc - optind, argv + optind);
797 else if(extract)
798 ret = extract_upg(argc - optind, argv + optind);
799 else
Amaury Poulycb09e362012-11-03 02:16:01 +0100800 {
Amaury Pouly214f2262012-11-12 18:35:00 +0100801 printf("Die from lack of action\n");
802 ret = 1;
Amaury Poulycb09e362012-11-03 02:16:01 +0100803 }
Amaury Poulycb09e362012-11-03 02:16:01 +0100804
805 color(OFF);
806
807 return ret;
808}
809