static int get_key_and_sig(bool is_extract, void *buf) { static char keysig[NWZ_KEYSIG_SIZE]; static char kas[NWZ_KAS_SIZE]; /* database lookup */ if(g_model_index != -1) g_kas = g_model_list[g_model_index].kas; /* always prefer KAS because it contains everything */ if(g_kas) { if(strlen(g_kas) != NWZ_KAS_SIZE) { cprintf(GREY, "The KAS has wrong length (must be %d hex digits)\n", NWZ_KAS_SIZE); return 4; } g_key = keysig; g_sig = keysig + NWZ_KEY_SIZE; decrypt_keysig(g_kas, g_key, g_sig); } /* Otherwise require key and signature */ else if(g_key && g_sig) { /* check key and signature size */ if(strlen(g_key) != 8) { cprintf(GREY, "The specified key has wrong length (must be 8 hex digits)\n"); return 4; } if(strlen(g_sig) != 8) { cprintf(GREY, "The specified sig has wrong length (must be 8 hex digits)\n"); return 5; } } /* for extraction, we offer a brute force search method from the MD5 */ else if(is_extract && g_keysig_search != KEYSIG_SEARCH_NONE) { struct upg_md5_t *md5 = (void *)buf; void *encrypted_hdr = (md5 + 1); cprintf(BLUE, "keysig Search\n"); cprintf_field(" Method: ", "%s\n", keysig_search_desc[g_keysig_search].name); bool ok = keysig_search(g_keysig_search, encrypted_hdr, 8, &upg_notify_keysig, keysig, g_nr_threads); cprintf(GREEN, " Result: "); cprintf(ok ? YELLOW : RED, "%s\n", ok ? "Key found" : "No key found"); if(!ok) return 2; } else { cprintf(GREY, "A KAS or a keysig is needed to decrypt the firmware\n"); cprintf(GREY, "You have the following options(see help for more details):\n"); cprintf(GREY, "- select a model with a known KAS\n"); cprintf(GREY, "- specify an explicit KAS or key+sig\n"); if(is_extract) cprintf(GREY, "- let me try to find the keysig by brute force\n"); return 1; } /* If we only have the key and signature, we can create a "fake" KAS * that decrypts to the same key and signature. Since it is not unique, * it will generally not match the "official" one from Sony but will produce * valid files anyway */ if(!g_kas) { /* This is useful to print the KAS for the user when brute-forcing since * the process will produce a key+sig and the database requires a KAS */ g_kas = kas; encrypt_keysig(g_kas, g_key, g_sig); } cprintf(BLUE, "Keys\n"); cprintf_field(" KAS: ", "%."STR(NWZ_KAS_SIZE)"s\n", g_kas); cprintf_field(" Key: ", "%."STR(NWZ_KEY_SIZE)"s\n", g_key); cprintf_field(" Sig: ", "%."STR(NWZ_SIG_SIZE)"s\n", g_sig); return 0; }
static int get_key_and_sig(bool is_extract, void *encrypted_hdr) { static char keysig[NWZ_KEYSIG_SIZE]; static char kas[NWZ_KAS_SIZE]; /* database lookup */ if(g_model_index != -1) { if(g_model_list[g_model_index].flags & HAS_KAS) g_kas = g_model_list[g_model_index].kas; if(g_model_list[g_model_index].flags & HAS_KEY) g_key = g_model_list[g_model_index].key; if(g_model_list[g_model_index].flags & HAS_SIG) g_sig = g_model_list[g_model_index].sig; } /* always prefer KAS because it contains everything */ if(g_kas) { if(strlen(g_kas) != NWZ_KAS_SIZE) { cprintf(GREY, "The KAS has wrong length (must be %d hex digits)\n", NWZ_KAS_SIZE); return 4; } g_key = keysig; g_sig = keysig + NWZ_KEY_SIZE; decrypt_keysig(g_kas, g_key, g_sig); } /* fall back to key and signature otherwise. The signature is not required * when extracting but prevents from checking decryption */ else if(g_key && (is_extract || g_sig)) { if(strlen(g_key) != 8) { cprintf(GREY, "The specified key has wrong length (must be 8 hex digits)\n"); return 4; } /* if there is a signature, it must have the correct size */ if(g_sig) { if(strlen(g_sig) != 8) { cprintf(GREY, "The specified sig has wrong length (must be 8 hex digits)\n"); return 5; } } else { cprintf(GREY, "Warning: you have specified a key but no sig, I won't be able to do any checks\n"); } } /* for extraction, we offer a brute force search method from the MD5 */ else if(is_extract && g_keysig_search != KEYSIG_SEARCH_NONE) { cprintf(BLUE, "keysig Search\n"); cprintf_field(" Method: ", "%s\n", keysig_search_desc[g_keysig_search].name); bool ok = keysig_search(g_keysig_search, encrypted_hdr, 8, &upg_notify_keysig, keysig, g_nr_threads); cprintf(GREEN, " Result: "); cprintf(ok ? YELLOW : RED, "%s\n", ok ? "Key found" : "No key found"); if(!ok) return 2; } else { cprintf(GREY, "A KAS or a keysig is needed to decrypt the firmware\n"); cprintf(GREY, "You have the following options(see help for more details):\n"); cprintf(GREY, "- select a model with a known KAS\n"); cprintf(GREY, "- specify an explicit KAS or key+sig\n"); if(is_extract) cprintf(GREY, "- let me try to find the keysig(slow !)\n"); return 1; } /* If we only have the key and signature, we can create a "fake" KAS * that decrypts to the same key and signature. Since it is not unique, * it will generally not match the "official" one from Sony but will produce * valid files anyway */ if(!g_kas) { if(!g_sig) { /* if we extract and don't have a signature, just use a random * one, we cannot check it anyway */ g_sig = keysig; memset(g_sig, '?', NWZ_SIG_SIZE); } g_kas = kas; encrypt_keysig(g_kas, g_key, g_sig); } cprintf(BLUE, "Keys\n"); cprintf_field(" KAS: ", "%."STR(NWZ_KAS_SIZE)"s\n", g_kas); cprintf_field(" Key: ", "%."STR(NWZ_KEY_SIZE)"s\n", g_key); if(g_sig) cprintf_field(" Sig: ", "%."STR(NWZ_SIG_SIZE)"s\n", g_sig); return 0; }