//TODO: The fwrite/fread error checking was broken. //Maybe the MS runtime is returning the number of bytes written instead of the element count? BOOL __stdcall np_sign_file(s8 *fname) { u8 padding_data[0x10] = { 0xbc, 0x3f, 0x7a, 0x48, 0xaf, 0x45, 0xef, 0x28, 0x3a, 0x05, 0x98, 0x10, 0xbc, 0x3f, 0x7a, 0x48 }; keyset_t *ks; FILE *fp = NULL; u8 *buffer = NULL; u32 length; u32 padding; u8 hash[0x14], R[0x15], S[0x15]; //Try to find keyset. if((ks = keyset_find_by_name(CONFIG_NP_SIG_KNAME)) == NULL) return FALSE; if((fp = fopen(fname, "r+b")) == NULL) return FALSE; fseek(fp, 0, SEEK_END); length = ftell(fp); padding = length % 0x10; if(padding > 0) { fwrite(padding_data, sizeof(u8), padding, fp); length += padding; } fseek(fp, 0, SEEK_SET); if((buffer = (u8 *)calloc(length, sizeof(char))) == NULL) { fclose(fp); return FALSE; } fread(buffer, sizeof(u8), length, fp); //Generate header hash. sha1(buffer, length, hash); //Generate signature. /* TODO: Set the right curve and private key */ ecdsa_set_curve(ks->ctype | USE_VSH_CURVE); ecdsa_set_pub(ks->pub); ecdsa_set_priv(ks->priv); ecdsa_sign(hash, R, S); fseek(fp, 0, SEEK_END); fwrite(R + 1, 0x14, 1, fp); fwrite(S + 1, 0x14, 1, fp); /* Let's be as stupid as sony here... */ fwrite(hash + 0xC, 8, 1, fp); free(buffer); fclose(fp); return TRUE; }
int add_npdrm_footer_sig(const char *filename) { FILE *fp; uint8_t s[21]; uint8_t r[21]; uint8_t hash[20]; static char padding[] = { 0x8b, 0x3f, 0x7a,0x48, 0xaf, 0x45, 0xef, 0x28, 0x3a, 0x05, 0x98, 0x10, 0xbc, 0x3f, 0x7a, 0x48 }; keyset_t *keyset = find_keyset_by_name("NP_sig"); if ( !keyset) return 0; fp = fopen(filename, "r+b"); if (!fp) return 0; fseek(fp, 0, SEEK_END); size_t size = ftell (fp); // Error ? SCETool takes left_not_aligned as (size & 0xF) size_t left_not_aligned = (0x10 - (size & 0xF)) & 0x0F; if (left_not_aligned) { fwrite(padding, 1, left_not_aligned, fp); size += left_not_aligned; } fseek(fp, 0, SEEK_SET); uint8_t *buffer = malloc(size); if (!buffer) { fclose(fp); return 0; } if(fread(buffer, 1, size, fp) != size) return 0; sha1(buffer, size, hash); ecdsa_set_curve(keyset->ctype | 0x40); ecdsa_set_pub(keyset->pub_key); ecdsa_set_priv(keyset->priv_key); ecdsa_sign(r, s, hash); fseek(fp, 0, SEEK_END); fwrite(&r[1], 20, 1, fp); fwrite(&s[1], 20, 1, fp); fwrite(&hash[12], 8, 1, fp); free(buffer); fclose(fp); return 1; }
int edata_sign_free(u8 *edata_buf, u8 *pgd_key) { MAC_KEY mkey; AES_ctx aes; u8 sha1_hash[20], license_key[16]; int flag, i; printf("re-sign EDATA ...\n"); flag = *(u8*)(edata_buf+15); // get license_key if(flag&1){ sceDrmBBMacInit(&mkey, 3); sceDrmBBMacUpdate(&mkey, edata_buf, 0x80); bbmac_getkey(&mkey, edata_buf+0x80, license_key); if(verbose) hex_dump("license key", license_key, 16); } // change to use free license *(u32*)(edata_buf+8) = 0x01000000; // build ecdsa ecdsa_set_curve(&ecdsa_app); ecdsa_set_priv(priv_key_edata); SHA1(edata_buf, 0x58, sha1_hash); ecdsa_sign(sha1_hash, edata_buf+0x58, edata_buf+0x6c, NULL); // build BBMAC if(flag&1){ sceDrmBBMacInit(&mkey, 3); sceDrmBBMacUpdate(&mkey, edata_buf, 0x80); sceDrmBBMacFinal(&mkey, edata_buf+0x80, license_key); bbmac_build_final2(3, edata_buf+0x80); } // build PGD key sceNpDrmGetFixedKey(pgd_key, (char*)(edata_buf+16), 0x01000000); if(verbose) hex_dump("get_fixed_key", pgd_key, 16); if(flag&1){ for(i=0; i<16; i++){ pgd_key[i] ^= license_key[i]; } } AES_set_key(&aes, edat_aeskey, 128); AES_decrypt(&aes, pgd_key, pgd_key); if(verbose) hex_dump("new PGD key", pgd_key, 16); return 0; }
static void get_keys(const char *suffix) { if (key_get(type, suffix, &ks) < 0) fail("key_get failed"); if (ks.pub_avail < 0) fail("no public key available"); if (ks.priv_avail < 0) fail("no private key available"); if (ecdsa_set_curve(ks.ctype) < 0) fail("ecdsa_set_curve failed"); ecdsa_set_pub(ks.pub); ecdsa_set_priv(ks.priv); }