Beispiel #1
0
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;
}
Beispiel #2
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;
}