diff options
Diffstat (limited to 'utils/nwztools/upgtools/upgtool.c')
-rw-r--r-- | utils/nwztools/upgtools/upgtool.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/utils/nwztools/upgtools/upgtool.c b/utils/nwztools/upgtools/upgtool.c index 065cede63c..3a8cf6174b 100644 --- a/utils/nwztools/upgtools/upgtool.c +++ b/utils/nwztools/upgtools/upgtool.c | |||
@@ -47,6 +47,7 @@ static int g_model_index = -1; | |||
47 | static char *g_kas = NULL; | 47 | static char *g_kas = NULL; |
48 | static char *g_key = NULL; | 48 | static char *g_key = NULL; |
49 | static char *g_sig = NULL; | 49 | static char *g_sig = NULL; |
50 | static int g_nr_threads = 1; | ||
50 | 51 | ||
51 | enum keysig_search_method_t g_keysig_search = KEYSIG_SEARCH_NONE; | 52 | enum keysig_search_method_t g_keysig_search = KEYSIG_SEARCH_NONE; |
52 | 53 | ||
@@ -74,6 +75,18 @@ struct nwz_model_t | |||
74 | char *sig; | 75 | char *sig; |
75 | }; | 76 | }; |
76 | 77 | ||
78 | /** Firmware format | ||
79 | * | ||
80 | * The firmware starts with the MD5 hash of the entire file (except the MD5 hash | ||
81 | * itself of course). This is used to check that the file was not corrupted. | ||
82 | * The remaining of the file is encrypted (using DES) with the model key. The | ||
83 | * encrypted part starts with a header containing the model signature and the | ||
84 | * number of files. Since the header is encrypted, decrypting the header with | ||
85 | * the key and finding the right signature serves to authenticate the firmware. | ||
86 | * The header is followed by N entries (where N is the number of files) giving | ||
87 | * the offset, within the file, and size of each file. Note that the files in | ||
88 | * the firmware have no name. */ | ||
89 | |||
77 | struct upg_md5_t | 90 | struct upg_md5_t |
78 | { | 91 | { |
79 | uint8_t md5[16]; | 92 | uint8_t md5[16]; |
@@ -81,7 +94,7 @@ struct upg_md5_t | |||
81 | 94 | ||
82 | struct upg_header_t | 95 | struct upg_header_t |
83 | { | 96 | { |
84 | char sig[NWZ_SIG_SIZE]; | 97 | uint8_t sig[NWZ_SIG_SIZE]; |
85 | uint32_t nr_files; | 98 | uint32_t nr_files; |
86 | uint32_t pad; // make sure structure size is a multiple of 8 | 99 | uint32_t pad; // make sure structure size is a multiple of 8 |
87 | } __attribute__((packed)); | 100 | } __attribute__((packed)); |
@@ -166,6 +179,7 @@ struct nwz_model_t g_model_list[] = | |||
166 | /* The following keys were obtained by brute forcing firmware upgrades, | 179 | /* The following keys were obtained by brute forcing firmware upgrades, |
167 | * someone with a device needs to confirm that they work */ | 180 | * someone with a device needs to confirm that they work */ |
168 | { "nw-a82x", HAS_KEY | HAS_SIG, "", "4df06482", "07fa0b6e" }, | 181 | { "nw-a82x", HAS_KEY | HAS_SIG, "", "4df06482", "07fa0b6e" }, |
182 | { "nwz-a1x", HAS_KEY | HAS_SIG, "", "ec2888e2", "f62ced8a" }, | ||
169 | }; | 183 | }; |
170 | 184 | ||
171 | static int digit_value(char c) | 185 | static int digit_value(char c) |
@@ -286,7 +300,8 @@ static int get_key_and_sig(bool is_extract, void *encrypted_hdr) | |||
286 | { | 300 | { |
287 | cprintf(BLUE, "keysig Search\n"); | 301 | cprintf(BLUE, "keysig Search\n"); |
288 | cprintf_field(" Method: ", "%s\n", keysig_search_desc[g_keysig_search].name); | 302 | cprintf_field(" Method: ", "%s\n", keysig_search_desc[g_keysig_search].name); |
289 | bool ok = keysig_search_desc[g_keysig_search].fn(encrypted_hdr, &upg_notify_keysig, keysig); | 303 | bool ok = keysig_search(g_keysig_search, encrypted_hdr, 8, |
304 | &upg_notify_keysig, keysig, g_nr_threads); | ||
290 | cprintf(GREEN, " Result: "); | 305 | cprintf(GREEN, " Result: "); |
291 | cprintf(ok ? YELLOW : RED, "%s\n", ok ? "Key found" : "No key found"); | 306 | cprintf(ok ? YELLOW : RED, "%s\n", ok ? "Key found" : "No key found"); |
292 | if(!ok) | 307 | if(!ok) |
@@ -576,6 +591,7 @@ static void usage(void) | |||
576 | printf(" -c/--no-color\t\tDisable color output\n"); | 591 | printf(" -c/--no-color\t\tDisable color output\n"); |
577 | printf(" -m/--model <model>\tSelect model (or ? to list them)\n"); | 592 | printf(" -m/--model <model>\tSelect model (or ? to list them)\n"); |
578 | printf(" -l/--search <method>\tTry to find the keysig (implies -e)\n"); | 593 | printf(" -l/--search <method>\tTry to find the keysig (implies -e)\n"); |
594 | printf(" -t/--threads <nr>\tSpecify number of threads to find the keysig\n"); | ||
579 | printf(" -a/--kas <kas>\tForce KAS\n"); | 595 | printf(" -a/--kas <kas>\tForce KAS\n"); |
580 | printf(" -k/--key <key>\tForce key\n"); | 596 | printf(" -k/--key <key>\tForce key\n"); |
581 | printf(" -s/--sig <sig>\tForce sig\n"); | 597 | printf(" -s/--sig <sig>\tForce sig\n"); |
@@ -594,7 +610,7 @@ int main(int argc, char **argv) | |||
594 | 610 | ||
595 | if(argc <= 1) | 611 | if(argc <= 1) |
596 | usage(); | 612 | usage(); |
597 | 613 | ||
598 | while(1) | 614 | while(1) |
599 | { | 615 | { |
600 | static struct option long_options[] = | 616 | static struct option long_options[] = |
@@ -610,10 +626,11 @@ int main(int argc, char **argv) | |||
610 | {"sig", required_argument, 0, 's'}, | 626 | {"sig", required_argument, 0, 's'}, |
611 | {"extract", no_argument, 0, 'e'}, | 627 | {"extract", no_argument, 0, 'e'}, |
612 | {"create", no_argument, 0 ,'c'}, | 628 | {"create", no_argument, 0 ,'c'}, |
629 | {"threads", required_argument, 0, 't'}, | ||
613 | {0, 0, 0, 0} | 630 | {0, 0, 0, 0} |
614 | }; | 631 | }; |
615 | 632 | ||
616 | int c = getopt_long(argc, argv, "?dnfo:m:l:a:k:s:ec", long_options, NULL); | 633 | int c = getopt_long(argc, argv, "?dnfo:m:l:a:k:s:ect:", long_options, NULL); |
617 | if(c == -1) | 634 | if(c == -1) |
618 | break; | 635 | break; |
619 | switch(c) | 636 | switch(c) |
@@ -665,6 +682,14 @@ int main(int argc, char **argv) | |||
665 | case 'c': | 682 | case 'c': |
666 | create = true; | 683 | create = true; |
667 | break; | 684 | break; |
685 | case 't': | ||
686 | g_nr_threads = strtol(optarg, NULL, 0); | ||
687 | if(g_nr_threads < 1 || g_nr_threads > 128) | ||
688 | { | ||
689 | cprintf(GREY, "Invalid number of threads\n"); | ||
690 | return 1; | ||
691 | } | ||
692 | break; | ||
668 | default: | 693 | default: |
669 | abort(); | 694 | abort(); |
670 | } | 695 | } |