CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/ELF/PrxDecrypter.cpp
Views: 1401
#include <algorithm>1#include <array>2#include <string.h>34extern "C"5{6#include "ext/libkirk/kirk_engine.h"7#include "ext/libkirk/SHA1.h"8}9#include "Common/Common.h"10#include "Common/Log.h"11#include "Common/Swap.h"12#include "Core/ELF/PrxDecrypter.h"1314#define ROUNDUP16(x) (((x)+15)&~15)1516// Thank you PSARDUMPER & JPCSP keys1718// PRXDecrypter 16-byte tag keys.19static const u8 keys260_0[] = {0xC3, 0x24, 0x89, 0xD3, 0x80, 0x87, 0xB2, 0x4E, 0x4C, 0xD7, 0x49, 0xE4, 0x9D, 0x1D, 0x34, 0xD1};20static const u8 keys260_1[] = {0xF3, 0xAC, 0x6E, 0x7C, 0x04, 0x0A, 0x23, 0xE7, 0x0D, 0x33, 0xD8, 0x24, 0x73, 0x39, 0x2B, 0x4A};21static const u8 keys260_2[] = {0x72, 0xB4, 0x39, 0xFF, 0x34, 0x9B, 0xAE, 0x82, 0x30, 0x34, 0x4A, 0x1D, 0xA2, 0xD8, 0xB4, 0x3C};22static const u8 keys280_0[] = {0xCA, 0xFB, 0xBF, 0xC7, 0x50, 0xEA, 0xB4, 0x40, 0x8E, 0x44, 0x5C, 0x63, 0x53, 0xCE, 0x80, 0xB1};23static const u8 keys280_1[] = {0x40, 0x9B, 0xC6, 0x9B, 0xA9, 0xFB, 0x84, 0x7F, 0x72, 0x21, 0xD2, 0x36, 0x96, 0x55, 0x09, 0x74};24static const u8 keys280_2[] = {0x03, 0xA7, 0xCC, 0x4A, 0x5B, 0x91, 0xC2, 0x07, 0xFF, 0xFC, 0x26, 0x25, 0x1E, 0x42, 0x4B, 0xB5};25static const u8 keys300_0[] = {0x9F, 0x67, 0x1A, 0x7A, 0x22, 0xF3, 0x59, 0x0B, 0xAA, 0x6D, 0xA4, 0xC6, 0x8B, 0xD0, 0x03, 0x77};26static const u8 keys300_1[] = {0x15, 0x07, 0x63, 0x26, 0xDB, 0xE2, 0x69, 0x34, 0x56, 0x08, 0x2A, 0x93, 0x4E, 0x4B, 0x8A, 0xB2};27static const u8 keys300_2[] = {0x56, 0x3B, 0x69, 0xF7, 0x29, 0x88, 0x2F, 0x4C, 0xDB, 0xD5, 0xDE, 0x80, 0xC6, 0x5C, 0xC8, 0x73};28static const u8 keys303_0[] = {0x7b, 0xa1, 0xe2, 0x5a, 0x91, 0xb9, 0xd3, 0x13, 0x77, 0x65, 0x4a, 0xb7, 0xc2, 0x8a, 0x10, 0xaf};29static const u8 keys310_0[] = {0xa2, 0x41, 0xe8, 0x39, 0x66, 0x5b, 0xfa, 0xbb, 0x1b, 0x2d, 0x6e, 0x0e, 0x33, 0xe5, 0xd7, 0x3f};30static const u8 keys310_1[] = {0xA4, 0x60, 0x8F, 0xAB, 0xAB, 0xDE, 0xA5, 0x65, 0x5D, 0x43, 0x3A, 0xD1, 0x5E, 0xC3, 0xFF, 0xEA};31static const u8 keys310_2[] = {0xE7, 0x5C, 0x85, 0x7A, 0x59, 0xB4, 0xE3, 0x1D, 0xD0, 0x9E, 0xCE, 0xC2, 0xD6, 0xD4, 0xBD, 0x2B};32static const u8 keys310_3[] = {0x2E, 0x00, 0xF6, 0xF7, 0x52, 0xCF, 0x95, 0x5A, 0xA1, 0x26, 0xB4, 0x84, 0x9B, 0x58, 0x76, 0x2F};33static const u8 keys330_0[] = {0x3B, 0x9B, 0x1A, 0x56, 0x21, 0x80, 0x14, 0xED, 0x8E, 0x8B, 0x08, 0x42, 0xFA, 0x2C, 0xDC, 0x3A};34static const u8 keys330_1[] = {0xE8, 0xBE, 0x2F, 0x06, 0xB1, 0x05, 0x2A, 0xB9, 0x18, 0x18, 0x03, 0xE3, 0xEB, 0x64, 0x7D, 0x26};35static const u8 keys330_2[] = {0xAB, 0x82, 0x25, 0xD7, 0x43, 0x6F, 0x6C, 0xC1, 0x95, 0xC5, 0xF7, 0xF0, 0x63, 0x73, 0x3F, 0xE7};36static const u8 keys330_3[] = {0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F, 0x38, 0x4C, 0x4D, 0x96, 0xBD, 0x49, 0xEC, 0x9B};37static const u8 keys330_4[] = {0xEC, 0x3B, 0xD2, 0xC0, 0xFA, 0xC1, 0xEE, 0xB9, 0x9A, 0xBC, 0xFF, 0xA3, 0x89, 0xF2, 0x60, 0x1F};38static const u8 keys360_0[] = {0x3C, 0x2B, 0x51, 0xD4, 0x2D, 0x85, 0x47, 0xDA, 0x2D, 0xCA, 0x18, 0xDF, 0xFE, 0x54, 0x09, 0xED};39static const u8 keys360_1[] = {0x31, 0x1F, 0x98, 0xD5, 0x7B, 0x58, 0x95, 0x45, 0x32, 0xAB, 0x3A, 0xE3, 0x89, 0x32, 0x4B, 0x34};40static const u8 keys370_0[] = {0x26, 0x38, 0x0A, 0xAC, 0xA5, 0xD8, 0x74, 0xD1, 0x32, 0xB7, 0x2A, 0xBF, 0x79, 0x9E, 0x6D, 0xDB};41static const u8 keys370_1[] = {0x53, 0xE7, 0xAB, 0xB9, 0xC6, 0x4A, 0x4B, 0x77, 0x92, 0x17, 0xB5, 0x74, 0x0A, 0xDA, 0xA9, 0xEA};42static const u8 keys370_2[] = {0x71, 0x10, 0xF0, 0xA4, 0x16, 0x14, 0xD5, 0x93, 0x12, 0xFF, 0x74, 0x96, 0xDF, 0x1F, 0xDA, 0x89};43static const u8 keys390_0[] = {0x45, 0xEF, 0x5C, 0x5D, 0xED, 0x81, 0x99, 0x84, 0x12, 0x94, 0x8F, 0xAB, 0xE8, 0x05, 0x6D, 0x7D};44static const u8 keys390_1[] = {0x70, 0x1B, 0x08, 0x25, 0x22, 0xA1, 0x4D, 0x3B, 0x69, 0x21, 0xF9, 0x71, 0x0A, 0xA8, 0x41, 0xA9};45static const u8 keys500_0[] = {0xEB, 0x1B, 0x53, 0x0B, 0x62, 0x49, 0x32, 0x58, 0x1F, 0x83, 0x0A, 0xF4, 0x99, 0x3D, 0x75, 0xD0};46static const u8 keys500_1[] = {0xBA, 0xE2, 0xA3, 0x12, 0x07, 0xFF, 0x04, 0x1B, 0x64, 0xA5, 0x11, 0x85, 0xF7, 0x2F, 0x99, 0x5B};47static const u8 keys500_2[] = {0x2C, 0x8E, 0xAF, 0x1D, 0xFF, 0x79, 0x73, 0x1A, 0xAD, 0x96, 0xAB, 0x09, 0xEA, 0x35, 0x59, 0x8B};48static const u8 keys500_c[] = {0xA3, 0x5D, 0x51, 0xE6, 0x56, 0xC8, 0x01, 0xCA, 0xE3, 0x77, 0xBF, 0xCD, 0xFF, 0x24, 0xDA, 0x4D};49static const u8 keys505_a[] = {0x7B, 0x94, 0x72, 0x27, 0x4C, 0xCC, 0x54, 0x3B, 0xAE, 0xDF, 0x46, 0x37, 0xAC, 0x01, 0x4D, 0x87};50static const u8 keys505_0[] = {0x2E, 0x8E, 0x97, 0xA2, 0x85, 0x42, 0x70, 0x73, 0x18, 0xDA, 0xA0, 0x8A, 0xF8, 0x62, 0xA2, 0xB0};51static const u8 keys505_1[] = {0x58, 0x2A, 0x4C, 0x69, 0x19, 0x7B, 0x83, 0x3D, 0xD2, 0x61, 0x61, 0xFE, 0x14, 0xEE, 0xAA, 0x11};52static const u8 keys570_5k[] = {0x6D, 0x72, 0xA4, 0xBA, 0x7F, 0xBF, 0xD1, 0xF1, 0xA9, 0xF3, 0xBB, 0x07, 0x1B, 0xC0, 0xB3, 0x66};53static const u8 keys600_1[] = {0xE3, 0x52, 0x39, 0x97, 0x3B, 0x84, 0x41, 0x1C, 0xC3, 0x23, 0xF1, 0xB8, 0xA9, 0x09, 0x4B, 0xF0};54static const u8 keys600_2[] = {0xE1, 0x45, 0x93, 0x2C, 0x53, 0xE2, 0xAB, 0x06, 0x6F, 0xB6, 0x8F, 0x0B, 0x66, 0x91, 0xE7, 0x1E};55static const u8 keys620_0[] = {0xD6, 0xBD, 0xCE, 0x1E, 0x12, 0xAF, 0x9A, 0xE6, 0x69, 0x30, 0xDE, 0xDA, 0x88, 0xB8, 0xFF, 0xFB};56static const u8 keys620_1[] = {0x1D, 0x13, 0xE9, 0x50, 0x04, 0x73, 0x3D, 0xD2, 0xE1, 0xDA, 0xB9, 0xC1, 0xE6, 0x7B, 0x25, 0xA7};57static const u8 keys620_a[] = {0xAC, 0x34, 0xBA, 0xB1, 0x97, 0x8D, 0xAE, 0x6F, 0xBA, 0xE8, 0xB1, 0xD6, 0xDF, 0xDF, 0xF1, 0xA2};58static const u8 keys620_e[] = {0xB1, 0xB3, 0x7F, 0x76, 0xC3, 0xFB, 0x88, 0xE6, 0xF8, 0x60, 0xD3, 0x35, 0x3C, 0xA3, 0x4E, 0xF3};59static const u8 keys620_5[] = {0xF1, 0xBC, 0x17, 0x07, 0xAE, 0xB7, 0xC8, 0x30, 0xD8, 0x34, 0x9D, 0x40, 0x6A, 0x8E, 0xDF, 0x4E};60static const u8 keys620_5k[] = {0x41, 0x8A, 0x35, 0x4F, 0x69, 0x3A, 0xDF, 0x04, 0xFD, 0x39, 0x46, 0xA2, 0x5C, 0x2D, 0xF2, 0x21};61static const u8 keys620_5v[] = {0xF2, 0x8F, 0x75, 0xA7, 0x31, 0x91, 0xCE, 0x9E, 0x75, 0xBD, 0x27, 0x26, 0xB4, 0xB4, 0x0C, 0x32};62static const u8 keys630_k1[] = {0x36, 0xB0, 0xDC, 0xFC, 0x59, 0x2A, 0x95, 0x1D, 0x80, 0x2D, 0x80, 0x3F, 0xCD, 0x30, 0xA0, 0x1B};63static const u8 keys630_k2[] = {0xd4, 0x35, 0x18, 0x02, 0x29, 0x68, 0xfb, 0xa0, 0x6a, 0xa9, 0xa5, 0xed, 0x78, 0xfd, 0x2e, 0x9d};64static const u8 keys630_k3[] = {0x23, 0x8D, 0x3D, 0xAE, 0x41, 0x50, 0xA0, 0xFA, 0xF3, 0x2F, 0x32, 0xCE, 0xC7, 0x27, 0xCD, 0x50};65static const u8 keys630_k4[] = {0xAA, 0xA1, 0xB5, 0x7C, 0x93, 0x5A, 0x95, 0xBD, 0xEF, 0x69, 0x16, 0xFC, 0x2B, 0x92, 0x31, 0xDD};66static const u8 keys630_k5[] = {0x87, 0x37, 0x21, 0xCC, 0x65, 0xAE, 0xAA, 0x5F, 0x40, 0xF6, 0x6F, 0x2A, 0x86, 0xC7, 0xA1, 0xC8};67static const u8 keys630_k6[] = {0x8D, 0xDB, 0xDC, 0x5C, 0xF2, 0x70, 0x2B, 0x40, 0xB2, 0x3D, 0x00, 0x09, 0x61, 0x7C, 0x10, 0x60};68static const u8 keys630_k7[] = {0x77, 0x1C, 0x06, 0x5F, 0x53, 0xEC, 0x3F, 0xFC, 0x22, 0xCE, 0x5A, 0x27, 0xFF, 0x78, 0xA8, 0x48};69static const u8 keys630_k8[] = {0x81, 0xD1, 0x12, 0x89, 0x35, 0xC8, 0xEA, 0x8B, 0xE0, 0x02, 0x2D, 0x2D, 0x6A, 0x18, 0x67, 0xB8};70static const u8 keys636_k1[] = {0x07, 0xE3, 0x08, 0x64, 0x7F, 0x60, 0xA3, 0x36, 0x6A, 0x76, 0x21, 0x44, 0xC9, 0xD7, 0x06, 0x83};71static const u8 keys636_k2[] = {0x91, 0xF2, 0x02, 0x9E, 0x63, 0x32, 0x30, 0xA9, 0x1D, 0xDA, 0x0B, 0xA8, 0xB7, 0x41, 0xA3, 0xCC};72static const u8 keys638_k4[] = {0x98, 0x43, 0xFF, 0x85, 0x68, 0xB2, 0xDB, 0x3B, 0xD4, 0x22, 0xD0, 0x4F, 0xAB, 0x5F, 0x0A, 0x31};73static const u8 keys639_k3[] = {0x01, 0x7B, 0xF0, 0xE9, 0xBE, 0x9A, 0xDD, 0x54, 0x37, 0xEA, 0x0E, 0xC4, 0xD6, 0x4D, 0x8E, 0x9E};74static const u8 keys660_k1[] = {0x76, 0xF2, 0x6C, 0x0A, 0xCA, 0x3A, 0xBA, 0x4E, 0xAC, 0x76, 0xD2, 0x40, 0xF5, 0xC3, 0xBF, 0xF9};75static const u8 keys660_k2[] = {0x7A, 0x3E, 0x55, 0x75, 0xB9, 0x6A, 0xFC, 0x4F, 0x3E, 0xE3, 0xDF, 0xB3, 0x6C, 0xE8, 0x2A, 0x82};76static const u8 keys660_k3[] = {0xFA, 0x79, 0x09, 0x36, 0xE6, 0x19, 0xE8, 0xA4, 0xA9, 0x41, 0x37, 0x18, 0x81, 0x02, 0xE9, 0xB3};77static const u8 keys660_v1[] = {0xBA, 0x76, 0x61, 0x47, 0x8B, 0x55, 0xA8, 0x72, 0x89, 0x15, 0x79, 0x6D, 0xD7, 0x2F, 0x78, 0x0E};78static const u8 keys660_v2[] = {0xF9, 0x4A, 0x6B, 0x96, 0x79, 0x3F, 0xEE, 0x0A, 0x04, 0xC8, 0x8D, 0x7E, 0x5F, 0x38, 0x3A, 0xCF};79static const u8 keys660_v3[] = {0x88, 0xAF, 0x18, 0xE9, 0xC3, 0xAA, 0x6B, 0x56, 0xF7, 0xC5, 0xA8, 0xBF, 0x1A, 0x84, 0xE9, 0xF3};80static const u8 keys660_v4[] = {0xD1, 0xB0, 0xAE, 0xC3, 0x24, 0x36, 0x13, 0x49, 0xD6, 0x49, 0xD7, 0x88, 0xEA, 0xA4, 0x99, 0x86};81static const u8 keys660_v5[] = {0xCB, 0x93, 0x12, 0x38, 0x31, 0xC0, 0x2D, 0x2E, 0x7A, 0x18, 0x5C, 0xAC, 0x92, 0x93, 0xAB, 0x32};82static const u8 keys660_v6[] = {0x92, 0x8C, 0xA4, 0x12, 0xD6, 0x5C, 0x55, 0x31, 0x5B, 0x94, 0x23, 0x9B, 0x62, 0xB3, 0xDB, 0x47};83static const u8 keys660_k4[] = {0xC8, 0xA0, 0x70, 0x98, 0xAE, 0xE6, 0x2B, 0x80, 0xD7, 0x91, 0xE6, 0xCA, 0x4C, 0xA9, 0x78, 0x4E};84static const u8 keys660_k5[] = {0xBF, 0xF8, 0x34, 0x02, 0x84, 0x47, 0xBD, 0x87, 0x1C, 0x52, 0x03, 0x23, 0x79, 0xBB, 0x59, 0x81};85static const u8 keys660_k6[] = {0xD2, 0x83, 0xCC, 0x63, 0xBB, 0x10, 0x15, 0xE7, 0x7B, 0xC0, 0x6D, 0xEE, 0x34, 0x9E, 0x4A, 0xFA};86static const u8 keys660_k7[] = {0xEB, 0xD9, 0x1E, 0x05, 0x3C, 0xAE, 0xAB, 0x62, 0xE3, 0xB7, 0x1F, 0x37, 0xE5, 0xCD, 0x68, 0xC3};87static const u8 keys660_v7[] = {0xC5, 0x9C, 0x77, 0x9C, 0x41, 0x01, 0xE4, 0x85, 0x79, 0xC8, 0x71, 0x63, 0xA5, 0x7D, 0x4F, 0xFB};88static const u8 keys660_v8[] = {0x86, 0xA0, 0x7D, 0x4D, 0xB3, 0x6B, 0xA2, 0xFD, 0xF4, 0x15, 0x85, 0x70, 0x2D, 0x6A, 0x0D, 0x3A};89static const u8 keys660_k8[] = {0x85, 0x93, 0x1F, 0xED, 0x2C, 0x4D, 0xA4, 0x53, 0x59, 0x9C, 0x3F, 0x16, 0xF3, 0x50, 0xDE, 0x46};90static const u8 key_21C0[] = {0x6A, 0x19, 0x71, 0xF3, 0x18, 0xDE, 0xD3, 0xA2, 0x6D, 0x3B, 0xDE, 0xC7, 0xBE, 0x98, 0xE2, 0x4C};91static const u8 key_2250[] = {0x50, 0xCC, 0x03, 0xAC, 0x3F, 0x53, 0x1A, 0xFA, 0x0A, 0xA4, 0x34, 0x23, 0x86, 0x61, 0x7F, 0x97};92static const u8 key_22E0[] = {0x66, 0x0F, 0xCB, 0x3B, 0x30, 0x75, 0xE3, 0x10, 0x0A, 0x95, 0x65, 0xC7, 0x3C, 0x93, 0x87, 0x22};93static const u8 key_2D80[] = {0x40, 0x02, 0xC0, 0xBF, 0x20, 0x02, 0xC0, 0xBF, 0x5C, 0x68, 0x2B, 0x95, 0x5F, 0x40, 0x7B, 0xB8};94static const u8 key_2D90[] = {0x55, 0x19, 0x35, 0x10, 0x48, 0xD8, 0x2E, 0x46, 0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F};95static const u8 key_2DA8[] = {0x80, 0x02, 0xC0, 0xBF, 0x00, 0x0A, 0xC0, 0xBF, 0x40, 0x03, 0xC0, 0xBF, 0x40, 0x00, 0x00, 0x00};96static const u8 key_2DB8[] = {0x4C, 0x2D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xB8, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};97static const u8 key_D91605F0[] = {0xB8, 0x8C, 0x45, 0x8B, 0xB6, 0xE7, 0x6E, 0xB8, 0x51, 0x59, 0xA6, 0x53, 0x7C, 0x5E, 0x86, 0x31};98static const u8 key_D91606F0[] = {0xED, 0x10, 0xE0, 0x36, 0xC4, 0xFE, 0x83, 0xF3, 0x75, 0x70, 0x5E, 0xF6, 0xA4, 0x40, 0x05, 0xF7};99static const u8 key_D91608F0[] = {0x5C, 0x77, 0x0C, 0xBB, 0xB4, 0xC2, 0x4F, 0xA2, 0x7E, 0x3B, 0x4E, 0xB4, 0xB4, 0xC8, 0x70, 0xAF};100static const u8 key_D91609F0[] = {0xD0, 0x36, 0x12, 0x75, 0x80, 0x56, 0x20, 0x43, 0xC4, 0x30, 0x94, 0x3E, 0x1C, 0x75, 0xD1, 0xBF};101static const u8 key_D9160AF0[] = {0x10, 0xA9, 0xAC, 0x16, 0xAE, 0x19, 0xC0, 0x7E, 0x3B, 0x60, 0x77, 0x86, 0x01, 0x6F, 0xF2, 0x63};102static const u8 key_D9160BF0[] = {0x83, 0x83, 0xF1, 0x37, 0x53, 0xD0, 0xBE, 0xFC, 0x8D, 0xA7, 0x32, 0x52, 0x46, 0x0A, 0xC2, 0xC2};103static const u8 key_D91611F0[] = {0x61, 0xB0, 0xC0, 0x58, 0x71, 0x57, 0xD9, 0xFA, 0x74, 0x67, 0x0E, 0x5C, 0x7E, 0x6E, 0x95, 0xB9};104static const u8 key_D91612F0[] = {0x9E, 0x20, 0xE1, 0xCD, 0xD7, 0x88, 0xDE, 0xC0, 0x31, 0x9B, 0x10, 0xAF, 0xC5, 0xB8, 0x73, 0x23};105static const u8 key_D91613F0[] = {0xEB, 0xFF, 0x40, 0xD8, 0xB4, 0x1A, 0xE1, 0x66, 0x91, 0x3B, 0x8F, 0x64, 0xB6, 0xFC, 0xB7, 0x12};106static const u8 key_D91614F0[] = {0xFD, 0xF7, 0xB7, 0x3C, 0x9F, 0xD1, 0x33, 0x95, 0x11, 0xB8, 0xB5, 0xBB, 0x54, 0x23, 0x73, 0x85};107static const u8 key_D91615F0[] = {0xC8, 0x03, 0xE3, 0x44, 0x50, 0xF1, 0xE7, 0x2A, 0x6A, 0x0D, 0xC3, 0x61, 0xB6, 0x8E, 0x5F, 0x51};108static const u8 key_D91616F0[] = {0x53, 0x03, 0xB8, 0x6A, 0x10, 0x19, 0x98, 0x49, 0x1C, 0xAF, 0x30, 0xE4, 0x25, 0x1B, 0x6B, 0x28};109static const u8 key_D91617F0[] = {0x02, 0xFA, 0x48, 0x73, 0x75, 0xAF, 0xAE, 0x0A, 0x67, 0x89, 0x2B, 0x95, 0x4B, 0x09, 0x87, 0xA3};110static const u8 key_D91618F0[] = {0x96, 0x96, 0x7C, 0xC3, 0xF7, 0x12, 0xDA, 0x62, 0x1B, 0xF6, 0x9A, 0x9A, 0x44, 0x44, 0xBC, 0x48};111static const u8 key_D91619F0[] = {0xE0, 0x32, 0xA7, 0x08, 0x6B, 0x2B, 0x29, 0x2C, 0xD1, 0x4D, 0x5B, 0xEE, 0xA8, 0xC8, 0xB4, 0xE9};112static const u8 key_D9161AF0[] = {0x27, 0xE5, 0xA7, 0x49, 0x52, 0xE1, 0x94, 0x67, 0x35, 0x66, 0x91, 0x0C, 0xE8, 0x9A, 0x25, 0x24};113static const u8 key_D91620F0[] = {0x52, 0x1C, 0xB4, 0x5F, 0x40, 0x3B, 0x9A, 0xDD, 0xAC, 0xFC, 0xEA, 0x92, 0xFD, 0xDD, 0xF5, 0x90};114static const u8 key_D91621F0[] = {0xD1, 0x91, 0x2E, 0xA6, 0x21, 0x14, 0x29, 0x62, 0xF6, 0xED, 0xAE, 0xCB, 0xDD, 0xA3, 0xBA, 0xFE};115static const u8 key_D91622F0[] = {0x59, 0x5D, 0x78, 0x4D, 0x21, 0xB2, 0x01, 0x17, 0x6C, 0x9A, 0xB5, 0x1B, 0xDA, 0xB7, 0xF9, 0xE6};116static const u8 key_D91623F0[] = {0xAA, 0x45, 0xEB, 0x4F, 0x62, 0xFB, 0xD1, 0x0D, 0x71, 0xD5, 0x62, 0xD2, 0xF5, 0xBF, 0xA5, 0x2F};117static const u8 key_D91624F0[] = {0x61, 0xB7, 0x26, 0xAF, 0x8B, 0xF1, 0x41, 0x58, 0x83, 0x6A, 0xC4, 0x92, 0x12, 0xCB, 0xB1, 0xE9};118static const u8 key_D91628F0[] = {0x49, 0xA4, 0xFC, 0x66, 0xDC, 0xE7, 0x62, 0x21, 0xDB, 0x18, 0xA7, 0x50, 0xD6, 0xA8, 0xC1, 0xB6};119static const u8 key_D91680F0[] = {0x2C, 0x22, 0x9B, 0x12, 0x36, 0x74, 0x11, 0x67, 0x49, 0xD1, 0xD1, 0x88, 0x92, 0xF6, 0xA1, 0xD8};120static const u8 key_D91681F0[] = {0x52, 0xB6, 0x36, 0x6C, 0x8C, 0x46, 0x7F, 0x7A, 0xCC, 0x11, 0x62, 0x99, 0xC1, 0x99, 0xBE, 0x98};121static const u8 key_2E5E0AF0[] = {0xAC, 0xD7, 0x6D, 0x90, 0x33, 0x37, 0x38, 0x92, 0x31, 0x41, 0xD6, 0x36, 0xAF, 0x9F, 0x17, 0x15};122static const u8 xor_2E5E0AF0[] = {0x69, 0xBA, 0x55, 0x34, 0xF0, 0xC0, 0xD6, 0x71, 0xE3, 0x1F, 0xDB, 0x97, 0xE0, 0x7C, 0xD2, 0x2A};123static const u8 key_2E5E10F0[] = {0x9D, 0x5C, 0x5B, 0xAF, 0x8C, 0xD8, 0x69, 0x7E, 0x51, 0x9F, 0x70, 0x96, 0xE6, 0xD5, 0xC4, 0xE8};124static const u8 xor_2E5E10F0[] = {0x69, 0xBA, 0x55, 0x34, 0xF0, 0xC0, 0xD6, 0x71, 0xE3, 0x1F, 0xDB, 0x97, 0xE0, 0x7C, 0xD2, 0x2A};125static const u8 key_2E5E11F0[] = {0x75, 0xEB, 0xE8, 0x43, 0xF4, 0x87, 0x8F, 0xD0, 0x14, 0x7F, 0x7E, 0x39, 0xAD, 0xAF, 0x04, 0x9D};126static const u8 xor_2E5E11F0[] = {0x69, 0xBA, 0x55, 0x34, 0xF0, 0xC0, 0xD6, 0x71, 0xE3, 0x1F, 0xDB, 0x97, 0xE0, 0x7C, 0xD2, 0x2A};127static const u8 key_2E5E12F0[] = {0x8A, 0x7B, 0xC9, 0xD6, 0x52, 0x58, 0x88, 0xEA, 0x51, 0x83, 0x60, 0xCA, 0x16, 0x79, 0xE2, 0x07};128static const u8 xor_2E5E12F0[] = {0x69, 0xBA, 0x55, 0x34, 0xF0, 0xC0, 0xD6, 0x71, 0xE3, 0x1F, 0xDB, 0x97, 0xE0, 0x7C, 0xD2, 0x2A};129static const u8 key_2E5E13F0[] = {0xFF, 0xA4, 0x68, 0xC3, 0x31, 0xCA, 0xB7, 0x4C, 0xF1, 0x23, 0xFF, 0x01, 0x65, 0x3D, 0x26, 0x36};130static const u8 xor_2E5E13F0[] = {0x69, 0xBA, 0x55, 0x34, 0xF0, 0xC0, 0xD6, 0x71, 0xE3, 0x1F, 0xDB, 0x97, 0xE0, 0x7C, 0xD2, 0x2A};131static const u8 key_2E5E80F0[] = {0x0F, 0x74, 0xAF, 0x43, 0x75, 0xCD, 0xDA, 0x39, 0x81, 0x56, 0xD9, 0x61, 0x3E, 0x16, 0xC8, 0x92};132static const u8 xor_2E5E80F0[] = {0x69, 0xBA, 0x55, 0x34, 0xF0, 0xC0, 0xD6, 0x71, 0xE3, 0x1F, 0xDB, 0x97, 0xE0, 0x7C, 0xD2, 0x2A};133static const u8 key_2E5E90F0[] = {0x67, 0xE4, 0x8F, 0x4C, 0x08, 0xA0, 0x7D, 0xB1, 0x5F, 0x51, 0xA7, 0x72, 0x98, 0xA8, 0x2D, 0x7E};134static const u8 xor_2E5E90F0[] = {0x69, 0xBA, 0x55, 0x34, 0xF0, 0xC0, 0xD6, 0x71, 0xE3, 0x1F, 0xDB, 0x97, 0xE0, 0x7C, 0xD2, 0x2A};135static const u8 key_2FD30BF0[] = {0xD8, 0x58, 0x79, 0xF9, 0xA4, 0x22, 0xAF, 0x86, 0x90, 0xAC, 0xDA, 0x45, 0xCE, 0x60, 0x40, 0x3F};136static const u8 keys02G_E[] = {0x9D, 0x09, 0xFD, 0x20, 0xF3, 0x8F, 0x10, 0x69, 0x0D, 0xB2, 0x6F, 0x00, 0xCC, 0xC5, 0x51, 0x2E};137static const u8 keys03G_E[] = {0x4F, 0x44, 0x5C, 0x62, 0xB3, 0x53, 0xC4, 0x30, 0xFC, 0x3A, 0xA4, 0x5B, 0xEC, 0xFE, 0x51, 0xEA};138static const u8 keys05G_E[] = {0x5D, 0xAA, 0x72, 0xF2, 0x26, 0x60, 0x4D, 0x1C, 0xE7, 0x2D, 0xC8, 0xA3, 0x2F, 0x79, 0xC5, 0x54};139static const u8 oneseg_310[] = {0xC7, 0x27, 0x72, 0x85, 0xAB, 0xA7, 0xF7, 0xF0, 0x4C, 0xC1, 0x86, 0xCC, 0xE3, 0x7F, 0x17, 0xCA};140static const u8 oneseg_300[] = {0x76, 0x40, 0x9E, 0x08, 0xDB, 0x9B, 0x3B, 0xA1, 0x47, 0x8A, 0x96, 0x8E, 0xF3, 0xF7, 0x62, 0x92};141static const u8 oneseg_280[] = {0x23, 0xDC, 0x3B, 0xB5, 0xA9, 0x82, 0xD6, 0xEA, 0x63, 0xA3, 0x6E, 0x2B, 0x2B, 0xE9, 0xE1, 0x54};142static const u8 oneseg_260_271[] = {0x22, 0x43, 0x57, 0x68, 0x2F, 0x41, 0xCE, 0x65, 0x4C, 0xA3, 0x7C, 0xC6, 0xC4, 0xAC, 0xF3, 0x60};143static const u8 oneseg_slim[] = {0x12, 0x57, 0x0D, 0x8A, 0x16, 0x6D, 0x87, 0x06, 0x03, 0x7D, 0xC8, 0x8B, 0x62, 0xA3, 0x32, 0xA9};144static const u8 ms_app_main[] = {0x1E, 0x2E, 0x38, 0x49, 0xDA, 0xD4, 0x16, 0x08, 0x27, 0x2E, 0xF3, 0xBC, 0x37, 0x75, 0x80, 0x93};145static const u8 demokeys_280[] = {0x12, 0x99, 0x70, 0x5E, 0x24, 0x07, 0x6C, 0xD0, 0x2D, 0x06, 0xFE, 0x7E, 0xB3, 0x0C, 0x11, 0x26};146static const u8 demokeys_3XX_1[] = {0x47, 0x05, 0xD5, 0xE3, 0x56, 0x1E, 0x81, 0x9B, 0x09, 0x2F, 0x06, 0xDB, 0x6B, 0x12, 0x92, 0xE0};147static const u8 demokeys_3XX_2[] = {0xF6, 0x62, 0x39, 0x6E, 0x26, 0x22, 0x4D, 0xCA, 0x02, 0x64, 0x16, 0x99, 0x7B, 0x9A, 0xE7, 0xB8};148static const u8 ebootbin_271_new[] = {0xF4, 0xAE, 0xF4, 0xE1, 0x86, 0xDD, 0xD2, 0x9C, 0x7C, 0xC5, 0x42, 0xA6, 0x95, 0xA0, 0x83, 0x88};149static const u8 gameshare_260_271[] = {0xF9, 0x48, 0x38, 0x0C, 0x96, 0x88, 0xA7, 0x74, 0x4F, 0x65, 0xA0, 0x54, 0xC2, 0x76, 0xD9, 0xB8};150static const u8 gameshare_280[] = {0x2D, 0x86, 0x77, 0x3A, 0x56, 0xA4, 0x4F, 0xDD, 0x3C, 0x16, 0x71, 0x93, 0xAA, 0x8E, 0x11, 0x43};151static const u8 gameshare_300[] = {0x78, 0x1A, 0xD2, 0x87, 0x24, 0xBD, 0xA2, 0x96, 0x18, 0x3F, 0x89, 0x36, 0x72, 0x90, 0x92, 0x85};152static const u8 gameshare_310[] = {0xC9, 0x7D, 0x3E, 0x0A, 0x54, 0x81, 0x6E, 0xC7, 0x13, 0x74, 0x99, 0x74, 0x62, 0x18, 0xE7, 0xDD};153static const u8 key_380210F0[] = {0x32, 0x2C, 0xFA, 0x75, 0xE4, 0x7E, 0x93, 0xEB, 0x9F, 0x22, 0x80, 0x85, 0x57, 0x08, 0x98, 0x48};154static const u8 key_380280F0[] = {0x97, 0x09, 0x12, 0xD3, 0xDB, 0x02, 0xBD, 0xD8, 0xE7, 0x74, 0x51, 0xFE, 0xF0, 0xEA, 0x6C, 0x5C};155static const u8 key_380283F0[] = {0x34, 0x20, 0x0C, 0x8E, 0xA1, 0x86, 0x79, 0x84, 0xAF, 0x13, 0xAE, 0x34, 0x77, 0x6F, 0xEA, 0x89};156static const u8 key_407810F0[] = {0xAF, 0xAD, 0xCA, 0xF1, 0x95, 0x59, 0x91, 0xEC, 0x1B, 0x27, 0xD0, 0x4E, 0x8A, 0xF3, 0x3D, 0xE7};157static const u8 drmkeys_6XX_1[] = {0x36, 0xEF, 0x82, 0x4E, 0x74, 0xFB, 0x17, 0x5B, 0x14, 0x14, 0x05, 0xF3, 0xB3, 0x8A, 0x76, 0x18};158static const u8 drmkeys_6XX_2[] = {0x21, 0x52, 0x5D, 0x76, 0xF6, 0x81, 0x0F, 0x15, 0x2F, 0x4A, 0x40, 0x89, 0x63, 0xA0, 0x10, 0x55};159static const u8 pauth_98b83b5d_1[] = {0xB0, 0x24, 0xC8, 0x16, 0x43, 0xE8, 0xF0, 0x1C, 0x8C, 0x30, 0x67, 0x73, 0x3E, 0x96, 0x35, 0xEF};160static const u8 pauth_98b83b5d_xor[] = {0xA9, 0x1E, 0xDD, 0x7B, 0x09, 0xBB, 0x22, 0xB5, 0x9D, 0xA3, 0x30, 0x69, 0x13, 0x6E, 0x0E, 0xD8};161static const u8 pauth_f7aa47f6_1[] = {0xC5, 0xFB, 0x69, 0x03, 0x20, 0x7A, 0xCF, 0xBA, 0x2C, 0x90, 0xF8, 0xB8, 0x4D, 0xD2, 0xF1, 0xDE};162static const u8 pauth_f7aa47f6_2[] = {0x3A, 0x6B, 0x48, 0x96, 0x86, 0xA5, 0xC8, 0x80, 0x69, 0x6C, 0xE6, 0x4B, 0xF6, 0x04, 0x17, 0x44};163static const u8 pauth_f7aa47f6_xor[] = {0xA9, 0x1E, 0xDD, 0x7B, 0x09, 0xBB, 0x22, 0xB5, 0x9D, 0xA3, 0x30, 0x69, 0x13, 0x6E, 0x0E, 0xD8};164165// PRXDecrypter 144-byte tag keys.166static const u32 g_key0[] = {1670x7b21f3be, 0x299c5e1d, 0x1c9c5e71, 0x96cb4645, 0x3c9b1be0, 0xeb85de3d,1680x4a7f2022, 0xc2206eaa, 0xd50b3265, 0x55770567, 0x3c080840, 0x981d55f2,1690x5fd8f6f3, 0xee8eb0c5, 0x944d8152, 0xf8278651, 0x2705bafa, 0x8420e533,1700x27154ae9, 0x4819aa32, 0x59a3aa40, 0x2cb3cf65, 0xf274466d, 0x3a655605,1710x21b0f88f, 0xc5b18d26, 0x64c19051, 0xd669c94e, 0xe87035f2, 0x9d3a5909,1720x6f4e7102, 0xdca946ce, 0x8416881b, 0xbab097a5, 0x249125c6, 0xb34c0872};173static const u32 g_key2[] = {1740xccfda932, 0x51c06f76, 0x046dcccf, 0x49e1821e, 0x7d3b024c, 0x9dda5865,1750xcc8c9825, 0xd1e97db5, 0x6874d8cb, 0x3471c987, 0x72edb3fc, 0x81c8365d,1760xe161e33a, 0xfc92db59, 0x2009b1ec, 0xb1a94ce4, 0x2f03696b, 0x87e236d8,1770x3b2b8ce9, 0x0305e784, 0xf9710883, 0xb039db39, 0x893bea37, 0xe74d6805,1780x2a5c38bd, 0xb08dc813, 0x15b32375, 0x46be4525, 0x0103fd90, 0xa90e87a2,1790x52aba66a, 0x85bf7b80, 0x45e8ce63, 0x4dd716d3, 0xf5e30d2d, 0xaf3ae456};180static const u32 g_key3[] = {1810xa6c8f5ca, 0x6d67c080, 0x924f4d3a, 0x047ca06a, 0x08640297, 0x4fd4a758,1820xbd685a87, 0x9b2701c2, 0x83b62a35, 0x726b533c, 0xe522fa0c, 0xc24b06b4,1830x459d1cac, 0xa8c5417b, 0x4fea62a2, 0x0615d742, 0x30628d09, 0xc44fab14,1840x69ff715e, 0xd2d8837d, 0xbeed0b8b, 0x1e6e57ae, 0x61e8c402, 0xbe367a06,1850x543f2b5e, 0xdb3ec058, 0xbe852075, 0x1e7e4dcc, 0x1564ea55, 0xec7825b4,1860xc0538cad, 0x70f72c7f, 0x49e8c3d0, 0xeda97ec5, 0xf492b0a4, 0xe05eb02a};187static const u32 g_key44[] = {1880xef80e005, 0x3a54689f, 0x43c99ccd, 0x1b7727be, 0x5cb80038, 0xdd2efe62,1890xf369f92c, 0x160f94c5, 0x29560019, 0xbf3c10c5, 0xf2ce5566, 0xcea2c626,1900xb601816f, 0x64e7481e, 0x0c34debd, 0x98f29cb0, 0x3fc504d7, 0xc8fb39f0,1910x0221b3d8, 0x63f936a2, 0x9a3a4800, 0x6ecc32e3, 0x8e120cfd, 0xb0361623,1920xaee1e689, 0x745502eb, 0xe4a6c61c, 0x74f23eb4, 0xd7fa5813, 0xb01916eb,1930x12328457, 0xd2bc97d2, 0x646425d8, 0x328380a5, 0x43da8ab1, 0x4b122ac9};194static const u32 g_key20[] = {1950x33b50800, 0xf32f5fcd, 0x3c14881f, 0x6e8a2a95, 0x29feefd5, 0x1394eae3,1960xbd6bd443, 0x0821c083, 0xfab379d3, 0xe613e165, 0xf5a754d3, 0x108b2952,1970x0a4b1e15, 0x61eadeba, 0x557565df, 0x3b465301, 0xae54ecc3, 0x61423309,1980x70c9ff19, 0x5b0ae5ec, 0x989df126, 0x9d987a5f, 0x55bc750e, 0xc66eba27,1990x2de988e8, 0xf76600da, 0x0382dccb, 0x5569f5f2, 0x8e431262, 0x288fe3d3,2000x656f2187, 0x37d12e9c, 0x2f539eb4, 0xa492998e, 0xed3958f7, 0x39e96523};201static const u32 g_key3A[] = {2020x67877069, 0x3abd5617, 0xc23ab1dc, 0xab57507d, 0x066a7f40, 0x24def9b9,2030x06f759e4, 0xdcf524b1, 0x13793e5e, 0x0359022d, 0xaae7e1a2, 0x76b9b2fa,2040x9a160340, 0x87822fba, 0x19e28fbb, 0x9e338a02, 0xd8007e9a, 0xea317af1,2050x630671de, 0x0b67ca7c, 0x865192af, 0xea3c3526, 0x2b448c8e, 0x8b599254,2060x4602e9cb, 0x4de16cda, 0xe164d5bb, 0x07ecd88e, 0x99ffe5f8, 0x768800c1,2070x53b091ed, 0x84047434, 0xb426dbbc, 0x36f948bb, 0x46142158, 0x749bb492};208static const u32 g_keyEBOOT1xx[] = {2090x18CB69EF, 0x158E8912, 0xDEF90EBB, 0x4CB0FB23, 0x3687EE18, 0x868D4A6E,2100x19B5C756, 0xEE16551D, 0xE7CB2D6C, 0x9747C660, 0xCE95143F, 0x2956F477,2110x03824ADE, 0x210C9DF1, 0x5029EB24, 0x81DFE69F, 0x39C89B00, 0xB00C8B91,2120xEF2DF9C2, 0xE13A93FC, 0x8B94A4A8, 0x491DD09D, 0x686A400D, 0xCED4C7E4,2130x96C8B7C9, 0x1EAADC28, 0xA4170B84, 0x505D5DDC, 0x5DA6C3CF, 0x0E5DFA2D,2140x6E7919B5, 0xCE5E29C7, 0xAAACDB94, 0x45F70CDD, 0x62A73725, 0xCCE6563D};215static const u32 g_keyEBOOT2xx[] = {2160xDA8E36FA, 0x5DD97447, 0x76C19874, 0x97E57EAF, 0x1CAB09BD, 0x9835BAC6,2170x03D39281, 0x03B205CF, 0x2882E734, 0xE714F663, 0xB96E2775, 0xBD8AAFC7,2180x1DD3EC29, 0xECA4A16C, 0x5F69EC87, 0x85981E92, 0x7CFCAE21, 0xBAE9DD16,2190xE6A97804, 0x2EEE02FC, 0x61DF8A3D, 0xDD310564, 0x9697E149, 0xC2453F3B,2200xF91D8456, 0x39DA6BC8, 0xB3E5FEF5, 0x89C593A3, 0xFB5C8ABC, 0x6C0B7212,2210xE10DD3CB, 0x98D0B2A8, 0x5FD61847, 0xF0DC2357, 0x7701166A, 0x0F5C3B68};222static const u32 g_demokeys_280[] = {2230x2A5282B4, 0x8706DDA5, 0x4C88EC1C, 0xD504708E, 0x72634DD2, 0xDD2E2F60,2240xE3D5FDB5, 0xE050637D, 0x295C69AC, 0x7B61F57D, 0x594412B0, 0x13D925CE,2250x2A6BE8DD, 0xBC9594E6, 0x1F4A8A39, 0xC56B5909, 0x52CFB2F7, 0x03EE089F,2260x5CA57A21, 0xDB64090F, 0x5E9A56F3, 0x13C56633, 0xD9C48D1D, 0xCDA05972,2270xD09E13B2, 0x7DEDD3DF, 0x364387BB, 0xCB207488, 0xBEC14B3F, 0x7C9C0D11,2280x9916ED40, 0x65909519, 0xC55BB1B3, 0xE997E084, 0xB483438B, 0xB8A2D255};229static const u32 g_keyUPDATER[] = {2300xA5603CBF, 0xD7482441, 0xF65764CC, 0x1F90060B, 0x4EA73E45, 0xE551D192,2310xE7B75D8A, 0x465A506E, 0x40FB1022, 0x2C273350, 0x8096DA44, 0x9947198E,2320x278DEE77, 0x745D062E, 0xC148FA45, 0x832582AF, 0x5FDB86DA, 0xCB15C4CE,2330x2524C62F, 0x6C2EC3B1, 0x369BE39E, 0xF7EB1FC4, 0x1E51CE1A, 0xD70536F4,2340xC34D39D8, 0x7418FB13, 0xE3C84DE1, 0xB118F03C, 0xA2018D4E, 0xE6D8770D,2350x5720F390, 0x17F96341, 0x60A4A68F, 0x1327DD28, 0x05944C64, 0x0C2C4C12};236static const u32 g_keyMEIMG250[] = {2370xA381FEBC, 0x99B9D5C9, 0x6C560A8D, 0x30309F95, 0x792646CC, 0x82B64E5E,2380x1A3951AD, 0x0A182EC4, 0xC46131B4, 0x77C50C8A, 0x325F16C6, 0x02D1942E,2390x0AA38AC4, 0x2A940AC6, 0x67034726, 0xE52DB133, 0xD2EF2107, 0x85C81E90,2400xC8D164BA, 0xC38DCE1D, 0x948BA275, 0x0DB84603, 0xE2473637, 0xCD74FCDA,2410x588E3D66, 0x6D28E822, 0x891E548B, 0xF53CF56D, 0x0BBDDB66, 0xC4B286AA,2420x2BEBBC4B, 0xFC261FF4, 0x92B8E705, 0xDCEE6952, 0x5E0442E5, 0x8BEB7F21};243static const u32 g_keyMEIMG260[] = {2440x11BFD698, 0xD7F9B324, 0xDD524927, 0x16215B86, 0x504AC36D, 0x5843B217,2450xE5A0DA47, 0xBB73A1E7, 0x2915DB35, 0x375CFD3A, 0xBB70A905, 0x272BEFCA,2460x2E960791, 0xEA0799BB, 0xB85AE6C8, 0xC9CAF773, 0x250EE641, 0x06E74A9E,2470x5244895D, 0x466755A5, 0x9A84AF53, 0xE1024174, 0xEEBA031E, 0xED80B9CE,2480xBC315F72, 0x5821067F, 0xE8313058, 0xD2D0E706, 0xE6D8933E, 0xD7D17FB4,2490x505096C4, 0xFDA50B3B, 0x4635AE3D, 0xEB489C8A, 0x422D762D, 0x5A8B3231};250static const u32 g_keyDEMOS27X[] = {2510x1ABF102F, 0xD596D071, 0x6FC552B2, 0xD4F2531F, 0xF025CDD9, 0xAF9AAF03,2520xE0CF57CF, 0x255494C4, 0x7003675E, 0x907BC884, 0x002D4EE4, 0x0B687A0D,2530x9E3AA44F, 0xF58FDA81, 0xEC26AC8C, 0x3AC9B49D, 0x3471C037, 0xB0F3834D,2540x10DC4411, 0xA232EA31, 0xE2E5FA6B, 0x45594B03, 0xE43A1C87, 0x31DAD9D1,2550x08CD7003, 0xFA9C2FDF, 0x5A891D25, 0x9B5C1934, 0x22F366E5, 0x5F084A32,2560x695516D5, 0x2245BE9F, 0x4F6DD705, 0xC4B8B8A1, 0xBC13A600, 0x77B7FC3B};257static const u32 g_keyUNK1[] = {2580x33B50800, 0xF32F5FCD, 0x3C14881F, 0x6E8A2A95, 0x29FEEFD5, 0x1394EAE3,2590xBD6BD443, 0x0821C083, 0xFAB379D3, 0xE613E165, 0xF5A754D3, 0x108B2952,2600x0A4B1E15, 0x61EADEBA, 0x557565DF, 0x3B465301, 0xAE54ECC3, 0x61423309,2610x70C9FF19, 0x5B0AE5EC, 0x989DF126, 0x9D987A5F, 0x55BC750E, 0xC66EBA27,2620x2DE988E8, 0xF76600DA, 0x0382DCCB, 0x5569F5F2, 0x8E431262, 0x288FE3D3,2630x656F2187, 0x37D12E9C, 0x2F539EB4, 0xA492998E, 0xED3958F7, 0x39E96523};264static const u32 g_key_GAMESHARE1xx[] = {2650x721B53E8, 0xFC3E31C6, 0xF85BA2A2, 0x3CF0AC72, 0x54EEA7AB, 0x5959BFCB,2660x54B8836B, 0xBC431313, 0x989EF2CF, 0xF0CE36B2, 0x98BA4CF8, 0xE971C931,2670xA0375DC8, 0x08E52FA0, 0xAC0DD426, 0x57E4D601, 0xC56E61C7, 0xEF1AB98A,2680xD1D9F8F4, 0x5FE9A708, 0x3EF09D07, 0xFA0C1A8C, 0xA91EEA5C, 0x58F482C5,2690x2C800302, 0x7EE6F6C3, 0xFF6ABBBB, 0x2110D0D0, 0xD3297A88, 0x980012D3,2700xDC59C87B, 0x7FDC5792, 0xDB3F5DA6, 0xFC23B787, 0x22698ED3, 0xB680E812};271static const u32 g_key_GAMESHARE2xx[] = {2720x94A757C7, 0x9FD39833, 0xF8508371, 0x328B0B29, 0x2CBCB9DA, 0x2918B9C6,2730x944C50BA, 0xF1DCE7D0, 0x640C3966, 0xC90B3D08, 0xF4AD17BA, 0x6CA0F84B,2740xF7767C67, 0xA4D3A55A, 0x4A085C6A, 0x6BB27071, 0xFA8B38FB, 0x3FDB31B8,2750x8B7196F2, 0xDB9BED4A, 0x51625B84, 0x4C1481B4, 0xF684F508, 0x30B44770,2760x93AA8E74, 0x90C579BC, 0x246EC88D, 0x2E051202, 0xC774842E, 0xA185D997,2770x7A2B3ADD, 0xFE835B6D, 0x508F184D, 0xEB4C4F13, 0x0E1993D3, 0xBA96DFD2};278static const u32 g_key_INDEXDAT1xx[] = {2790x76CB00AF, 0x111CE62F, 0xB7B27E36, 0x6D8DE8F9, 0xD54BF16A, 0xD9E90373,2800x7599D982, 0x51F82B0E, 0x636103AD, 0x8E40BC35, 0x2F332C94, 0xF513AAE9,2810xD22AFEE9, 0x04343987, 0xFC5BB80C, 0x12349D89, 0x14A481BB, 0x25ED3AE8,2820x7D500E4F, 0x43D1B757, 0x7B59FDAD, 0x4CFBBF34, 0xC3D17436, 0xC1DA21DB,2830xA34D8C80, 0x962B235D, 0x3E420548, 0x09CF9FFE, 0xD4883F5C, 0xD90E9CB5,2840x00AEF4E9, 0xF0886DE9, 0x62A58A5B, 0x52A55546, 0x971941B5, 0xF5B79FAC};285286struct TAG_INFO287{288u32 tag; // 4 byte value at offset 0xD0 in the PRX file289const u32 *key; // "step1_result" use for XOR step290u8 code;291u8 codeExtra;292};293294static const TAG_INFO g_tagInfo[] =295{296{ 0x00000000, g_key0, 0x42 },297{ 0x02000000, g_key2, 0x45 },298{ 0x03000000, g_key3, 0x46 },299{ 0x4467415d, g_key44, 0x59, 0x59 },300{ 0x207bbf2f, g_key20, 0x5A, 0x5A },301{ 0x3ace4dce, g_key3A, 0x5B, 0x5B },302{ 0x07000000, g_key_INDEXDAT1xx, 0x4A },303{ 0x08000000, g_keyEBOOT1xx, 0x4B },304{ 0xC0CB167C, g_keyEBOOT2xx, 0x5D, 0x5D },305{ 0x7F24BDCD, g_demokeys_280, 0x60, 0x60 },306{ 0x0B000000, g_keyUPDATER, 0x4E },307{ 0x0C000000, g_keyDEMOS27X, 0x4F },308{ 0x0F000000, g_keyMEIMG250, 0x52 },309{ 0x862648D1, g_keyMEIMG260, 0x52, 0x52 },310{ 0x207BBF2F, g_keyUNK1, 0x5A, 0x5A },311{ 0x09000000, g_key_GAMESHARE1xx, 0x4C },312{ 0xBB67C59F, g_key_GAMESHARE2xx, 0x5E, 0x5E }313};314315static const TAG_INFO *GetTagInfo(u32 tagFind)316{317for (u32 iTag = 0; iTag < sizeof(g_tagInfo)/sizeof(TAG_INFO); iTag++)318if (g_tagInfo[iTag].tag == tagFind)319return &g_tagInfo[iTag];320return NULL; // not found321}322323////////// Decryption 2 //////////324325struct TAG_INFO2326{327u32 tag; // 4 byte value at offset 0xD0 in the PRX file328const u8 *key; // 16 bytes keys329u8 code; // code for scramble330u8 type;331const u8 *seed;332};333334static const TAG_INFO2 g_tagInfo2[] =335{336{ 0x4C9494F0, keys660_k1, 0x43 },337{ 0x4C9495F0, keys660_k2, 0x43 },338{ 0x4C9490F0, keys660_k3, 0x43 },339{ 0x4C9491F0, keys660_k8, 0x43 },340{ 0x4C9493F0, keys660_k4, 0x43 },341{ 0x4C9497F0, keys660_k5, 0x43 },342{ 0x4C9492F0, keys660_k6, 0x43 },343{ 0x4C9496F0, keys660_k7, 0x43 },344{ 0x457B90F0, keys660_v1, 0x5B },345{ 0x457B91F0, keys660_v7, 0x5B },346{ 0x457B92F0, keys660_v6, 0x5B },347{ 0x457B93F0, keys660_v3, 0x5B },348{ 0x380290F0, keys660_v2, 0x5A },349{ 0x380291F0, keys660_v8, 0x5A },350{ 0x380292F0, keys660_v4, 0x5A },351{ 0x380293F0, keys660_v5, 0x5A },352{ 0x4C948CF0, keys639_k3, 0x43 },353{ 0x4C948DF0, keys638_k4, 0x43 },354{ 0x4C948BF0, keys636_k2, 0x43 },355{ 0x4C948AF0, keys636_k1, 0x43 },356{ 0x4C9487F0, keys630_k8, 0x43 },357{ 0x457B83F0, keys630_k7, 0x5B },358{ 0x4C9486F0, keys630_k6, 0x43 },359{ 0x457B82F0, keys630_k5, 0x5B },360{ 0x457B81F0, keys630_k4, 0x5B },361{ 0x4C9485F0, keys630_k3, 0x43 },362{ 0x457B80F0, keys630_k2, 0x5B },363{ 0x4C9484F0, keys630_k1, 0x43 },364{ 0x457B28F0, keys620_e, 0x5B },365{ 0x457B0CF0, keys620_a, 0x5B },366{ 0x380228F0, keys620_5v, 0x5A },367{ 0x4C942AF0, keys620_5k, 0x43 },368{ 0x4C9428F0, keys620_5, 0x43 },369{ 0x4C941DF0, keys620_1, 0x43 },370{ 0x4C941CF0, keys620_0, 0x43 },371{ 0x4C9422F0, keys600_2, 0x43 },372{ 0x4C941EF0, keys600_1, 0x43 },373{ 0x4C9429F0, keys570_5k, 0x43 },374{ 0x457B0BF0, keys505_a, 0x5B },375{ 0x4C9419F0, keys505_1, 0x43 },376{ 0x4C9418F0, keys505_0, 0x43 },377{ 0x457B1EF0, keys500_c, 0x5B },378{ 0x4C941FF0, keys500_2, 0x43 },379{ 0x4C9417F0, keys500_1, 0x43 },380{ 0x4C9416F0, keys500_0, 0x43 },381{ 0x4C9414F0, keys390_0, 0x43 },382{ 0x4C9415F0, keys390_1, 0x43 },383{ 0x4C9412F0, keys370_0, 0x43 },384{ 0x4C9413F0, keys370_1, 0x43 },385{ 0x457B10F0, keys370_2, 0x5B },386{ 0x4C940DF0, keys360_0, 0x43 },387{ 0x4C9410F0, keys360_1, 0x43 },388{ 0x4C940BF0, keys330_0, 0x43 },389{ 0x457B0AF0, keys330_1, 0x5B },390{ 0x38020AF0, keys330_2, 0x5A },391{ 0x4C940AF0, keys330_3, 0x43 },392{ 0x4C940CF0, keys330_4, 0x43 },393{ 0xcfef09f0, keys310_0, 0x62 },394{ 0x457b08f0, keys310_1, 0x5B },395{ 0x380208F0, keys310_2, 0x5A },396{ 0xcfef08f0, keys310_3, 0x62 },397{ 0xCFEF07F0, keys303_0, 0x62 },398{ 0xCFEF06F0, keys300_0, 0x62 },399{ 0x457B06F0, keys300_1, 0x5B },400{ 0x380206F0, keys300_2, 0x5A },401{ 0xCFEF05F0, keys280_0, 0x62 },402{ 0x457B05F0, keys280_1, 0x5B },403{ 0x380205F0, keys280_2, 0x5A },404{ 0x16D59E03, keys260_0, 0x62 },405{ 0x76202403, keys260_1, 0x5B },406{ 0x0F037303, keys260_2, 0x5A },407{ 0x4C940FF0, key_2DA8, 0x43 },408{ 0x4467415D, key_22E0, 0x59 },409{ 0x00000000, key_21C0, 0x42 },410{ 0x01000000, key_2250, 0x43 },411{ 0x2E5E0AF0, key_2E5E0AF0, 0x48, 5, xor_2E5E0AF0 }, //[32]6.20412{ 0x2E5E10F0, key_2E5E10F0, 0x48, 5, xor_2E5E10F0 }, //[32]5.00 PSP-2000 (Game PSN Update 2 LBP)413{ 0x2E5E11F0, key_2E5E11F0, 0x48, 5, xor_2E5E11F0 }, //[32]6.00414{ 0x2E5E12F0, key_2E5E12F0, 0x48, 5, xor_2E5E12F0 },415{ 0x2E5E13F0, key_2E5E13F0, 0x48, 5, xor_2E5E13F0 },416{ 0x2E5E80F0, key_2E5E80F0, 0x48, 5, xor_2E5E80F0 }, //[32]6.30417{ 0x2E5E90F0, key_2E5E90F0, 0x48, 5, xor_2E5E90F0 },418{ 0x2FD30BF0, key_2FD30BF0, 0x47 },419{ 0xD91605F0, key_D91605F0, 0x5D, 2},420{ 0xD91606F0, key_D91606F0, 0x5D, 2},421{ 0xD91608F0, key_D91608F0, 0x5D, 2},422{ 0xD91609F0, key_D91609F0, 0x5D, 2},423{ 0xD9160AF0, key_D9160AF0, 0x5D, 2},424{ 0xD9160BF0, key_D9160BF0, 0x5D, 2},425{ 0xD91611F0, key_D91611F0, 0x5D, 2},426{ 0xD91612F0, key_D91612F0, 0x5D, 2},427{ 0xD91613F0, key_D91613F0, 0x5D, 2},428{ 0xD91614F0, key_D91614F0, 0x5D, 2},429{ 0xD91615F0, key_D91615F0, 0x5D, 2},430{ 0xD91616F0, key_D91616F0, 0x5D, 2},431{ 0xD91617F0, key_D91617F0, 0x5D, 2},432{ 0xD91618F0, key_D91618F0, 0x5D, 2},433{ 0xD91619F0, key_D91619F0, 0x5D, 2},434{ 0xD9161AF0, key_D9161AF0, 0x5D, 2},435{ 0xD91620F0, key_D91620F0, 0x5D, 2},436{ 0xD91621F0, key_D91621F0, 0x5D, 2},437{ 0xD91622F0, key_D91622F0, 0x5D, 2},438{ 0xD91623F0, key_D91623F0, 0x5D, 2},439{ 0xD91624F0, key_D91624F0, 0x5D, 2},440{ 0xD91628F0, key_D91628F0, 0x5D, 2},441{ 0xD91680F0, key_D91680F0, 0x5D, 6},442{ 0xD91681F0, key_D91681F0, 0x5D, 6},443{ 0xD82310F0, keys02G_E, 0x51 },444{ 0xD8231EF0, keys03G_E, 0x51 },445{ 0xD82328F0, keys05G_E, 0x51 },446{ 0x279D08F0, oneseg_310, 0x61 },447{ 0x279D06F0, oneseg_300, 0x61 },448{ 0x279D05F0, oneseg_280, 0x61 },449{ 0xD66DF703, oneseg_260_271, 0x61 },450{ 0x279D10F0, oneseg_slim, 0x61 },451{ 0x3C2A08F0, ms_app_main, 0x67 },452{ 0xADF305F0, demokeys_280, 0x60 },453{ 0xADF306F0, demokeys_3XX_1, 0x60 },454{ 0xADF308F0, demokeys_3XX_2, 0x60 },455{ 0x8004FD03, ebootbin_271_new, 0x5D, 2 },456{ 0x0A35EA03, gameshare_260_271, 0x5E },457{ 0x7B0505F0, gameshare_280, 0x5E },458{ 0x7B0506F0, gameshare_300, 0x5E },459{ 0x7B0508F0, gameshare_310, 0x5E },460{ 0x380210F0, key_380210F0, 0x5A },461{ 0x380280F0, key_380280F0, 0x5A },462{ 0x380283F0, key_380283F0, 0x5A },463{ 0x407810F0, key_407810F0, 0x6A },464{ 0xE92410F0, drmkeys_6XX_1, 0x40 },465{ 0x692810F0, drmkeys_6XX_2, 0x40 },466{ 0x2FD313F0, pauth_98b83b5d_1, 0x47, 5, pauth_98b83b5d_xor },467{ 0x2FD312F0, pauth_f7aa47f6_1, 0x47, 5, pauth_f7aa47f6_xor },468{ 0x2FD311F0, pauth_f7aa47f6_2, 0x47, 5, pauth_f7aa47f6_xor },469};470471static const TAG_INFO2 *GetTagInfo2(u32 tagFind)472{473for (u32 iTag = 0; iTag < sizeof(g_tagInfo2) / sizeof(TAG_INFO2); iTag++)474{475if (g_tagInfo2[iTag].tag == tagFind)476{477return &g_tagInfo2[iTag];478}479}480481return NULL; // not found482}483484static std::array<u8, 0x90> expandSeed(const u8 *seed, int key, const u8 *bonusSeed = nullptr)485{486std::array<u8, 0x90> expandedSeed;487488// perform some AES-CTR like encryption of seed489for (auto i = 0u; i < expandedSeed.size(); i += 0x10)490{491memcpy(expandedSeed.data()+i, seed, 0x10);492expandedSeed[i] = i/0x10;493}494495kirk7(expandedSeed.data(), expandedSeed.data(), expandedSeed.size(), key);496497if (bonusSeed)498{499for (auto i = 0u; i < expandedSeed.size(); ++i)500{501expandedSeed[i] ^= bonusSeed[i % 0x10];502}503}504505return expandedSeed;506}507508template<typename It>509static void decryptKirkHeader(u8 *outbuf, const u8 *inbuf, It xorbuf, int key)510{511for (auto i = 0; i < 0x40; ++i)512{513outbuf[i] = inbuf[i] ^ *xorbuf++;514}515516kirk7(outbuf, outbuf, 0x40, key);517518for (auto i = 0; i < 0x40; ++i)519{520outbuf[i] = outbuf[i] ^ *xorbuf++;521}522}523524template <typename T>525static void decryptKirkHeaderType0(u8 *outbuf, const u8 *inbuf, T xorbuf, int key)526{527for (auto i = 0; i < 0x70; ++i)528{529outbuf[i] = inbuf[i] ^ xorbuf[i+0x14];530}531532kirk7(outbuf, outbuf, 0x70, key);533534for (auto i = 0; i < 0x70; ++i)535{536outbuf[i] = outbuf[i] ^ xorbuf[i+0x20];537}538}539540struct PRXType0541{542explicit PRXType0(const u8 *prx)543{544memcpy(tag, prx+0xD0, sizeof(tag));545memcpy(sha1, prx+0xD4, sizeof(sha1));546memcpy(unused, prx+0xE8, sizeof(unused));547memcpy(kirkBlock, prx+0x110, 0x40); // key data548memcpy(kirkBlock+0x40, prx+0x80, sizeof(kirkBlock)-0x40);549memcpy(prxHeader, prx, sizeof(prxHeader));550}551552u8 tag[4];553u8 sha1[0x14];554u8 unused[0x28];555u8 kirkBlock[0x90];556u8 prxHeader[0x80];557};558559static_assert(sizeof(PRXType0) == 0x150, "inconsistent size of PRX Type 0");560561struct PRXType1562{563explicit PRXType1(const u8 *prx)564{565memcpy(tag, prx+0xD0, sizeof(tag));566memcpy(sha1, prx+0xD4, sizeof(sha1));567memcpy(unused, prx+0xE8, sizeof(unused));568memcpy(kirkBlock, prx+0x110, 0x40); // key data569memcpy(kirkBlock+0x40, prx+0x80, sizeof(kirkBlock)-0x40);570memcpy(prxHeader, prx, sizeof(prxHeader));571}572573void decrypt(int key)574{575kirk7(sha1+0xC, sha1+0xC, 0xA0, key);576}577578u8 tag[4];579u8 sha1[0x14];580u8 unused[0x28];581u8 kirkBlock[0x90];582u8 prxHeader[0x80];583};584585static_assert(sizeof(PRXType1) == 0x150, "inconsistent size of PRX Type 1");586587struct PRXType2588{589explicit PRXType2(const u8 *prx)590{591memcpy(tag, prx+0xD0, sizeof(tag));592memset(empty, 0, sizeof(empty));593memcpy(id, prx+0x140, sizeof(id));594memcpy(sha1, prx+0x12C, sizeof(sha1));595// kirk header is split between 0x80->0xB0 and 0xC0->0xD0596memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);597memcpy(kirkHeader+0x30, prx+0xC0, 0x10);598memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));599memcpy(prxHeader, prx, sizeof(prxHeader));600}601602void decrypt(int key)603{604kirk7(id, id, 0x60, key);605}606607u8 tag[4];608u8 empty[0x58];609u8 id[0x10];610u8 sha1[0x14];611u8 kirkHeader[0x40];612u8 kirkMetadata[0x10];613u8 prxHeader[0x80];614};615static_assert(sizeof(PRXType2) == 0x150, "inconsistent size of PRX Type 2");616617struct PRXType5618{619explicit PRXType5(const u8 *prx)620{621memcpy(tag, prx+0xD0, sizeof(tag));622memset(empty, 0, sizeof(empty));623memcpy(id, prx+0x140, sizeof(id));624memcpy(sha1, prx+0x12C, sizeof(sha1));625// kirk header is split between 0x80->0xB0 and 0xC0->0xD0626memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);627memcpy(kirkHeader+0x30, prx+0xC0, 0x10);628memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));629memcpy(prxHeader, prx, sizeof(prxHeader));630}631632void decrypt(int key, const u8 *xor1, const u8 *xor2)633{634// first step is to decrypt kirk header + SHA1635u8 data[0x50];636memcpy(data, kirkHeader, sizeof(kirkHeader));637memcpy(data+sizeof(kirkHeader), sha1, 0x10);638639for (auto i = 0; i < 0x50; ++i)640{641if (xor1)642{643data[i] ^= xor1[i % 0x10];644}645646if (xor2)647{648data[i] ^= xor2[i % 0x10];649}650}651652kirk7(data, data, 0x50, key);653654// copy the result back655memcpy(kirkHeader, data, sizeof(kirkHeader));656memcpy(sha1, data+sizeof(kirkHeader), 0x10);657658// second step is a XOR then decrypt id through to kirk header659if (xor1)660{661u8 *p = id;662for (auto i = 0; i < 0x60; ++i)663{664p[i] ^= xor1[i % 0x10];665}666}667668kirk7(id, id, 0x60, key);669}670671u8 tag[4];672u8 empty[0x58];673u8 id[0x10];674u8 sha1[0x14];675u8 kirkHeader[0x40];676u8 kirkMetadata[0x10];677u8 prxHeader[0x80];678};679static_assert(sizeof(PRXType5) == 0x150, "inconsistent size of PRX Type 5");680681struct PRXType6682{683explicit PRXType6(const u8 *prx)684{685memcpy(tag, prx+0xD0, sizeof(tag));686memset(empty, 0, sizeof(empty));687memcpy(ecdsaSignatureTail, prx+0x10C, sizeof(ecdsaSignatureTail));688memcpy(id, prx+0x140, sizeof(id));689memcpy(sha1, prx+0x12C, sizeof(sha1));690// kirk header is split between 0x80->0xB0 and 0xC0->0xD0691memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);692memcpy(kirkHeader+0x30, prx+0xC0, 0x10);693memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));694memcpy(prxHeader, prx, sizeof(prxHeader));695}696697void decrypt(int key)698{699kirk7(id, id, 0x60, key);700}701702u8 tag[4];703u8 empty[0x38];704u8 ecdsaSignatureTail[0x20];705u8 id[0x10];706u8 sha1[0x14];707u8 kirkHeader[0x40];708u8 kirkMetadata[0x10];709u8 prxHeader[0x80];710};711static_assert(sizeof(PRXType6) == 0x150, "inconsistent size of PRX Type 6");712713static int pspDecryptType0(const u8 *inbuf, u8 *outbuf, u32 size)714{715INFO_LOG(Log::Loader, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);716const auto decryptSize = *(s32_le*)&inbuf[0xB0];717const auto pti = GetTagInfo((u32)*(u32_le *)&inbuf[0xD0]);718719if (!pti)720{721return -1;722}723724// no need to expand seed, and no need to decrypt725// normally this would be a kirk7 op, but we have the seed pre-decrypted726std::array<u8, 0x90> xorbuf;727memcpy(xorbuf.data(), reinterpret_cast<const u8 *>(pti->key), xorbuf.size());728729// construct the header format for a type 0 prx730PRXType0 type0(inbuf);731732SHA_CTX ctx;733SHAInit(&ctx);734SHAUpdate(&ctx, xorbuf.data(), 0x14);735SHAUpdate(&ctx, type0.unused, sizeof(type0.unused));736SHAUpdate(&ctx, type0.kirkBlock, sizeof(type0.kirkBlock));737SHAUpdate(&ctx, type0.prxHeader, sizeof(type0.prxHeader));738739u8 sha1[0x14];740SHAFinal(sha1, &ctx);741742if (memcmp(sha1, type0.sha1, sizeof(sha1)) != 0)743{744return -3;745}746747constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type0.prxHeader);748KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);749750if (outbuf != inbuf)751{752memcpy(outbuf, inbuf, size);753}754755memcpy(header, type0.kirkBlock, sizeof(KIRK_CMD1_HEADER));756memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type0.prxHeader, sizeof(type0.prxHeader));757decryptKirkHeaderType0(reinterpret_cast<u8*>(header), type0.kirkBlock, xorbuf, pti->code);758759if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)760{761return -4;762}763764return decryptSize;765}766767static int pspDecryptType1(const u8 *inbuf, u8 *outbuf, u32 size)768{769INFO_LOG(Log::Loader, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);770const auto decryptSize = *(s32_le*)&inbuf[0xB0];771const auto pti = GetTagInfo((u32)*(u32_le *)&inbuf[0xD0]);772773if (!pti)774{775return -1;776}777778// no need to expand seed, and no need to decrypt779// normally this would be a kirk7 op, but we have the seed pre-decrypted780std::array<u8, 0x90> xorbuf;781memcpy(xorbuf.data(), reinterpret_cast<const u8 *>(pti->key), xorbuf.size());782783// construct the header format for a type 1 prx784PRXType1 type1(inbuf);785type1.decrypt(pti->code);786787SHA_CTX ctx;788SHAInit(&ctx);789SHAUpdate(&ctx, xorbuf.data(), 0x14);790SHAUpdate(&ctx, type1.unused, sizeof(type1.unused));791SHAUpdate(&ctx, type1.kirkBlock, sizeof(type1.kirkBlock));792SHAUpdate(&ctx, type1.prxHeader, sizeof(type1.prxHeader));793794u8 sha1[0x14];795SHAFinal(sha1, &ctx);796797if (memcmp(sha1, type1.sha1, sizeof(sha1)) != 0)798{799return -3;800}801802constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type1.prxHeader);803KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);804805if (outbuf != inbuf)806{807memcpy(outbuf, inbuf, size);808}809810memcpy(header, type1.kirkBlock, sizeof(KIRK_CMD1_HEADER));811memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type1.prxHeader, sizeof(type1.prxHeader));812decryptKirkHeaderType0(reinterpret_cast<u8*>(header), type1.kirkBlock, xorbuf, pti->code);813814if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)815{816return -4;817}818819return decryptSize;820}821822static int pspDecryptType2(const u8 *inbuf, u8 *outbuf, u32 size)823{824INFO_LOG(Log::Loader, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);825const auto decryptSize = *(s32_le*)&inbuf[0xB0];826const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);827828if (!pti)829{830return -1;831}832833// check if range is non-zero834if (std::any_of(inbuf+0xD4, inbuf+0xD4+0x58, [](u8 x) { return x != 0; }))835{836return -2;837}838839// expand the seed into a xor buffer840auto xorbuf = expandSeed(pti->key, pti->code);841842// construct the header format for a type 2 prx843PRXType2 type2(inbuf);844type2.decrypt(pti->code);845846SHA_CTX ctx;847SHAInit(&ctx);848SHAUpdate(&ctx, type2.tag, sizeof(type2.tag));849SHAUpdate(&ctx, xorbuf.data(), 0x10);850SHAUpdate(&ctx, type2.empty, sizeof(type2.empty));851SHAUpdate(&ctx, type2.id, sizeof(type2.id));852SHAUpdate(&ctx, type2.kirkHeader, sizeof(type2.kirkHeader));853SHAUpdate(&ctx, type2.kirkMetadata, sizeof(type2.kirkMetadata));854SHAUpdate(&ctx, type2.prxHeader, sizeof(type2.prxHeader));855856u8 sha1[0x14];857SHAFinal(sha1, &ctx);858859if (memcmp(sha1, type2.sha1, sizeof(sha1)) != 0)860{861return -3;862}863864constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type2.prxHeader);865KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);866867if (outbuf != inbuf)868{869memcpy(outbuf, inbuf, size);870}871872memset(header, 0, sizeof(KIRK_CMD1_HEADER));873memcpy(reinterpret_cast<u8*>(&header->data_size), type2.kirkMetadata, sizeof(type2.kirkMetadata));874memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type2.prxHeader, sizeof(type2.prxHeader));875decryptKirkHeader(reinterpret_cast<u8*>(header), type2.kirkHeader, xorbuf.cbegin()+0x10, pti->code);876header->mode = 1;877878if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)879{880return -4;881}882883return decryptSize;884}885886static int pspDecryptType5(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed)887{888INFO_LOG(Log::Loader, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);889const auto decryptSize = *(s32_le*)&inbuf[0xB0];890const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);891892if (!pti)893{894return -1;895}896897// check if range is non-zero898if (std::any_of(inbuf+0xD4+1, inbuf+0xD4+0x58, [](u8 x) { return x != 0; }))899{900return -2;901}902903// expand the seed into a xor buffer904auto xorbuf = expandSeed(pti->key, pti->code, seed);905906// construct the header format for a type 2 prx907PRXType5 type5(inbuf);908type5.decrypt(pti->code, pti->seed, seed);909910SHA_CTX ctx;911SHAInit(&ctx);912SHAUpdate(&ctx, type5.tag, sizeof(type5.tag));913SHAUpdate(&ctx, xorbuf.data(), 0x10);914SHAUpdate(&ctx, type5.empty, sizeof(type5.empty));915SHAUpdate(&ctx, type5.id, sizeof(type5.id));916SHAUpdate(&ctx, type5.kirkHeader, sizeof(type5.kirkHeader));917SHAUpdate(&ctx, type5.kirkMetadata, sizeof(type5.kirkMetadata));918SHAUpdate(&ctx, type5.prxHeader, sizeof(type5.prxHeader));919920u8 sha1[0x14];921SHAFinal(sha1, &ctx);922923if (memcmp(sha1, type5.sha1, sizeof(sha1)) != 0)924{925return -3;926}927928constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type5.prxHeader);929KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);930931if (outbuf != inbuf)932{933memcpy(outbuf, inbuf, size);934}935936memset(header, 0, sizeof(KIRK_CMD1_HEADER));937memcpy(reinterpret_cast<u8*>(&header->data_size), type5.kirkMetadata, sizeof(type5.kirkMetadata));938memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type5.prxHeader, sizeof(type5.prxHeader));939decryptKirkHeader(reinterpret_cast<u8*>(header), type5.kirkHeader, xorbuf.cbegin()+0x10, pti->code);940header->mode = 1;941942if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)943{944return -4;945}946947return decryptSize;948}949950static int pspDecryptType6(const u8 *inbuf, u8 *outbuf, u32 size)951{952INFO_LOG(Log::Loader, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);953const auto decryptSize = *(s32_le*)&inbuf[0xB0];954const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);955956if (!pti)957{958return -1;959}960961// check if range is non-zero962if (std::any_of(inbuf+0xD4, inbuf+0xD4+0x38, [](u8 x) { return x != 0; }))963{964return -2;965}966967// expand the seed into a xor buffer968auto xorbuf = expandSeed(pti->key, pti->code);969970// construct the header format for a type 2 prx971PRXType6 type6(inbuf);972type6.decrypt(pti->code);973974SHA_CTX ctx;975SHAInit(&ctx);976SHAUpdate(&ctx, type6.tag, sizeof(type6.tag));977SHAUpdate(&ctx, xorbuf.data(), 0x10);978SHAUpdate(&ctx, type6.empty, sizeof(type6.empty));979SHAUpdate(&ctx, type6.ecdsaSignatureTail, sizeof(type6.ecdsaSignatureTail));980SHAUpdate(&ctx, type6.id, sizeof(type6.id));981SHAUpdate(&ctx, type6.kirkHeader, sizeof(type6.kirkHeader));982SHAUpdate(&ctx, type6.kirkMetadata, sizeof(type6.kirkMetadata));983SHAUpdate(&ctx, type6.prxHeader, sizeof(type6.prxHeader));984985u8 sha1[0x14];986SHAFinal(sha1, &ctx);987988if (memcmp(sha1, type6.sha1, sizeof(sha1)) != 0)989{990return -3;991}992993constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_ECDSA_HEADER)-sizeof(type6.prxHeader);994KIRK_CMD1_ECDSA_HEADER *header = reinterpret_cast<KIRK_CMD1_ECDSA_HEADER *>(outbuf+offset);995996if (outbuf != inbuf)997{998memcpy(outbuf, inbuf, size);999}10001001memset(header, 0, sizeof(KIRK_CMD1_ECDSA_HEADER));1002memcpy(outbuf+offset+0x40, type6.ecdsaSignatureTail, sizeof(type6.ecdsaSignatureTail));1003memcpy(reinterpret_cast<u8*>(&header->data_size), type6.kirkMetadata, sizeof(type6.kirkMetadata));1004memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_ECDSA_HEADER), type6.prxHeader, sizeof(type6.prxHeader));1005decryptKirkHeader(reinterpret_cast<u8*>(header), type6.kirkHeader, xorbuf.cbegin()+0x10, pti->code);1006header->mode = 1;1007header->ecdsa_hash = 1;10081009if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)1010{1011return -4;1012}10131014return decryptSize;1015}10161017int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed)1018{1019kirk_init();10201021// this would be significantly better if we had a log of the tags1022// and their appropriate prx types1023// since we don't know the PRX type we attempt a decrypt using all1024auto res = pspDecryptType0(inbuf, outbuf, size);10251026if (res >= 0)1027return res;10281029res = pspDecryptType1(inbuf, outbuf, size);10301031if (res >= 0)1032return res;10331034res = pspDecryptType2(inbuf, outbuf, size);10351036if (res >= 0)1037return res;10381039res = pspDecryptType5(inbuf, outbuf, size, seed);10401041if (res >= 0)1042return res;10431044return pspDecryptType6(inbuf, outbuf, size);1045}104610471048